Merge change 3305 into donut
* changes:
Fix parameter mismatch for a couple of RIL commands.
diff --git a/api/current.xml b/api/current.xml
index 9e9eaad4..69660d6 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -34943,6 +34943,16 @@
visibility="public"
>
</field>
+<field name="expandable"
+ type="boolean"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="flags"
type="int"
transient="false"
@@ -36787,6 +36797,17 @@
visibility="public"
>
</field>
+<field name="GET_EXPANDABLE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="131072"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="GET_GIDS"
type="int"
transient="false"
@@ -48750,6 +48771,16 @@
visibility="public"
>
</field>
+<field name="inInputShareable"
+ type="boolean"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="inJustDecodeBounds"
type="boolean"
transient="false"
@@ -107249,6 +107280,50 @@
visibility="public"
>
</field>
+<field name="TTS_DEFAULT_PITCH"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""tts_default_pitch""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TTS_DEFAULT_RATE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""tts_default_rate""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TTS_DEFAULT_SYNTH"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""tts_default_synth""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TTS_USE_DEFAULTS"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""tts_use_defaults""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="USB_MASS_STORAGE_ENABLED"
type="java.lang.String"
transient="false"
@@ -108297,6 +108372,17 @@
visibility="public"
>
</field>
+<field name="SHOW_WEB_SUGGESTIONS"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""show_web_suggestions""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="SOUND_EFFECTS_ENABLED"
type="java.lang.String"
transient="false"
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 88ad265..2a4a672 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -526,7 +526,7 @@
private void showUsage() {
System.err.println("usage: am [start|broadcast|instrument|profile]");
- System.err.println(" am start -D INTENT");
+ System.err.println(" am start [-D] INTENT");
System.err.println(" am broadcast INTENT");
System.err.println(" am instrument [-r] [-e <ARG_NAME> <ARG_VALUE>] [-p <PROF_FILE>]");
System.err.println(" [-w] <COMPONENT> ");
diff --git a/cmds/backup/backup.cpp b/cmds/backup/backup.cpp
index 51ac943..22dd486 100644
--- a/cmds/backup/backup.cpp
+++ b/cmds/backup/backup.cpp
@@ -1,5 +1,20 @@
+/*
+ * 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.
+ */
-#include <utils/backup_helpers.h>
+#include <utils/BackupHelpers.h>
#include <utils/String8.h>
#include <fcntl.h>
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 29e57cd..d08fc11 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -162,7 +162,7 @@
return metrics;
}
- Resources getTopLevelResources(String appDir, float applicationScale) {
+ Resources getTopLevelResources(String appDir, PackageInfo pkgInfo) {
synchronized (mPackages) {
//Log.w(TAG, "getTopLevelResources: " + appDir);
WeakReference<Resources> wr = mActiveResources.get(appDir);
@@ -181,23 +181,17 @@
if (assets.addAssetPath(appDir) == 0) {
return null;
}
- DisplayMetrics metrics = getDisplayMetricsLocked(false);
- // density used to load resources
- // scaledDensity is calculated in Resources constructor
- //
- boolean usePreloaded = true;
-
- // TODO: use explicit flag to indicate the compatibility mode.
- if (applicationScale != 1.0f) {
- usePreloaded = false;
- DisplayMetrics newMetrics = new DisplayMetrics();
- newMetrics.setTo(metrics);
- float newDensity = metrics.density / applicationScale;
- newMetrics.updateDensity(newDensity);
- metrics = newMetrics;
+ ApplicationInfo appInfo;
+ try {
+ appInfo = getPackageManager().getApplicationInfo(
+ pkgInfo.getPackageName(),
+ PackageManager.GET_SUPPORTS_DENSITIES | PackageManager.GET_EXPANDABLE);
+ } catch (RemoteException e) {
+ throw new AssertionError(e);
}
//Log.i(TAG, "Resource:" + appDir + ", display metrics=" + metrics);
- r = new Resources(assets, metrics, getConfiguration(), usePreloaded);
+ DisplayMetrics metrics = getDisplayMetricsLocked(false);
+ r = new Resources(assets, metrics, getConfiguration(), appInfo);
//Log.i(TAG, "Created app resources " + r + ": " + r.getConfiguration());
// XXX need to remove entries when weak references go away
mActiveResources.put(appDir, new WeakReference<Resources>(r));
@@ -225,7 +219,6 @@
private Resources mResources;
private ClassLoader mClassLoader;
private Application mApplication;
- private float mApplicationScale;
private final HashMap<Context, HashMap<BroadcastReceiver, ReceiverDispatcher>> mReceivers
= new HashMap<Context, HashMap<BroadcastReceiver, ReceiverDispatcher>>();
@@ -268,8 +261,6 @@
mClassLoader = mSystemContext.getClassLoader();
mResources = mSystemContext.getResources();
}
-
- mApplicationScale = -1.0f;
}
public PackageInfo(ActivityThread activityThread, String name,
@@ -288,7 +279,6 @@
mIncludeCode = true;
mClassLoader = systemContext.getClassLoader();
mResources = systemContext.getResources();
- mApplicationScale = systemContext.getApplicationScale();
}
public String getPackageName() {
@@ -299,45 +289,6 @@
return mSecurityViolation;
}
- public float getApplicationScale() {
- if (mApplicationScale > 0.0f) {
- return mApplicationScale;
- }
- DisplayMetrics metrics = mActivityThread.getDisplayMetricsLocked(false);
- // Find out the density scale (relative to 160) of the supported density that
- // is closest to the system's density.
- try {
- ApplicationInfo ai = getPackageManager().getApplicationInfo(
- mPackageName, PackageManager.GET_SUPPORTS_DENSITIES);
-
- float appScale = -1.0f;
- if (ai.supportsDensities != null) {
- int minDiff = Integer.MAX_VALUE;
- for (int density : ai.supportsDensities) {
- int tmpDiff = (int) Math.abs(DisplayMetrics.DEVICE_DENSITY - density);
- if (tmpDiff == 0) {
- appScale = 1.0f;
- break;
- }
- // prefer higher density (appScale>1.0), unless that's only option.
- if (tmpDiff < minDiff && appScale < 1.0f) {
- appScale = DisplayMetrics.DEVICE_DENSITY / density;
- minDiff = tmpDiff;
- }
- }
- }
- if (appScale < 0.0f) {
- mApplicationScale = metrics.density;
- } else {
- mApplicationScale = appScale;
- }
- } catch (RemoteException e) {
- throw new AssertionError(e);
- }
- if (localLOGV) Log.v(TAG, "appScale=" + mApplicationScale + ", pkg=" + mPackageName);
- return mApplicationScale;
- }
-
/**
* Gets the array of shared libraries that are listed as
* used by the given package.
@@ -495,7 +446,7 @@
public Resources getResources(ActivityThread mainThread) {
if (mResources == null) {
- mResources = mainThread.getTopLevelResources(mResDir, getApplicationScale());
+ mResources = mainThread.getTopLevelResources(mResDir, this);
}
return mResources;
}
@@ -3606,8 +3557,6 @@
}
mConfiguration.updateFrom(config);
DisplayMetrics dm = getDisplayMetricsLocked(true);
- DisplayMetrics appDm = new DisplayMetrics();
- appDm.setTo(dm);
// set it for java, this also affects newly created Resources
if (config.locale != null) {
@@ -3627,11 +3576,7 @@
WeakReference<Resources> v = it.next();
Resources r = v.get();
if (r != null) {
- // keep the original density based on application cale.
- appDm.updateDensity(r.getDisplayMetrics().density);
- r.updateConfiguration(config, appDm);
- // reset
- appDm.setTo(dm);
+ r.updateConfiguration(config, dm);
//Log.i(TAG, "Updated app resources " + v.getKey()
// + " " + r + ": " + r.getConfiguration());
} else {
diff --git a/core/java/android/app/ApplicationContext.java b/core/java/android/app/ApplicationContext.java
index 2d6381a..98bbf7b 100644
--- a/core/java/android/app/ApplicationContext.java
+++ b/core/java/android/app/ApplicationContext.java
@@ -551,19 +551,6 @@
}
}
- /**
- * @hide
- */
- @Override
- public float getApplicationScale() {
- if (mPackageInfo != null) {
- return mPackageInfo.getApplicationScale();
- } else {
- // same as system density
- return 1.0f;
- }
- }
-
@Override
public void setWallpaper(Bitmap bitmap) throws IOException {
try {
@@ -2028,8 +2015,7 @@
ActivityThread.PackageInfo pi = mContext.mMainThread.getPackageInfoNoCheck(app);
Resources r = mContext.mMainThread.getTopLevelResources(
app.uid == Process.myUid() ? app.sourceDir
- : app.publicSourceDir,
- pi.getApplicationScale());
+ : app.publicSourceDir, pi);
if (r != null) {
return r;
}
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index e28fd0f..6750d12 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -350,6 +350,14 @@
scheduleCreateBackupAgent(appInfo, backupMode);
return true;
}
+
+ case SCHEDULE_DESTROY_BACKUP_AGENT_TRANSACTION:
+ {
+ data.enforceInterface(IApplicationThread.descriptor);
+ ApplicationInfo appInfo = ApplicationInfo.CREATOR.createFromParcel(data);
+ scheduleDestroyBackupAgent(appInfo);
+ return true;
+ }
}
return super.onTransact(code, data, reply, flags);
diff --git a/core/java/android/app/ISearchManager.aidl b/core/java/android/app/ISearchManager.aidl
index 39eb4f1..374423e 100644
--- a/core/java/android/app/ISearchManager.aidl
+++ b/core/java/android/app/ISearchManager.aidl
@@ -23,4 +23,7 @@
interface ISearchManager {
SearchableInfo getSearchableInfo(in ComponentName launchActivity, boolean globalSearch);
List<SearchableInfo> getSearchablesInGlobalSearch();
+ List<SearchableInfo> getSearchablesForWebSearch();
+ SearchableInfo getDefaultSearchableForWebSearch();
+ void setDefaultWebSearch(in ComponentName component);
}
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java
index bcb2791..0bb483b 100644
--- a/core/java/android/app/SearchDialog.java
+++ b/core/java/android/app/SearchDialog.java
@@ -1202,16 +1202,7 @@
protected boolean launchSuggestion(int position, int actionKey, String actionMsg) {
Cursor c = mSuggestionsAdapter.getCursor();
if ((c != null) && c.moveToPosition(position)) {
- // let the cursor know which position was clicked
- final Bundle clickResponse = new Bundle(1);
- clickResponse.putInt(SearchManager.RESPOND_EXTRA_POSITION_CLICKED, position);
- final Bundle response = c.respond(clickResponse);
-
- // the convention is to send a position to select in response to a click (if applicable)
- final int posToSelect = response.getInt(
- SearchManager.RESPOND_EXTRA_POSITION_SELECTED,
- SuggestionsAdapter.NO_ITEM_TO_SELECT);
- mSuggestionsAdapter.setListItemToSelect(posToSelect);
+ mSuggestionsAdapter.callCursorOnClick(c, position);
// launch the intent
Intent intent = createIntentFromSuggestion(c, actionKey, actionMsg);
diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java
index b4a3a78..f1cc24a 100644
--- a/core/java/android/app/SearchManager.java
+++ b/core/java/android/app/SearchManager.java
@@ -1167,38 +1167,50 @@
*/
public final static String EXTRA_DATA_KEY = "intent_extra_data_key";
-
/**
- * Used by the search dialog to ask the global search provider whether there are any pending
- * sources that have yet to respond. Specifically, the search dialog will call
- * {@link Cursor#respond} with a bundle containing this extra as a key, and expect the same key
- * to be in the response, with a boolean value indicating whether there are pending sources.
+ * Defines the constants used in the communication between {@link android.app.SearchDialog} and
+ * the global search provider via {@link Cursor#respond(android.os.Bundle)}.
*
- * {@hide}
+ * @hide
*/
- public final static String RESPOND_EXTRA_PENDING_SOURCES = "respond_extra_pending_sources";
+ public static class DialogCursorProtocol {
- /**
- * Used by the search dialog to tell the cursor that supplied suggestions which item was clicked
- * before launching the intent. The search dialog will call {@link Cursor#respond} with a
- * bundle containing this extra as a key and the position that was clicked as the value.
- *
- * The response bundle will use {@link #RESPOND_EXTRA_POSITION_SELECTED} to return an int value
- * of the index that should be selected, if applicable.
- *
- * {@hide}
- */
- public final static String RESPOND_EXTRA_POSITION_CLICKED = "respond_extra_position_clicked";
+ /**
+ * The sent bundle will contain this integer key, with a value set to one of the events
+ * below.
+ */
+ public final static String METHOD = "DialogCursorProtocol.method";
- /**
- * Used as a key in the response bundle from a call to {@link Cursor#respond} that sends the
- * position that is clicked.
- *
- * @see #RESPOND_EXTRA_POSITION_CLICKED
- *
- * {@hide}
- */
- public final static String RESPOND_EXTRA_POSITION_SELECTED = "respond_extra_position_selected";
+ /**
+ * After data has been refreshed.
+ */
+ public final static int POST_REFRESH = 0;
+ public final static String POST_REFRESH_RECEIVE_ISPENDING
+ = "DialogCursorProtocol.POST_REFRESH.isPending";
+ public final static String POST_REFRESH_RECEIVE_DISPLAY_NOTIFY
+ = "DialogCursorProtocol.POST_REFRESH.displayNotify";
+
+ /**
+ * Just before closing the cursor.
+ */
+ public final static int PRE_CLOSE = 1;
+ public final static String PRE_CLOSE_SEND_MAX_DISPLAY_POS
+ = "DialogCursorProtocol.PRE_CLOSE.sendDisplayPosition";
+
+ /**
+ * When a position has been clicked.
+ */
+ public final static int CLICK = 2;
+ public final static String CLICK_SEND_POSITION
+ = "DialogCursorProtocol.CLICK.sendPosition";
+ public final static String CLICK_RECEIVE_SELECTED_POS
+ = "DialogCursorProtocol.CLICK.receiveSelectedPosition";
+
+ /**
+ * When the threshold received in {@link #POST_REFRESH_RECEIVE_DISPLAY_NOTIFY} is displayed.
+ */
+ public final static int THRESH_HIT = 3;
+ }
/**
* Intent extra data key: Use this key with Intent.ACTION_SEARCH and
@@ -1292,28 +1304,6 @@
*/
public final static String SUGGEST_COLUMN_ICON_2 = "suggest_icon_2";
/**
- * Column name for suggestions cursor. <i>Optional.</i> If your cursor includes this column,
- * then all suggestions will be provided in a format that includes space for two small icons,
- * one at the left and one at the right of each suggestion. The data in the column must
- * be a blob that contains a bitmap.
- *
- * This column overrides any icon provided in the {@link #SUGGEST_COLUMN_ICON_1} column.
- *
- * @hide
- */
- public final static String SUGGEST_COLUMN_ICON_1_BITMAP = "suggest_icon_1_bitmap";
- /**
- * Column name for suggestions cursor. <i>Optional.</i> If your cursor includes this column,
- * then all suggestions will be provided in a format that includes space for two small icons,
- * one at the left and one at the right of each suggestion. The data in the column must
- * be a blob that contains a bitmap.
- *
- * This column overrides any icon provided in the {@link #SUGGEST_COLUMN_ICON_2} column.
- *
- * @hide
- */
- public final static String SUGGEST_COLUMN_ICON_2_BITMAP = "suggest_icon_2_bitmap";
- /**
* Column name for suggestions cursor. <i>Optional.</i> If this column exists <i>and</i>
* this element exists at the given row, this is the action that will be used when
* forming the suggestion's intent. If the element is not provided, the action will be taken
@@ -1415,6 +1405,26 @@
*/
public final static String INTENT_ACTION_SEARCH_SETTINGS
= "android.search.action.SEARCH_SETTINGS";
+
+ /**
+ * Intent action for starting a web search provider's settings activity.
+ * Web search providers should handle this intent if they have provider-specific
+ * settings to implement.
+ *
+ * @hide Pending API council approval.
+ */
+ public final static String INTENT_ACTION_WEB_SEARCH_SETTINGS
+ = "android.search.action.WEB_SEARCH_SETTINGS";
+
+ /**
+ * Intent action broadcasted to inform that the searchables list or default have changed.
+ * Components should handle this intent if they cache any searchable data and wish to stay
+ * up to date on changes.
+ *
+ * @hide Pending API council approval.
+ */
+ public final static String INTENT_ACTION_SEARCHABLES_CHANGED
+ = "android.search.action.SEARCHABLES_CHANGED";
/**
* If a suggestion has this value in {@link #SUGGEST_COLUMN_INTENT_ACTION},
@@ -1744,4 +1754,48 @@
return null;
}
}
+
+ /**
+ * Returns a list of the searchable activities that handle web searches.
+ *
+ * @return a a list of all searchable activities that handle {@link SearchManager#ACTION_WEB_SEARCH}.
+ *
+ * @hide because SearchableInfo is not part of the API.
+ */
+ public static List<SearchableInfo> getSearchablesForWebSearch() {
+ try {
+ return sService.getSearchablesForWebSearch();
+ } catch (RemoteException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Returns the default searchable activity for web searches.
+ *
+ * @return searchable information for the activity handling web searches by default.
+ *
+ * @hide because SearchableInfo is not part of the API.
+ */
+ public static SearchableInfo getDefaultSearchableForWebSearch() {
+ try {
+ return sService.getDefaultSearchableForWebSearch();
+ } catch (RemoteException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Sets the default searchable activity for web searches.
+ *
+ * @param component Name of the component to set as default activity for web searches.
+ *
+ * @hide
+ */
+ public static void setDefaultWebSearch(ComponentName component) {
+ try {
+ sService.setDefaultWebSearch(component);
+ } catch (RemoteException e) {
+ }
+ }
}
diff --git a/core/java/android/app/SuggestionsAdapter.java b/core/java/android/app/SuggestionsAdapter.java
index 747bec9..e515594 100644
--- a/core/java/android/app/SuggestionsAdapter.java
+++ b/core/java/android/app/SuggestionsAdapter.java
@@ -20,9 +20,6 @@
import android.content.Context;
import android.content.res.Resources.NotFoundException;
import android.database.Cursor;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
@@ -36,6 +33,8 @@
import android.widget.ResourceCursorAdapter;
import android.widget.TextView;
+import static android.app.SearchManager.DialogCursorProtocol;
+
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
@@ -47,15 +46,7 @@
* @hide
*/
class SuggestionsAdapter extends ResourceCursorAdapter {
- // The value used to query a cursor whether it is still expecting more input,
- // so we can correctly display (or not display) the 'working' spinner in the search dialog.
- public static final String IS_WORKING = "isWorking";
-
- // The value used to tell a cursor to display the corpus selectors, if this is global
- // search. Also returns the index of the more results item to allow the SearchDialog
- // to tell the ListView to scroll to that list item.
- public static final String SHOW_CORPUS_SELECTORS = "showCorpusSelectors";
-
+
private static final boolean DBG = false;
private static final String LOG_TAG = "SuggestionsAdapter";
@@ -71,17 +62,21 @@
private int mText2Col;
private int mIconName1Col;
private int mIconName2Col;
- private int mIconBitmap1Col;
- private int mIconBitmap2Col;
// This value is stored in SuggestionsAdapter by the SearchDialog to indicate whether
// a particular list item should be selected upon the next call to notifyDataSetChanged.
// This is used to indicate the index of the "More results..." list item so that when
// the data set changes after a click of "More results...", we can correctly tell the
- // ListView to scroll to the right line item. It gets reset to NO_ITEM_TO_SELECT every time it
+ // ListView to scroll to the right line item. It gets reset to NONE every time it
// is consumed.
- private int mListItemToSelect = NO_ITEM_TO_SELECT;
- static final int NO_ITEM_TO_SELECT = -1;
+ private int mListItemToSelect = NONE;
+ static final int NONE = -1;
+
+ // holds the maximum position that has been displayed to the user
+ int mMaxDisplayed = NONE;
+
+ // holds the position that, when displayed, should result in notifying the cursor
+ int mDisplayNotifyPos = NONE;
public SuggestionsAdapter(Context context, SearchDialog searchDialog, SearchableInfo searchable,
WeakHashMap<String, Drawable> outsideDrawablesCache, boolean globalSearchMode) {
@@ -132,6 +127,11 @@
@Override
public void changeCursor(Cursor c) {
if (DBG) Log.d(LOG_TAG, "changeCursor(" + c + ")");
+
+ if (mCursor != null) {
+ callCursorPreClose(mCursor);
+ }
+
super.changeCursor(c);
if (c != null) {
mFormatCol = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_FORMAT);
@@ -139,42 +139,73 @@
mText2Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_TEXT_2);
mIconName1Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_ICON_1);
mIconName2Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_ICON_2);
- mIconBitmap1Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_ICON_1_BITMAP);
- mIconBitmap2Col = c.getColumnIndex(SearchManager.SUGGEST_COLUMN_ICON_2_BITMAP);
}
- updateWorking();
}
-
+
+ /**
+ * Handle sending and receiving information associated with
+ * {@link DialogCursorProtocol#PRE_CLOSE}.
+ *
+ * @param cursor The cursor to call.
+ */
+ private void callCursorPreClose(Cursor cursor) {
+ if (!mGlobalSearchMode) return;
+ final Bundle request = new Bundle();
+ request.putInt(DialogCursorProtocol.METHOD, DialogCursorProtocol.PRE_CLOSE);
+ request.putInt(DialogCursorProtocol.PRE_CLOSE_SEND_MAX_DISPLAY_POS, mMaxDisplayed);
+ final Bundle response = cursor.respond(request);
+
+ mMaxDisplayed = -1;
+ }
+
@Override
public void notifyDataSetChanged() {
+ if (DBG) Log.d(LOG_TAG, "notifyDataSetChanged");
super.notifyDataSetChanged();
- updateWorking();
- if (mListItemToSelect != NO_ITEM_TO_SELECT) {
+
+ callCursorPostRefresh(mCursor);
+
+ // look out for the pending item we are supposed to scroll to
+ if (mListItemToSelect != NONE) {
mSearchDialog.setListSelection(mListItemToSelect);
- mListItemToSelect = NO_ITEM_TO_SELECT;
+ mListItemToSelect = NONE;
}
}
-
- /**
- * Specifies the list item to select upon next call of {@link #notifyDataSetChanged()},
- * in order to let us scroll the "More results..." list item to the top of the screen
- * (or as close as it can get) when clicked.
- */
- public void setListItemToSelect(int index) {
- mListItemToSelect = index;
- }
-
- /**
- * Updates the search dialog according to the current working status of the cursor.
- */
- private void updateWorking() {
- if (!mGlobalSearchMode || mCursor == null) return;
-
- Bundle request = new Bundle();
- request.putString(SearchManager.RESPOND_EXTRA_PENDING_SOURCES, "DUMMY");
- Bundle response = mCursor.respond(request);
- mSearchDialog.setWorking(response.getBoolean(SearchManager.RESPOND_EXTRA_PENDING_SOURCES));
+ /**
+ * Handle sending and receiving information associated with
+ * {@link DialogCursorProtocol#POST_REFRESH}.
+ *
+ * @param cursor The cursor to call.
+ */
+ private void callCursorPostRefresh(Cursor cursor) {
+ if (!mGlobalSearchMode) return;
+ final Bundle request = new Bundle();
+ request.putInt(DialogCursorProtocol.METHOD, DialogCursorProtocol.POST_REFRESH);
+ final Bundle response = cursor.respond(request);
+
+ mSearchDialog.setWorking(
+ response.getBoolean(DialogCursorProtocol.POST_REFRESH_RECEIVE_ISPENDING, false));
+
+ mDisplayNotifyPos =
+ response.getInt(DialogCursorProtocol.POST_REFRESH_RECEIVE_DISPLAY_NOTIFY, -1);
+ }
+
+ /**
+ * Tell the cursor which position was clicked, handling sending and receiving information
+ * associated with {@link DialogCursorProtocol#CLICK}.
+ *
+ * @param cursor The cursor
+ * @param position The position that was clicked.
+ */
+ void callCursorOnClick(Cursor cursor, int position) {
+ if (!mGlobalSearchMode) return;
+ final Bundle request = new Bundle(1);
+ request.putInt(DialogCursorProtocol.METHOD, DialogCursorProtocol.CLICK);
+ request.putInt(DialogCursorProtocol.CLICK_SEND_POSITION, position);
+ final Bundle response = cursor.respond(request);
+ mListItemToSelect = response.getInt(
+ DialogCursorProtocol.CLICK_RECEIVE_SELECTED_POS, SuggestionsAdapter.NONE);
}
/**
@@ -186,7 +217,7 @@
v.setTag(new ChildViewCache(v));
return v;
}
-
+
/**
* Cache of the child views of drop-drown list items, to avoid looking up the children
* each time the contents of a list item are changed.
@@ -208,15 +239,26 @@
@Override
public void bindView(View view, Context context, Cursor cursor) {
ChildViewCache views = (ChildViewCache) view.getTag();
- boolean isHtml = false;
- if (mFormatCol >= 0) {
- String format = cursor.getString(mFormatCol);
- isHtml = "html".equals(format);
+ final int pos = cursor.getPosition();
+
+ // update the maximum position displayed since last refresh
+ if (pos > mMaxDisplayed) {
+ mMaxDisplayed = pos;
}
+
+ // if the cursor wishes to be notified about this position, send it
+ if (mGlobalSearchMode && mDisplayNotifyPos != NONE && pos == mDisplayNotifyPos) {
+ final Bundle request = new Bundle();
+ request.putInt(DialogCursorProtocol.METHOD, DialogCursorProtocol.THRESH_HIT);
+ mCursor.respond(request);
+ mDisplayNotifyPos = NONE; // only notify the first time
+ }
+
+ final boolean isHtml = mFormatCol > 0 && "html".equals(cursor.getString(mFormatCol));
setViewText(cursor, views.mText1, mText1Col, isHtml);
setViewText(cursor, views.mText2, mText2Col, isHtml);
- setViewIcon(cursor, views.mIcon1, mIconBitmap1Col, mIconName1Col);
- setViewIcon(cursor, views.mIcon2, mIconBitmap2Col, mIconName2Col);
+ setViewIcon(cursor, views.mIcon1, mIconName1Col);
+ setViewIcon(cursor, views.mIcon2, mIconName2Col);
}
private void setViewText(Cursor cursor, TextView v, int textCol, boolean isHtml) {
@@ -238,26 +280,15 @@
}
}
- private void setViewIcon(Cursor cursor, ImageView v, int iconBitmapCol, int iconNameCol) {
+ private void setViewIcon(Cursor cursor, ImageView v, int iconNameCol) {
if (v == null) {
return;
}
- Drawable drawable = null;
- // First try the bitmap column
- if (iconBitmapCol >= 0) {
- byte[] data = cursor.getBlob(iconBitmapCol);
- if (data != null) {
- Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
- if (bitmap != null) {
- drawable = new BitmapDrawable(bitmap);
- }
- }
+ if (iconNameCol < 0) {
+ return;
}
- // If there was no bitmap, try the icon resource column.
- if (drawable == null && iconNameCol >= 0) {
- String value = cursor.getString(iconNameCol);
- drawable = getDrawableFromResourceValue(value);
- }
+ String value = cursor.getString(iconNameCol);
+ Drawable drawable = getDrawableFromResourceValue(value);
// Set the icon even if the drawable is null, since we need to clear any
// previous icon.
v.setImageDrawable(drawable);
@@ -418,7 +449,7 @@
*/
public static String getColumnString(Cursor cursor, String columnName) {
int col = cursor.getColumnIndex(columnName);
- if (col == NO_ITEM_TO_SELECT) {
+ if (col == NONE) {
return null;
}
return cursor.getString(col);
diff --git a/core/java/android/backup/BackupManager.java b/core/java/android/backup/BackupManager.java
index 6f0b2ee..30f781e 100644
--- a/core/java/android/backup/BackupManager.java
+++ b/core/java/android/backup/BackupManager.java
@@ -42,6 +42,12 @@
private IBackupManager mService;
/**
+ * Defined backup transports understood by {@link IBackupManager.selectBackupTransport}.
+ */
+ public static final int TRANSPORT_ADB = 1;
+ public static final int TRANSPORT_GOOGLE = 2;
+
+ /**
* Constructs a BackupManager object through which the application can
* communicate with the Android backup system.
*
diff --git a/core/java/android/backup/IBackupManager.aidl b/core/java/android/backup/IBackupManager.aidl
index 3468d70..f5b82fe 100644
--- a/core/java/android/backup/IBackupManager.aidl
+++ b/core/java/android/backup/IBackupManager.aidl
@@ -36,20 +36,28 @@
/**
* Notifies the Backup Manager Service that an agent has become available. This
* method is only invoked by the Activity Manager.
- * !!! TODO: permission
*/
oneway void agentConnected(String packageName, IBinder agent);
/**
* Notify the Backup Manager Service that an agent has unexpectedly gone away.
* This method is only invoked by the Activity Manager.
- * !!! TODO: permission
*/
oneway void agentDisconnected(String packageName);
/**
- * Schedule a full backup of the given package.
- * !!! TODO: permission
+ * Schedule a full backup of the given package. Callers must hold the
+ * android.permission.BACKUP permission to use this method.
*/
oneway void scheduleFullBackup(String packageName);
+
+ /**
+ * Specify a default backup transport. Callers must hold the
+ * android.permission.BACKUP permission to use this method.
+ *
+ * @param transportID The ID of the transport to select. This should be one
+ * of {@link BackupManager.TRANSPORT_GOOGLE} or {@link BackupManager.TRANSPORT_ADB}.
+ * @return The ID of the previously selected transport.
+ */
+ int selectBackupTransport(int transportID);
}
diff --git a/core/java/android/content/AbstractTableMerger.java b/core/java/android/content/AbstractTableMerger.java
index 700f1d8..94afcee 100644
--- a/core/java/android/content/AbstractTableMerger.java
+++ b/core/java/android/content/AbstractTableMerger.java
@@ -61,8 +61,10 @@
_SYNC_ID +"=? and " + _SYNC_ACCOUNT + "=?";
private static final String SELECT_BY_ID = BaseColumns._ID +"=?";
+ // The last clause rejects events with a null _SYNC_VERSION if they've already been synced
private static final String SELECT_UNSYNCED = ""
- + _SYNC_DIRTY + " > 0 and (" + _SYNC_ACCOUNT + "=? or " + _SYNC_ACCOUNT + " is null)";
+ + _SYNC_DIRTY + " > 0 and (" + _SYNC_ACCOUNT + "=? or " + _SYNC_ACCOUNT + " is null) "
+ + "and (" + _SYNC_VERSION + " is not null or " + _SYNC_ACCOUNT + " is null)";
public AbstractTableMerger(SQLiteDatabase database,
String table, Uri tableURL, String deletedTable,
@@ -365,26 +367,32 @@
if (!TextUtils.isEmpty(localSyncID)) {
// An existing server item has changed
- boolean recordChanged = (localSyncVersion == null) ||
- !serverSyncVersion.equals(localSyncVersion);
- if (recordChanged) {
- if (localSyncDirty) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "remote record " + serverSyncId
- + " conflicts with local _sync_id " + localSyncID
- + ", local _id " + localRowId);
+ // If serverSyncVersion is null, there is no edit URL;
+ // server won't let this change be written.
+ // Just hold onto it, I guess, in case the server permissions
+ // change later.
+ if (serverSyncVersion != null) {
+ boolean recordChanged = (localSyncVersion == null) ||
+ !serverSyncVersion.equals(localSyncVersion);
+ if (recordChanged) {
+ if (localSyncDirty) {
+ if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ Log.v(TAG, "remote record " + serverSyncId
+ + " conflicts with local _sync_id " + localSyncID
+ + ", local _id " + localRowId);
+ }
+ conflict = true;
+ } else {
+ if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ Log.v(TAG,
+ "remote record " +
+ serverSyncId +
+ " updates local _sync_id " +
+ localSyncID + ", local _id " +
+ localRowId);
+ }
+ update = true;
}
- conflict = true;
- } else {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG,
- "remote record " +
- serverSyncId +
- " updates local _sync_id " +
- localSyncID + ", local _id " +
- localRowId);
- }
- update = true;
}
}
} else {
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index c328d1614..ec847a4 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -527,16 +527,6 @@
public abstract int getWallpaperDesiredMinimumHeight();
/**
- * Returns the scale in which the application will be drawn on the
- * screen. This is usually 1.0f if the application supports the device's
- * resolution/density. This will be 1.5f, for example, if the application
- * that supports only 160 density runs on 240 density screen.
- *
- * @hide
- */
- public abstract float getApplicationScale();
-
- /**
* Change the current system wallpaper to a bitmap. The given bitmap is
* converted to a PNG and stored as the wallpaper. On success, the intent
* {@link Intent#ACTION_WALLPAPER_CHANGED} is broadcast.
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index 25b2cae..36e1c34 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -419,12 +419,4 @@
throws PackageManager.NameNotFoundException {
return mBase.createPackageContext(packageName, flags);
}
-
- /**
- * @hide
- */
- @Override
- public float getApplicationScale() {
- return mBase.getApplicationScale();
- }
}
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index f16eb74..f3dfc5a 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -186,7 +186,6 @@
*/
public int uid;
-
/**
* The list of densities in DPI that application supprots. This
* field is only set if the {@link PackageManager#GET_SUPPORTS_DENSITIES} flag was
@@ -195,6 +194,12 @@
public int[] supportsDensities;
/**
+ * True when the application's window can be expanded over default window
+ * size in target density (320x480 for 1.0 density, 480x720 for 1.5 density etc)
+ */
+ public boolean expandable = false;
+
+ /**
* The minimum SDK version this application targets. It may run on earilier
* versions, but it knows how to work with any new behavior added at this
* version. Will be {@link android.os.Build.VERSION_CODES#CUR_DEVELOPMENT}
@@ -228,6 +233,7 @@
pw.println(prefix + "manageSpaceActivityName="+manageSpaceActivityName);
pw.println(prefix + "description=0x"+Integer.toHexString(descriptionRes));
pw.println(prefix + "supportsDensities=" + supportsDensities);
+ pw.println(prefix + "expandable=" + expandable);
super.dumpBack(pw, prefix);
}
@@ -275,6 +281,7 @@
manageSpaceActivityName = orig.manageSpaceActivityName;
descriptionRes = orig.descriptionRes;
supportsDensities = orig.supportsDensities;
+ expandable = orig.expandable;
}
@@ -307,6 +314,7 @@
dest.writeString(backupAgentName);
dest.writeInt(descriptionRes);
dest.writeIntArray(supportsDensities);
+ dest.writeInt(expandable ? 1 : 0);
}
public static final Parcelable.Creator<ApplicationInfo> CREATOR
@@ -338,6 +346,7 @@
backupAgentName = source.readString();
descriptionRes = source.readInt();
supportsDensities = source.createIntArray();
+ expandable = source.readInt() != 0;
}
/**
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index a2c82e8..65783917 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -180,6 +180,12 @@
public static final int MATCH_DEFAULT_ONLY = 0x00010000;
/**
+ * {@link ApplicationInfo} flag: return the
+ * {link ApplicationInfo#expandable} boolean flag of the package.
+ */
+ public static final int GET_EXPANDABLE = 0x00020000;
+
+ /**
* Permission check result: this is returned by {@link #checkPermission}
* if the permission has been granted to the given package.
*/
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 212b590..e2c0fe6 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -835,6 +835,26 @@
+ parser.getName();
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return null;
+
+
+ } else if (tagName.equals("supports-density")) {
+ sa = res.obtainAttributes(attrs,
+ com.android.internal.R.styleable.AndroidManifestSupportsDensity);
+
+ int density = sa.getInteger(
+ com.android.internal.R.styleable.AndroidManifestSupportsDensity_density, -1);
+
+ sa.recycle();
+
+ if (density != -1 && !pkg.supportsDensityList.contains(density)) {
+ pkg.supportsDensityList.add(density);
+ }
+
+ XmlUtils.skipCurrentTag(parser);
+
+ } else if (tagName.equals("expandable")) {
+ pkg.expandable = true;
+ XmlUtils.skipCurrentTag(parser);
} else {
Log.w(TAG, "Bad element under <manifest>: "
+ parser.getName());
@@ -866,7 +886,8 @@
pkg.usesLibraryFiles = new String[pkg.usesLibraries.size()];
pkg.usesLibraries.toArray(pkg.usesLibraryFiles);
}
-
+ // TODO: enable all density & expandable if target sdk is higher than donut
+
int size = pkg.supportsDensityList.size();
if (size > 0) {
int densities[] = pkg.supportsDensities = new int[size];
@@ -1345,21 +1366,6 @@
XmlUtils.skipCurrentTag(parser);
- } else if (tagName.equals("supports-density")) {
- sa = res.obtainAttributes(attrs,
- com.android.internal.R.styleable.AndroidManifestSupportsDensity);
-
- int density = sa.getInteger(
- com.android.internal.R.styleable.AndroidManifestSupportsDensity_density, -1);
-
- sa.recycle();
-
- if (density != -1 && !owner.supportsDensityList.contains(density)) {
- owner.supportsDensityList.add(density);
- }
-
- XmlUtils.skipCurrentTag(parser);
-
} else {
if (!RIGID_PARSER) {
Log.w(TAG, "Problem in package " + mArchiveSourcePath + ":");
@@ -2244,6 +2250,9 @@
public final ArrayList<Integer> supportsDensityList = new ArrayList<Integer>();
public int[] supportsDensities = null;
+ // If the application's window is expandable.
+ public boolean expandable;
+
// If this is a 3rd party app, this is the path of the zip file.
public String mPath;
@@ -2415,7 +2424,10 @@
return true;
}
if ((flags & PackageManager.GET_SUPPORTS_DENSITIES) != 0
- && p.supportsDensities != null) {
+ && p.supportsDensities != null) {
+ return true;
+ }
+ if ((flags & PackageManager.GET_EXPANDABLE) != 0) {
return true;
}
return false;
@@ -2438,6 +2450,9 @@
if ((flags & PackageManager.GET_SUPPORTS_DENSITIES) != 0) {
ai.supportsDensities = p.supportsDensities;
}
+ if ((flags & PackageManager.GET_EXPANDABLE) != 0) {
+ ai.expandable = p.expandable;
+ }
return ai;
}
diff --git a/core/java/android/content/res/CompatibilityInfo.java b/core/java/android/content/res/CompatibilityInfo.java
new file mode 100644
index 0000000..19379fb
--- /dev/null
+++ b/core/java/android/content/res/CompatibilityInfo.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.res;
+
+import android.content.pm.ApplicationInfo;
+import android.util.DisplayMetrics;
+import android.view.Gravity;
+
+/**
+ * CompatibilityInfo class keeps the information about compatibility mode that the application is
+ * running under.
+ *
+ * {@hide}
+ */
+public class CompatibilityInfo {
+ /** default compatibility info object for compatible applications */
+ public static final CompatibilityInfo DEFAULT_COMPATIBILITY_INFO = new CompatibilityInfo();
+
+ /**
+ * The default width of the screen in portrait mode.
+ */
+ public static final int DEFAULT_PORTRAIT_WIDTH = 320;
+
+ /**
+ * The default height of the screen in portrait mode.
+ */
+ public static final int DEFAULT_PORTRAIT_HEIGHT = 480;
+
+ /**
+ * Application's scale.
+ */
+ public final float mApplicationScale;
+
+ /**
+ * Application's inverted scale.
+ */
+ public final float mApplicationInvertedScale;
+
+ /**
+ *
+ * A boolean flag to indicates that the application can expand over the original size.
+ */
+ public final boolean mExpandable;
+
+ /**
+ * A boolean flag to tell if the application needs scaling (when mApplicationScale != 1.0f)
+ */
+ public final boolean mScalingRequired;
+
+ public CompatibilityInfo(ApplicationInfo appInfo) {
+ // A temp workaround to fix rotation issue.
+ // mExpandable = appInfo.expandable;
+ mExpandable = true;
+ float packageDensityScale = -1.0f;
+ if (appInfo.supportsDensities != null) {
+ int minDiff = Integer.MAX_VALUE;
+ for (int density : appInfo.supportsDensities) {
+ int tmpDiff = Math.abs(DisplayMetrics.DEVICE_DENSITY - density);
+ if (tmpDiff == 0) {
+ packageDensityScale = 1.0f;
+ break;
+ }
+ // prefer higher density (appScale>1.0), unless that's only option.
+ if (tmpDiff < minDiff && packageDensityScale < 1.0f) {
+ packageDensityScale = DisplayMetrics.DEVICE_DENSITY / (float) density;
+ minDiff = tmpDiff;
+ }
+ }
+ }
+ if (packageDensityScale > 0.0f) {
+ mApplicationScale = packageDensityScale;
+ } else {
+ mApplicationScale = DisplayMetrics.DEVICE_DENSITY / (float) DisplayMetrics.DEFAULT_DENSITY;
+ }
+ mApplicationInvertedScale = 1.0f / mApplicationScale;
+ mScalingRequired = mApplicationScale != 1.0f;
+ }
+
+ private CompatibilityInfo() {
+ mApplicationScale = mApplicationInvertedScale = 1.0f;
+ mExpandable = true;
+ mScalingRequired = false;
+ }
+
+ @Override
+ public String toString() {
+ return "CompatibilityInfo{scale=" + mApplicationScale +
+ ", expandable=" + mExpandable + "}";
+ }
+}
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 665e40c..976b618 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -22,6 +22,8 @@
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
+import android.app.ActivityThread.PackageInfo;
+import android.content.pm.ApplicationInfo;
import android.graphics.Movie;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.BitmapDrawable;
@@ -84,7 +86,9 @@
private final Configuration mConfiguration = new Configuration();
/*package*/ final DisplayMetrics mMetrics = new DisplayMetrics();
PluralRules mPluralRule;
-
+
+ private final CompatibilityInfo mCompatibilityInfo;
+
private static final SparseArray<Object> EMPTY_ARRAY = new SparseArray<Object>() {
@Override
public void put(int k, Object o) {
@@ -126,23 +130,36 @@
*/
public Resources(AssetManager assets, DisplayMetrics metrics,
Configuration config) {
- this(assets, metrics, config, true);
+ this(assets, metrics, config, null);
}
/**
- * Create a resource with an additional flag for preloaded
- * drawable cache. Used by {@link ActivityThread}.
- *
+ * Creates a new Resources object with ApplicationInfo.
+ *
+ * @param assets Previously created AssetManager.
+ * @param metrics Current display metrics to consider when
+ * selecting/computing resource values.
+ * @param config Desired device configuration to consider when
+ * selecting/computing resource values (optional).
+ * @param appInfo this resource's application info.
* @hide
*/
public Resources(AssetManager assets, DisplayMetrics metrics,
- Configuration config, boolean usePreloadedCache) {
+ Configuration config, ApplicationInfo appInfo) {
mAssets = assets;
mConfiguration.setToDefaults();
mMetrics.setToDefaults();
+ if (appInfo != null) {
+ mCompatibilityInfo = new CompatibilityInfo(appInfo);
+ if (DEBUG_CONFIG) {
+ Log.d(TAG, "compatibility for " + appInfo.packageName + " : " + mCompatibilityInfo);
+ }
+ } else {
+ mCompatibilityInfo = CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
+ }
updateConfiguration(config, metrics);
assets.ensureStringBlocks();
- if (usePreloadedCache) {
+ if (!mCompatibilityInfo.mScalingRequired) {
mPreloadedDrawables = sPreloadedDrawables;
} else {
mPreloadedDrawables = emptySparseArray();
@@ -1251,6 +1268,7 @@
}
if (metrics != null) {
mMetrics.setTo(metrics);
+ mMetrics.updateMetrics(mCompatibilityInfo, mConfiguration);
}
mMetrics.scaledDensity = mMetrics.density * mConfiguration.fontScale;
@@ -1356,6 +1374,17 @@
public Configuration getConfiguration() {
return mConfiguration;
}
+
+ /**
+ * Return the compatibility mode information for the application.
+ * The returned object should be treated as read-only.
+ *
+ * @return compatibility info. null if the app does not require compatibility mode.
+ * @hide
+ */
+ public CompatibilityInfo getCompatibilityInfo() {
+ return mCompatibilityInfo;
+ }
/**
* Return a resource identifier for the given resource name. A fully
@@ -1920,5 +1949,6 @@
updateConfiguration(null, null);
mAssets.ensureStringBlocks();
mPreloadedDrawables = sPreloadedDrawables;
+ mCompatibilityInfo = CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
}
}
diff --git a/core/java/android/database/sqlite/SQLiteContentHelper.java b/core/java/android/database/sqlite/SQLiteContentHelper.java
new file mode 100644
index 0000000..2800d86
--- /dev/null
+++ b/core/java/android/database/sqlite/SQLiteContentHelper.java
@@ -0,0 +1,92 @@
+/*
+ * 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.database.sqlite;
+
+import android.content.res.AssetFileDescriptor;
+import android.database.Cursor;
+import android.os.MemoryFile;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+
+/**
+ * Some helper functions for using SQLite database to implement content providers.
+ *
+ * @hide
+ */
+public class SQLiteContentHelper {
+
+ /**
+ * Runs an SQLite query and returns an AssetFileDescriptor for the
+ * blob in column 0 of the first row. If the first column does
+ * not contain a blob, an unspecified exception is thrown.
+ *
+ * @param db Handle to a readable database.
+ * @param sql SQL query, possibly with query arguments.
+ * @param selectionArgs Query argument values, or {@code null} for no argument.
+ * @return If no exception is thrown, a non-null AssetFileDescriptor is returned.
+ * @throws FileNotFoundException If the query returns no results or the
+ * value of column 0 is NULL, or if there is an error creating the
+ * asset file descriptor.
+ */
+ public static AssetFileDescriptor getBlobColumnAsAssetFile(SQLiteDatabase db, String sql,
+ String[] selectionArgs) throws FileNotFoundException {
+ try {
+ MemoryFile file = simpleQueryForBlobMemoryFile(db, sql, selectionArgs);
+ if (file == null) {
+ throw new FileNotFoundException("No results.");
+ }
+ return AssetFileDescriptor.fromMemoryFile(file);
+ } catch (IOException ex) {
+ throw new FileNotFoundException(ex.toString());
+ }
+ }
+
+ /**
+ * Runs an SQLite query and returns a MemoryFile for the
+ * blob in column 0 of the first row. If the first column does
+ * not contain a blob, an unspecified exception is thrown.
+ *
+ * @return A memory file, or {@code null} if the query returns no results
+ * or the value column 0 is NULL.
+ * @throws IOException If there is an error creating the memory file.
+ */
+ // TODO: make this native and use the SQLite blob API to reduce copying
+ private static MemoryFile simpleQueryForBlobMemoryFile(SQLiteDatabase db, String sql,
+ String[] selectionArgs) throws IOException {
+ Cursor cursor = db.rawQuery(sql, selectionArgs);
+ if (cursor == null) {
+ return null;
+ }
+ try {
+ if (!cursor.moveToFirst()) {
+ return null;
+ }
+ byte[] bytes = cursor.getBlob(0);
+ if (bytes == null) {
+ return null;
+ }
+ MemoryFile file = new MemoryFile(null, bytes.length);
+ file.writeBytes(bytes, 0, 0, bytes.length);
+ file.deactivate();
+ return file;
+ } finally {
+ cursor.close();
+ }
+ }
+
+}
diff --git a/core/java/android/gesture/GestureOverlayView.java b/core/java/android/gesture/GestureOverlayView.java
index 6f2c2a7..1251964 100755
--- a/core/java/android/gesture/GestureOverlayView.java
+++ b/core/java/android/gesture/GestureOverlayView.java
@@ -93,6 +93,7 @@
private float mTotalLength;
private boolean mIsGesturing = false;
+ private boolean mPreviousWasGesturing = false;
private boolean mInterceptEvents = true;
private boolean mIsListeningForGestures;
@@ -425,6 +426,7 @@
clear(false);
mIsGesturing = false;
+ mPreviousWasGesturing = false;
mStrokeBuffer.clear();
final ArrayList<OnGesturingListener> otherListeners = mOnGesturingListeners;
@@ -442,8 +444,10 @@
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
if (isEnabled()) {
- boolean cancelDispatch = (mIsGesturing || (mCurrentGesture != null &&
- mCurrentGesture.getStrokesCount() > 0)) && mInterceptEvents;
+ final boolean cancelDispatch = (mIsGesturing || (mCurrentGesture != null &&
+ mCurrentGesture.getStrokesCount() > 0 && mPreviousWasGesturing)) &&
+ mInterceptEvents;
+
processEvent(event);
if (cancelDispatch) {
@@ -451,6 +455,7 @@
}
super.dispatchTouchEvent(event);
+
return true;
}
@@ -647,6 +652,7 @@
}
mStrokeBuffer.clear();
+ mPreviousWasGesturing = mIsGesturing;
mIsGesturing = false;
final ArrayList<OnGesturingListener> listeners = mOnGesturingListeners;
@@ -688,6 +694,7 @@
fireOnGesturePerformed();
}
+ mPreviousWasGesturing = false;
mIsFadingOut = false;
mFadingHasStarted = false;
mPath.rewind();
@@ -707,6 +714,7 @@
mFadingHasStarted = false;
mPath.rewind();
mCurrentGesture = null;
+ mPreviousWasGesturing = false;
setPaintAlpha(255);
}
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 358a546..528def5 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -307,6 +307,13 @@
* @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
*/
public abstract int getStarts(int which);
+
+ /**
+ * Returns the cpu time spent in microseconds while the process was in the foreground.
+ * @param which one of STATS_TOTAL, STATS_LAST, STATS_CURRENT or STATS_UNPLUGGED
+ * @return foreground cpu time in microseconds
+ */
+ public abstract long getForegroundTime(int which);
}
/**
@@ -364,7 +371,7 @@
public abstract int getStartCount();
/**
- * Returns the time in milliseconds that the screen has been on while the device was
+ * Returns the time in microseconds that the screen has been on while the device was
* running on battery.
*
* {@hide}
@@ -384,7 +391,7 @@
public static final int NUM_SCREEN_BRIGHTNESS_BINS = 5;
/**
- * Returns the time in milliseconds that the screen has been on with
+ * Returns the time in microseconds that the screen has been on with
* the given brightness
*
* {@hide}
@@ -395,7 +402,7 @@
public abstract int getInputEventCount(int which);
/**
- * Returns the time in milliseconds that the phone has been on while the device was
+ * Returns the time in microseconds that the phone has been on while the device was
* running on battery.
*
* {@hide}
@@ -415,7 +422,7 @@
public static final int NUM_SIGNAL_STRENGTH_BINS = 5;
/**
- * Returns the time in milliseconds that the phone has been running with
+ * Returns the time in microseconds that the phone has been running with
* the given signal strength.
*
* {@hide}
@@ -443,7 +450,7 @@
public static final int NUM_DATA_CONNECTION_TYPES = 5;
/**
- * Returns the time in milliseconds that the phone has been running with
+ * Returns the time in microseconds that the phone has been running with
* the given data connection.
*
* {@hide}
@@ -460,7 +467,7 @@
public abstract int getPhoneDataConnectionCount(int dataType, int which);
/**
- * Returns the time in milliseconds that wifi has been on while the device was
+ * Returns the time in microseconds that wifi has been on while the device was
* running on battery.
*
* {@hide}
@@ -468,7 +475,7 @@
public abstract long getWifiOnTime(long batteryRealtime, int which);
/**
- * Returns the time in milliseconds that wifi has been on and the driver has
+ * Returns the time in microseconds that wifi has been on and the driver has
* been in the running state while the device was running on battery.
*
* {@hide}
@@ -476,7 +483,7 @@
public abstract long getWifiRunningTime(long batteryRealtime, int which);
/**
- * Returns the time in milliseconds that bluetooth has been on while the device was
+ * Returns the time in microseconds that bluetooth has been on while the device was
* running on battery.
*
* {@hide}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 5d10675..42a5075 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1276,6 +1276,14 @@
* boolean (1 or 0).
*/
public static final String HAPTIC_FEEDBACK_ENABLED = "haptic_feedback_enabled";
+
+ /**
+ * Whether live web suggestions while the user types into search dialogs are
+ * enabled. Browsers and other search UIs should respect this, as it allows
+ * a user to avoid sending partial queries to a search engine, if it poses
+ * any privacy concern. The value is boolean (1 or 0).
+ */
+ public static final String SHOW_WEB_SUGGESTIONS = "show_web_suggestions";
// Settings moved to Settings.Secure
@@ -1916,6 +1924,29 @@
"enabled_accessibility_services";
/**
+ * Setting to always use the default text-to-speech settings regardless
+ * of the application settings.
+ * 1 = override application settings,
+ * 0 = use application settings (if specified).
+ */
+ public static final String TTS_USE_DEFAULTS = "tts_use_defaults";
+
+ /**
+ * Default text-to-speech engine speech rate. 100 = 1x
+ */
+ public static final String TTS_DEFAULT_RATE = "tts_default_rate";
+
+ /**
+ * Default text-to-speech engine pitch. 100 = 1x
+ */
+ public static final String TTS_DEFAULT_PITCH = "tts_default_pitch";
+
+ /**
+ * Default text-to-speech engine.
+ */
+ public static final String TTS_DEFAULT_SYNTH = "tts_default_synth";
+
+ /**
* Whether to notify the user of open networks.
* <p>
* If not connected and the scan results have an open network, we will
diff --git a/core/java/android/server/search/SearchManagerService.java b/core/java/android/server/search/SearchManagerService.java
index 952372f..060bcea 100644
--- a/core/java/android/server/search/SearchManagerService.java
+++ b/core/java/android/server/search/SearchManagerService.java
@@ -23,12 +23,13 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Handler;
+import android.os.RemoteException;
import java.util.List;
/**
* This is a simplified version of the Search Manager service. It no longer handles
- * presentation (UI). Its function is to maintain the map & list of "searchable"
+ * presentation (UI). Its function is to maintain the map & list of "searchable"
* items, which provides a mapping from individual activities (where a user might have
* invoked search) to specific searchable activities (where the search will be dispatched).
*/
@@ -43,19 +44,19 @@
private final Handler mHandler;
private boolean mSearchablesDirty;
private Searchables mSearchables;
-
+
/**
* Initializes the Search Manager service in the provided system context.
* Only one instance of this object should be created!
*
* @param context to use for accessing DB, window manager, etc.
*/
- public SearchManagerService(Context context) {
+ public SearchManagerService(Context context) {
mContext = context;
mHandler = new Handler();
mSearchablesDirty = true;
mSearchables = new Searchables(context);
-
+
// Setup the infrastructure for updating and maintaining the list
// of searchable activities.
IntentFilter filter = new IntentFilter();
@@ -64,15 +65,15 @@
filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
filter.addDataScheme("package");
mContext.registerReceiver(mIntentReceiver, filter, null, mHandler);
-
+
// After startup settles down, preload the searchables list,
// which will reduce the delay when the search UI is invoked.
mHandler.post(mRunUpdateSearchable);
}
-
+
/**
* Listens for intent broadcasts.
- *
+ *
* The primary purpose here is to refresh the "searchables" list
* if packages are added/removed.
*/
@@ -80,7 +81,7 @@
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
-
+
// First, test for intents that matter at any time
if (action.equals(Intent.ACTION_PACKAGE_ADDED) ||
action.equals(Intent.ACTION_PACKAGE_REMOVED) ||
@@ -91,14 +92,14 @@
}
}
};
-
+
/**
* This runnable (for the main handler / UI thread) will update the searchables list.
*/
private Runnable mRunUpdateSearchable = new Runnable() {
public void run() {
updateSearchablesIfDirty();
- }
+ }
};
/**
@@ -124,7 +125,7 @@
*
* @param launchActivity The activity from which we're launching this search.
* @param globalSearch If false, this will only launch the search that has been specifically
- * defined by the application (which is usually defined as a local search). If no default
+ * defined by the application (which is usually defined as a local search). If no default
* search is defined in the current application or activity, no search will be launched.
* If true, this will always launch a platform-global (e.g. web-based) search instead.
* @return Returns a SearchableInfo record describing the parameters of the search,
@@ -141,7 +142,7 @@
return si;
}
-
+
/**
* Returns a list of the searchable activities that can be included in global search.
*/
@@ -150,4 +151,26 @@
return mSearchables.getSearchablesInGlobalSearchList();
}
+ /**
+ * Returns a list of the searchable activities that handle web searches.
+ */
+ public List<SearchableInfo> getSearchablesForWebSearch() {
+ updateSearchablesIfDirty();
+ return mSearchables.getSearchablesForWebSearchList();
+ }
+
+ /**
+ * Returns the default searchable activity for web searches.
+ */
+ public SearchableInfo getDefaultSearchableForWebSearch() {
+ updateSearchablesIfDirty();
+ return mSearchables.getDefaultSearchableForWebSearch();
+ }
+
+ /**
+ * Sets the default searchable activity for web searches.
+ */
+ public void setDefaultWebSearch(ComponentName component) {
+ mSearchables.setDefaultWebSearch(component);
+ }
}
diff --git a/core/java/android/server/search/SearchableInfo.java b/core/java/android/server/search/SearchableInfo.java
index 842fc75..c083142 100644
--- a/core/java/android/server/search/SearchableInfo.java
+++ b/core/java/android/server/search/SearchableInfo.java
@@ -40,7 +40,7 @@
public final class SearchableInfo implements Parcelable {
// general debugging support
- private static final boolean DBG = true;
+ private static final boolean DBG = false;
private static final String LOG_TAG = "SearchableInfo";
// static strings used for XML lookups.
diff --git a/core/java/android/server/search/Searchables.java b/core/java/android/server/search/Searchables.java
index 62631d6..a27667b 100644
--- a/core/java/android/server/search/Searchables.java
+++ b/core/java/android/server/search/Searchables.java
@@ -16,13 +16,18 @@
package android.server.search;
+import com.android.internal.app.ResolverActivity;
+import com.android.internal.R;
+
import android.app.SearchManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
+import android.content.res.Resources;
import android.os.Bundle;
import android.util.Log;
@@ -31,37 +36,39 @@
import java.util.List;
/**
- * This class maintains the information about all searchable activities.
+ * This class maintains the information about all searchable activities.
*/
public class Searchables {
private static final String LOG_TAG = "Searchables";
// static strings used for XML lookups, etc.
- // TODO how should these be documented for the developer, in a more structured way than
+ // TODO how should these be documented for the developer, in a more structured way than
// the current long wordy javadoc in SearchManager.java ?
private static final String MD_LABEL_DEFAULT_SEARCHABLE = "android.app.default_searchable";
private static final String MD_SEARCHABLE_SYSTEM_SEARCH = "*";
-
+
private Context mContext;
-
+
private HashMap<ComponentName, SearchableInfo> mSearchablesMap = null;
private ArrayList<SearchableInfo> mSearchablesList = null;
private ArrayList<SearchableInfo> mSearchablesInGlobalSearchList = null;
+ private ArrayList<SearchableInfo> mSearchablesForWebSearchList = null;
private SearchableInfo mDefaultSearchable = null;
-
+ private SearchableInfo mDefaultSearchableForWebSearch = null;
+
/**
- *
+ *
* @param context Context to use for looking up activities etc.
*/
public Searchables (Context context) {
mContext = context;
}
-
+
/**
* Look up, or construct, based on the activity.
- *
- * The activities fall into three cases, based on meta-data found in
+ *
+ * The activities fall into three cases, based on meta-data found in
* the manifest entry:
* <ol>
* <li>The activity itself implements search. This is indicated by the
@@ -73,16 +80,16 @@
* case the factory will "redirect" and return the searchable data.</li>
* <li>No searchability data is provided. We return null here and other
* code will insert the "default" (e.g. contacts) search.
- *
+ *
* TODO: cache the result in the map, and check the map first.
* TODO: it might make sense to implement the searchable reference as
* an application meta-data entry. This way we don't have to pepper each
* and every activity.
* TODO: can we skip the constructor step if it's a non-searchable?
- * TODO: does it make sense to plug the default into a slot here for
+ * TODO: does it make sense to plug the default into a slot here for
* automatic return? Probably not, but it's one way to do it.
*
- * @param activity The name of the current activity, or null if the
+ * @param activity The name of the current activity, or null if the
* activity does not define any explicit searchable metadata.
*/
public SearchableInfo getSearchableInfo(ComponentName activity) {
@@ -92,18 +99,18 @@
result = mSearchablesMap.get(activity);
if (result != null) return result;
}
-
+
// Step 2. See if the current activity references a searchable.
// Note: Conceptually, this could be a while(true) loop, but there's
- // no point in implementing reference chaining here and risking a loop.
+ // no point in implementing reference chaining here and risking a loop.
// References must point directly to searchable activities.
-
+
ActivityInfo ai = null;
try {
ai = mContext.getPackageManager().
getActivityInfo(activity, PackageManager.GET_META_DATA );
String refActivityName = null;
-
+
// First look for activity-specific reference
Bundle md = ai.metaData;
if (md != null) {
@@ -116,11 +123,11 @@
refActivityName = md.getString(MD_LABEL_DEFAULT_SEARCHABLE);
}
}
-
+
// Irrespective of source, if a reference was found, follow it.
if (refActivityName != null)
{
- // An app or activity can declare that we should simply launch
+ // An app or activity can declare that we should simply launch
// "system default search" if search is invoked.
if (refActivityName.equals(MD_SEARCHABLE_SYSTEM_SEARCH)) {
return getDefaultSearchable();
@@ -146,80 +153,101 @@
} catch (PackageManager.NameNotFoundException e) {
// case 3: no metadata
}
-
+
// Step 3. None found. Return null.
return null;
-
+
}
-
+
/**
* Provides the system-default search activity, which you can use
* whenever getSearchableInfo() returns null;
- *
+ *
* @return Returns the system-default search activity, null if never defined
*/
public synchronized SearchableInfo getDefaultSearchable() {
return mDefaultSearchable;
}
-
+
public synchronized boolean isDefaultSearchable(SearchableInfo searchable) {
return searchable == mDefaultSearchable;
}
-
+
/**
- * Builds an entire list (suitable for display) of
- * activities that are searchable, by iterating the entire set of
- * ACTION_SEARCH intents.
- *
+ * Builds an entire list (suitable for display) of
+ * activities that are searchable, by iterating the entire set of
+ * ACTION_SEARCH & ACTION_WEB_SEARCH intents.
+ *
* Also clears the hash of all activities -> searches which will
* refill as the user clicks "search".
- *
+ *
* This should only be done at startup and again if we know that the
* list has changed.
- *
+ *
* TODO: every activity that provides a ACTION_SEARCH intent should
* also provide searchability meta-data. There are a bunch of checks here
* that, if data is not found, silently skip to the next activity. This
* won't help a developer trying to figure out why their activity isn't
* showing up in the list, but an exception here is too rough. I would
* like to find a better notification mechanism.
- *
+ *
* TODO: sort the list somehow? UI choice.
*/
public void buildSearchableList() {
// These will become the new values at the end of the method
- HashMap<ComponentName, SearchableInfo> newSearchablesMap
+ HashMap<ComponentName, SearchableInfo> newSearchablesMap
= new HashMap<ComponentName, SearchableInfo>();
ArrayList<SearchableInfo> newSearchablesList
= new ArrayList<SearchableInfo>();
ArrayList<SearchableInfo> newSearchablesInGlobalSearchList
= new ArrayList<SearchableInfo>();
+ ArrayList<SearchableInfo> newSearchablesForWebSearchList
+ = new ArrayList<SearchableInfo>();
final PackageManager pm = mContext.getPackageManager();
-
- // use intent resolver to generate list of ACTION_SEARCH receivers
- List<ResolveInfo> infoList;
+
+ // Use intent resolver to generate list of ACTION_SEARCH & ACTION_WEB_SEARCH receivers.
+ List<ResolveInfo> searchList;
final Intent intent = new Intent(Intent.ACTION_SEARCH);
- infoList = pm.queryIntentActivities(intent, PackageManager.GET_META_DATA);
-
+ searchList = pm.queryIntentActivities(intent, PackageManager.GET_META_DATA);
+
+ List<ResolveInfo> webSearchInfoList;
+ final Intent webSearchIntent = new Intent(Intent.ACTION_WEB_SEARCH);
+ webSearchInfoList = pm.queryIntentActivities(webSearchIntent, PackageManager.GET_META_DATA);
+
// analyze each one, generate a Searchables record, and record
- if (infoList != null) {
- int count = infoList.size();
+ if (searchList != null || webSearchInfoList != null) {
+ int search_count = (searchList == null ? 0 : searchList.size());
+ int web_search_count = (webSearchInfoList == null ? 0 : webSearchInfoList.size());
+ int count = search_count + web_search_count;
for (int ii = 0; ii < count; ii++) {
// for each component, try to find metadata
- ResolveInfo info = infoList.get(ii);
+ ResolveInfo info = (ii < search_count)
+ ? searchList.get(ii)
+ : webSearchInfoList.get(ii - search_count);
ActivityInfo ai = info.activityInfo;
- SearchableInfo searchable = SearchableInfo.getActivityMetaData(mContext, ai);
- if (searchable != null) {
- newSearchablesList.add(searchable);
- newSearchablesMap.put(searchable.getSearchActivity(), searchable);
- if (searchable.shouldIncludeInGlobalSearch()) {
- newSearchablesInGlobalSearchList.add(searchable);
+ // Check first to avoid duplicate entries.
+ if (newSearchablesMap.get(new ComponentName(ai.packageName, ai.name)) == null) {
+ SearchableInfo searchable = SearchableInfo.getActivityMetaData(mContext, ai);
+ if (searchable != null) {
+ newSearchablesList.add(searchable);
+ newSearchablesMap.put(searchable.getSearchActivity(), searchable);
+ if (searchable.shouldIncludeInGlobalSearch()) {
+ newSearchablesInGlobalSearchList.add(searchable);
+ }
}
}
}
}
-
+
+ if (webSearchInfoList != null) {
+ for (int i = 0; i < webSearchInfoList.size(); ++i) {
+ ActivityInfo ai = webSearchInfoList.get(i).activityInfo;
+ ComponentName component = new ComponentName(ai.packageName, ai.name);
+ newSearchablesForWebSearchList.add(newSearchablesMap.get(component));
+ }
+ }
+
// Find the global search provider
Intent globalSearchIntent = new Intent(SearchManager.INTENT_ACTION_GLOBAL_SEARCH);
ComponentName globalSearchActivity = globalSearchIntent.resolveActivity(pm);
@@ -230,15 +258,95 @@
+ globalSearchActivity);
}
+ // Find the default web search provider.
+ ComponentName webSearchActivity = getPreferredWebSearchActivity();
+ SearchableInfo newDefaultSearchableForWebSearch = null;
+ if (webSearchActivity != null) {
+ newDefaultSearchableForWebSearch = newSearchablesMap.get(webSearchActivity);
+ }
+ if (newDefaultSearchableForWebSearch == null) {
+ Log.w(LOG_TAG, "No searchable info found for new default web search activity "
+ + webSearchActivity);
+ }
+
// Store a consistent set of new values
synchronized (this) {
mSearchablesMap = newSearchablesMap;
mSearchablesList = newSearchablesList;
mSearchablesInGlobalSearchList = newSearchablesInGlobalSearchList;
+ mSearchablesForWebSearchList = newSearchablesForWebSearchList;
mDefaultSearchable = newDefaultSearchable;
+ mDefaultSearchableForWebSearch = newDefaultSearchableForWebSearch;
}
+
+ // Inform all listeners that the list of searchables has been updated.
+ mContext.sendBroadcast(new Intent(SearchManager.INTENT_ACTION_SEARCHABLES_CHANGED));
}
-
+
+ /**
+ * Checks if the given activity component is present in the system and if so makes it the
+ * preferred activity for handling ACTION_WEB_SEARCH.
+ * @param component Name of the component to check and set as preferred.
+ * @param action Intent action for which this activity is to be set as preferred.
+ * @return true if component was detected and set as preferred activity, false if not.
+ */
+ private boolean setPreferredActivity(ComponentName component, String action) {
+ Log.d(LOG_TAG, "Checking component " + component);
+ PackageManager pm = mContext.getPackageManager();
+ ActivityInfo ai;
+ try {
+ ai = pm.getActivityInfo(component, 0);
+ } catch (PackageManager.NameNotFoundException e) {
+ return false;
+ }
+
+ // The code here to find the value for bestMatch is heavily inspired by the code
+ // in ResolverActivity where the preferred activity is set.
+ Intent intent = new Intent(action);
+ intent.addCategory(Intent.CATEGORY_DEFAULT);
+ List<ResolveInfo> webSearchActivities = pm.queryIntentActivities(intent, 0);
+ ComponentName set[] = new ComponentName[webSearchActivities.size()];
+ int bestMatch = 0;
+ for (int i = 0; i < webSearchActivities.size(); ++i) {
+ ResolveInfo ri = webSearchActivities.get(i);
+ set[i] = new ComponentName(ri.activityInfo.packageName,
+ ri.activityInfo.name);
+ if (ri.match > bestMatch) bestMatch = ri.match;
+ }
+
+ Log.d(LOG_TAG, "Setting preferred web search activity to " + component);
+ IntentFilter filter = new IntentFilter(action);
+ filter.addCategory(Intent.CATEGORY_DEFAULT);
+ pm.replacePreferredActivity(filter, bestMatch, set, component);
+ return true;
+ }
+
+ public ComponentName getPreferredWebSearchActivity() {
+ // Check if we have a preferred web search activity.
+ Intent intent = new Intent(Intent.ACTION_WEB_SEARCH);
+ PackageManager pm = mContext.getPackageManager();
+ ResolveInfo ri = pm.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
+
+ if (ri == null || ri.activityInfo.name.equals(ResolverActivity.class.getName())) {
+ Log.d(LOG_TAG, "No preferred activity set for action web search.");
+
+ // The components in the providers array are checked in the order of declaration so the
+ // first one has the highest priority. If the component exists in the system it is set
+ // as the preferred activity to handle intent action web search.
+ String[] preferredActivities = mContext.getResources().getStringArray(
+ com.android.internal.R.array.default_web_search_providers);
+ for (String componentName : preferredActivities) {
+ ComponentName component = ComponentName.unflattenFromString(componentName);
+ if (setPreferredActivity(component, Intent.ACTION_WEB_SEARCH)) {
+ return component;
+ }
+ }
+ }
+
+ if (ri == null) return null;
+ return new ComponentName(ri.activityInfo.packageName, ri.activityInfo.name);
+ }
+
/**
* Returns the list of searchable activities.
*/
@@ -246,11 +354,33 @@
ArrayList<SearchableInfo> result = new ArrayList<SearchableInfo>(mSearchablesList);
return result;
}
-
+
/**
* Returns a list of the searchable activities that can be included in global search.
*/
public synchronized ArrayList<SearchableInfo> getSearchablesInGlobalSearchList() {
return new ArrayList<SearchableInfo>(mSearchablesInGlobalSearchList);
}
+
+ /**
+ * Returns a list of the searchable activities that handle web searches.
+ */
+ public synchronized ArrayList<SearchableInfo> getSearchablesForWebSearchList() {
+ return new ArrayList<SearchableInfo>(mSearchablesForWebSearchList);
+ }
+
+ /**
+ * Returns the default searchable activity for web searches.
+ */
+ public synchronized SearchableInfo getDefaultSearchableForWebSearch() {
+ return mDefaultSearchableForWebSearch;
+ }
+
+ /**
+ * Sets the default searchable activity for web searches.
+ */
+ public synchronized void setDefaultWebSearch(ComponentName component) {
+ setPreferredActivity(component, Intent.ACTION_WEB_SEARCH);
+ buildSearchableList();
+ }
}
diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java
index e4dd020..987be2b 100644
--- a/core/java/android/util/DisplayMetrics.java
+++ b/core/java/android/util/DisplayMetrics.java
@@ -16,6 +16,8 @@
package android.util;
+import android.content.res.CompatibilityInfo;
+import android.content.res.Configuration;
import android.os.*;
@@ -101,17 +103,46 @@
}
/**
- * Set the display metrics' density and update parameters depend on it.
- * @hide
+ * Update the display metrics based on the compatibility info and configuration.
+ * {@hide}
*/
- public void updateDensity(float newDensity) {
- float ratio = newDensity / density;
- density = newDensity;
- scaledDensity = density;
- widthPixels *= ratio;
- heightPixels *= ratio;
- xdpi *= ratio;
- ydpi *= ratio;
+ public void updateMetrics(CompatibilityInfo compatibilityInfo, Configuration configuration) {
+ if (compatibilityInfo.mScalingRequired) {
+ float invertedRatio = compatibilityInfo.mApplicationInvertedScale;
+ density *= invertedRatio;
+ scaledDensity *= invertedRatio;
+ xdpi *= invertedRatio;
+ ydpi *= invertedRatio;
+ widthPixels *= invertedRatio;
+ heightPixels *= invertedRatio;
+ }
+ if (!compatibilityInfo.mExpandable) {
+ // Note: this assume that configuration is updated before calling
+ // updateMetrics method.
+ int defaultWidth;
+ int defaultHeight;
+ switch (configuration.orientation) {
+ case Configuration.ORIENTATION_LANDSCAPE: {
+ defaultWidth = (int)(CompatibilityInfo.DEFAULT_PORTRAIT_HEIGHT * density);
+ defaultHeight = (int)(CompatibilityInfo.DEFAULT_PORTRAIT_WIDTH * density);
+ break;
+ }
+ case Configuration.ORIENTATION_UNDEFINED:
+ case Configuration.ORIENTATION_PORTRAIT:
+ case Configuration.ORIENTATION_SQUARE:
+ default: {
+ defaultWidth = (int)(CompatibilityInfo.DEFAULT_PORTRAIT_WIDTH * density);
+ defaultHeight = (int)(CompatibilityInfo.DEFAULT_PORTRAIT_HEIGHT * density);
+ }
+ }
+ // adjust the size only when the device's screen is bigger.
+ if (defaultWidth < widthPixels) {
+ widthPixels = defaultWidth;
+ }
+ if (defaultHeight < heightPixels) {
+ heightPixels = defaultHeight;
+ }
+ }
}
public String toString() {
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 0dc2570..082cca2 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -17,6 +17,7 @@
package android.view;
import android.content.Context;
+import android.content.res.CompatibilityInfo;
import android.graphics.Canvas;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
@@ -137,28 +138,24 @@
int mFormat = -1;
int mType = -1;
final Rect mSurfaceFrame = new Rect();
- private final float mAppScale;
- private final float mAppScaleInverted;
+ private final CompatibilityInfo mCompatibilityInfo;
public SurfaceView(Context context) {
super(context);
setWillNotDraw(true);
- mAppScale = context.getApplicationScale();
- mAppScaleInverted = 1.0f / mAppScale;
+ mCompatibilityInfo = context.getResources().getCompatibilityInfo();
}
public SurfaceView(Context context, AttributeSet attrs) {
super(context, attrs);
setWillNotDraw(true);
- mAppScale = context.getApplicationScale();
- mAppScaleInverted = 1.0f / mAppScale;
+ mCompatibilityInfo = context.getResources().getCompatibilityInfo();
}
public SurfaceView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setWillNotDraw(true);
- mAppScale = context.getApplicationScale();
- mAppScaleInverted = 1.0f / mAppScale;
+ mCompatibilityInfo = context.getResources().getCompatibilityInfo();
}
/**
@@ -261,9 +258,9 @@
public boolean dispatchTouchEvent(MotionEvent event) {
// SurfaceView uses pre-scaled size unless fixed size is requested. This hook
// scales the event back to the pre-scaled coordinates for such surface.
- if (mRequestedWidth < 0 && mAppScale != 1.0f) {
+ if (mRequestedWidth < 0 && mCompatibilityInfo.mScalingRequired) {
MotionEvent scaledBack = MotionEvent.obtain(event);
- scaledBack.scale(mAppScale);
+ scaledBack.scale(mCompatibilityInfo.mApplicationScale);
try {
return super.dispatchTouchEvent(scaledBack);
} finally {
@@ -300,6 +297,7 @@
if (!mHaveFrame) {
return;
}
+ float appScale = mCompatibilityInfo.mApplicationScale;
int myWidth = mRequestedWidth;
if (myWidth <= 0) myWidth = getWidth();
@@ -307,9 +305,9 @@
if (myHeight <= 0) myHeight = getHeight();
// Use original size for surface unless fixed size is requested.
- if (mRequestedWidth <= 0) {
- myWidth *= mAppScale;
- myHeight *= mAppScale;
+ if (mRequestedWidth <= 0 && mCompatibilityInfo.mScalingRequired) {
+ myWidth *= appScale;
+ myHeight *= appScale;
}
getLocationInWindow(mLocation);
@@ -337,11 +335,11 @@
mFormat = mRequestedFormat;
mType = mRequestedType;
- // Scaling window's layout here beause mLayout is not used elsewhere.
- mLayout.x = (int) (mLeft * mAppScale);
- mLayout.y = (int) (mTop * mAppScale);
- mLayout.width = (int) (getWidth() * mAppScale);
- mLayout.height = (int) (getHeight() * mAppScale);
+ // Scaling window's layout here because mLayout is not used elsewhere.
+ mLayout.x = (int) (mLeft * appScale);
+ mLayout.y = (int) (mTop * appScale);
+ mLayout.width = (int) (getWidth() * appScale);
+ mLayout.height = (int) (getHeight() * appScale);
mLayout.format = mRequestedFormat;
mLayout.flags |=WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
| WindowManager.LayoutParams.FLAG_SCALED
@@ -367,14 +365,18 @@
mSurfaceLock.lock();
mDrawingStopped = !visible;
+
final int relayoutResult = mSession.relayout(
mWindow, mLayout, mWidth, mHeight,
visible ? VISIBLE : GONE, false, mWinFrame, mContentInsets,
mVisibleInsets, mSurface);
- mContentInsets.scale(mAppScaleInverted);
- mVisibleInsets.scale(mAppScaleInverted);
- mWinFrame.scale(mAppScaleInverted);
+ if (mCompatibilityInfo.mScalingRequired) {
+ float invertedScale = mCompatibilityInfo.mApplicationInvertedScale;
+ mContentInsets.scale(invertedScale);
+ mVisibleInsets.scale(invertedScale);
+ mWinFrame.scale(invertedScale);
+ }
if (localLOGV) Log.i(TAG, "New surface: " + mSurface
+ ", vis=" + visible + ", frame=" + mWinFrame);
@@ -444,23 +446,23 @@
private static class MyWindow extends IWindow.Stub {
private final WeakReference<SurfaceView> mSurfaceView;
- private final float mAppScale;
- private final float mAppScaleInverted;
+ private final CompatibilityInfo mCompatibilityInfo;
public MyWindow(SurfaceView surfaceView) {
mSurfaceView = new WeakReference<SurfaceView>(surfaceView);
- mAppScale = surfaceView.getContext().getApplicationScale();
- mAppScaleInverted = 1.0f / mAppScale;
+ mCompatibilityInfo = surfaceView.getContext().getResources().getCompatibilityInfo();
}
public void resized(int w, int h, Rect coveredInsets,
Rect visibleInsets, boolean reportDraw) {
SurfaceView surfaceView = mSurfaceView.get();
- float scale = mAppScaleInverted;
- w *= scale;
- h *= scale;
- coveredInsets.scale(scale);
- visibleInsets.scale(scale);
+ if (mCompatibilityInfo.mScalingRequired) {
+ float scale = mCompatibilityInfo.mApplicationInvertedScale;
+ w *= scale;
+ h *= scale;
+ coveredInsets.scale(scale);
+ visibleInsets.scale(scale);
+ }
if (surfaceView != null) {
if (localLOGV) Log.v(
@@ -624,7 +626,9 @@
Canvas c = null;
if (!mDrawingStopped && mWindow != null) {
Rect frame = dirty != null ? dirty : mSurfaceFrame;
- frame.scale(mAppScale);
+ if (mCompatibilityInfo.mScalingRequired) {
+ frame.scale(mCompatibilityInfo.mApplicationScale);
+ }
try {
c = mSurface.lockCanvas(frame);
} catch (Exception e) {
diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java
index aaaadef..46aea02 100644
--- a/core/java/android/view/ViewDebug.java
+++ b/core/java/android/view/ViewDebug.java
@@ -87,17 +87,17 @@
* check that this value is set to true as not to affect performance.
*/
public static final boolean TRACE_RECYCLER = false;
-
+
/**
* The system property of dynamic switch for capturing view information
* when it is set, we dump interested fields and methods for the view on focus
- */
+ */
static final String SYSTEM_PROPERTY_CAPTURE_VIEW = "debug.captureview";
-
+
/**
* The system property of dynamic switch for capturing event information
* when it is set, we log key events, touch/motion and trackball events
- */
+ */
static final String SYSTEM_PROPERTY_CAPTURE_EVENT = "debug.captureevent";
/**
@@ -216,7 +216,7 @@
* <pre>
*
* A specified String is output when the following is true:
- *
+ *
* @return An array of int to String mappings
*/
FlagToString[] flagMapping() default { };
@@ -228,7 +228,7 @@
*
* @return true if the properties of this property should be dumped
*
- * @see #prefix()
+ * @see #prefix()
*/
boolean deepExport() default false;
@@ -313,15 +313,15 @@
@Retention(RetentionPolicy.RUNTIME)
public @interface CapturedViewProperty {
/**
- * When retrieveReturn is true, we need to retrieve second level methods
+ * When retrieveReturn is true, we need to retrieve second level methods
* e.g., we need myView.getFirstLevelMethod().getSecondLevelMethod()
- * we will set retrieveReturn = true on the annotation of
+ * we will set retrieveReturn = true on the annotation of
* myView.getFirstLevelMethod()
- * @return true if we need the second level methods
+ * @return true if we need the second level methods
*/
- boolean retrieveReturn() default false;
+ boolean retrieveReturn() default false;
}
-
+
private static HashMap<Class<?>, Method[]> mCapturedViewMethodsForClasses = null;
private static HashMap<Class<?>, Field[]> mCapturedViewFieldsForClasses = null;
@@ -401,7 +401,7 @@
*/
public static long getViewRootInstanceCount() {
return ViewRoot.getInstanceCount();
- }
+ }
/**
* Outputs a trace to the currently opened recycler traces. The trace records the type of
@@ -624,7 +624,7 @@
*
* This method will return immediately if TRACE_HIERARCHY is false.
*
- * @see #startHierarchyTracing(String, View)
+ * @see #startHierarchyTracing(String, View)
* @see #trace(View, android.view.ViewDebug.HierarchyTraceType)
*/
public static void stopHierarchyTracing() {
@@ -671,7 +671,7 @@
sHierarhcyRoot = null;
}
-
+
static void dispatchCommand(View view, String command, String parameters,
OutputStream clientStream) throws IOException {
@@ -1039,10 +1039,10 @@
final ArrayList<Method> foundMethods = new ArrayList<Method>();
methods = klass.getDeclaredMethods();
-
+
int count = methods.length;
for (int i = 0; i < count; i++) {
- final Method method = methods[i];
+ final Method method = methods[i];
if (method.getParameterTypes().length == 0 &&
method.isAnnotationPresent(ExportedProperty.class) &&
method.getReturnType() != Void.class) {
@@ -1075,7 +1075,7 @@
klass = klass.getSuperclass();
} while (klass != Object.class);
}
-
+
private static void exportMethods(Context context, Object view, BufferedWriter out,
Class<?> klass, String prefix) throws IOException {
@@ -1260,7 +1260,7 @@
for (int j = 0; j < valuesCount; j++) {
String name;
- String value;
+ String value = null;
final int intValue = array[j];
@@ -1276,7 +1276,6 @@
}
}
- value = String.valueOf(intValue);
if (hasMapping) {
int mappingCount = mapping.length;
for (int k = 0; k < mappingCount; k++) {
@@ -1289,7 +1288,9 @@
}
if (resolveId) {
- value = (String) resolveId(context, intValue);
+ if (value == null) value = (String) resolveId(context, intValue);
+ } else {
+ value = String.valueOf(intValue);
}
writeEntry(out, prefix, name, suffix, value);
@@ -1397,10 +1398,10 @@
final ArrayList<Method> foundMethods = new ArrayList<Method>();
methods = klass.getMethods();
-
+
int count = methods.length;
for (int i = 0; i < count; i++) {
- final Method method = methods[i];
+ final Method method = methods[i];
if (method.getParameterTypes().length == 0 &&
method.isAnnotationPresent(CapturedViewProperty.class) &&
method.getReturnType() != Void.class) {
@@ -1414,14 +1415,14 @@
return methods;
}
-
- private static String capturedViewExportMethods(Object obj, Class<?> klass,
+
+ private static String capturedViewExportMethods(Object obj, Class<?> klass,
String prefix) {
if (obj == null) {
return "null";
}
-
+
StringBuilder sb = new StringBuilder();
final Method[] methods = capturedViewGetPropertyMethods(klass);
@@ -1431,41 +1432,41 @@
try {
Object methodValue = method.invoke(obj, (Object[]) null);
final Class<?> returnType = method.getReturnType();
-
+
CapturedViewProperty property = method.getAnnotation(CapturedViewProperty.class);
if (property.retrieveReturn()) {
//we are interested in the second level data only
sb.append(capturedViewExportMethods(methodValue, returnType, method.getName() + "#"));
- } else {
+ } else {
sb.append(prefix);
sb.append(method.getName());
sb.append("()=");
-
+
if (methodValue != null) {
- final String value = methodValue.toString().replace("\n", "\\n");
- sb.append(value);
+ final String value = methodValue.toString().replace("\n", "\\n");
+ sb.append(value);
} else {
sb.append("null");
}
sb.append("; ");
}
} catch (IllegalAccessException e) {
- //Exception IllegalAccess, it is OK here
+ //Exception IllegalAccess, it is OK here
//we simply ignore this method
} catch (InvocationTargetException e) {
- //Exception InvocationTarget, it is OK here
+ //Exception InvocationTarget, it is OK here
//we simply ignore this method
- }
- }
+ }
+ }
return sb.toString();
}
private static String capturedViewExportFields(Object obj, Class<?> klass, String prefix) {
-
+
if (obj == null) {
return "null";
}
-
+
StringBuilder sb = new StringBuilder();
final Field[] fields = capturedViewGetPropertyFields(klass);
@@ -1487,25 +1488,25 @@
}
sb.append(' ');
} catch (IllegalAccessException e) {
- //Exception IllegalAccess, it is OK here
+ //Exception IllegalAccess, it is OK here
//we simply ignore this field
}
}
return sb.toString();
}
-
+
/**
- * Dump view info for id based instrument test generation
+ * Dump view info for id based instrument test generation
* (and possibly further data analysis). The results are dumped
- * to the log.
+ * to the log.
* @param tag for log
* @param view for dump
*/
- public static void dumpCapturedView(String tag, Object view) {
+ public static void dumpCapturedView(String tag, Object view) {
Class<?> klass = view.getClass();
StringBuilder sb = new StringBuilder(klass.getName() + ": ");
sb.append(capturedViewExportFields(view, klass, ""));
- sb.append(capturedViewExportMethods(view, klass, ""));
- Log.d(tag, sb.toString());
+ sb.append(capturedViewExportMethods(view, klass, ""));
+ Log.d(tag, sb.toString());
}
}
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index 7cd65e2..d8bab56 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -30,6 +30,7 @@
import android.os.SystemProperties;
import android.util.AndroidRuntimeException;
import android.util.Config;
+import android.util.DisplayMetrics;
import android.util.Log;
import android.util.EventLog;
import android.util.SparseArray;
@@ -40,6 +41,7 @@
import android.view.inputmethod.InputMethodManager;
import android.widget.Scroller;
import android.content.pm.PackageManager;
+import android.content.res.CompatibilityInfo;
import android.content.Context;
import android.app.ActivityManagerNative;
import android.Manifest;
@@ -125,9 +127,8 @@
int mHeight;
Rect mDirty; // will be a graphics.Region soon
boolean mIsAnimating;
- // TODO: change these to scalar class.
- private float mAppScale;
- private float mAppScaleInverted; // = 1.0f / mAppScale
+
+ private CompatibilityInfo mCompatibilityInfo;
private int[] mWindowLayoutParamsBackup = null;
final View.AttachInfo mAttachInfo;
@@ -386,12 +387,15 @@
synchronized (this) {
if (mView == null) {
mView = view;
- mAppScale = mView.getContext().getApplicationScale();
- if (mAppScale != 1.0f) {
+ mWindowAttributes.copyFrom(attrs);
+ mCompatibilityInfo =
+ mView.getContext().getResources().getCompatibilityInfo();
+ if (mCompatibilityInfo.mScalingRequired) {
mWindowLayoutParamsBackup = new int[4];
}
- mAppScaleInverted = 1.0f / mAppScale;
- mWindowAttributes.copyFrom(attrs);
+ if (!mCompatibilityInfo.mExpandable) {
+ adjustWindowAttributesForCompatibleMode(mWindowAttributes);
+ }
mSoftInputMode = attrs.softInputMode;
mWindowAttributesChanged = true;
mAttachInfo.mRootView = view;
@@ -406,9 +410,8 @@
// manager, to make sure we do the relayout before receiving
// any other events from the system.
requestLayout();
-
try {
- res = sWindowSession.add(mWindow, attrs,
+ res = sWindowSession.add(mWindow, mWindowAttributes,
getHostVisibility(), mAttachInfo.mContentInsets);
} catch (RemoteException e) {
mAdded = false;
@@ -417,7 +420,10 @@
unscheduleTraversals();
throw new RuntimeException("Adding window failed", e);
}
- mAttachInfo.mContentInsets.scale(mAppScaleInverted);
+ if (mCompatibilityInfo.mScalingRequired) {
+ mAttachInfo.mContentInsets.scale(
+ mCompatibilityInfo.mApplicationInvertedScale);
+ }
mPendingContentInsets.set(mAttachInfo.mContentInsets);
mPendingVisibleInsets.set(0, 0, 0, 0);
if (Config.LOGV) Log.v("ViewRoot", "Added window " + mWindow);
@@ -529,13 +535,13 @@
public void invalidateChild(View child, Rect dirty) {
checkThread();
if (LOCAL_LOGV) Log.v(TAG, "Invalidate child: " + dirty);
- if (mCurScrollY != 0 || mAppScale != 1.0f) {
+ if (mCurScrollY != 0 || mCompatibilityInfo.mScalingRequired) {
mTempRect.set(dirty);
if (mCurScrollY != 0) {
mTempRect.offset(0, -mCurScrollY);
}
- if (mAppScale != 1.0f) {
- mTempRect.scale(mAppScale);
+ if (mCompatibilityInfo.mScalingRequired) {
+ mTempRect.scale(mCompatibilityInfo.mApplicationScale);
}
dirty = mTempRect;
}
@@ -615,6 +621,8 @@
boolean viewVisibilityChanged = mViewVisibility != viewVisibility
|| mNewSurfaceNeeded;
+ float appScale = mCompatibilityInfo.mApplicationScale;
+
WindowManager.LayoutParams params = null;
if (mWindowAttributesChanged) {
mWindowAttributesChanged = false;
@@ -625,9 +633,10 @@
fullRedrawNeeded = true;
mLayoutRequested = true;
- Display d = new Display(0);
- desiredWindowWidth = (int) (d.getWidth() * mAppScaleInverted);
- desiredWindowHeight = (int) (d.getHeight() * mAppScaleInverted);
+ DisplayMetrics packageMetrics =
+ mView.getContext().getResources().getDisplayMetrics();
+ desiredWindowWidth = packageMetrics.widthPixels;
+ desiredWindowHeight = packageMetrics.heightPixels;
// For the very first time, tell the view hierarchy that it
// is attached to the window. Note that at this point the surface
@@ -696,9 +705,10 @@
|| lp.height == ViewGroup.LayoutParams.WRAP_CONTENT) {
windowResizesToFitContent = true;
- Display d = new Display(0);
- desiredWindowWidth = (int) (d.getWidth() * mAppScaleInverted);
- desiredWindowHeight = (int) (d.getHeight() * mAppScaleInverted);
+ DisplayMetrics packageMetrics =
+ mView.getContext().getResources().getDisplayMetrics();
+ desiredWindowWidth = packageMetrics.widthPixels;
+ desiredWindowHeight = packageMetrics.heightPixels;
}
}
@@ -878,7 +888,7 @@
mHeight = frame.height();
if (initialized) {
- mGlCanvas.setViewport((int) (mWidth * mAppScale), (int) (mHeight * mAppScale));
+ mGlCanvas.setViewport((int) (mWidth * appScale), (int) (mHeight * appScale));
}
boolean focusChangedDueToTouchMode = ensureTouchModeLocally(
@@ -968,11 +978,7 @@
mTmpLocation[1] + host.mBottom - host.mTop);
host.gatherTransparentRegion(mTransparentRegion);
-
- // TODO: scale the region, like:
- // Region uses native methods. We probabl should have ScalableRegion class.
-
- // Region does not have equals method ?
+ mTransparentRegion.scale(appScale);
if (!mTransparentRegion.equals(mPreviousTransparentRegion)) {
mPreviousTransparentRegion.set(mTransparentRegion);
// reconfigure window manager
@@ -983,7 +989,6 @@
}
}
-
if (DBG) {
System.out.println("======================================");
System.out.println("performTraversals -- after setFrame");
@@ -1003,10 +1008,11 @@
givenContent.left = givenContent.top = givenContent.right
= givenContent.bottom = givenVisible.left = givenVisible.top
= givenVisible.right = givenVisible.bottom = 0;
- insets.contentInsets.scale(mAppScale);
- insets.visibleInsets.scale(mAppScale);
-
attachInfo.mTreeObserver.dispatchOnComputeInternalInsets(insets);
+ if (mCompatibilityInfo.mScalingRequired) {
+ insets.contentInsets.scale(appScale);
+ insets.visibleInsets.scale(appScale);
+ }
if (insetsPending || !mLastGivenInsets.equals(insets)) {
mLastGivenInsets.set(insets);
try {
@@ -1154,6 +1160,8 @@
mCurScrollY = yoff;
fullRedrawNeeded = true;
}
+ float appScale = mCompatibilityInfo.mApplicationScale;
+ boolean scalingRequired = mCompatibilityInfo.mScalingRequired;
Rect dirty = mDirty;
if (mUseGL) {
@@ -1169,12 +1177,11 @@
mAttachInfo.mIgnoreDirtyState = true;
mView.mPrivateFlags |= View.DRAWN;
- float scale = mAppScale;
int saveCount = canvas.save(Canvas.MATRIX_SAVE_FLAG);
try {
canvas.translate(0, -yoff);
- if (scale != 1.0f) {
- canvas.scale(scale, scale);
+ if (scalingRequired) {
+ canvas.scale(appScale, appScale);
}
mView.draw(canvas);
if (Config.DEBUG && ViewDebug.consistencyCheckEnabled) {
@@ -1206,8 +1213,8 @@
}
if (fullRedrawNeeded) {
- mAttachInfo.mIgnoreDirtyState = true;
- dirty.union(0, 0, (int) (mWidth * mAppScale), (int) (mHeight * mAppScale));
+ mAttachInfo.mIgnoreDirtyState = true;
+ dirty.union(0, 0, (int) (mWidth * appScale), (int) (mHeight * appScale));
}
if (DEBUG_ORIENTATION || DEBUG_DRAW) {
@@ -1215,7 +1222,8 @@
+ mWindowAttributes.getTitle()
+ ": dirty={" + dirty.left + "," + dirty.top
+ "," + dirty.right + "," + dirty.bottom + "} surface="
- + surface + " surface.isValid()=" + surface.isValid());
+ + surface + " surface.isValid()=" + surface.isValid() + ", appScale:" +
+ appScale + ", width=" + mWidth + ", height=" + mHeight);
}
Canvas canvas;
@@ -1272,18 +1280,16 @@
mAttachInfo.mDrawingTime = SystemClock.uptimeMillis();
mView.mPrivateFlags |= View.DRAWN;
- float scale = mAppScale;
if (DEBUG_DRAW) {
Context cxt = mView.getContext();
Log.i(TAG, "Drawing: package:" + cxt.getPackageName() +
- ", appScale=" + mAppScale);
+ ", metrics=" + mView.getContext().getResources().getDisplayMetrics());
}
- int saveCount = canvas.save(Canvas.MATRIX_SAVE_FLAG);
+ int saveCount = canvas.save(Canvas.MATRIX_SAVE_FLAG);
try {
canvas.translate(0, -yoff);
- if (scale != 1.0f) {
- // re-scale this
- canvas.scale(scale, scale);
+ if (scalingRequired) {
+ canvas.scale(appScale, appScale);
}
mView.draw(canvas);
} finally {
@@ -1586,8 +1592,8 @@
} else {
didFinish = event.getAction() == MotionEvent.ACTION_OUTSIDE;
}
- if (event != null) {
- event.scale(mAppScaleInverted);
+ if (event != null && mCompatibilityInfo.mScalingRequired) {
+ event.scale(mCompatibilityInfo.mApplicationInvertedScale);
}
try {
@@ -1709,8 +1715,9 @@
if (mGlWanted && !mUseGL) {
initializeGL();
if (mGlCanvas != null) {
- mGlCanvas.setViewport((int) (mWidth * mAppScale),
- (int) (mHeight * mAppScale));
+ float appScale = mCompatibilityInfo.mApplicationScale;
+ mGlCanvas.setViewport(
+ (int) (mWidth * appScale), (int) (mHeight * appScale));
}
}
}
@@ -1914,8 +1921,8 @@
} else {
didFinish = false;
}
- if (event != null) {
- event.scale(mAppScaleInverted);
+ if (event != null && mCompatibilityInfo.mScalingRequired) {
+ event.scale(mCompatibilityInfo.mApplicationInvertedScale);
}
if (DEBUG_TRACKBALL) Log.v(TAG, "Motion event:" + event);
@@ -2345,27 +2352,59 @@
private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility,
boolean insetsPending) throws RemoteException {
-
boolean restore = false;
- if (params != null && mAppScale != 1.0f) {
+ float appScale = mCompatibilityInfo.mApplicationScale;
+ boolean scalingRequired = mCompatibilityInfo.mScalingRequired;
+
+ if (params != null && !mCompatibilityInfo.mExpandable) {
+ adjustWindowAttributesForCompatibleMode(params);
+ }
+ if (params != null && scalingRequired) {
restore = true;
- params.scale(mAppScale, mWindowLayoutParamsBackup);
+ params.scale(appScale, mWindowLayoutParamsBackup);
}
int relayoutResult = sWindowSession.relayout(
mWindow, params,
- (int) (mView.mMeasuredWidth * mAppScale),
- (int) (mView.mMeasuredHeight * mAppScale),
+ (int) (mView.mMeasuredWidth * appScale),
+ (int) (mView.mMeasuredHeight * appScale),
viewVisibility, insetsPending, mWinFrame,
mPendingContentInsets, mPendingVisibleInsets, mSurface);
if (restore) {
params.restore(mWindowLayoutParamsBackup);
}
-
- mPendingContentInsets.scale(mAppScaleInverted);
- mPendingVisibleInsets.scale(mAppScaleInverted);
- mWinFrame.scale(mAppScaleInverted);
+ if (scalingRequired) {
+ float invertedScale = mCompatibilityInfo.mApplicationInvertedScale;
+ mPendingContentInsets.scale(invertedScale);
+ mPendingVisibleInsets.scale(invertedScale);
+ mWinFrame.scale(invertedScale);
+ }
return relayoutResult;
}
+
+ /**
+ * Adjust the window's layout parameter for compatibility mode. It replaces FILL_PARENT
+ * with the default window size, and centers if the window wanted to fill
+ * horizontally.
+ *
+ * @param attrs the window's layout params to adjust
+ */
+ private void adjustWindowAttributesForCompatibleMode(WindowManager.LayoutParams attrs) {
+ // fix app windows only
+ if (attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
+ DisplayMetrics metrics = mView.getContext().getResources().getDisplayMetrics();
+ // TODO: improve gravity logic
+ if (attrs.width == ViewGroup.LayoutParams.FILL_PARENT) {
+ attrs.width = metrics.widthPixels;
+ attrs.gravity |= Gravity.CENTER_HORIZONTAL;
+ }
+ if (attrs.height == ViewGroup.LayoutParams.FILL_PARENT) {
+ attrs.height = metrics.heightPixels;
+ }
+ if (DEBUG_LAYOUT) {
+ Log.d(TAG, "Attributes fixed for compatibility : " + attrs);
+ }
+ }
+ }
/**
* {@inheritDoc}
@@ -2470,11 +2509,16 @@
+ " visibleInsets=" + visibleInsets.toShortString()
+ " reportDraw=" + reportDraw);
Message msg = obtainMessage(reportDraw ? RESIZED_REPORT :RESIZED);
-
- coveredInsets.scale(mAppScaleInverted);
- visibleInsets.scale(mAppScaleInverted);
- msg.arg1 = (int) (w * mAppScaleInverted);
- msg.arg2 = (int) (h * mAppScaleInverted);
+ if (mCompatibilityInfo.mScalingRequired) {
+ float invertedScale = mCompatibilityInfo.mApplicationInvertedScale;
+ coveredInsets.scale(invertedScale);
+ visibleInsets.scale(invertedScale);
+ msg.arg1 = (int) (w * invertedScale);
+ msg.arg2 = (int) (h * invertedScale);
+ } else {
+ msg.arg1 = w;
+ msg.arg2 = h;
+ }
msg.obj = new Rect[] { new Rect(coveredInsets), new Rect(visibleInsets) };
sendMessage(msg);
}
diff --git a/core/java/android/webkit/TextDialog.java b/core/java/android/webkit/TextDialog.java
index 9de97c9..99de56d 100644
--- a/core/java/android/webkit/TextDialog.java
+++ b/core/java/android/webkit/TextDialog.java
@@ -538,7 +538,8 @@
* removing the password input type.
*/
public void setSingleLine(boolean single) {
- int inputType = EditorInfo.TYPE_CLASS_TEXT;
+ int inputType = EditorInfo.TYPE_CLASS_TEXT
+ | EditorInfo.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT;
if (!single) {
inputType |= EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE
| EditorInfo.TYPE_TEXT_FLAG_CAP_SENTENCES
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index ec02143..f62487f 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -472,7 +472,6 @@
private ViewTreeObserver.OnGlobalLayoutListener mGesturesLayoutListener;
private boolean mGlobalLayoutListenerAddedGestures;
private boolean mInstallGesturesOverlay;
- private boolean mPreviousGesturing;
private boolean mGlobalLayoutListenerAddedFilter;
@@ -737,8 +736,6 @@
mGesturesOverlay.removeAllOnGestureListeners();
mGesturesOverlay.setGestureStrokeType(GestureOverlayView.GESTURE_STROKE_TYPE_MULTIPLE);
mGesturesOverlay.addOnGesturePerformedListener(new GesturesProcessor());
-
- mPreviousGesturing = false;
}
}
@@ -753,25 +750,10 @@
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (mGestures != GESTURES_NONE) {
- if (ev.getAction() != MotionEvent.ACTION_DOWN || mFastScroller == null ||
- !mFastScroller.isPointInside(ev.getX(), ev.getY())) {
-
- if (mGesturesPopup.isShowing()) {
- mGesturesOverlay.dispatchTouchEvent(ev);
-
- final boolean isGesturing = mGesturesOverlay.isGesturing();
-
- if (!isGesturing) {
- mPreviousGesturing = isGesturing;
- return super.dispatchTouchEvent(ev);
- } else if (!mPreviousGesturing){
- mPreviousGesturing = isGesturing;
- final MotionEvent event = MotionEvent.obtain(ev);
- event.setAction(MotionEvent.ACTION_CANCEL);
- super.dispatchTouchEvent(event);
- return true;
- }
- }
+ if ((ev.getAction() != MotionEvent.ACTION_DOWN || mFastScroller == null ||
+ !mFastScroller.isPointInside(ev.getX(), ev.getY())) &&
+ mGesturesPopup.isShowing()) {
+ mGesturesOverlay.dispatchTouchEvent(ev);
}
}
@@ -1056,11 +1038,12 @@
public Parcelable onSaveInstanceState() {
/*
* This doesn't really make sense as the place to dismiss the
- * popup, but there don't seem to be any other useful hooks
+ * popups, but there don't seem to be any other useful hooks
* that happen early enough to keep from getting complaints
* about having leaked the window.
*/
dismissPopup();
+ dismissGesturesPopup();
Parcelable superState = super.onSaveInstanceState();
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index 99cf6f8c..a195ac7 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -1852,18 +1852,25 @@
public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
boolean populated = super.dispatchPopulateAccessibilityEvent(event);
+ // If the item count is less than 15 then subtract disabled items from the count and
+ // position. Otherwise ignore disabled items.
if (!populated) {
int itemCount = 0;
int currentItemIndex = getSelectedItemPosition();
ListAdapter adapter = getAdapter();
if (adapter != null) {
- for (int i = 0, count = adapter.getCount(); i < count; i++) {
- if (adapter.isEnabled(i)) {
- itemCount++;
- } else if (i <= currentItemIndex) {
- currentItemIndex--;
+ final int count = adapter.getCount();
+ if (count < 15) {
+ for (int i = 0; i < count; i++) {
+ if (adapter.isEnabled(i)) {
+ itemCount++;
+ } else if (i <= currentItemIndex) {
+ currentItemIndex--;
+ }
}
+ } else {
+ itemCount = count;
}
}
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java
index ef240e0..84cf2c8 100644
--- a/core/java/android/widget/RelativeLayout.java
+++ b/core/java/android/widget/RelativeLayout.java
@@ -37,19 +37,19 @@
* A Layout where the positions of the children can be described in relation to each other or to the
* parent. For the sake of efficiency, the relations between views are evaluated in one pass, so if
* view Y is dependent on the position of view X, make sure the view X comes first in the layout.
- *
+ *
* <p>
* Note that you cannot have a circular dependency between the size of the RelativeLayout and the
* position of its children. For example, you cannot have a RelativeLayout whose height is set to
* {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT WRAP_CONTENT} and a child set to
* {@link #ALIGN_PARENT_BOTTOM}.
* </p>
- *
+ *
* <p>
* Also see {@link android.widget.RelativeLayout.LayoutParams RelativeLayout.LayoutParams} for
* layout attributes
* </p>
- *
+ *
* @attr ref android.R.styleable#RelativeLayout_gravity
* @attr ref android.R.styleable#RelativeLayout_ignoreGravity
*/
@@ -327,7 +327,7 @@
}
if (widthMode != MeasureSpec.EXACTLY) {
- // Width already has left padding in it since it was calculated by looking at
+ // Width already has left padding in it since it was calculated by looking at
// the right of each child view
width += mPaddingRight;
@@ -339,7 +339,7 @@
width = resolveSize(width, widthMeasureSpec);
}
if (heightMode != MeasureSpec.EXACTLY) {
- // Height already has top padding in it since it was calculated by looking at
+ // Height already has top padding in it since it was calculated by looking at
// the bottom of each child view
height += mPaddingBottom;
@@ -881,7 +881,7 @@
@ViewDebug.IntToString(from = RIGHT_OF, to = "rightOf")
}, mapping = {
@ViewDebug.IntToString(from = TRUE, to = "true"),
- @ViewDebug.IntToString(from = 0, to = "FALSE/NO_ID")
+ @ViewDebug.IntToString(from = 0, to = "false/NO_ID")
})
private int[] mRules = new int[VERB_COUNT];
diff --git a/core/java/com/android/internal/backup/AdbTransport.java b/core/java/com/android/internal/backup/AdbTransport.java
new file mode 100644
index 0000000..acb3273
--- /dev/null
+++ b/core/java/com/android/internal/backup/AdbTransport.java
@@ -0,0 +1,28 @@
+package com.android.internal.backup;
+
+import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
+
+/**
+ * Backup transport for full backup over adb. This transport pipes everything to
+ * a file in a known location in /cache, which 'adb backup' then pulls to the desktop
+ * (deleting it afterwards).
+ */
+
+public class AdbTransport extends IBackupTransport.Stub {
+
+ public int startSession() throws RemoteException {
+ return 0;
+ }
+
+ public int endSession() throws RemoteException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ public int performBackup(String packageName, ParcelFileDescriptor data)
+ throws RemoteException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+}
diff --git a/core/java/com/android/internal/backup/GoogleTransport.java b/core/java/com/android/internal/backup/GoogleTransport.java
new file mode 100644
index 0000000..85ab21e
--- /dev/null
+++ b/core/java/com/android/internal/backup/GoogleTransport.java
@@ -0,0 +1,28 @@
+package com.android.internal.backup;
+
+import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
+
+/**
+ * Backup transport for saving data to Google cloud storage.
+ */
+
+public class GoogleTransport extends IBackupTransport.Stub {
+
+ public int endSession() throws RemoteException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ public int performBackup(String packageName, ParcelFileDescriptor data)
+ throws RemoteException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ public int startSession() throws RemoteException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+}
diff --git a/core/java/com/android/internal/backup/IBackupTransport.aidl b/core/java/com/android/internal/backup/IBackupTransport.aidl
index ce39768..2b44fe7 100644
--- a/core/java/com/android/internal/backup/IBackupTransport.aidl
+++ b/core/java/com/android/internal/backup/IBackupTransport.aidl
@@ -16,6 +16,7 @@
package com.android.internal.backup;
+import android.os.Bundle;
import android.os.ParcelFileDescriptor;
/** {@hide} */
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 51f3b02..99a381c 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -53,7 +53,7 @@
private static final int MAGIC = 0xBA757475; // 'BATSTATS'
// Current on-disk Parcel version
- private static final int VERSION = 37;
+ private static final int VERSION = 38;
private final File mFile;
private final File mBackupFile;
@@ -1342,11 +1342,13 @@
public Map<String, ? extends BatteryStats.Uid.Pkg> getPackageStats() {
return mPackageStats;
}
-
+
+ @Override
public int getUid() {
return mUid;
}
-
+
+ @Override
public long getTcpBytesReceived(int which) {
if (which == STATS_LAST) {
return mLoadedTcpBytesReceived;
@@ -1365,7 +1367,8 @@
return mCurrentTcpBytesReceived + (mStartedTcpBytesReceived >= 0
? (NetStat.getUidRxBytes(mUid) - mStartedTcpBytesReceived) : 0);
}
-
+
+ @Override
public long getTcpBytesSent(int which) {
if (which == STATS_LAST) {
return mLoadedTcpBytesSent;
@@ -1754,7 +1757,8 @@
public Timer getSensorTime() {
return mTimer;
}
-
+
+ @Override
public int getHandle() {
return mHandle;
}
@@ -1780,6 +1784,11 @@
int mStarts;
/**
+ * Amount of time the process was running in the foreground.
+ */
+ long mForegroundTime;
+
+ /**
* The amount of user time loaded from a previous save.
*/
long mLoadedUserTime;
@@ -1795,6 +1804,11 @@
int mLoadedStarts;
/**
+ * The amount of foreground time loaded from a previous save.
+ */
+ long mLoadedForegroundTime;
+
+ /**
* The amount of user time loaded from the previous run.
*/
long mLastUserTime;
@@ -1810,6 +1824,11 @@
int mLastStarts;
/**
+ * The amount of foreground time loaded from the previous run
+ */
+ long mLastForegroundTime;
+
+ /**
* The amount of user time when last unplugged.
*/
long mUnpluggedUserTime;
@@ -1824,6 +1843,11 @@
*/
int mUnpluggedStarts;
+ /**
+ * The amount of foreground time since unplugged.
+ */
+ long mUnpluggedForegroundTime;
+
Proc() {
mUnpluggables.add(this);
}
@@ -1832,6 +1856,7 @@
mUnpluggedUserTime = mUserTime;
mUnpluggedSystemTime = mSystemTime;
mUnpluggedStarts = mStarts;
+ mUnpluggedForegroundTime = mForegroundTime;
}
public void plug(long batteryUptime, long batteryRealtime) {
@@ -1843,30 +1868,38 @@
out.writeLong(mUserTime);
out.writeLong(mSystemTime);
+ out.writeLong(mForegroundTime);
out.writeInt(mStarts);
out.writeLong(mLoadedUserTime);
out.writeLong(mLoadedSystemTime);
+ out.writeLong(mLoadedForegroundTime);
out.writeInt(mLoadedStarts);
out.writeLong(mLastUserTime);
out.writeLong(mLastSystemTime);
+ out.writeLong(mLastForegroundTime);
out.writeInt(mLastStarts);
out.writeLong(mUnpluggedUserTime);
out.writeLong(mUnpluggedSystemTime);
+ out.writeLong(mUnpluggedForegroundTime);
out.writeInt(mUnpluggedStarts);
}
void readFromParcelLocked(Parcel in) {
mUserTime = in.readLong();
mSystemTime = in.readLong();
+ mForegroundTime = in.readLong();
mStarts = in.readInt();
mLoadedUserTime = in.readLong();
mLoadedSystemTime = in.readLong();
+ mLoadedForegroundTime = in.readLong();
mLoadedStarts = in.readInt();
mLastUserTime = in.readLong();
mLastSystemTime = in.readLong();
+ mLastForegroundTime = in.readLong();
mLastStarts = in.readInt();
mUnpluggedUserTime = in.readLong();
mUnpluggedSystemTime = in.readLong();
+ mUnpluggedForegroundTime = in.readLong();
mUnpluggedStarts = in.readInt();
}
@@ -1879,6 +1912,10 @@
mSystemTime += stime;
}
+ public void addForegroundTimeLocked(long ttime) {
+ mForegroundTime += ttime;
+ }
+
public void incStartsLocked() {
mStarts++;
}
@@ -1916,6 +1953,22 @@
}
@Override
+ public long getForegroundTime(int which) {
+ long val;
+ if (which == STATS_LAST) {
+ val = mLastForegroundTime;
+ } else {
+ val = mForegroundTime;
+ if (which == STATS_CURRENT) {
+ val -= mLoadedForegroundTime;
+ } else if (which == STATS_UNPLUGGED) {
+ val -= mUnpluggedForegroundTime;
+ }
+ }
+ return val;
+ }
+
+ @Override
public int getStarts(int which) {
int val;
if (which == STATS_LAST) {
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index 1fd15d6..137707f 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -311,7 +311,7 @@
int sampleSize) {
SkPixelRef* pr;
// only use ashmem for large images, since mmaps come at a price
- if (bitmap->getSize() >= 32 * 65536) {
+ if (bitmap->getSize() >= 32 * 1024) {
pr = new SkImageRef_ashmem(stream, bitmap->config(), sampleSize);
} else {
pr = new SkImageRef_GlobalPool(stream, bitmap->config(), sampleSize);
@@ -520,7 +520,10 @@
*/
AutoFDSeek as(descriptor);
- return doDecode(env, stream, padding, bitmapFactoryOptions, true);
+ /* Allow purgeable iff we own the FD, i.e., in the puregeable and
+ shareable case.
+ */
+ return doDecode(env, stream, padding, bitmapFactoryOptions, weOwnTheFD);
}
/* make a deep copy of the asset, and return it as a stream, or NULL if there
diff --git a/core/jni/android_backup_BackupDataOutput.cpp b/core/jni/android_backup_BackupDataOutput.cpp
index 8fce2a2..aab1233 100644
--- a/core/jni/android_backup_BackupDataOutput.cpp
+++ b/core/jni/android_backup_BackupDataOutput.cpp
@@ -20,7 +20,7 @@
#include "JNIHelp.h"
#include <android_runtime/AndroidRuntime.h>
-#include <utils/backup_helpers.h>
+#include <utils/BackupHelpers.h>
namespace android
{
diff --git a/core/jni/android_backup_FileBackupHelper.cpp b/core/jni/android_backup_FileBackupHelper.cpp
index a05d812..a46f37b 100644
--- a/core/jni/android_backup_FileBackupHelper.cpp
+++ b/core/jni/android_backup_FileBackupHelper.cpp
@@ -20,7 +20,7 @@
#include "JNIHelp.h"
#include <android_runtime/AndroidRuntime.h>
-#include <utils/backup_helpers.h>
+#include <utils/BackupHelpers.h>
namespace android
{
diff --git a/core/res/res/values/arrays.xml b/core/res/res/values/arrays.xml
index eb94812..9b9c2e4 100644
--- a/core/res/res/values/arrays.xml
+++ b/core/res/res/values/arrays.xml
@@ -125,4 +125,14 @@
<item><xliff:g id="id">sync_failing</xliff:g></item>
<item><xliff:g id="id">ime</xliff:g></item>
</string-array>
+
+ <!-- Do not translate. Each string points to the component name of an ACTION_WEB_SEARCH
+ handling activity. On startup if there were no preferred ACTION_WEB_SEARCH handlers,
+ the first component from this list which is found to be installed is set as the
+ preferred activity. -->
+ <string-array name="default_web_search_providers">
+ <item>com.google.android.providers.genie/.GenieLauncher</item>
+ <item>com.android.googlesearch/.GoogleSearch</item>
+ <item>com.android.websearch/.Search.1</item>
+ </string-array>
</resources>
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 817a566..0a2d208 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -810,12 +810,19 @@
<!-- The <code>supports-density</code> specifies a screen density that this
package supports. Application can specify multiple densities it supports.
<p>This appears as a child tag of the
- {@link #AndroidManifestApplication application} tag. -->
- <declare-styleable name="AndroidManifestSupportsDensity" parent="AndroidManifestApplication">
+ {@link #AndroidManifest manifest} tag. -->
+ <declare-styleable name="AndroidManifestSupportsDensity" parent="AndroidManifest">
<!-- Required value of the density in dip (device independent pixel). -->
<attr name="density" format="integer" />
</declare-styleable>
+ <!-- The <code>expandable</code> specifies if this package supports screen metrics
+ other than 320x480 dip.
+ <p>This appears as a child tag of the
+ {@link #AndroidManifest manifest} tag. -->
+ <declare-styleable name="AndroidManifestExpandable" parent="AndroidManifest">
+ </declare-styleable>
+
<!-- The <code>provider</code> tag declares a
{@link android.content.ContentProvider} class that is available
as part of the package's application components, supplying structured
diff --git a/core/res/res/xml/power_profile_default.xml b/core/res/res/xml/power_profile_default.xml
index d265b46..ceecb1a 100644
--- a/core/res/res/xml/power_profile_default.xml
+++ b/core/res/res/xml/power_profile_default.xml
@@ -22,7 +22,7 @@
<item name="screen.on">30</item>
<item name="bluetooth.active">103</item>
<item name="bluetooth.on">5</item>
- <item name="screen.full">144</item>
+ <item name="screen.full">114</item>
<item name="wifi.on">23</item>
<item name="wifi.active">200</item>
<item name="wifi.scan">200</item>
@@ -33,4 +33,5 @@
<item name="dsp.video">100</item>
<item name="radio.on">3</item>
<item name="radio.active">175</item>
+ <item name="gps.on">120</item>
</device>
diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java
index 141cc68..e5a9aab 100644
--- a/graphics/java/android/graphics/BitmapFactory.java
+++ b/graphics/java/android/graphics/BitmapFactory.java
@@ -125,8 +125,6 @@
* false, then this field is ignored. If inPurgeable is true, then this
* field determines whether the bitmap can share a reference to the
* input data (inputstream, array, etc.) or if it must make a deep copy.
- *
- * @hide pending API council approval
*/
public boolean inInputShareable;
diff --git a/include/utils/backup_helpers.h b/include/utils/BackupHelpers.h
similarity index 100%
rename from include/utils/backup_helpers.h
rename to include/utils/BackupHelpers.h
diff --git a/libs/utils/Android.mk b/libs/utils/Android.mk
index 5a1a89b..9bdd64a 100644
--- a/libs/utils/Android.mk
+++ b/libs/utils/Android.mk
@@ -117,8 +117,8 @@
IPermissionController.cpp \
IServiceManager.cpp \
Unicode.cpp \
- backup_data.cpp \
- backup_helper_file.cpp
+ BackupData.cpp \
+ BackupHelpers.cpp
ifeq ($(TARGET_SIMULATOR),true)
LOCAL_SRC_FILES += $(hostSources)
diff --git a/libs/utils/backup_data.cpp b/libs/utils/BackupData.cpp
similarity index 99%
rename from libs/utils/backup_data.cpp
rename to libs/utils/BackupData.cpp
index 95c05b7..120f23d 100644
--- a/libs/utils/backup_data.cpp
+++ b/libs/utils/BackupData.cpp
@@ -16,7 +16,7 @@
#define LOG_TAG "backup_data"
-#include <utils/backup_helpers.h>
+#include <utils/BackupHelpers.h>
#include <utils/ByteOrder.h>
#include <stdio.h>
diff --git a/libs/utils/backup_helper_file.cpp b/libs/utils/BackupHelpers.cpp
similarity index 99%
rename from libs/utils/backup_helper_file.cpp
rename to libs/utils/BackupHelpers.cpp
index 7ec2ce8..7f423a8 100644
--- a/libs/utils/backup_helper_file.cpp
+++ b/libs/utils/BackupHelpers.cpp
@@ -16,7 +16,7 @@
#define LOG_TAG "file_backup_helper"
-#include <utils/backup_helpers.h>
+#include <utils/BackupHelpers.h>
#include <utils/KeyedVector.h>
#include <utils/ByteOrder.h>
@@ -350,10 +350,11 @@
FileState& g = newSnapshot.editValueAt(m);
int fd = open(realFilename.string(), O_RDONLY);
- if (fd != -1) {
+ if (fd < 0) {
// We can't open the file. Don't report it as a delete either. Let the
// server keep the old version. Maybe they'll be able to deal with it
// on restore.
+ LOGP("Unable to open file %s - skipping", realFilename.string());
} else {
g.crc32 = compute_crc32(fd);
diff --git a/libs/utils/characterData.h b/libs/utils/CharacterData.h
similarity index 100%
rename from libs/utils/characterData.h
rename to libs/utils/CharacterData.h
diff --git a/libs/utils/Unicode.cpp b/libs/utils/Unicode.cpp
index 33f535f..f92703e 100644
--- a/libs/utils/Unicode.cpp
+++ b/libs/utils/Unicode.cpp
@@ -14,11 +14,11 @@
* limitations under the License.
*/
-#include "utils/AndroidUnicode.h"
-#include "characterData.h"
+#include <utils/AndroidUnicode.h>
+#include "CharacterData.h"
#define LOG_TAG "Unicode"
-#include "utils/Log.h"
+#include <utils/Log.h>
// ICU headers for using macros
#include <unicode/utf16.h>
diff --git a/libs/utils/ZipEntry.cpp b/libs/utils/ZipEntry.cpp
index fbc9e67..96f9fc4 100644
--- a/libs/utils/ZipEntry.cpp
+++ b/libs/utils/ZipEntry.cpp
@@ -20,8 +20,8 @@
#define LOG_TAG "zip"
-#include "utils/ZipEntry.h"
-#include "utils/Log.h"
+#include <utils/ZipEntry.h>
+#include <utils/Log.h>
#include <stdio.h>
#include <string.h>
diff --git a/libs/utils/ZipFile.cpp b/libs/utils/ZipFile.cpp
index 89aa874..6f27d17 100644
--- a/libs/utils/ZipFile.cpp
+++ b/libs/utils/ZipFile.cpp
@@ -20,9 +20,9 @@
#define LOG_TAG "zip"
-#include "utils/ZipFile.h"
-#include "utils/ZipUtils.h"
-#include "utils/Log.h"
+#include <utils/ZipFile.h>
+#include <utils/ZipUtils.h>
+#include <utils/Log.h>
#include <zlib.h>
#define DEF_MEM_LEVEL 8 // normally in zutil.h?
diff --git a/libs/utils/ZipFileCRO.cpp b/libs/utils/ZipFileCRO.cpp
index d312daf..45f6c8b 100644
--- a/libs/utils/ZipFileCRO.cpp
+++ b/libs/utils/ZipFileCRO.cpp
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#include "utils/ZipFileCRO.h"
-#include "utils/ZipFileRO.h"
+#include <utils/ZipFileCRO.h>
+#include <utils/ZipFileRO.h>
using namespace android;
diff --git a/libs/utils/ZipFileRO.cpp b/libs/utils/ZipFileRO.cpp
index ae8c719..6c701dd 100644
--- a/libs/utils/ZipFileRO.cpp
+++ b/libs/utils/ZipFileRO.cpp
@@ -19,9 +19,9 @@
//
#define LOG_TAG "zipro"
//#define LOG_NDEBUG 0
-#include "utils/ZipFileRO.h"
-#include "utils/Log.h"
-#include "utils/misc.h"
+#include <utils/ZipFileRO.h>
+#include <utils/Log.h>
+#include <utils/misc.h>
#include <zlib.h>
diff --git a/libs/utils/ZipUtils.cpp b/libs/utils/ZipUtils.cpp
index bfbacfe..5df94cb 100644
--- a/libs/utils/ZipUtils.cpp
+++ b/libs/utils/ZipUtils.cpp
@@ -20,9 +20,9 @@
#define LOG_TAG "ziputil"
-#include "utils/ZipUtils.h"
-#include "utils/ZipFileRO.h"
-#include "utils/Log.h"
+#include <utils/ZipUtils.h>
+#include <utils/ZipFileRO.h>
+#include <utils/Log.h>
#include <stdlib.h>
#include <string.h>
diff --git a/opengl/libagl/array.cpp b/opengl/libagl/array.cpp
index 8fa7566..3e9c6a5 100644
--- a/opengl/libagl/array.cpp
+++ b/opengl/libagl/array.cpp
@@ -951,6 +951,8 @@
v->index = first;
first &= vertex_cache_t::INDEX_MASK;
const GLubyte* vp = c->arrays.vertex.element(first);
+ v->obj.z = 0;
+ v->obj.w = 0x10000;
c->arrays.vertex.fetch(c, v->obj.v, vp);
c->arrays.mvp_transform(&c->transforms.mvp, &v->clip, &v->obj);
c->arrays.perspective(c, v);
@@ -966,6 +968,8 @@
do {
v->flags = 0;
v->index = first++;
+ v->obj.z = 0;
+ v->obj.w = 0x10000;
c->arrays.vertex.fetch(c, v->obj.v, vp);
c->arrays.mvp_transform(mvp, &v->clip, &v->obj);
c->arrays.perspective(c, v);
diff --git a/opengl/libagl/light.cpp b/opengl/libagl/light.cpp
index 25c41d0..8ae32cc0f 100644
--- a/opengl/libagl/light.cpp
+++ b/opengl/libagl/light.cpp
@@ -38,13 +38,14 @@
static void lightVertexMaterial(ogles_context_t* c, vertex_t* v);
static inline void vscale3(GLfixed* d, const GLfixed* m, GLfixed s);
-static inline void vsub3w(GLfixed* d, const GLfixed* a, const GLfixed* b);
static __attribute__((noinline))
void vnorm3(GLfixed* d, const GLfixed* a);
static inline void vsa3(GLfixed* d,
const GLfixed* m, GLfixed s, const GLfixed* a);
+static inline void vss3(GLfixed* d,
+ const GLfixed* m, GLfixed s, const GLfixed* a);
static inline void vmla3(GLfixed* d,
const GLfixed* m0, const GLfixed* m1, const GLfixed* a);
static inline void vmul3(GLfixed* d,
@@ -151,18 +152,10 @@
}
static inline
-void vsub3w(GLfixed* d, const GLfixed* a, const GLfixed* b) {
- const GLfixed wa = a[3];
- const GLfixed wb = b[3];
- if (ggl_likely(wa == wb)) {
- d[0] = a[0] - b[0];
- d[1] = a[1] - b[1];
- d[2] = a[2] - b[2];
- } else {
- d[0] = gglMulSubx(a[0], wb, gglMulx(b[0], wa));
- d[1] = gglMulSubx(a[1], wb, gglMulx(b[1], wa));
- d[2] = gglMulSubx(a[2], wb, gglMulx(b[2], wa));
- }
+void vss3(GLfixed* d, const GLfixed* m, GLfixed s, const GLfixed* a) {
+ d[0] = gglMulSubx(m[0], s, a[0]);
+ d[1] = gglMulSubx(m[1], s, a[1]);
+ d[2] = gglMulSubx(m[2], s, a[2]);
}
static inline
@@ -227,7 +220,7 @@
const int i = 31 - gglClz(en);
en &= ~(1<<i);
light_t& l = c->lighting.lights[i];
- c->transforms.mvui.point3(&c->transforms.mvui,
+ c->transforms.mvui.point4(&c->transforms.mvui,
&l.objPosition, &l.position);
vnorm3(l.normalizedObjPosition.v, l.objPosition.v);
}
@@ -318,6 +311,11 @@
vmul3(l.implicitAmbient.v, material.ambient.v, l.ambient.v);
vmul3(l.implicitDiffuse.v, material.diffuse.v, l.diffuse.v);
vmul3(l.implicitSpecular.v, material.specular.v, l.specular.v);
+ // this is just a flag to tell if we have a specular component
+ l.implicitSpecular.v[3] =
+ l.implicitSpecular.r |
+ l.implicitSpecular.g |
+ l.implicitSpecular.b;
}
// emission and ambient for the whole scene
vmla3( c->lighting.implicitSceneEmissionAndAmbient.v,
@@ -343,7 +341,11 @@
vec4_t n;
c->arrays.normal.fetch(c, n.v,
c->arrays.normal.element(v->index & vertex_cache_t::INDEX_MASK));
- if (c->transforms.rescaleNormals == GL_NORMALIZE)
+
+ // TODO: right now we handle GL_RESCALE_NORMALS as if ti were
+ // GL_NORMALIZE. We could optimize this by scaling mvui
+ // appropriately instead.
+ if (c->transforms.rescaleNormals)
vnorm3(n.v, n.v);
const material_t& material = c->lighting.front;
@@ -360,7 +362,8 @@
// compute vertex-to-light vector
if (ggl_unlikely(l.position.w)) {
- vsub3w(d.v, l.objPosition.v, v->obj.v);
+ // lightPos/1.0 - vertex/vertex.w == lightPos*vertex.w - vertex
+ vss3(d.v, l.objPosition.v, v->obj.w, v->obj.v);
sqDist = dot3(d.v, d.v);
vscale3(d.v, d.v, gglSqrtRecipx(sqDist));
} else {
diff --git a/opengl/libagl/matrix.cpp b/opengl/libagl/matrix.cpp
index f175cda..0b68dc0 100644
--- a/opengl/libagl/matrix.cpp
+++ b/opengl/libagl/matrix.cpp
@@ -55,7 +55,7 @@
static void point2__generic(transform_t const*, vec4_t* c, vec4_t const* o);
static void point3__generic(transform_t const*, vec4_t* c, vec4_t const* o);
static void point4__generic(transform_t const*, vec4_t* c, vec4_t const* o);
-static void normal__generic(transform_t const*, vec4_t* c, vec4_t const* o);
+static void point4__mvui(transform_t const*, vec4_t* c, vec4_t const* o);
// ----------------------------------------------------------------------------
#if 0
@@ -209,7 +209,8 @@
{
flags = 0;
ops = OP_ALL;
- point3 = normal__generic;
+ point3 = point4__mvui;
+ point4 = point4__mvui;
}
void transform_t::dump(const char* what)
@@ -596,66 +597,19 @@
void transform_state_t::update_mvui()
{
+ GLfloat r[16];
const GLfloat* const mv = modelview.top().elements();
-
- /*
- When transforming normals, we can use the upper 3x3 matrix, see:
- http://www.opengl.org/documentation/specs/version1.1/glspec1.1/node26.html
- */
- // Also note that:
- // l(obj) = tr(M).l(eye) for infinite light
- // l(obj) = inv(M).l(eye) for local light
-
- const uint32_t ops = modelview.top_ops() & ~OP_TRANSLATE;
- if (ggl_likely((!(ops & ~OP_ROTATE)) ||
- (rescaleNormals && modelview.isRigidBody()))) {
- // if the modelview matrix is a rigid body transformation
- // (translation, rotation, uniform scaling), then we can bypass
- // the inverse by transposing the matrix.
- GLfloat rescale = 1.0f;
- if (rescaleNormals == GL_RESCALE_NORMAL) {
- if (!(ops & ~OP_UNIFORM_SCALE)) {
- rescale = reciprocalf(mv[I(0,0)]);
- } else {
- rescale = rsqrtf(
- sqrf(mv[I(2,0)]) + sqrf(mv[I(2,1)]) + sqrf(mv[I(2,2)]));
- }
- }
- GLfixed* const x = mvui.matrix.m;
- for (int i=0 ; i<3 ; i++) {
- x[I(i,0)] = gglFloatToFixed(mv[I(0,i)] * rescale);
- x[I(i,1)] = gglFloatToFixed(mv[I(1,i)] * rescale);
- x[I(i,2)] = gglFloatToFixed(mv[I(2,i)] * rescale);
- }
- mvui.picker();
- return;
- }
-
- GLfloat r[3][3];
- r[0][0] = det22(mv[I(1,1)], mv[I(2,1)], mv[I(1,2)], mv[I(2,2)]);
- r[0][1] =ndet22(mv[I(0,1)], mv[I(2,1)], mv[I(0,2)], mv[I(2,2)]);
- r[0][2] = det22(mv[I(0,1)], mv[I(1,1)], mv[I(0,2)], mv[I(1,2)]);
- r[1][0] =ndet22(mv[I(1,0)], mv[I(2,0)], mv[I(1,2)], mv[I(2,2)]);
- r[1][1] = det22(mv[I(0,0)], mv[I(2,0)], mv[I(0,2)], mv[I(2,2)]);
- r[1][2] =ndet22(mv[I(0,0)], mv[I(1,0)], mv[I(0,2)], mv[I(1,2)]);
- r[2][0] = det22(mv[I(1,0)], mv[I(2,0)], mv[I(1,1)], mv[I(2,1)]);
- r[2][1] =ndet22(mv[I(0,0)], mv[I(2,0)], mv[I(0,1)], mv[I(2,1)]);
- r[2][2] = det22(mv[I(0,0)], mv[I(1,0)], mv[I(0,1)], mv[I(1,1)]);
-
- GLfloat rdet;
- if (rescaleNormals == GL_RESCALE_NORMAL) {
- rdet = rsqrtf(sqrf(r[0][2]) + sqrf(r[1][2]) + sqrf(r[2][2]));
- } else {
- rdet = reciprocalf(
- r[0][0]*mv[I(0,0)] + r[0][1]*mv[I(1,0)] + r[0][2]*mv[I(2,0)]);
- }
+ // TODO: we need a faster invert, especially for when the modelview
+ // is a rigid-body matrix
+ invert(r, mv);
GLfixed* const x = mvui.matrix.m;
- for (int i=0 ; i<3 ; i++) {
- x[I(i,0)] = gglFloatToFixed(r[i][0] * rdet);
- x[I(i,1)] = gglFloatToFixed(r[i][1] * rdet);
- x[I(i,2)] = gglFloatToFixed(r[i][2] * rdet);
+ for (int i=0 ; i<4 ; i++) {
+ x[I(i,0)] = gglFloatToFixed(r[I(i,0)]);
+ x[I(i,1)] = gglFloatToFixed(r[I(i,1)]);
+ x[I(i,2)] = gglFloatToFixed(r[I(i,2)]);
+ x[I(i,4)] = gglFloatToFixed(r[I(i,3)]);
}
mvui.picker();
}
@@ -783,14 +737,19 @@
lhs->w = mla4(rx, m[ 3], ry, m[ 7], rz, m[11], rw, m[15]);
}
-void normal__generic(transform_t const* mx, vec4_t* lhs, vec4_t const* rhs) {
+void point4__mvui(transform_t const* mx, vec4_t* lhs, vec4_t const* rhs) {
+ // this used for transforming light positions back to object space.
+ // Lights have 3 components positions, so w is always 1.
+ // however, it is used as a switch for directional lights, so we need
+ // to preserve it.
const GLfixed* const m = mx->matrix.m;
const GLfixed rx = rhs->x;
const GLfixed ry = rhs->y;
const GLfixed rz = rhs->z;
- lhs->x = mla3(rx, m[ 0], ry, m[ 4], rz, m[ 8]);
- lhs->y = mla3(rx, m[ 1], ry, m[ 5], rz, m[ 9]);
- lhs->z = mla3(rx, m[ 2], ry, m[ 6], rz, m[10]);
+ lhs->x = mla3a(rx, m[ 0], ry, m[ 4], rz, m[ 8], m[12]);
+ lhs->y = mla3a(rx, m[ 1], ry, m[ 5], rz, m[ 9], m[13]);
+ lhs->z = mla3a(rx, m[ 2], ry, m[ 6], rz, m[10], m[14]);
+ lhs->w = rhs->w;
}
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index 82ed1e3..5770a77 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -26,6 +26,7 @@
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
@@ -34,11 +35,17 @@
import android.os.IBinder;
import android.os.Message;
import android.os.ParcelFileDescriptor;
+import android.os.Process;
import android.os.RemoteException;
import android.util.Log;
import android.util.SparseArray;
import android.backup.IBackupManager;
+import android.backup.BackupManager;
+
+import com.android.internal.backup.AdbTransport;
+import com.android.internal.backup.GoogleTransport;
+import com.android.internal.backup.IBackupTransport;
import java.io.File;
import java.io.FileDescriptor;
@@ -59,6 +66,7 @@
//private static final long COLLECTION_INTERVAL = 3 * 60 * 1000;
private static final int MSG_RUN_BACKUP = 1;
+ private static final int MSG_RUN_FULL_BACKUP = 2;
private Context mContext;
private PackageManager mPackageManager;
@@ -89,6 +97,16 @@
private ArrayList<BackupRequest> mBackupQueue;
private final Object mQueueLock = new Object();
+ // The thread performing the sequence of queued backups binds to each app's agent
+ // in succession. Bind notifications are asynchronously delivered through the
+ // Activity Manager; use this lock object to signal when a requested binding has
+ // completed.
+ private final Object mAgentConnectLock = new Object();
+ private IBackupAgent mConnectedAgent;
+ private volatile boolean mConnecting;
+
+ private int mTransportId;
+
private File mStateDir;
private File mDataDir;
@@ -101,6 +119,7 @@
mStateDir = new File(Environment.getDataDirectory(), "backup");
mStateDir.mkdirs();
mDataDir = Environment.getDownloadCacheDirectory();
+ mTransportId = BackupManager.TRANSPORT_GOOGLE;
// Build our mapping of uid to backup client services
synchronized (mBackupParticipants) {
@@ -130,6 +149,8 @@
return;
}
+ // !!! TODO: this is buggy right now; we wind up with duplicate participant entries
+ // after using 'adb install -r' of a participating app
String action = intent.getAction();
if (Intent.ACTION_PACKAGE_ADDED.equals(action)) {
synchronized (mBackupParticipants) {
@@ -166,7 +187,7 @@
// snapshot the pending-backup set and work on that
synchronized (mQueueLock) {
if (mBackupQueue == null) {
- mBackupQueue = new ArrayList();
+ mBackupQueue = new ArrayList<BackupRequest>();
for (BackupRequest b: mPendingBackups.values()) {
mBackupQueue.add(b);
}
@@ -176,68 +197,24 @@
// WARNING: If we crash after this line, anything in mPendingBackups will
// be lost. FIX THIS.
}
- startOneAgent();
+ (new PerformBackupThread(mTransportId, mBackupQueue)).run();
+ break;
+
+ case MSG_RUN_FULL_BACKUP:
break;
}
}
}
- void startOneAgent() {
- // Loop until we find someone to start or the queue empties out.
- while (true) {
- BackupRequest request;
- synchronized (mQueueLock) {
- int queueSize = mBackupQueue.size();
- Log.d(TAG, "mBackupQueue.size=" + queueSize);
- if (queueSize == 0) {
- mBackupQueue = null;
- // if there are pending backups, start those after a short delay
- if (mPendingBackups.size() > 0) {
- mBackupHandler.sendEmptyMessageDelayed(MSG_RUN_BACKUP, COLLECTION_INTERVAL);
- }
- return;
- }
- request = mBackupQueue.get(0);
- // Take it off the queue when we're done.
- }
-
- Log.d(TAG, "starting agent for " + request);
- // !!! TODO: need to handle the restore case?
- int mode = (request.fullBackup)
- ? IApplicationThread.BACKUP_MODE_FULL
- : IApplicationThread.BACKUP_MODE_INCREMENTAL;
- try {
- if (mActivityManager.bindBackupAgent(request.appInfo, mode)) {
- Log.d(TAG, "awaiting agent for " + request);
- // success
- return;
- }
- } catch (RemoteException e) {
- // can't happen; activity manager is local
- } catch (SecurityException ex) {
- // Try for the next one.
- Log.d(TAG, "error in bind", ex);
- }
- }
- }
-
- void processOneBackup(String packageName, IBackupAgent bs) {
+ void processOneBackup(BackupRequest request, IBackupAgent agent, IBackupTransport transport) {
+ final String packageName = request.appInfo.packageName;
Log.d(TAG, "processOneBackup doBackup() on " + packageName);
- BackupRequest request;
- synchronized (mQueueLock) {
- if (mBackupQueue == null) {
- Log.d(TAG, "mBackupQueue is null. WHY?");
- }
- request = mBackupQueue.get(0);
- }
-
try {
- // !!! TODO right now these naming schemes limit applications to
- // one backup service per package
- File savedStateName = new File(mStateDir, request.appInfo.packageName);
- File backupDataName = new File(mDataDir, request.appInfo.packageName + ".data");
- File newStateName = new File(mStateDir, request.appInfo.packageName + ".new");
+ // !!! TODO: get the state file dir from the transport
+ File savedStateName = new File(mStateDir, packageName);
+ File backupDataName = new File(mDataDir, packageName + ".data");
+ File newStateName = new File(mStateDir, packageName + ".new");
// In a full backup, we pass a null ParcelFileDescriptor as
// the saved-state "file"
@@ -259,9 +236,10 @@
ParcelFileDescriptor.MODE_CREATE);
// Run the target's backup pass
+ boolean success = false;
try {
- // TODO: Make this oneway
- bs.doBackup(savedState, backupData, newState);
+ agent.doBackup(savedState, backupData, newState);
+ success = true;
} finally {
if (savedState != null) {
savedState.close();
@@ -270,43 +248,35 @@
newState.close();
}
- // !!! TODO: Now propagate the newly-backed-up data to the transport
-
- // !!! TODO: After successful transport, delete the now-stale data
- // and juggle the files so that next time the new state is passed
- //backupDataName.delete();
- newStateName.renameTo(savedStateName);
-
+ // Now propagate the newly-backed-up data to the transport
+ if (success) {
+ if (DEBUG) Log.v(TAG, "doBackup() success; calling transport");
+ backupData =
+ ParcelFileDescriptor.open(backupDataName, ParcelFileDescriptor.MODE_READ_ONLY);
+ int error = transport.performBackup(packageName, backupData);
+
+ // !!! TODO: After successful transport, delete the now-stale data
+ // and juggle the files so that next time the new state is passed
+ //backupDataName.delete();
+ newStateName.renameTo(savedStateName);
+ }
} catch (FileNotFoundException fnf) {
Log.d(TAG, "File not found on backup: ");
fnf.printStackTrace();
} catch (RemoteException e) {
- Log.d(TAG, "Remote target " + packageName + " threw during backup:");
+ Log.d(TAG, "Remote target " + request.appInfo.packageName + " threw during backup:");
e.printStackTrace();
} catch (Exception e) {
Log.w(TAG, "Final exception guard in backup: ");
e.printStackTrace();
}
- synchronized (mQueueLock) {
- mBackupQueue.remove(0);
- }
-
- if (request != null) {
- try {
- mActivityManager.unbindBackupAgent(request.appInfo);
- } catch (RemoteException e) {
- // can't happen
- }
- }
-
- // start the next one
- startOneAgent();
}
// Add the backup agents in the given package to our set of known backup participants.
// If 'packageName' is null, adds all backup agents in the whole system.
void addPackageParticipantsLocked(String packageName) {
// Look for apps that define the android:backupAgent attribute
+ if (DEBUG) Log.v(TAG, "addPackageParticipantsLocked: " + packageName);
List<ApplicationInfo> targetApps = allAgentApps();
addPackageParticipantsLockedInner(packageName, targetApps);
}
@@ -336,6 +306,7 @@
// Remove the given package's backup services from our known active set. If
// 'packageName' is null, *all* backup services will be removed.
void removePackageParticipantsLocked(String packageName) {
+ if (DEBUG) Log.v(TAG, "removePackageParticipantsLocked: " + packageName);
List<ApplicationInfo> allApps = null;
if (packageName != null) {
allApps = new ArrayList<ApplicationInfo>();
@@ -354,6 +325,13 @@
private void removePackageParticipantsLockedInner(String packageName,
List<ApplicationInfo> agents) {
+ if (DEBUG) {
+ Log.v(TAG, "removePackageParticipantsLockedInner (" + packageName
+ + ") removing " + agents.size() + " entries");
+ for (ApplicationInfo a : agents) {
+ Log.v(TAG, " - " + a);
+ }
+ }
for (ApplicationInfo app : agents) {
if (packageName == null || app.packageName.equals(packageName)) {
int uid = app.uid;
@@ -361,8 +339,7 @@
if (set != null) {
set.remove(app);
if (set.size() == 0) {
- mBackupParticipants.put(uid, null);
- }
+ mBackupParticipants.delete(uid); }
}
}
}
@@ -390,6 +367,7 @@
Log.e(TAG, "updatePackageParticipants called with null package name");
return;
}
+ if (DEBUG) Log.v(TAG, "updatePackageParticipantsLocked: " + packageName);
// brute force but small code size
List<ApplicationInfo> allApps = allAgentApps();
@@ -397,6 +375,128 @@
addPackageParticipantsLockedInner(packageName, allApps);
}
+ // ----- Back up a set of applications via a worker thread -----
+
+ class PerformBackupThread extends Thread {
+ private static final String TAG = "PerformBackupThread";
+ int mTransport;
+ ArrayList<BackupRequest> mQueue;
+
+ public PerformBackupThread(int transportId, ArrayList<BackupRequest> queue) {
+ mTransport = transportId;
+ mQueue = queue;
+ }
+
+ @Override
+ public void run() {
+ /*
+ * 1. start up the current transport
+ * 2. for each item in the queue:
+ * 2a. bind the agent [wait for async attach]
+ * 2b. set up the files and call doBackup()
+ * 2c. unbind the agent
+ * 3. tear down the transport
+ * 4. done!
+ */
+ if (DEBUG) Log.v(TAG, "Beginning backup of " + mQueue.size() + " targets");
+
+ // stand up the current transport
+ IBackupTransport transport = null;
+ switch (mTransport) {
+ case BackupManager.TRANSPORT_ADB:
+ if (DEBUG) Log.v(TAG, "Initializing adb transport");
+ transport = new AdbTransport();
+ break;
+
+ case BackupManager.TRANSPORT_GOOGLE:
+ if (DEBUG) Log.v(TAG, "Initializing Google transport");
+ //!!! TODO: stand up the google backup transport here
+ transport = new GoogleTransport();
+ break;
+
+ default:
+ Log.e(TAG, "Perform backup with unknown transport " + mTransport);
+ // !!! TODO: re-enqueue the backup queue for later?
+ return;
+ }
+
+ try {
+ transport.startSession();
+ } catch (Exception e) {
+ Log.e(TAG, "Error starting backup session");
+ e.printStackTrace();
+ // !!! TODO: re-enqueue the backup queue for later?
+ return;
+ }
+
+ // The transport is up and running; now run all the backups in our queue
+ doQueuedBackups(transport);
+
+ // Finally, tear down the transport
+ try {
+ transport.endSession();
+ } catch (Exception e) {
+ Log.e(TAG, "Error ending transport");
+ e.printStackTrace();
+ }
+ }
+
+ private void doQueuedBackups(IBackupTransport transport) {
+ for (BackupRequest request : mQueue) {
+ Log.d(TAG, "starting agent for " + request);
+ // !!! TODO: need to handle the restore case?
+
+ IBackupAgent agent = null;
+ int mode = (request.fullBackup)
+ ? IApplicationThread.BACKUP_MODE_FULL
+ : IApplicationThread.BACKUP_MODE_INCREMENTAL;
+ try {
+ synchronized(mAgentConnectLock) {
+ mConnecting = true;
+ mConnectedAgent = null;
+ if (mActivityManager.bindBackupAgent(request.appInfo, mode)) {
+ Log.d(TAG, "awaiting agent for " + request);
+
+ // success; wait for the agent to arrive
+ while (mConnecting && mConnectedAgent == null) {
+ try {
+ mAgentConnectLock.wait(10000);
+ } catch (InterruptedException e) {
+ // just retry
+ continue;
+ }
+ }
+
+ // if we timed out with no connect, abort and move on
+ if (mConnecting == true) {
+ Log.w(TAG, "Timeout waiting for agent " + request);
+ continue;
+ }
+ agent = mConnectedAgent;
+ }
+ }
+ } catch (RemoteException e) {
+ // can't happen; activity manager is local
+ } catch (SecurityException ex) {
+ // Try for the next one.
+ Log.d(TAG, "error in bind", ex);
+ }
+
+ // successful bind? run the backup for this agent
+ if (agent != null) {
+ processOneBackup(request, agent, transport);
+ }
+
+ // send the unbind even on timeout, just in case
+ try {
+ mActivityManager.unbindBackupAgent(request.appInfo);
+ } catch (RemoteException e) {
+ // can't happen
+ }
+ }
+ }
+ }
+
// ----- IBackupManager binder interface -----
public void dataChanged(String packageName) throws RemoteException {
@@ -432,45 +532,75 @@
// Schedule a backup pass in a few minutes. As backup-eligible data
// keeps changing, continue to defer the backup pass until things
// settle down, to avoid extra overhead.
+ mBackupHandler.removeMessages(MSG_RUN_BACKUP);
mBackupHandler.sendEmptyMessageDelayed(MSG_RUN_BACKUP, COLLECTION_INTERVAL);
}
}
}
- // Schedule a backup pass for a given package, even if the caller is not part of
- // that uid or package itself.
+ // Schedule a backup pass for a given package. This method will schedule a
+ // full backup even for apps that do not declare an android:backupAgent, so
+ // use with care.
public void scheduleFullBackup(String packageName) throws RemoteException {
- // !!! TODO: protect with a signature-or-system permission?
+ mContext.enforceCallingPermission("android.permission.BACKUP", "scheduleFullBackup");
+
+ if (DEBUG) Log.v(TAG, "Scheduling immediate full backup for " + packageName);
synchronized (mQueueLock) {
- int numKeys = mBackupParticipants.size();
- for (int index = 0; index < numKeys; index++) {
- int uid = mBackupParticipants.keyAt(index);
- HashSet<ApplicationInfo> servicesAtUid = mBackupParticipants.get(uid);
- for (ApplicationInfo app: servicesAtUid) {
- if (app.packageName.equals(packageName)) {
- mPendingBackups.put(app, new BackupRequest(app, true));
- }
- }
+ try {
+ ApplicationInfo app = mPackageManager.getApplicationInfo(packageName, 0);
+ mPendingBackups.put(app, new BackupRequest(app, true));
+ mBackupHandler.sendEmptyMessage(MSG_RUN_FULL_BACKUP);
+ } catch (NameNotFoundException e) {
+ Log.w(TAG, "Could not find app for " + packageName + " to schedule full backup");
}
}
}
- // Callback: a requested backup agent has been instantiated
+ // Select which transport to use for the next backup operation
+ public int selectBackupTransport(int transportId) {
+ mContext.enforceCallingPermission("android.permission.BACKUP", "selectBackupTransport");
+
+ int prevTransport = mTransportId;
+ mTransportId = transportId;
+ return prevTransport;
+ }
+
+ // Callback: a requested backup agent has been instantiated. This should only
+ // be called from the Activity Manager.
public void agentConnected(String packageName, IBinder agentBinder) {
- Log.d(TAG, "agentConnected pkg=" + packageName + " agent=" + agentBinder);
- IBackupAgent bs = IBackupAgent.Stub.asInterface(agentBinder);
- processOneBackup(packageName, bs);
+ synchronized(mAgentConnectLock) {
+ if (Binder.getCallingUid() == Process.SYSTEM_UID) {
+ Log.d(TAG, "agentConnected pkg=" + packageName + " agent=" + agentBinder);
+ IBackupAgent agent = IBackupAgent.Stub.asInterface(agentBinder);
+ mConnectedAgent = agent;
+ mConnecting = false;
+ } else {
+ Log.w(TAG, "Non-system process uid=" + Binder.getCallingUid()
+ + " claiming agent connected");
+ }
+ mAgentConnectLock.notifyAll();
+ }
}
// Callback: a backup agent has failed to come up, or has unexpectedly quit.
// If the agent failed to come up in the first place, the agentBinder argument
- // will be null.
+ // will be null. This should only be called from the Activity Manager.
public void agentDisconnected(String packageName) {
// TODO: handle backup being interrupted
+ synchronized(mAgentConnectLock) {
+ if (Binder.getCallingUid() == Process.SYSTEM_UID) {
+ mConnectedAgent = null;
+ mConnecting = false;
+ } else {
+ Log.w(TAG, "Non-system process uid=" + Binder.getCallingUid()
+ + " claiming agent disconnected");
+ }
+ mAgentConnectLock.notifyAll();
+ }
}
-
-
+
+
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
synchronized (mQueueLock) {
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 8da40ac..6a2e62f 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -4147,6 +4147,7 @@
return false;
}
synchronized (mPackages) {
+ grantPermissionsLP(newPkg, true);
mSettings.writeLP();
}
return true;
diff --git a/services/java/com/android/server/ProcessStats.java b/services/java/com/android/server/ProcessStats.java
index 55adabb..58f8980 100644
--- a/services/java/com/android/server/ProcessStats.java
+++ b/services/java/com/android/server/ProcessStats.java
@@ -54,7 +54,10 @@
PROC_SPACE_TERM|PROC_OUT_LONG // 14: stime
};
+ /** Stores user time and system time in 100ths of a second. */
private final long[] mProcessStatsData = new long[2];
+ /** Stores user time and system time in 100ths of a second. */
+ private final long[] mSinglePidStatsData = new long[2];
private static final int[] PROCESS_FULL_STATS_FORMAT = new int[] {
PROC_SPACE_TERM,
@@ -418,7 +421,18 @@
return pids;
}
-
+
+ public long getCpuTimeForPid(int pid) {
+ final String statFile = "/proc/" + pid + "/stat";
+ final long[] statsData = mSinglePidStatsData;
+ if (Process.readProcFile(statFile, PROCESS_STATS_FORMAT,
+ null, statsData, null)) {
+ long time = statsData[0] + statsData[1];
+ return time;
+ }
+ return 0;
+ }
+
final public int getLastUserTime() {
return mRelUserTime;
}
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 3b26cb7..736c0da 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -62,6 +62,7 @@
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.net.Uri;
+import android.os.BatteryStats;
import android.os.Binder;
import android.os.Bundle;
import android.os.Environment;
@@ -182,7 +183,7 @@
// The flags that are set for all calls we make to the package manager.
static final int STOCK_PM_FLAGS = PackageManager.GET_SHARED_LIBRARY_FILES
- | PackageManager.GET_SUPPORTS_DENSITIES;
+ | PackageManager.GET_SUPPORTS_DENSITIES | PackageManager.GET_EXPANDABLE;
private static final String SYSTEM_SECURE = "ro.secure";
@@ -1438,7 +1439,7 @@
synchronized (mProcessStatsThread) {
final long now = SystemClock.uptimeMillis();
boolean haveNewCpuStats = false;
-
+
if (MONITOR_CPU_USAGE &&
mLastCpuTime < (now-MONITOR_CPU_MIN_TIME)) {
mLastCpuTime = now;
@@ -2063,6 +2064,25 @@
if (prev != null) {
prev.resumeKeyDispatchingLocked();
}
+
+ if (prev.app != null && prev.cpuTimeAtResume > 0 && mBatteryStatsService.isOnBattery()) {
+ long diff = 0;
+ synchronized (mProcessStatsThread) {
+ diff = mProcessStats.getCpuTimeForPid(prev.app.pid) - prev.cpuTimeAtResume;
+ }
+ if (diff > 0) {
+ BatteryStatsImpl bsi = mBatteryStatsService.getActiveStatistics();
+ synchronized (bsi) {
+ BatteryStatsImpl.Uid.Proc ps =
+ bsi.getProcessStatsLocked(prev.info.applicationInfo.uid,
+ prev.info.packageName);
+ if (ps != null) {
+ ps.addForegroundTimeLocked(diff);
+ }
+ }
+ }
+ }
+ prev.cpuTimeAtResume = 0; // reset it
}
/**
@@ -2095,6 +2115,17 @@
next.resumeKeyDispatchingLocked();
ensureActivitiesVisibleLocked(null, 0);
mWindowManager.executeAppTransition();
+
+ // Mark the point when the activity is resuming
+ // TODO: To be more accurate, the mark should be before the onCreate,
+ // not after the onResume. But for subsequent starts, onResume is fine.
+ if (next.app != null) {
+ synchronized (mProcessStatsThread) {
+ next.cpuTimeAtResume = mProcessStats.getCpuTimeForPid(next.app.pid);
+ }
+ } else {
+ next.cpuTimeAtResume = 0; // Couldn't get the cpu time of process
+ }
}
/**
@@ -10346,6 +10377,7 @@
return;
}
+ long oldIdent = Binder.clearCallingIdentity();
try {
IBackupManager bm = IBackupManager.Stub.asInterface(
ServiceManager.getService(Context.BACKUP_SERVICE));
@@ -10355,6 +10387,8 @@
} catch (Exception e) {
Log.w(TAG, "Exception trying to deliver BackupAgent binding: ");
e.printStackTrace();
+ } finally {
+ Binder.restoreCallingIdentity(oldIdent);
}
}
}
diff --git a/services/java/com/android/server/am/HistoryRecord.java b/services/java/com/android/server/am/HistoryRecord.java
index 1789687..944ea02 100644
--- a/services/java/com/android/server/am/HistoryRecord.java
+++ b/services/java/com/android/server/am/HistoryRecord.java
@@ -66,6 +66,7 @@
int theme; // resource identifier of activity's theme.
TaskRecord task; // the task this is in.
long startTime; // when we starting launching this activity
+ long cpuTimeAtResume; // the cpu time of host process at the time of resuming activity
Configuration configuration; // configuration activity was last running in
HistoryRecord resultTo; // who started this entry, so will get our reply
final String resultWho; // additional identifier for use by resultTo.
diff --git a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
index 77755ce..af79404 100644
--- a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
@@ -93,6 +93,7 @@
protected static final int EVENT_NV_READY = 31;
protected static final int EVENT_PS_RESTRICT_ENABLED = 32;
protected static final int EVENT_PS_RESTRICT_DISABLED = 33;
+ public static final int EVENT_CLEAN_UP_CONNECTION = 34;
//***** Constants
protected static final int RECONNECT_DELAY_INITIAL_MILLIS = 5 * 1000;
@@ -149,7 +150,7 @@
/** Intent sent when the reconnect alarm fires. */
protected PendingIntent mReconnectIntent = null;
-
+
/** CID of active data connection */
protected int cidActive;
@@ -226,6 +227,7 @@
protected abstract void onDisconnectDone(AsyncResult ar);
protected abstract void onVoiceCallStarted();
protected abstract void onVoiceCallEnded();
+ protected abstract void onCleanUpConnection(boolean tearDown, String reason);
//***** Overridden from Handler
public void handleMessage (Message msg) {
@@ -272,6 +274,11 @@
onVoiceCallEnded();
break;
+ case EVENT_CLEAN_UP_CONNECTION:
+ boolean tearDown = (msg.arg1 == 0) ? false : true;
+ onCleanUpConnection(tearDown, (String)msg.obj);
+ break;
+
default:
Log.e("DATA", "Unidentified event = " + msg.what);
break;
@@ -279,12 +286,6 @@
}
/**
- * Simply tear down data connections due to radio off
- * and don't setup again.
- */
- public abstract void cleanConnectionBeforeRadioOff();
-
- /**
* Report the current state of data connectivity (enabled or disabled)
* @return {@code false} if data connectivity has been explicitly disabled,
* {@code true} otherwise.
diff --git a/telephony/java/com/android/internal/telephony/Phone.java b/telephony/java/com/android/internal/telephony/Phone.java
index 260f662..a6b0480 100644
--- a/telephony/java/com/android/internal/telephony/Phone.java
+++ b/telephony/java/com/android/internal/telephony/Phone.java
@@ -229,7 +229,7 @@
/**
* Get the current DataState. No change notification exists at this
* interface -- use
- * {@link com.android.internal.telephony.PhoneStateIntentReceiver PhoneStateIntentReceiver}
+ * {@link com.android.telephony.PhoneStateListener PhoneStateListener}
* instead.
*/
DataState getDataConnectionState();
diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
index 7ba9951..0ebe507 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
@@ -38,6 +38,7 @@
import static com.android.internal.telephony.TelephonyProperties.PROPERTY_INECM_MODE;
import com.android.internal.telephony.CallStateException;
+import com.android.internal.telephony.CommandException;
import com.android.internal.telephony.CommandsInterface;
import com.android.internal.telephony.Connection;
import com.android.internal.telephony.DataConnection;
@@ -525,8 +526,20 @@
public void
getNeighboringCids(Message response) {
- // WINK:TODO: implement after Cupcake merge
- mCM.getNeighboringCids(response); // workaround.
+ /*
+ * This is currently not implemented. At least as of June
+ * 2009, there is no neighbor cell information available for
+ * CDMA because some party is resisting making this
+ * information readily available. Consequently, calling this
+ * function can have no useful effect. This situation may
+ * (and hopefully will) change in the future.
+ */
+ if (response != null) {
+ CommandException ce = new CommandException(
+ CommandException.Error.REQUEST_NOT_SUPPORTED);
+ AsyncResult.forMessage(response).exception = ce;
+ response.sendToTarget();
+ }
}
public DataState getDataConnectionState() {
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
index b92e9e4..900480f 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
@@ -263,14 +263,6 @@
}
/**
- * Simply tear down data connections due to radio off
- * and don't setup again.
- */
- public void cleanConnectionBeforeRadioOff() {
- cleanUpConnection(true, Phone.REASON_RADIO_TURNED_OFF);
- }
-
- /**
* The data connection is expected to be setup while device
* 1. has ruim card or non-volatile data store
* 2. registered to data connection service
@@ -821,6 +813,13 @@
}
}
+ /**
+ * @override com.android.internal.telephony.DataConnectionTracker
+ */
+ protected void onCleanUpConnection(boolean tearDown, String reason) {
+ cleanUpConnection(tearDown, reason);
+ }
+
private boolean tryAgain(FailCause cause) {
return (cause != FailCause.RADIO_NOT_AVAILABLE)
&& (cause != FailCause.RADIO_OFF)
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
index a9c810d..12ceeaf 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
@@ -449,7 +449,10 @@
(dcTracker.getAnyDataEnabled() ? 1 : 0) );
EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_DATA_STATE_RADIO_OFF, val);
}
- dcTracker.cleanConnectionBeforeRadioOff();
+ Message msg = dcTracker.obtainMessage(DataConnectionTracker.EVENT_CLEAN_UP_CONNECTION);
+ msg.arg1 = 1; // tearDown is true
+ msg.obj = CDMAPhone.REASON_RADIO_TURNED_OFF;
+ sendMessage(msg);
// Poll data state up to 15 times, with a 100ms delay
// totaling 1.5 sec. Normal data disable action will finish in 100ms.
@@ -679,7 +682,7 @@
newSS.setCdmaRoamingIndicator(EriInfo.ROAMING_INDICATOR_OFF);
} else {
// System is acquired, prl match, no nam match or mRoamingIndicator > 2
- newSS.setCdmaRoamingIndicator(mRoamingIndicator);
+ newSS.setCdmaRoamingIndicator(mRoamingIndicator);
}
} else {
if (mRegistrationState == 5) {
@@ -688,8 +691,8 @@
} else {
// Use the default indicator
}
- }
-
+ }
+
newSS.setCdmaDefaultRoamingIndicator(mDefaultRoamingIndicator);
// NOTE: Some operator may require to override the mCdmaRoaming (set by the modem)
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
index 6e4a495..3f43502 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
@@ -28,10 +28,9 @@
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.NetworkInfo;
-import android.net.wifi.WifiManager;
import android.net.Uri;
+import android.net.wifi.WifiManager;
import android.os.AsyncResult;
-import android.os.Handler;
import android.os.INetStatService;
import android.os.Message;
import android.os.RemoteException;
@@ -42,7 +41,6 @@
import android.provider.Checkin;
import android.provider.Settings;
import android.provider.Telephony;
-import android.provider.Settings.SettingNotFoundException;
import android.telephony.ServiceState;
import android.telephony.TelephonyManager;
import android.telephony.gsm.GsmCellLocation;
@@ -52,11 +50,10 @@
import com.android.internal.telephony.DataCallState;
import com.android.internal.telephony.DataConnection;
-import com.android.internal.telephony.DataConnection.FailCause;
import com.android.internal.telephony.DataConnectionTracker;
import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.PhoneProxy;
import com.android.internal.telephony.TelephonyEventLog;
+import com.android.internal.telephony.DataConnection.FailCause;
import java.io.IOException;
import java.util.ArrayList;
@@ -177,9 +174,12 @@
String reason = intent.getStringExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON);
if (state == State.FAILED) {
- cleanUpConnection(false, reason);
+ Message msg = obtainMessage(EVENT_CLEAN_UP_CONNECTION);
+ msg.arg1 = 0; // tearDown is false
+ msg.obj = (String) reason;
+ sendMessage(msg);
}
- trySetupData(reason);
+ sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA));
} else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
final android.net.NetworkInfo networkInfo = (NetworkInfo)
intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
@@ -260,7 +260,7 @@
((GSMPhone) phone).mSST.unregisterForRoamingOff(this);
((GSMPhone) phone).mSST.unregisterForPsRestrictedEnabled(this);
((GSMPhone) phone).mSST.unregisterForPsRestrictedDisabled(this);
-
+
phone.getContext().unregisterReceiver(this.mIntentReceiver);
phone.getContext().getContentResolver().unregisterContentObserver(this.apnObserver);
@@ -362,7 +362,7 @@
* The APN of the specified type is no longer needed. Ensure that if
* use of the default APN has not been explicitly disabled, we are connected
* to the default APN.
- * @param type the APN type. The only valid values are currently
+ * @param type the APN type. The only valid values are currently
* {@link Phone#APN_TYPE_MMS} and {@link Phone#APN_TYPE_SUPL}.
* @return
*/
@@ -410,7 +410,7 @@
if (((GSMPhone) phone).mSIMRecords.getRecordsLoaded() &&
((GSMPhone) phone).mSST.getCurrentGprsState() == ServiceState.STATE_IN_SERVICE &&
(!roaming || getDataOnRoamingEnabled()) &&
- !mIsWifiConnected &&
+ !mIsWifiConnected &&
!mIsPsRestricted ) {
return (state == State.CONNECTED);
}
@@ -494,14 +494,6 @@
return true;
}
}
-
- /**
- * Simply tear down data connections due to radio off
- * and don't setup again.
- */
- public void cleanConnectionBeforeRadioOff() {
- cleanUpConnection(true, Phone.REASON_RADIO_TURNED_OFF);
- }
/**
* Report the current state of data connectivity (enabled or disabled) for
@@ -566,7 +558,7 @@
if (DBG) log("***trySetupData due to " + (reason == null ? "(unspecified)" : reason));
Log.d(LOG_TAG, "[DSAC DEB] " + "trySetupData with mIsPsRestricted=" + mIsPsRestricted);
-
+
if (phone.getSimulatedRadioControl() != null) {
// Assume data is connected on the simulator
// FIXME this can be improved
@@ -664,7 +656,7 @@
* IDLE before the code below runs. If we didn't check
* for that, future calls to trySetupData would fail,
* and we would never get out of the DISCONNECTING state.
- */
+ */
if (!tearDown) {
setState(State.IDLE);
phone.notifyDataConnection(reason);
@@ -1061,7 +1053,7 @@
}
int watchdogTrigger = Settings.Gservices.getInt(mResolver,
- Settings.Gservices.PDP_WATCHDOG_TRIGGER_PACKET_COUNT,
+ Settings.Gservices.PDP_WATCHDOG_TRIGGER_PACKET_COUNT,
NUMBER_SENT_PACKETS_OF_HANG);
if (sentSinceLastRecv >= watchdogTrigger) {
@@ -1084,7 +1076,7 @@
// Slow down the poll interval to let things happen
netStatPollPeriod = Settings.Gservices.getInt(mResolver,
- Settings.Gservices.PDP_WATCHDOG_ERROR_POLL_INTERVAL_MS,
+ Settings.Gservices.PDP_WATCHDOG_ERROR_POLL_INTERVAL_MS,
POLL_NETSTAT_SLOW_MILLIS);
} else {
if (DBG) log("Sent " + String.valueOf(sentSinceLastRecv) +
@@ -1117,7 +1109,7 @@
}
}
};
-
+
private void runPingTest () {
int status = -1;
try {
@@ -1166,19 +1158,19 @@
/**
* Return true if data connection need to be setup after disconnected due to
* reason.
- *
+ *
* @param reason the reason why data is disconnected
- * @return true if try setup data connection is need for this reason
+ * @return true if try setup data connection is need for this reason
*/
private boolean retryAfterDisconnected(String reason) {
boolean retry = true;
-
+
if ( Phone.REASON_RADIO_TURNED_OFF.equals(reason) ||
- Phone.REASON_DATA_DISABLED.equals(reason) ) {
+ Phone.REASON_DATA_DISABLED.equals(reason) ) {
retry = false;
}
return retry;
- }
+ }
private void reconnectAfterFail(FailCause lastFailCauseCode, String reason) {
if (state == State.FAILED) {
@@ -1331,7 +1323,7 @@
cause = (PdpConnection.FailCause) (ar.result);
if(DBG) log("PDP setup failed " + cause);
// Log this failure to the Event Logs.
- if (cause == PdpConnection.FailCause.BAD_APN ||
+ if (cause == PdpConnection.FailCause.BAD_APN ||
cause == PdpConnection.FailCause.BAD_PAP_SECRET ||
cause == PdpConnection.FailCause.BARRED ||
cause == PdpConnection.FailCause.RADIO_ERROR_RETRY ||
@@ -1343,7 +1335,7 @@
if (loc != null) cid = loc.getCid();
EventLog.List val = new EventLog.List(
- cause.ordinal(), cid,
+ cause.ordinal(), cid,
TelephonyManager.getDefault().getNetworkType());
EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_RADIO_PDP_SETUP_FAIL, val);
}
@@ -1416,6 +1408,10 @@
}
}
+ protected void onCleanUpConnection(boolean tearDown, String reason) {
+ cleanUpConnection(tearDown, reason);
+ }
+
private boolean tryNextApn(FailCause cause) {
return (cause != FailCause.RADIO_NOT_AVAILABLE)
&& (cause != FailCause.RADIO_OFF)
@@ -1576,7 +1572,7 @@
ContentResolver resolver = phone.getContext().getContentResolver();
resolver.delete(PREFERAPN_URI, null, null);
- if (pos >= 0) {
+ if (pos >= 0) {
ContentValues values = new ContentValues();
values.put(APN_ID, pos);
resolver.insert(PREFERAPN_URI, values);
@@ -1589,7 +1585,7 @@
}
Cursor cursor = phone.getContext().getContentResolver().query(
- PREFERAPN_URI, new String[] { "_id", "name", "apn" },
+ PREFERAPN_URI, new String[] { "_id", "name", "apn" },
null, null, Telephony.Carriers.DEFAULT_SORT_ORDER);
if (cursor != null) {
@@ -1673,9 +1669,9 @@
* PDP context and notify us with PDP_CONTEXT_CHANGED.
* But we should stop the network polling and prevent reset PDP.
*/
- Log.d(LOG_TAG, "[DSAC DEB] " + "EVENT_PS_RESTRICT_ENABLED " + mIsPsRestricted);
+ Log.d(LOG_TAG, "[DSAC DEB] " + "EVENT_PS_RESTRICT_ENABLED " + mIsPsRestricted);
stopNetStatPoll();
- mIsPsRestricted = true;
+ mIsPsRestricted = true;
break;
case EVENT_PS_RESTRICT_DISABLED:
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
index 63b6a5e..066f782 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
@@ -16,7 +16,13 @@
package com.android.internal.telephony.gsm;
-import com.android.internal.telephony.Phone;
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE;
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA;
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC;
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_ALPHA;
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY;
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_ISROAMING;
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_NUMERIC;
import android.app.AlarmManager;
import android.app.Notification;
import android.app.NotificationManager;
@@ -50,21 +56,11 @@
import com.android.internal.telephony.CommandsInterface;
import com.android.internal.telephony.DataConnectionTracker;
import com.android.internal.telephony.IccCard;
-import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.PhoneProxy;
import com.android.internal.telephony.RILConstants;
import com.android.internal.telephony.ServiceStateTracker;
import com.android.internal.telephony.TelephonyEventLog;
import com.android.internal.telephony.TelephonyIntents;
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE;
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA;
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC;
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_ALPHA;
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY;
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_ISROAMING;
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_NUMERIC;
-
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
@@ -541,7 +537,10 @@
(dcTracker.getAnyDataEnabled() ? 1 : 0) );
EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_DATA_STATE_RADIO_OFF, val);
}
- dcTracker.cleanConnectionBeforeRadioOff();
+ Message msg = dcTracker.obtainMessage(DataConnectionTracker.EVENT_CLEAN_UP_CONNECTION);
+ msg.arg1 = 1; // tearDown is true
+ msg.obj = GSMPhone.REASON_RADIO_TURNED_OFF;
+ sendMessage(msg);
// poll data state up to 15 times, with a 100ms delay
// totaling 1.5 sec. Normal data disable action will finish in 100ms.
diff --git a/test-runner/android/test/mock/MockContext.java b/test-runner/android/test/mock/MockContext.java
index bd39a14..e733dd1 100644
--- a/test-runner/android/test/mock/MockContext.java
+++ b/test-runner/android/test/mock/MockContext.java
@@ -386,12 +386,4 @@
throws PackageManager.NameNotFoundException {
throw new UnsupportedOperationException();
}
-
- /**
- * @hide
- */
- @Override
- public float getApplicationScale() {
- throw new UnsupportedOperationException();
- }
}
diff --git a/tests/AndroidTests/src/com/android/unit_tests/SearchablesTest.java b/tests/AndroidTests/src/com/android/unit_tests/SearchablesTest.java
index bdf67ba..6b56e6c 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/SearchablesTest.java
+++ b/tests/AndroidTests/src/com/android/unit_tests/SearchablesTest.java
@@ -20,6 +20,7 @@
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ProviderInfo;
@@ -306,6 +307,14 @@
throws PackageManager.NameNotFoundException {
return mRealContext.createPackageContext(packageName, flags);
}
+
+ /**
+ * Message broadcast. Pass through for now.
+ */
+ @Override
+ public void sendBroadcast(Intent intent) {
+ mRealContext.sendBroadcast(intent);
+ }
}
/**
@@ -361,7 +370,8 @@
@Override
public List<ResolveInfo> queryIntentActivities(Intent intent, int flags) {
assertNotNull(intent);
- assertEquals(intent.getAction(), Intent.ACTION_SEARCH);
+ assertTrue(intent.getAction().equals(Intent.ACTION_SEARCH)
+ || intent.getAction().equals(Intent.ACTION_WEB_SEARCH));
switch (mSearchablesMode) {
case SEARCHABLES_PASSTHROUGH:
return mRealPackageManager.queryIntentActivities(intent, flags);
@@ -375,7 +385,8 @@
@Override
public ResolveInfo resolveActivity(Intent intent, int flags) {
assertNotNull(intent);
- assertEquals(intent.getAction(), SearchManager.INTENT_ACTION_GLOBAL_SEARCH);
+ assertTrue(intent.getAction().equals(Intent.ACTION_WEB_SEARCH)
+ || intent.getAction().equals(SearchManager.INTENT_ACTION_GLOBAL_SEARCH));
switch (mSearchablesMode) {
case SEARCHABLES_PASSTHROUGH:
return mRealPackageManager.resolveActivity(intent, flags);
@@ -438,6 +449,29 @@
throw new UnsupportedOperationException();
}
}
+
+ /**
+ * Get the activity information for a particular activity.
+ *
+ * @param name The name of the activity to find.
+ * @param flags Additional option flags.
+ *
+ * @return ActivityInfo Information about the activity, if found, else null.
+ */
+ @Override
+ public ActivityInfo getActivityInfo(ComponentName name, int flags)
+ throws NameNotFoundException {
+ assertNotNull(name);
+ MoreAsserts.assertNotEqual(name, "");
+ switch (mSearchablesMode) {
+ case SEARCHABLES_PASSTHROUGH:
+ return mRealPackageManager.getActivityInfo(name, flags);
+ case SEARCHABLES_MOCK_ZERO:
+ throw new NameNotFoundException();
+ default:
+ throw new UnsupportedOperationException();
+ }
+ }
}
}
diff --git a/tests/DumpRenderTree/assets/run_reliability_tests.py b/tests/DumpRenderTree/assets/run_reliability_tests.py
index 6aab009..076c508 100755
--- a/tests/DumpRenderTree/assets/run_reliability_tests.py
+++ b/tests/DumpRenderTree/assets/run_reliability_tests.py
@@ -10,8 +10,10 @@
import logging
import optparse
+import os
import subprocess
import sys
+import time
TEST_LIST_FILE = "/sdcard/android/reliability_tests_list.txt"
TEST_STATUS_FILE = "/sdcard/android/reliability_running_test.txt"
@@ -46,6 +48,20 @@
stderr=subprocess.PIPE).communicate()
+def Bugreport(url, bugreport_dir, adb_cmd):
+ """Pull a bugreport from the device."""
+ bugreport_filename = "%s/reliability_bugreport_%d.txt" % (bugreport_dir,
+ int(time.time()))
+
+ # prepend the report with url
+ handle = open(bugreport_filename, "w")
+ handle.writelines("Bugreport for crash in url - %s\n\n" % url)
+ handle.close()
+
+ cmd = "%s bugreport >> %s" % (adb_cmd, bugreport_filename)
+ os.system(cmd)
+
+
def main(options, args):
"""Send the url list to device and start testing, restart if crashed."""
@@ -80,6 +96,16 @@
else:
manual_delay = options.delay
+ if not options.bugreport:
+ bugreport_dir = "."
+ else:
+ bugreport_dir = options.bugreport
+ if not os.path.exists(bugreport_dir):
+ os.makedirs(bugreport_dir)
+ if not os.path.isdir(bugreport_dir):
+ logging.error("Cannot create results dir: " + bugreport_dir)
+ sys.exit(1)
+
adb_cmd = "adb "
if options.adb_options:
adb_cmd += options.adb_options + " "
@@ -128,6 +154,7 @@
stdout=subprocess.PIPE).communicate()[0]
logging.info(crashed_test + " CRASHED")
crashed_tests.append(crashed_test)
+ Bugreport(crashed_test, bugreport_dir, adb_cmd)
logging.info("Resuming reliability test runner...")
adb_output = subprocess.Popen(test_cmd, shell=True, stdout=subprocess.PIPE,
@@ -172,9 +199,12 @@
help="the list of sites that cause browser to crash")
option_parser.add_option("-f", "--timeout-file",
default="reliability_timedout_sites.txt",
- help="the list of sites that timedout during test.")
+ help="the list of sites that timedout during test")
option_parser.add_option("-d", "--delay",
default=0,
help="add a manual delay between pages (in ms)")
+ option_parser.add_option("-b", "--bugreport",
+ default=".",
+ help="the directory to store bugreport for crashes")
opts, arguments = option_parser.parse_args()
main(opts, arguments)
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTest.java b/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTest.java
index e63aa95..22c458c 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTest.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTest.java
@@ -55,6 +55,9 @@
//read from BufferedReader instead of populating a list in advance,
//this will avoid excessive memory usage in case of a large list
while((url = listReader.readLine()) != null) {
+ url = url.trim();
+ if(url.length() == 0)
+ continue;
start = System.currentTimeMillis();
Log.v(LOGTAG, "Testing URL: " + url);
updateTestStatus(url);
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTestActivity.java b/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTestActivity.java
index a374a41..cbec104 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTestActivity.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTestActivity.java
@@ -215,6 +215,12 @@
}
@Override
+ public boolean onJsConfirm(WebView view, String url, String message, JsResult result) {
+ result.confirm();
+ return true;
+ }
+
+ @Override
public boolean onJsPrompt(WebView view, String url, String message, String defaultValue,
JsPromptResult result) {
result.confirm();
diff --git a/tests/backup/backup_helper_test.cpp b/tests/backup/backup_helper_test.cpp
index 1085909..f087941 100644
--- a/tests/backup/backup_helper_test.cpp
+++ b/tests/backup/backup_helper_test.cpp
@@ -1,4 +1,20 @@
-#include <utils/backup_helpers.h>
+/*
+ * 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.
+ */
+
+#include <utils/BackupHelpers.h>
#include <stdio.h>
#include <string.h>
diff --git a/tools/layoutlib/bridge/src/android/graphics/Matrix.java b/tools/layoutlib/bridge/src/android/graphics/Matrix.java
index 3f9a993..18c0e17 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Matrix.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Matrix.java
@@ -24,8 +24,8 @@
*/
public class Matrix extends _Original_Matrix {
- float mValues[] = new float[9];
-
+ float mValues[] = new float[9];
+
/**
* Create an identity matrix
*/
@@ -40,7 +40,7 @@
public Matrix(Matrix src) {
set(src);
}
-
+
/**
* Creates a Matrix object from the float array. The array becomes the internal storage
* of the object.
@@ -50,14 +50,14 @@
assert data.length != 9;
mValues = data;
}
-
+
@Override
public void finalize() throws Throwable {
// pass
}
-
+
//---------- Custom Methods
-
+
/**
* Adds the given transformation to the current Matrix
* <p/>This in effect does this = this*matrix
@@ -65,17 +65,17 @@
*/
private void addTransform(float[] matrix) {
float[] tmp = new float[9];
-
- // first row
+
+ // first row
tmp[0] = matrix[0] * mValues[0] + matrix[1] * mValues[3] + matrix[2] * mValues[6];
tmp[1] = matrix[0] * mValues[1] + matrix[1] * mValues[4] + matrix[2] * mValues[7];
tmp[2] = matrix[0] * mValues[2] + matrix[1] * mValues[5] + matrix[2] * mValues[8];
-
+
// 2nd row
tmp[3] = matrix[3] * mValues[0] + matrix[4] * mValues[3] + matrix[5] * mValues[6];
tmp[4] = matrix[3] * mValues[1] + matrix[4] * mValues[4] + matrix[5] * mValues[7];
tmp[5] = matrix[3] * mValues[2] + matrix[4] * mValues[5] + matrix[5] * mValues[8];
-
+
// 3rd row
tmp[6] = matrix[6] * mValues[0] + matrix[7] * mValues[3] + matrix[8] * mValues[6];
tmp[7] = matrix[6] * mValues[1] + matrix[7] * mValues[4] + matrix[8] * mValues[7];
@@ -84,16 +84,16 @@
// copy the result over to mValues
mValues = tmp;
}
-
+
public AffineTransform getTransform() {
return new AffineTransform(mValues[0], mValues[1], mValues[2],
mValues[3], mValues[4], mValues[5]);
}
-
+
public boolean hasPerspective() {
return (mValues[6] != 0 || mValues[7] != 0 || mValues[8] != 1);
}
-
+
//----------
/**
@@ -109,7 +109,7 @@
}
}
}
-
+
return true;
}
@@ -122,7 +122,7 @@
public boolean rectStaysRect() {
return (computeTypeMask() & kRectStaysRect_Mask) != 0;
}
-
+
/**
* (deep) copy the src matrix into this matrix. If src is null, reset this
* matrix to the identity matrix.
@@ -151,10 +151,10 @@
return false;
}
}
-
+
return true;
}
-
+
return false;
}
@@ -179,7 +179,7 @@
mValues[5] = dy;
mValues[6] = 0;
mValues[7] = 0;
- mValues[7] = 1;
+ mValues[8] = 1;
}
/**
@@ -200,7 +200,7 @@
mValues[5] = -py;
mValues[6] = 0;
mValues[7] = 0;
- mValues[7] = 1;
+ mValues[8] = 1;
// scale
addTransform(new float[] { sx, 0, 0, 0, sy, 0, 0, 0, 1 });
@@ -219,7 +219,7 @@
mValues[5] = 0;
mValues[6] = 0;
mValues[7] = 0;
- mValues[7] = 1;
+ mValues[8] = 1;
}
/**
@@ -240,13 +240,13 @@
mValues[5] = -py;
mValues[6] = 0;
mValues[7] = 0;
- mValues[7] = 1;
+ mValues[8] = 1;
// scale
double rad = Math.toRadians(degrees);
float cos = (float)Math.cos(rad);
float sin = (float)Math.sin(rad);
- addTransform(new float[] { cos, -sin, 0, sin, cos, 0, 0, 0, 1 });
+ addTransform(new float[] { cos, -sin, 0, sin, cos, 0, 0, 0, 1 });
// translate back the pivot
addTransform(new float[] { 1, 0, px, 0, 1, py, 0, 0, 1 });
}
@@ -268,7 +268,7 @@
mValues[5] = 0;
mValues[6] = 0;
mValues[7] = 0;
- mValues[7] = 1;
+ mValues[8] = 1;
}
/**
@@ -289,10 +289,10 @@
mValues[5] = -py;
mValues[6] = 0;
mValues[7] = 0;
- mValues[7] = 1;
+ mValues[8] = 1;
// scale
- addTransform(new float[] { cosValue, -sinValue, 0, sinValue, cosValue, 0, 0, 0, 1 });
+ addTransform(new float[] { cosValue, -sinValue, 0, sinValue, cosValue, 0, 0, 0, 1 });
// translate back the pivot
addTransform(new float[] { 1, 0, px, 0, 1, py, 0, 0, 1 });
}
@@ -308,7 +308,7 @@
mValues[5] = 0;
mValues[6] = 0;
mValues[7] = 0;
- mValues[7] = 1;
+ mValues[8] = 1;
}
/**
@@ -329,7 +329,7 @@
mValues[5] = -py;
mValues[6] = 0;
mValues[7] = 0;
- mValues[7] = 1;
+ mValues[8] = 1;
// scale
addTransform(new float[] { 1, kx, 0, ky, 1, 0, 0, 0, 1 });
@@ -348,7 +348,7 @@
mValues[5] = 0;
mValues[6] = 0;
mValues[7] = 0;
- mValues[7] = 1;
+ mValues[8] = 1;
}
/**
@@ -366,10 +366,10 @@
tmp.addTransform(a.mValues);
set(tmp);
}
-
+
return true;
}
-
+
@Override
public boolean setConcat(_Original_Matrix a, _Original_Matrix b) {
throw new UnsupportedOperationException("CALL TO PARENT FORBIDDEN");
@@ -384,7 +384,7 @@
// create a matrix that will be multiply by this
Matrix m = new Matrix(new float[] { 1, 0, dx, 0, 1, dy, 0, 0, 1 });
m.addTransform(this.mValues);
-
+
System.arraycopy(m.mValues, 0, mValues, 0, 9);
return true;
}
@@ -399,7 +399,7 @@
m.setScale(sx, sy, px, py);
m.addTransform(mValues);
set(m);
-
+
return true;
}
@@ -413,7 +413,7 @@
m.setScale(sx, sy);
m.addTransform(mValues);
set(m);
-
+
return true;
}
@@ -427,7 +427,7 @@
m.setRotate(degrees, px, py);
m.addTransform(mValues);
set(m);
-
+
return true;
}
@@ -441,7 +441,7 @@
m.setRotate(degrees);
m.addTransform(mValues);
set(m);
-
+
return true;
}
@@ -455,7 +455,7 @@
m.setSkew(kx, ky, px, py);
m.addTransform(mValues);
set(m);
-
+
return true;
}
@@ -469,7 +469,7 @@
m.setSkew(kx, ky);
m.addTransform(mValues);
set(m);
-
+
return true;
}
@@ -481,10 +481,10 @@
Matrix m = new Matrix(other);
other.addTransform(mValues);
set(m);
-
+
return true;
}
-
+
@Override
public boolean preConcat(_Original_Matrix other) {
throw new UnsupportedOperationException("CALL TO PARENT FORBIDDEN");
@@ -513,7 +513,7 @@
addTransform(new float[] { sx, 0, 0, 0, sy, 0, 0, 0, 1 });
// translate back the pivot
addTransform(new float[] { 1, 0, px, 0, 1, py, 0, 0, 1 });
-
+
return true;
}
@@ -540,10 +540,10 @@
double rad = Math.toRadians(degrees);
float cos = (float)Math.cos(rad);
float sin = (float)Math.sin(rad);
- addTransform(new float[] { cos, -sin, 0, sin, cos, 0, 0, 0, 1 });
+ addTransform(new float[] { cos, -sin, 0, sin, cos, 0, 0, 0, 1 });
// translate back the pivot
addTransform(new float[] { 1, 0, px, 0, 1, py, 0, 0, 1 });
-
+
return true;
}
@@ -557,7 +557,7 @@
float cos = (float)Math.cos(rad);
float sin = (float)Math.sin(rad);
addTransform(new float[] { cos, -sin, 0, sin, cos, 0, 0, 0, 1 });
-
+
return true;
}
@@ -574,7 +574,7 @@
addTransform(new float[] { 1, kx, 0, ky, 1, 0, 0, 0, 1 });
// translate back the pivot
addTransform(new float[] { 1, 0, px, 0, 1, py, 0, 0, 1 });
-
+
return true;
}
@@ -585,7 +585,7 @@
@Override
public boolean postSkew(float kx, float ky) {
addTransform(new float[] { 1, kx, 0, ky, 1, 0, 0, 0, 1 });
-
+
return true;
}
@@ -595,7 +595,7 @@
*/
public boolean postConcat(Matrix other) {
addTransform(other.mValues);
-
+
return true;
}
@@ -603,7 +603,7 @@
public boolean postConcat(_Original_Matrix other) {
throw new UnsupportedOperationException("CALL TO PARENT FORBIDDEN");
}
-
+
/** Controlls how the src rect should align into the dst rect for
setRectToRect().
*/
@@ -634,7 +634,7 @@
*/
END (3);
- // the native values must match those in SkMatrix.h
+ // the native values must match those in SkMatrix.h
ScaleToFit(int nativeInt) {
this.nativeInt = nativeInt;
}
@@ -655,7 +655,7 @@
if (dst == null || src == null) {
throw new NullPointerException();
}
-
+
if (src.isEmpty()) {
reset();
return false;
@@ -689,7 +689,7 @@
} else {
diff = dst.height() - src.height() * sy;
}
-
+
if (stf == ScaleToFit.CENTER) {
diff = diff / 2;
}
@@ -712,12 +712,12 @@
mValues[8] = 1;
return true;
}
-
+
@Override
public boolean setRectToRect(RectF src, RectF dst, _Original_Matrix.ScaleToFit stf) {
throw new UnsupportedOperationException("CALL TO PARENT FORBIDDEN");
}
-
+
/**
* Set the matrix such that the specified src points would map to the
* specified dst points. The "points" are represented as an array of floats,
@@ -749,7 +749,7 @@
public boolean invert(Matrix inverse) {
throw new UnsupportedOperationException("STUB NEEDED");
}
-
+
@Override
public boolean invert(_Original_Matrix inverse) {
throw new UnsupportedOperationException("CALL TO PARENT FORBIDDEN");
@@ -772,7 +772,7 @@
checkPointArrays(src, srcIndex, dst, dstIndex, pointCount);
throw new UnsupportedOperationException("STUB NEEDED");
}
-
+
/**
* Apply this matrix to the array of 2D vectors specified by src, and write
* the transformed vectors into the array of vectors specified by dst. The
@@ -790,7 +790,7 @@
checkPointArrays(src, srcIndex, dst, dstIndex, vectorCount);
throw new UnsupportedOperationException("STUB NEEDED");
}
-
+
/**
* Apply this matrix to the array of 2D points specified by src, and write
* the transformed points into the array of points specified by dst. The
@@ -883,7 +883,7 @@
public float mapRadius(float radius) {
throw new UnsupportedOperationException("STUB NEEDED");
}
-
+
/** Copy 9 values from the matrix into the array.
*/
@Override
@@ -907,7 +907,7 @@
}
System.arraycopy(values, 0, mValues, 0, mValues.length);
}
-
+
@SuppressWarnings("unused")
private final static int kIdentity_Mask = 0;
private final static int kTranslate_Mask = 0x01; //!< set if the matrix has translation
@@ -917,7 +917,7 @@
private final static int kRectStaysRect_Mask = 0x10;
@SuppressWarnings("unused")
private final static int kUnknown_Mask = 0x80;
-
+
@SuppressWarnings("unused")
private final static int kAllMasks = kTranslate_Mask |
kScale_Mask |
@@ -942,43 +942,43 @@
if (mValues[6] != 0. || mValues[7] != 0. || mValues[8] != 1.) {
mask |= kPerspective_Mask;
}
-
+
if (mValues[2] != 0. || mValues[5] != 0.) {
mask |= kTranslate_Mask;
}
-
+
float m00 = mValues[0];
float m01 = mValues[1];
float m10 = mValues[3];
float m11 = mValues[4];
-
+
if (m01 != 0. || m10 != 0.) {
mask |= kAffine_Mask;
}
-
+
if (m00 != 1. || m11 != 1.) {
mask |= kScale_Mask;
}
-
+
if ((mask & kPerspective_Mask) == 0) {
// map non-zero to 1
int im00 = m00 != 0 ? 1 : 0;
int im01 = m01 != 0 ? 1 : 0;
int im10 = m10 != 0 ? 1 : 0;
int im11 = m11 != 0 ? 1 : 0;
-
+
// record if the (p)rimary and (s)econdary diagonals are all 0 or
// all non-zero (answer is 0 or 1)
int dp0 = (im00 | im11) ^ 1; // true if both are 0
int dp1 = im00 & im11; // true if both are 1
int ds0 = (im01 | im10) ^ 1; // true if both are 0
int ds1 = im01 & im10; // true if both are 1
-
+
// return 1 if primary is 1 and secondary is 0 or
// primary is 0 and secondary is 1
mask |= ((dp0 & ds1) | (dp1 & ds0)) << kRectStaysRect_Shift;
}
-
+
return mask;
}
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java
index f434e14..baa3d53 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java
@@ -1145,12 +1145,4 @@
public Context getApplicationContext() {
throw new UnsupportedOperationException();
}
-
- /**
- * @hide
- */
- @Override
- public float getApplicationScale() {
- throw new UnsupportedOperationException();
- }
}
diff --git a/tools/localize/Android.mk b/tools/localize/Android.mk
index 186177f5..ab79f8d 100644
--- a/tools/localize/Android.mk
+++ b/tools/localize/Android.mk
@@ -53,4 +53,3 @@
endif
include $(BUILD_HOST_EXECUTABLE)
-
diff --git a/tools/localize/file_utils.cpp b/tools/localize/file_utils.cpp
index bb82a9c..8792b9e 100644
--- a/tools/localize/file_utils.cpp
+++ b/tools/localize/file_utils.cpp
@@ -3,12 +3,46 @@
#include <unistd.h>
#include "file_utils.h"
#include "Perforce.h"
+#include <utils/String8.h>
#include <sys/fcntl.h>
#include <sys/stat.h>
#include <errno.h>
-#include <host/Directories.h>
#include "log.h"
+using namespace android;
+using namespace std;
+
+static string
+parent_dir(const string& path)
+{
+ return string(String8(path.c_str()).getPathDir().string());
+}
+
+static int
+mkdirs(const char* last)
+{
+ String8 dest;
+ const char* s = last-1;
+ int err;
+ do {
+ s++;
+ if (s > last && (*s == '.' || *s == 0)) {
+ String8 part(last, s-last);
+ dest.appendPath(part);
+#ifdef HAVE_MS_C_RUNTIME
+ err = _mkdir(dest.string());
+#else
+ err = mkdir(dest.string(), S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP);
+#endif
+ if (err != 0) {
+ return err;
+ }
+ last = s+1;
+ }
+ } while (*s);
+ return 0;
+}
+
string
translated_file_name(const string& file, const string& locale)
{