diff options
Diffstat (limited to 'core/java')
81 files changed, 1568 insertions, 2276 deletions
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 49ebce3..1c3414d 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -2087,8 +2087,8 @@ public class Activity extends ContextThemeWrapper event.setPackageName(getPackageName()); LayoutParams params = getWindow().getAttributes(); - boolean isFullScreen = (params.width == LayoutParams.FILL_PARENT) && - (params.height == LayoutParams.FILL_PARENT); + boolean isFullScreen = (params.width == LayoutParams.MATCH_PARENT) && + (params.height == LayoutParams.MATCH_PARENT); event.setFullScreen(isFullScreen); CharSequence title = getTitle(); diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index 930ab65..932ad53 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -622,7 +622,6 @@ public class ActivityManager { /** * The stack trace where the error originated. May be null. - * @pending */ public String stackTrace; diff --git a/core/java/android/app/AlertDialog.java b/core/java/android/app/AlertDialog.java index 20a579a..2603579 100644 --- a/core/java/android/app/AlertDialog.java +++ b/core/java/android/app/AlertDialog.java @@ -40,7 +40,7 @@ import com.android.internal.app.AlertController; * * <pre> * FrameLayout fl = (FrameLayout) findViewById(R.id.body); - * fl.add(myView, new LayoutParams(FILL_PARENT, WRAP_CONTENT)); + * fl.add(myView, new LayoutParams(MATCH_PARENT, WRAP_CONTENT)); * </pre> * * <p>The AlertDialog class takes care of automatically setting diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java index 58e8b32..fa5d4a8 100644 --- a/core/java/android/app/Dialog.java +++ b/core/java/android/app/Dialog.java @@ -668,8 +668,8 @@ public class Dialog implements DialogInterface, Window.Callback, event.setPackageName(mContext.getPackageName()); LayoutParams params = getWindow().getAttributes(); - boolean isFullScreen = (params.width == LayoutParams.FILL_PARENT) && - (params.height == LayoutParams.FILL_PARENT); + boolean isFullScreen = (params.width == LayoutParams.MATCH_PARENT) && + (params.height == LayoutParams.MATCH_PARENT); event.setFullScreen(isFullScreen); return false; diff --git a/core/java/android/app/ExpandableListActivity.java b/core/java/android/app/ExpandableListActivity.java index a2e048f..9651078 100644 --- a/core/java/android/app/ExpandableListActivity.java +++ b/core/java/android/app/ExpandableListActivity.java @@ -65,21 +65,21 @@ import java.util.Map; * <?xml version="1.0" encoding="UTF-8"?> * <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" * android:orientation="vertical" - * android:layout_width="fill_parent" - * android:layout_height="fill_parent" + * android:layout_width="match_parent" + * android:layout_height="match_parent" * android:paddingLeft="8dp" * android:paddingRight="8dp"> * * <ExpandableListView android:id="@id/android:list" - * android:layout_width="fill_parent" - * android:layout_height="fill_parent" + * android:layout_width="match_parent" + * android:layout_height="match_parent" * android:background="#00FF00" * android:layout_weight="1" * android:drawSelectorOnTop="false"/> * * <TextView android:id="@id/android:empty" - * android:layout_width="fill_parent" - * android:layout_height="fill_parent" + * android:layout_width="match_parent" + * android:layout_height="match_parent" * android:background="#FF0000" * android:text="No data"/> * </LinearLayout> @@ -114,19 +114,19 @@ import java.util.Map; * <pre> * <?xml version="1.0" encoding="utf-8"?> * <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - * android:layout_width="fill_parent" + * android:layout_width="match_parent" * android:layout_height="wrap_content" * android:orientation="vertical"> * * <TextView android:id="@+id/text1" * android:textSize="16sp" * android:textStyle="bold" - * android:layout_width="fill_parent" + * android:layout_width="match_parent" * android:layout_height="wrap_content"/> * * <TextView android:id="@+id/text2" * android:textSize="16sp" - * android:layout_width="fill_parent" + * android:layout_width="match_parent" * android:layout_height="wrap_content"/> * </LinearLayout> * </pre> diff --git a/core/java/android/app/ListActivity.java b/core/java/android/app/ListActivity.java index 19b99c8..4b4cc05 100644 --- a/core/java/android/app/ListActivity.java +++ b/core/java/android/app/ListActivity.java @@ -56,21 +56,21 @@ import android.widget.ListView; * <?xml version="1.0" encoding="utf-8"?> * <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" * android:orientation="vertical" - * android:layout_width="fill_parent" - * android:layout_height="fill_parent" + * android:layout_width="match_parent" + * android:layout_height="match_parent" * android:paddingLeft="8dp" * android:paddingRight="8dp"> * * <ListView android:id="@id/android:list" - * android:layout_width="fill_parent" - * android:layout_height="fill_parent" + * android:layout_width="match_parent" + * android:layout_height="match_parent" * android:background="#00FF00" * android:layout_weight="1" * android:drawSelectorOnTop="false"/> * * <TextView id="@id/android:empty" - * android:layout_width="fill_parent" - * android:layout_height="fill_parent" + * android:layout_width="match_parent" + * android:layout_height="match_parent" * android:background="#FF0000" * android:text="No data"/> * </LinearLayout> @@ -100,19 +100,19 @@ import android.widget.ListView; * <pre> * <?xml version="1.0" encoding="utf-8"?> * <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - * android:layout_width="fill_parent" + * android:layout_width="match_parent" * android:layout_height="wrap_content" * android:orientation="vertical"> * * <TextView android:id="@+id/text1" * android:textSize="16sp" * android:textStyle="bold" - * android:layout_width="fill_parent" + * android:layout_width="match_parent" * android:layout_height="wrap_content"/> * * <TextView android:id="@+id/text2" * android:textSize="16sp" - * android:layout_width="fill_parent" + * android:layout_width="match_parent" * android:layout_height="wrap_content"/> * </LinearLayout> * </pre> diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java index b204c79..b396396 100644 --- a/core/java/android/app/SearchDialog.java +++ b/core/java/android/app/SearchDialog.java @@ -60,7 +60,6 @@ import android.widget.AdapterView; import android.widget.AutoCompleteTextView; import android.widget.Button; import android.widget.ImageButton; -import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.TextView; @@ -106,7 +105,7 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS // views & widgets private TextView mBadgeLabel; - private ImageView mAppIcon; + private SearchSourceSelector mSourceSelector; private SearchAutoComplete mSearchAutoComplete; private Button mGoButton; private ImageButton mVoiceButton; @@ -182,11 +181,11 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS Window theWindow = getWindow(); WindowManager.LayoutParams lp = theWindow.getAttributes(); lp.type = WindowManager.LayoutParams.TYPE_SEARCH_BAR; - lp.width = ViewGroup.LayoutParams.FILL_PARENT; + lp.width = ViewGroup.LayoutParams.MATCH_PARENT; // taking up the whole window (even when transparent) is less than ideal, // but necessary to show the popup window until the window manager supports // having windows anchored by their parent but not clipped by them. - lp.height = ViewGroup.LayoutParams.FILL_PARENT; + lp.height = ViewGroup.LayoutParams.MATCH_PARENT; lp.gravity = Gravity.TOP | Gravity.FILL_HORIZONTAL; lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; theWindow.setAttributes(lp); @@ -209,7 +208,8 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS mBadgeLabel = (TextView) findViewById(com.android.internal.R.id.search_badge); mSearchAutoComplete = (SearchAutoComplete) findViewById(com.android.internal.R.id.search_src_text); - mAppIcon = (ImageView) findViewById(com.android.internal.R.id.search_app_icon); + mSourceSelector = new SearchSourceSelector( + findViewById(com.android.internal.R.id.search_source_selector)); mGoButton = (Button) findViewById(com.android.internal.R.id.search_go_btn); mVoiceButton = (ImageButton) findViewById(com.android.internal.R.id.search_voice_btn); mSearchPlate = findViewById(com.android.internal.R.id.search_plate); @@ -606,13 +606,16 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS } private void updateSearchAppIcon() { + mSourceSelector.setSource(mSearchable.getSearchActivity()); + mSourceSelector.setAppSearchData(mAppSearchData); + // In Donut, we special-case the case of the browser to hide the app icon as if it were // global search, for extra space for url entry. // // TODO: Remove this special case once the issue has been reconciled in Eclair. if (mGlobalSearchMode || isBrowserSearch()) { - mAppIcon.setImageResource(0); - mAppIcon.setVisibility(View.GONE); + mSourceSelector.setSourceIcon(null); + mSourceSelector.setVisibility(View.GONE); mSearchPlate.setPadding(SEARCH_PLATE_LEFT_PADDING_GLOBAL, mSearchPlate.getPaddingTop(), mSearchPlate.getPaddingRight(), @@ -628,8 +631,8 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS icon = pm.getDefaultActivityIcon(); Log.w(LOG_TAG, mLaunchComponent + " not found, using generic app icon"); } - mAppIcon.setImageDrawable(icon); - mAppIcon.setVisibility(View.VISIBLE); + mSourceSelector.setSourceIcon(icon); + mSourceSelector.setVisibility(View.VISIBLE); mSearchPlate.setPadding(SEARCH_PLATE_LEFT_PADDING_NON_GLOBAL, mSearchPlate.getPaddingTop(), mSearchPlate.getPaddingRight(), @@ -812,6 +815,7 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS if (!mSearchAutoComplete.isPerformingCompletion()) { // The user changed the query, remember it. mUserQuery = s == null ? "" : s.toString(); + mSourceSelector.setQuery(mUserQuery); } } @@ -1927,6 +1931,7 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS query = ""; } mUserQuery = query; + mSourceSelector.setQuery(query); mSearchAutoComplete.setText(query); mSearchAutoComplete.setSelection(query.length()); } diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java index 5d9034b..a75e8dc 100644 --- a/core/java/android/app/SearchManager.java +++ b/core/java/android/app/SearchManager.java @@ -1346,6 +1346,7 @@ public class SearchManager * @hide Pending API council approval */ public final static String SELECT_INITIAL_QUERY = "select_initial_query"; + /** * Defines the constants used in the communication between {@link android.app.SearchDialog} and * the global search provider via {@link Cursor#respond(android.os.Bundle)}. @@ -1612,6 +1613,15 @@ public class SearchManager public final static String SUGGEST_PARAMETER_LIMIT = "limit"; /** + * Intent action for opening the search source selection activity. + * The intent may include these extra values: + * {@link #QUERY}, + * {@link #APP_DATA}. + */ + public static final String INTENT_ACTION_SELECT_SEARCH_SOURCE + = "android.intent.action.SELECT_SEARCH_SOURCE"; + + /** * If a suggestion has this value in {@link #SUGGEST_COLUMN_INTENT_ACTION}, * the search dialog will switch to a different suggestion source when the * suggestion is clicked. @@ -2020,8 +2030,23 @@ public class SearchManager } /** - * Gets information about a searchable activity. This method is static so that it can - * be used from non-Activity contexts. + * Gets information about a searchable activity. + * + * @param componentName The activity to get searchable information for. + * @return Searchable information, or <code>null</code> if the activity does not + * exist, or is not searchable. + */ + public SearchableInfo getSearchableInfo(ComponentName componentName) { + try { + return mService.getSearchableInfo(componentName, false); + } catch (RemoteException ex) { + Log.e(TAG, "getSearchableInfo() failed: " + ex); + return null; + } + } + + /** + * Gets information about a searchable activity. * * @param componentName The activity to get searchable information for. * @param globalSearch If <code>false</code>, return information about the given activity. diff --git a/core/java/android/app/SearchSourceSelector.java b/core/java/android/app/SearchSourceSelector.java new file mode 100644 index 0000000..fabf858 --- /dev/null +++ b/core/java/android/app/SearchSourceSelector.java @@ -0,0 +1,197 @@ +/* + * 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.app; + +import com.android.internal.R; + +import android.content.ActivityNotFoundException; +import android.content.ComponentName; +import android.content.ContentResolver; +import android.content.Intent; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.net.Uri; +import android.os.Bundle; +import android.text.TextUtils; +import android.util.Log; +import android.view.View; +import android.widget.ImageButton; + +import java.util.List; + +/** + * Utilities for setting up the search source selector. + * + * This class has two copies: + * android.app.SearchSourceSelector + * com.android.quicksearchbox.ui.SearchSourceSelector + * + * They should keep the same look and feel as much as possible, + * but only the intent details must absolutely stay in sync. + * + * @hide + */ +public class SearchSourceSelector implements View.OnClickListener { + + private static final String TAG = "SearchSourceSelector"; + + // TODO: This should be defined in android.provider.Applications, + // and have a less made-up value. + private static final String APPLICATION_TYPE = "application/vnd.android.application"; + + public static final int ICON_VIEW_ID = R.id.search_source_selector_icon; + + private final View mView; + + private final ImageButton mIconView; + + private ComponentName mSource; + + private Bundle mAppSearchData; + + private String mQuery; + + public SearchSourceSelector(View view) { + mView = view; + mIconView = (ImageButton) view.findViewById(ICON_VIEW_ID); + mIconView.setOnClickListener(this); + } + + /** + * Sets the icon displayed in the search source selector. + */ + public void setSourceIcon(Drawable icon) { + mIconView.setImageDrawable(icon); + } + + /** + * Sets the current search source. + */ + public void setSource(ComponentName source) { + mSource = source; + } + + /** + * Sets the app-specific data that will be passed to the search activity if + * the user opens the source selector and chooses a source. + */ + public void setAppSearchData(Bundle appSearchData) { + mAppSearchData = appSearchData; + } + + /** + * Sets the initial query that will be passed to the search activity if + * the user opens the source selector and chooses a source. + */ + public void setQuery(String query) { + mQuery = query; + } + + public void setVisibility(int visibility) { + mView.setVisibility(visibility); + } + + /** + * Creates an intent for opening the search source selector activity. + * + * @param source The current search source. + * @param query The initial query that will be passed to the search activity if + * the user opens the source selector and chooses a source. + * @param appSearchData The app-specific data that will be passed to the search + * activity if the user opens the source selector and chooses a source. + */ + public static Intent createIntent(ComponentName source, String query, Bundle appSearchData) { + Intent intent = new Intent(SearchManager.INTENT_ACTION_SELECT_SEARCH_SOURCE); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK + | Intent.FLAG_ACTIVITY_CLEAR_TOP + | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); + Uri sourceUri = componentNameToUri(source); + if (sourceUri != null) { + intent.setDataAndType(sourceUri, APPLICATION_TYPE); + } + if (query != null) { + intent.putExtra(SearchManager.QUERY, query); + } + if (query != null) { + intent.putExtra(SearchManager.APP_DATA, appSearchData); + } + return intent; + } + + /** + * Gets the search source from which the given + * {@link SearchManager.INTENT_ACTION_SELECT_SEARCH_SOURCE} intent was sent. + */ + public static ComponentName getSource(Intent intent) { + return uriToComponentName(intent.getData()); + } + + private static Uri componentNameToUri(ComponentName name) { + if (name == null) return null; + // TODO: This URI format is specificed in android.provider.Applications which is @hidden + return new Uri.Builder() + .scheme(ContentResolver.SCHEME_CONTENT) + .authority("applications") + .appendEncodedPath("applications") + .appendPath(name.getPackageName()) + .appendPath(name.getClassName()) + .build(); + } + + private static ComponentName uriToComponentName(Uri uri) { + if (uri == null) return null; + List<String> path = uri.getPathSegments(); + if (path == null || path.size() != 3) return null; + String pkg = path.get(1); + String cls = path.get(2); + if (TextUtils.isEmpty(pkg) || TextUtils.isEmpty(cls)) return null; + return new ComponentName(pkg, cls); + } + + public void onClick(View v) { + trigger(); + } + + private void trigger() { + try { + Intent intent = createIntent(mSource, mQuery, mAppSearchData); + intent.setSourceBounds(getOnScreenRect(mIconView)); + mIconView.getContext().startActivity(intent); + } catch (ActivityNotFoundException ex) { + Log.e(TAG, "No source selector activity found", ex); + } + } + + // TODO: This code is replicated in lots of places: + // - android.provider.ContactsContract.QuickContact.showQuickContact() + // - android.widget.RemoteViews.setOnClickPendingIntent() + // - com.android.launcher2.Launcher.onClick() + // - com.android.launcher.Launcher.onClick() + // - com.android.server.status.StatusBarService.Launcher.onClick() + private static Rect getOnScreenRect(View v) { + final float appScale = v.getResources().getCompatibilityInfo().applicationScale; + final int[] pos = new int[2]; + v.getLocationOnScreen(pos); + final Rect rect = new Rect(); + rect.left = (int) (pos[0] * appScale + 0.5f); + rect.top = (int) (pos[1] * appScale + 0.5f); + rect.right = (int) ((pos[0] + v.getWidth()) * appScale + 0.5f); + rect.bottom = (int) ((pos[1] + v.getHeight()) * appScale + 0.5f); + return rect; + } + +} diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java index 2f719f3..792b289 100644 --- a/core/java/android/appwidget/AppWidgetHostView.java +++ b/core/java/android/appwidget/AppWidgetHostView.java @@ -311,8 +311,8 @@ public class AppWidgetHostView extends FrameLayout { // Take requested dimensions from child, but apply default gravity. FrameLayout.LayoutParams requested = (FrameLayout.LayoutParams)view.getLayoutParams(); if (requested == null) { - requested = new FrameLayout.LayoutParams(LayoutParams.FILL_PARENT, - LayoutParams.FILL_PARENT); + requested = new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, + LayoutParams.MATCH_PARENT); } requested.gravity = Gravity.CENTER; diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java index 6e7e6d7..eb2d7b1 100644 --- a/core/java/android/content/ContentResolver.java +++ b/core/java/android/content/ContentResolver.java @@ -88,11 +88,11 @@ public abstract class ContentResolver { * <code>content://com.company.provider.imap/inbox/1</code> for a particular * message in the inbox, whose MIME type would be reported as * <code>CURSOR_ITEM_BASE_TYPE + "/vnd.company.imap-msg"</code> - * + * * <p>Compare with {@link #CURSOR_DIR_BASE_TYPE}. */ public static final String CURSOR_ITEM_BASE_TYPE = "vnd.android.cursor.item"; - + /** * This is the Android platform's base MIME type for a content: URI * containing a Cursor of zero or more items. Applications should use this @@ -102,7 +102,7 @@ public abstract class ContentResolver { * <code>content://com.company.provider.imap/inbox</code> for all of the * messages in its inbox, whose MIME type would be reported as * <code>CURSOR_DIR_BASE_TYPE + "/vnd.company.imap-msg"</code> - * + * * <p>Note how the base MIME type varies between this and * {@link #CURSOR_ITEM_BASE_TYPE} depending on whether there is * one single item or multiple items in the data set, while the sub-type @@ -173,13 +173,25 @@ public abstract class ContentResolver { } /** + * <p> * Query the given URI, returning a {@link Cursor} over the result set. + * </p> + * <p> + * For best performance, the caller should follow these guidelines: + * <ul> + * <li>Provide an explicit projection, to prevent + * reading data from storage that aren't going to be used.</li> + * <li>Use question mark parameter markers such as 'phone=?' instead of + * explicit values in the {@code selection} parameter, so that queries + * that differ only by those values will be recognized as the same + * for caching purposes.</li> + * </ul> + * </p> * * @param uri The URI, using the content:// scheme, for the content to * retrieve. * @param projection A list of which columns to return. Passing null will - * return all columns, which is discouraged to prevent reading data - * from storage that isn't going to be used. + * return all columns, which is inefficient. * @param selection A filter declaring which rows to return, formatted as an * SQL WHERE clause (excluding the WHERE itself). Passing null will * return all rows for the given URI. @@ -225,10 +237,10 @@ public abstract class ContentResolver { * <li>android.resource ({@link #SCHEME_ANDROID_RESOURCE})</li> * <li>file ({@link #SCHEME_FILE})</li> * </ul> - * + * * <p>See {@link #openAssetFileDescriptor(Uri, String)} for more information * on these schemes. - * + * * @param uri The desired URI. * @return InputStream * @throws FileNotFoundException if the provided URI could not be opened. @@ -283,7 +295,7 @@ public abstract class ContentResolver { * * <p>See {@link #openAssetFileDescriptor(Uri, String)} for more information * on these schemes. - * + * * @param uri The desired URI. * @param mode May be "w", "wa", "rw", or "rwt". * @return OutputStream @@ -318,7 +330,7 @@ public abstract class ContentResolver { * * <p>See {@link #openAssetFileDescriptor(Uri, String)} for more information * on these schemes. - * + * * @param uri The desired URI to open. * @param mode The file mode to use, as per {@link ContentProvider#openFile * ContentProvider.openFile}. @@ -334,19 +346,19 @@ public abstract class ContentResolver { if (afd == null) { return null; } - + if (afd.getDeclaredLength() < 0) { // This is a full file! return afd.getParcelFileDescriptor(); } - + // Client can't handle a sub-section of a file, so close what // we got and bail with an exception. try { afd.close(); } catch (IOException e) { } - + throw new FileNotFoundException("Not a whole file"); } @@ -491,7 +503,7 @@ public abstract class ContentResolver { res.id = id; return res; } - + /** @hide */ static public int modeToMode(Uri uri, String mode) throws FileNotFoundException { int modeBits; @@ -518,7 +530,7 @@ public abstract class ContentResolver { } return modeBits; } - + /** * Inserts a row into a table at the given URL. * @@ -1146,7 +1158,7 @@ public abstract class ContentResolver { /** @hide */ public static final String CONTENT_SERVICE_NAME = "content"; - + /** @hide */ public static IContentService getContentService() { if (sContentService != null) { @@ -1158,7 +1170,7 @@ public abstract class ContentResolver { if (Config.LOGV) Log.v("ContentService", "default service = " + sContentService); return sContentService; } - + private static IContentService sContentService; private final Context mContext; private static final String TAG = "ContentResolver"; diff --git a/core/java/android/content/EventLogTags.logtags b/core/java/android/content/EventLogTags.logtags deleted file mode 100644 index af50a3c..0000000 --- a/core/java/android/content/EventLogTags.logtags +++ /dev/null @@ -1,10 +0,0 @@ -# See system/core/logcat/event.logtags for a description of the format of this file. - -option java_package android.content - -# --------------------------- -# SyncAdapter.java -# --------------------------- -# What happens in a sync operation (bytes sent and received, and -# operation details) -2743 sync_details (authority|3),(send|1|2),(recv|1|2),(details|3) diff --git a/core/java/android/content/package.html b/core/java/android/content/package.html index dd5360f..eac679d 100644 --- a/core/java/android/content/package.html +++ b/core/java/android/content/package.html @@ -421,7 +421,7 @@ can supply them explicitly in the XML file:</p> <?xml version="1.0" encoding="utf-8"?> <root> <EditText id="text" - android:layout_width="fill_parent" android:layout_height="fill_parent" + android:layout_width="match_parent" android:layout_height="match_parent" <b>android:textSize="18" android:textColor="#008"</b> android:text="Hello, World!" /> </root> @@ -447,7 +447,7 @@ one of those resources:</p> <?xml version="1.0" encoding="utf-8"?> <root> <EditText id="text" - android:layout_width="fill_parent" android:layout_height="fill_parent" + android:layout_width="match_parent" android:layout_height="match_parent" <b>android:textColor="@color/opaque_red"</b> android:text="Hello, World!" /> </root> @@ -463,7 +463,7 @@ reference a system resource, you would need to write:</p> <?xml version="1.0" encoding="utf-8"?> <root> <EditText id="text" - android:layout_width="fill_parent" android:layout_height="fill_parent" + android:layout_width="match_parent" android:layout_height="match_parent" android:textColor="@<b>android:</b>color/opaque_red" android:text="Hello, World!" /> </root> @@ -476,7 +476,7 @@ strings in a layout file so that they can be localized:</p> <?xml version="1.0" encoding="utf-8"?> <root> <EditText id="text" - android:layout_width="fill_parent" android:layout_height="fill_parent" + android:layout_width="match_parent" android:layout_height="match_parent" android:textColor="@android:color/opaque_red" android:text="@string/hello_world" /> </root> @@ -509,7 +509,7 @@ one of the standard colors defined in the base system theme:</p> <?xml version="1.0" encoding="utf-8"?> <root> <EditText id="text" - android:layout_width="fill_parent" android:layout_height="fill_parent" + android:layout_width="match_parent" android:layout_height="match_parent" <b>android:textColor="?android:textDisabledColor"</b> android:text="@string/hello_world" /> </root> @@ -637,10 +637,10 @@ new style resource with the desired values:</p> <?xml version="1.0" encoding="utf-8"?> <root> <EditText id="text1" <b>style="@style/SpecialText"</b> - android:layout_width="fill_parent" android:layout_height="wrap_content" + android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Hello, World!" /> <EditText id="text2" <b>style="@style/SpecialText"</b> - android:layout_width="fill_parent" android:layout_height="wrap_content" + android:layout_width="match_parent" android:layout_height="wrap_content" android:text="I love you all." /> </root></pre> <h4> </h4> diff --git a/core/java/android/database/sqlite/SQLiteCursor.java b/core/java/android/database/sqlite/SQLiteCursor.java index 70b9b83..b178d4f 100644 --- a/core/java/android/database/sqlite/SQLiteCursor.java +++ b/core/java/android/database/sqlite/SQLiteCursor.java @@ -582,21 +582,23 @@ public class SQLiteCursor extends AbstractWindowedCursor { @Override protected void finalize() { try { + // if the cursor hasn't been closed yet, close it first if (mWindow != null) { close(); - String message = "Finalizing cursor " + this + " on " + mEditTable - + " that has not been deactivated or closed"; + Log.e(TAG, "Finalizing cursor that has not been deactivated or closed." + + " database = " + mDatabase.getPath() + ", table = " + mEditTable + + ", query = " + mQuery.mSql); if (SQLiteDebug.DEBUG_ACTIVE_CURSOR_FINALIZATION) { - Log.d(TAG, message + "\nThis cursor was created in:"); + Log.d(TAG, "This cursor was created in:"); for (StackTraceElement ste : mStackTraceElements) { Log.d(TAG, " " + ste); } } SQLiteDebug.notifyActiveCursorFinalized(); - throw new IllegalStateException(message); } else { if (Config.LOGV) { - Log.v(TAG, "Finalizing cursor " + this + " on " + mEditTable); + Log.v(TAG, "Finalizing cursor on database = " + mDatabase.getPath() + + ", table = " + mEditTable + ", query = " + mQuery.mSql); } } } finally { diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java index 657bbcc..f310586 100644 --- a/core/java/android/database/sqlite/SQLiteDatabase.java +++ b/core/java/android/database/sqlite/SQLiteDatabase.java @@ -323,6 +323,7 @@ public class SQLiteDatabase extends SQLiteClosable { close(); } finally { Log.e(TAG, "Removing corrupt database: " + mPath); + EventLog.writeEvent(EVENT_DB_CORRUPT, mPath); // Delete the corrupt file. Don't re-create it now -- that would just confuse people // -- but the next time someone tries to open it, they can set it up from scratch. new File(mPath).delete(); diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java index 01c67cf..0c6bb1a 100644 --- a/core/java/android/hardware/SensorManager.java +++ b/core/java/android/hardware/SensorManager.java @@ -545,8 +545,8 @@ public class SensorManager i = sensors_module_get_next_sensor(sensor, i); if (i>=0) { - Log.d(TAG, "found sensor: " + sensor.getName() + - ", handle=" + sensor.getHandle()); + //Log.d(TAG, "found sensor: " + sensor.getName() + + // ", handle=" + sensor.getHandle()); sensor.setLegacyType(getLegacySensorType(sensor.getType())); fullList.add(sensor); sHandleToSensor.append(sensor.getHandle(), sensor); diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index 5499bba..b315932 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -16,7 +16,7 @@ package android.inputmethodservice; -import static android.view.ViewGroup.LayoutParams.FILL_PARENT; +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; import android.app.Dialog; @@ -556,7 +556,7 @@ public class InputMethodService extends AbstractInputMethodService { Context.LAYOUT_INFLATER_SERVICE); mWindow = new SoftInputWindow(this, mTheme, mDispatcherState); initViews(); - mWindow.getWindow().setLayout(FILL_PARENT, WRAP_CONTENT); + mWindow.getWindow().setLayout(MATCH_PARENT, WRAP_CONTENT); } /** @@ -803,8 +803,8 @@ public class InputMethodService extends AbstractInputMethodService { * candidates only mode changes. * * <p>The default implementation makes the layout for the window - * FILL_PARENT x FILL_PARENT when in fullscreen mode, and - * FILL_PARENT x WRAP_CONTENT when in non-fullscreen mode. + * MATCH_PARENT x MATCH_PARENT when in fullscreen mode, and + * MATCH_PARENT x WRAP_CONTENT when in non-fullscreen mode. * * @param win The input method's window. * @param isFullscreen If true, the window is running in fullscreen mode @@ -816,9 +816,9 @@ public class InputMethodService extends AbstractInputMethodService { public void onConfigureWindow(Window win, boolean isFullscreen, boolean isCandidatesOnly) { if (isFullscreen) { - mWindow.getWindow().setLayout(FILL_PARENT, FILL_PARENT); + mWindow.getWindow().setLayout(MATCH_PARENT, MATCH_PARENT); } else { - mWindow.getWindow().setLayout(FILL_PARENT, WRAP_CONTENT); + mWindow.getWindow().setLayout(MATCH_PARENT, WRAP_CONTENT); } } @@ -1049,8 +1049,8 @@ public class InputMethodService extends AbstractInputMethodService { public void setExtractView(View view) { mExtractFrame.removeAllViews(); mExtractFrame.addView(view, new FrameLayout.LayoutParams( - ViewGroup.LayoutParams.FILL_PARENT, - ViewGroup.LayoutParams.FILL_PARENT)); + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT)); mExtractView = view; if (view != null) { mExtractEditText = (ExtractEditText)view.findViewById( @@ -1079,7 +1079,7 @@ public class InputMethodService extends AbstractInputMethodService { public void setCandidatesView(View view) { mCandidatesFrame.removeAllViews(); mCandidatesFrame.addView(view, new FrameLayout.LayoutParams( - ViewGroup.LayoutParams.FILL_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); } @@ -1092,7 +1092,7 @@ public class InputMethodService extends AbstractInputMethodService { public void setInputView(View view) { mInputFrame.removeAllViews(); mInputFrame.addView(view, new FrameLayout.LayoutParams( - ViewGroup.LayoutParams.FILL_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); mInputView = view; } diff --git a/core/java/android/net/SSLCertificateSocketFactory.java b/core/java/android/net/SSLCertificateSocketFactory.java index a97b9e5..e40f1b8 100644 --- a/core/java/android/net/SSLCertificateSocketFactory.java +++ b/core/java/android/net/SSLCertificateSocketFactory.java @@ -16,11 +16,12 @@ package android.net; -import android.net.http.DomainNameChecker; import android.os.SystemProperties; import android.util.Config; import android.util.Log; +import com.android.common.DomainNameValidator; + import java.io.IOException; import java.net.InetAddress; import java.net.Socket; @@ -200,7 +201,7 @@ public class SSLCertificateSocketFactory extends SSLSocketFactory { X509Certificate lastChainCert = (X509Certificate) certs[0]; - if (!DomainNameChecker.match(lastChainCert, destHost)) { + if (!DomainNameValidator.match(lastChainCert, destHost)) { if (Config.LOGD) { Log.d(LOG_TAG,"validateSocket(): domain name check failed"); } diff --git a/core/java/android/net/http/CertificateChainValidator.java b/core/java/android/net/http/CertificateChainValidator.java index ed6b4c2..da6af9d 100644 --- a/core/java/android/net/http/CertificateChainValidator.java +++ b/core/java/android/net/http/CertificateChainValidator.java @@ -16,6 +16,8 @@ package android.net.http; +import com.android.common.DomainNameValidator; + import org.apache.harmony.xnet.provider.jsse.SSLParameters; import java.io.IOException; @@ -112,7 +114,7 @@ class CertificateChainValidator { closeSocketThrowException( sslSocket, "certificate for this site is null"); } else { - if (!DomainNameChecker.match(currCertificate, domain)) { + if (!DomainNameValidator.match(currCertificate, domain)) { String errorMessage = "certificate not for this host: " + domain; if (HttpLog.LOGV) { diff --git a/core/java/android/net/http/DomainNameChecker.java b/core/java/android/net/http/DomainNameChecker.java deleted file mode 100644 index 3e01d2c..0000000 --- a/core/java/android/net/http/DomainNameChecker.java +++ /dev/null @@ -1,280 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.http; - -import org.bouncycastle.asn1.x509.X509Name; - -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.security.cert.X509Certificate; -import java.security.cert.CertificateParsingException; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.regex.PatternSyntaxException; -import java.util.Vector; - -/** - * Implements basic domain-name validation as specified by RFC2818. - * - * {@hide} - */ -public class DomainNameChecker { - private static Pattern QUICK_IP_PATTERN; - static { - try { - QUICK_IP_PATTERN = Pattern.compile("^[a-f0-9\\.:]+$"); - } catch (PatternSyntaxException e) {} - } - - private static final int ALT_DNS_NAME = 2; - private static final int ALT_IPA_NAME = 7; - - /** - * Checks the site certificate against the domain name of the site being visited - * @param certificate The certificate to check - * @param thisDomain The domain name of the site being visited - * @return True iff if there is a domain match as specified by RFC2818 - */ - public static boolean match(X509Certificate certificate, String thisDomain) { - if (certificate == null || thisDomain == null || thisDomain.length() == 0) { - return false; - } - - thisDomain = thisDomain.toLowerCase(); - if (!isIpAddress(thisDomain)) { - return matchDns(certificate, thisDomain); - } else { - return matchIpAddress(certificate, thisDomain); - } - } - - /** - * @return True iff the domain name is specified as an IP address - */ - private static boolean isIpAddress(String domain) { - boolean rval = (domain != null && domain.length() != 0); - if (rval) { - try { - // do a quick-dirty IP match first to avoid DNS lookup - rval = QUICK_IP_PATTERN.matcher(domain).matches(); - if (rval) { - rval = domain.equals( - InetAddress.getByName(domain).getHostAddress()); - } - } catch (UnknownHostException e) { - String errorMessage = e.getMessage(); - if (errorMessage == null) { - errorMessage = "unknown host exception"; - } - - if (HttpLog.LOGV) { - HttpLog.v("DomainNameChecker.isIpAddress(): " + errorMessage); - } - - rval = false; - } - } - - return rval; - } - - /** - * Checks the site certificate against the IP domain name of the site being visited - * @param certificate The certificate to check - * @param thisDomain The DNS domain name of the site being visited - * @return True iff if there is a domain match as specified by RFC2818 - */ - private static boolean matchIpAddress(X509Certificate certificate, String thisDomain) { - if (HttpLog.LOGV) { - HttpLog.v("DomainNameChecker.matchIpAddress(): this domain: " + thisDomain); - } - - try { - Collection subjectAltNames = certificate.getSubjectAlternativeNames(); - if (subjectAltNames != null) { - Iterator i = subjectAltNames.iterator(); - while (i.hasNext()) { - List altNameEntry = (List)(i.next()); - if (altNameEntry != null && 2 <= altNameEntry.size()) { - Integer altNameType = (Integer)(altNameEntry.get(0)); - if (altNameType != null) { - if (altNameType.intValue() == ALT_IPA_NAME) { - String altName = (String)(altNameEntry.get(1)); - if (altName != null) { - if (HttpLog.LOGV) { - HttpLog.v("alternative IP: " + altName); - } - if (thisDomain.equalsIgnoreCase(altName)) { - return true; - } - } - } - } - } - } - } - } catch (CertificateParsingException e) {} - - return false; - } - - /** - * Checks the site certificate against the DNS domain name of the site being visited - * @param certificate The certificate to check - * @param thisDomain The DNS domain name of the site being visited - * @return True iff if there is a domain match as specified by RFC2818 - */ - private static boolean matchDns(X509Certificate certificate, String thisDomain) { - boolean hasDns = false; - try { - Collection subjectAltNames = certificate.getSubjectAlternativeNames(); - if (subjectAltNames != null) { - Iterator i = subjectAltNames.iterator(); - while (i.hasNext()) { - List altNameEntry = (List)(i.next()); - if (altNameEntry != null && 2 <= altNameEntry.size()) { - Integer altNameType = (Integer)(altNameEntry.get(0)); - if (altNameType != null) { - if (altNameType.intValue() == ALT_DNS_NAME) { - hasDns = true; - String altName = (String)(altNameEntry.get(1)); - if (altName != null) { - if (matchDns(thisDomain, altName)) { - return true; - } - } - } - } - } - } - } - } catch (CertificateParsingException e) { - // one way we can get here is if an alternative name starts with - // '*' character, which is contrary to one interpretation of the - // spec (a valid DNS name must start with a letter); there is no - // good way around this, and in order to be compatible we proceed - // to check the common name (ie, ignore alternative names) - if (HttpLog.LOGV) { - String errorMessage = e.getMessage(); - if (errorMessage == null) { - errorMessage = "failed to parse certificate"; - } - - if (HttpLog.LOGV) { - HttpLog.v("DomainNameChecker.matchDns(): " + errorMessage); - } - } - } - - if (!hasDns) { - X509Name xName = new X509Name(certificate.getSubjectDN().getName()); - Vector val = xName.getValues(); - Vector oid = xName.getOIDs(); - for (int i = 0; i < oid.size(); i++) { - if (oid.elementAt(i).equals(X509Name.CN)) { - return matchDns(thisDomain, (String)(val.elementAt(i))); - } - } - } - - return false; - } - - /** - * @param thisDomain The domain name of the site being visited - * @param thatDomain The domain name from the certificate - * @return True iff thisDomain matches thatDomain as specified by RFC2818 - */ - private static boolean matchDns(String thisDomain, String thatDomain) { - if (HttpLog.LOGV) { - HttpLog.v("DomainNameChecker.matchDns():" + - " this domain: " + thisDomain + - " that domain: " + thatDomain); - } - - if (thisDomain == null || thisDomain.length() == 0 || - thatDomain == null || thatDomain.length() == 0) { - return false; - } - - thatDomain = thatDomain.toLowerCase(); - - // (a) domain name strings are equal, ignoring case: X matches X - boolean rval = thisDomain.equals(thatDomain); - if (!rval) { - String[] thisDomainTokens = thisDomain.split("\\."); - String[] thatDomainTokens = thatDomain.split("\\."); - - int thisDomainTokensNum = thisDomainTokens.length; - int thatDomainTokensNum = thatDomainTokens.length; - - // (b) OR thatHost is a '.'-suffix of thisHost: Z.Y.X matches X - if (thisDomainTokensNum >= thatDomainTokensNum) { - for (int i = thatDomainTokensNum - 1; i >= 0; --i) { - rval = thisDomainTokens[i].equals(thatDomainTokens[i]); - if (!rval) { - // (c) OR we have a special *-match: - // *.Y.X matches Z.Y.X but *.X doesn't match Z.Y.X - rval = (i == 0 && thisDomainTokensNum == thatDomainTokensNum); - if (rval) { - rval = thatDomainTokens[0].equals("*"); - if (!rval) { - // (d) OR we have a *-component match: - // f*.com matches foo.com but not bar.com - rval = domainTokenMatch( - thisDomainTokens[0], thatDomainTokens[0]); - } - } - break; - } - } - } else { - // (e) OR thatHost has a '*.'-prefix of thisHost: - // *.Y.X matches Y.X - rval = thatDomain.equals("*." + thisDomain); - } - } - - return rval; - } - - /** - * @param thisDomainToken The domain token from the current domain name - * @param thatDomainToken The domain token from the certificate - * @return True iff thisDomainToken matches thatDomainToken, using the - * wildcard match as specified by RFC2818-3.1. For example, f*.com must - * match foo.com but not bar.com - */ - private static boolean domainTokenMatch(String thisDomainToken, String thatDomainToken) { - if (thisDomainToken != null && thatDomainToken != null) { - int starIndex = thatDomainToken.indexOf('*'); - if (starIndex >= 0) { - if (thatDomainToken.length() - 1 <= thisDomainToken.length()) { - String prefix = thatDomainToken.substring(0, starIndex); - String suffix = thatDomainToken.substring(starIndex + 1); - - return thisDomainToken.startsWith(prefix) && thisDomainToken.endsWith(suffix); - } - } - } - - return false; - } -} diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java index 5f6c9d6..fcd8f38 100644 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -21,7 +21,7 @@ package android.os; */ public class Build { /** Value used for when a build property is unknown. */ - private static final String UNKNOWN = "unknown"; + public static final String UNKNOWN = "unknown"; /** Either a changelist number, or a label like "M4-rc20". */ public static final String ID = getString("ro.build.id"); @@ -53,6 +53,15 @@ public class Build { /** The end-user-visible name for the end product. */ public static final String MODEL = getString("ro.product.model"); + /** @pending The system bootloader version number. */ + public static final String BOOTLOADER = getString("ro.bootloader"); + + /** @pending The radio firmware version number. */ + public static final String RADIO = getString("gsm.version.baseband"); + + /** @pending The device serial number. */ + public static final String SERIAL = getString("ro.serialno"); + /** Various version strings. */ public static class VERSION { /** diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java index eed2af7..9491bd4 100644 --- a/core/java/android/os/Environment.java +++ b/core/java/android/os/Environment.java @@ -181,7 +181,7 @@ public class Environment { .getService("mount")); } return mMntSvc.getVolumeState(getExternalStorageDirectory().toString()); - } catch (android.os.RemoteException rex) { + } catch (Exception rex) { return Environment.MEDIA_REMOVED; } } diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java index 51dfb5b..4780cf3 100644 --- a/core/java/android/os/FileUtils.java +++ b/core/java/android/os/FileUtils.java @@ -153,14 +153,16 @@ public class FileUtils public static String readTextFile(File file, int max, String ellipsis) throws IOException { InputStream input = new FileInputStream(file); try { - if (max > 0) { // "head" mode: read the first N bytes + long size = file.length(); + if (max > 0 || (size > 0 && max == 0)) { // "head" mode: read the first N bytes + if (size > 0 && (max == 0 || size < max)) max = (int) size; byte[] data = new byte[max + 1]; int length = input.read(data); if (length <= 0) return ""; if (length <= max) return new String(data, 0, length); if (ellipsis == null) return new String(data, 0, max); return new String(data, 0, max) + ellipsis; - } else if (max < 0) { // "tail" mode: read it all, keep the last N + } else if (max < 0) { // "tail" mode: keep the last N int len; boolean rolled = false; byte[] last = null, data = null; @@ -180,7 +182,7 @@ public class FileUtils } if (ellipsis == null || !rolled) return new String(last); return ellipsis + new String(last); - } else { // "cat" mode: read it all + } else { // "cat" mode: size unknown, read it all in streaming fashion ByteArrayOutputStream contents = new ByteArrayOutputStream(); int len; byte[] data = new byte[1024]; diff --git a/core/java/android/os/IMountService.aidl b/core/java/android/os/IMountService.aidl index 2f60c34..e73569a 100644 --- a/core/java/android/os/IMountService.aidl +++ b/core/java/android/os/IMountService.aidl @@ -42,17 +42,17 @@ interface IMountService /** * Mount external storage at given mount point. */ - void mountMedia(String mountPoint); + void mountVolume(String mountPoint); /** * Safely unmount external storage at given mount point. */ - void unmountMedia(String mountPoint); + void unmountVolume(String mountPoint); /** * Format external storage given a mount point. */ - void formatMedia(String mountPoint); + void formatVolume(String mountPoint); /** * Returns true if media notification sounds are enabled. @@ -65,60 +65,46 @@ interface IMountService void setPlayNotificationSounds(boolean value); /** - * Returns true if USB Mass Storage is automatically started - * when a UMS host is detected. - */ - boolean getAutoStartUms(); - - /** - * Sets whether or not USB Mass Storage is automatically started - * when a UMS host is detected. - */ - void setAutoStartUms(boolean value); - - /** * Gets the state of an volume via it's mountpoint. */ String getVolumeState(String mountPoint); /* - * Creates a secure cache with the specified parameters. - * On success, the filesystem cache-path is returned. + * Creates a secure container with the specified parameters. + * On success, the filesystem container-path is returned. */ - String createSecureCache(String id, int sizeMb, String fstype, String key, int ownerUid); + String createSecureContainer(String id, int sizeMb, String fstype, String key, int ownerUid); /* - * Finalize a cache which has just been created and populated. - * After finalization, the cache is immutable. + * Finalize a container which has just been created and populated. + * After finalization, the container is immutable. */ - void finalizeSecureCache(String id); + void finalizeSecureContainer(String id); /* - * Destroy a secure cache, and free up all resources associated with it. + * Destroy a secure container, and free up all resources associated with it. * NOTE: Ensure all references are released prior to deleting. */ - void destroySecureCache(String id); + void destroySecureContainer(String id); /* - * Mount a secure cache with the specified key and owner UID. - * On success, the filesystem cache-path is returned. + * Mount a secure container with the specified key and owner UID. + * On success, the filesystem container-path is returned. */ - String mountSecureCache(String id, String key, int ownerUid); + String mountSecureContainer(String id, String key, int ownerUid); /* - * Returns the filesystem path of a mounted secure cache. + * Returns the filesystem path of a mounted secure container. */ - String getSecureCachePath(String id); + String getSecureContainerPath(String id); /** - * Gets an Array of currently known secure cache IDs + * Gets an Array of currently known secure container IDs */ - String[] getSecureCacheList(); + String[] getSecureContainerList(); /** - * Shuts down the MountService and gracefully unmounts - * all external media. + * Shuts down the MountService and gracefully unmounts all external media. */ void shutdown(); - } diff --git a/core/java/android/os/Power.java b/core/java/android/os/Power.java index 3679e47..bc76180 100644 --- a/core/java/android/os/Power.java +++ b/core/java/android/os/Power.java @@ -17,6 +17,8 @@ package android.os; import java.io.IOException; +import android.os.ServiceManager; +import android.os.IMountService; /** * Class that provides access to some of the power management functions. @@ -97,5 +99,19 @@ public class Power * @throws IOException if reboot fails for some reason (eg, lack of * permission) */ - public static native void reboot(String reason) throws IOException; + public static void reboot(String reason) throws IOException + { + IMountService mSvc = IMountService.Stub.asInterface( + ServiceManager.getService("mount")); + + if (mSvc != null) { + try { + mSvc.shutdown(); + } catch (Exception e) { + } + } + rebootNative(reason); + } + + private static native void rebootNative(String reason) throws IOException ; } diff --git a/core/java/android/preference/EditTextPreference.java b/core/java/android/preference/EditTextPreference.java index 84ee950..aa27627 100644 --- a/core/java/android/preference/EditTextPreference.java +++ b/core/java/android/preference/EditTextPreference.java @@ -28,7 +28,6 @@ import android.view.View; import android.view.ViewGroup; import android.view.ViewParent; import android.widget.EditText; -import android.widget.LinearLayout; /** * A {@link Preference} that allows for string @@ -128,7 +127,7 @@ public class EditTextPreference extends DialogPreference { ViewGroup container = (ViewGroup) dialogView .findViewById(com.android.internal.R.id.edittext_container); if (container != null) { - container.addView(editText, ViewGroup.LayoutParams.FILL_PARENT, + container.addView(editText, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); } } diff --git a/core/java/android/provider/Calendar.java b/core/java/android/provider/Calendar.java index d210ed4..509aac5 100644 --- a/core/java/android/provider/Calendar.java +++ b/core/java/android/provider/Calendar.java @@ -583,14 +583,14 @@ public final class Calendar { * {@link #ACCOUNT_TYPE} identifies a specific account. * <P>Type: TEXT</P> */ - public static final String ACCOUNT_NAME = "account_name"; + public static final String ACCOUNT_NAME = "_sync_account"; /** * The type of account to which this row belongs, which when paired with * {@link #ACCOUNT_NAME} identifies a specific account. * <P>Type: TEXT</P> */ - public static final String ACCOUNT_TYPE = "account_type"; + public static final String ACCOUNT_TYPE = "_sync_account_type"; public static EntityIterator newEntityIterator(Cursor cursor, ContentResolver resolver) { return new EntityIteratorImpl(cursor, resolver); @@ -1049,18 +1049,6 @@ public final class Calendar { public static final String MAX_INSTANCE = "maxInstance"; /** - * The minimum Julian day in the BusyBits table. - * <P>Type: INTEGER</P> - */ - public static final String MIN_BUSYBITS = "minBusyBits"; - - /** - * The maximum Julian day in the BusyBits table. - * <P>Type: INTEGER</P> - */ - public static final String MAX_BUSYBITS = "maxBusyBits"; - - /** * The minimum Julian day in the EventDays table. * <P>Type: INTEGER</P> */ @@ -1075,68 +1063,6 @@ public final class Calendar { public static final class CalendarMetaData implements CalendarMetaDataColumns { } - /*busybits*/ - public interface BusyBitsColumns { - /** - * The Julian day number. - * <P>Type: INTEGER (int)</P> - */ - public static final String DAY = "day"; - - /** - * The 24 bits representing the 24 1-hour time slots in a day. - * If an event in the Instances table overlaps part of a 1-hour - * time slot then the corresponding bit is set. The first time slot - * (12am to 1am) is bit 0. The last time slot (11pm to midnight) - * is bit 23. - * <P>Type: INTEGER (int)</P> - */ - public static final String BUSYBITS = "busyBits"; - - /** - * The number of all-day events that occur on this day. - * <P>Type: INTEGER (int)</P> - */ - public static final String ALL_DAY_COUNT = "allDayCount"; - } - - /*busybits*/ - public static final class BusyBits implements BusyBitsColumns { - public static final Uri CONTENT_URI = Uri.parse("content://calendar/busybits/when"); - - public static final String[] PROJECTION = { DAY, BUSYBITS, ALL_DAY_COUNT }; - - // The number of minutes represented by one busy bit - public static final int MINUTES_PER_BUSY_INTERVAL = 60; - - // The number of intervals in a day - public static final int INTERVALS_PER_DAY = 24 * 60 / MINUTES_PER_BUSY_INTERVAL; - - /** - * Retrieves the busy bits for the Julian days starting at "startDay" - * for "numDays". - * This is being phased out so has been changed to an empty method so - * that it doesn't reference anything that needs to be cleaned up else- - * where. - * - * @param cr the ContentResolver - * @param startDay the first Julian day in the range - * @param numDays the number of days to load (must be at least 1) - * @return a database cursor - */ - public static final Cursor query(ContentResolver cr, int startDay, int numDays) { -// if (numDays < 1) { -// return null; -// } -// int endDay = startDay + numDays - 1; -// Uri.Builder builder = CONTENT_URI.buildUpon(); -// ContentUris.appendId(builder, startDay); -// ContentUris.appendId(builder, endDay); -// return cr.query(builder.build(), PROJECTION, null /* selection */, -// null /* selection args */, DAY); - return null; - } - } public interface EventDaysColumns { /** diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java index 69874c6..7fb9daf 100644 --- a/core/java/android/provider/ContactsContract.java +++ b/core/java/android/provider/ContactsContract.java @@ -23,10 +23,10 @@ import android.content.ContentResolver; import android.content.ContentUris; import android.content.ContentValues; import android.content.Context; -import android.content.Intent; import android.content.CursorEntityIterator; -import android.content.EntityIterator; import android.content.Entity; +import android.content.EntityIterator; +import android.content.Intent; import android.content.res.Resources; import android.database.Cursor; import android.database.DatabaseUtils; @@ -62,7 +62,8 @@ import java.io.InputStream; * </li> * <li> * A row in the {@link RawContacts} table represents a set of Data describing a - * person and associated with a single account. + * person and associated with a single account (for example, a single Gmail + * account). * </li> * <li> * A row in the {@link Contacts} table represents an aggregate of one or more @@ -245,6 +246,9 @@ public final class ContactsContract { } /** + * Columns of {@link ContactsContract.Contacts} that track the user's + * preferences for, or interactions with, the contact. + * * @see Contacts * @see RawContacts * @see ContactsContract.Data @@ -271,20 +275,25 @@ public final class ContactsContract { public static final String STARRED = "starred"; /** - * A custom ringtone associated with a contact. Not always present. + * URI for a custom ringtone associated with the contact. If null or missing, + * the default ringtone is used. * <P>Type: TEXT (URI to the ringtone)</P> */ public static final String CUSTOM_RINGTONE = "custom_ringtone"; /** - * Whether the contact should always be sent to voicemail. Not always - * present. + * Whether the contact should always be sent to voicemail. If missing, + * defaults to false. * <P>Type: INTEGER (0 for false, 1 for true)</P> */ public static final String SEND_TO_VOICEMAIL = "send_to_voicemail"; } /** + * Columns of {@link ContactsContract.Contacts} that refer to intrinsic + * properties of the contact, as opposed to the user-specified options + * found in {@link ContactOptionsColumns}. + * * @see Contacts * @see ContactsContract.Data * @see PhoneLookup @@ -441,6 +450,8 @@ public final class ContactsContract { } /** + * Contact name and contact name metadata columns in the RawContacts table. + * * @see Contacts * @see RawContacts * @hide @@ -1616,14 +1627,34 @@ public final class ContactsContract { @Deprecated public static final String PRESENCE_STATUS = PRESENCE; - /* - * Presence Status definition + /** + * An allowed value of {@link #PRESENCE}. */ int OFFLINE = 0; + + /** + * An allowed value of {@link #PRESENCE}. + */ int INVISIBLE = 1; + + /** + * An allowed value of {@link #PRESENCE}. + */ int AWAY = 2; + + /** + * An allowed value of {@link #PRESENCE}. + */ int IDLE = 3; + + /** + * An allowed value of {@link #PRESENCE}. + */ int DO_NOT_DISTURB = 4; + + /** + * An allowed value of {@link #PRESENCE}. + */ int AVAILABLE = 5; /** @@ -1635,6 +1666,7 @@ public final class ContactsContract { /** * @deprecated use {@link #STATUS} */ + @Deprecated public static final String PRESENCE_CUSTOM_STATUS = STATUS; /** @@ -1691,7 +1723,7 @@ public final class ContactsContract { public static final String RAW_CONTACT_ID = "raw_contact_id"; /** - * Whether this is the primary entry of its kind for the raw contact it belongs to + * Whether this is the primary entry of its kind for the raw contact it belongs to. * <P>Type: INTEGER (if set, non-0 means true)</P> */ public static final String IS_PRIMARY = "is_primary"; @@ -1740,7 +1772,10 @@ public final class ContactsContract { public static final String DATA13 = "data13"; /** Generic data column, the meaning is {@link #MIMETYPE} specific */ public static final String DATA14 = "data14"; - /** Generic data column, the meaning is {@link #MIMETYPE} specific */ + /** + * Generic data column, the meaning is {@link #MIMETYPE} specific. By convention, + * this field is used to store BLOBs (binary data). + */ public static final String DATA15 = "data15"; /** Generic column for use by sync adapters. */ @@ -1766,23 +1801,28 @@ public final class ContactsContract { /** * <p> * Constants for the data table, which contains data points tied to a raw - * contact. For example, a phone number or email address. + * contact. Each row of the data table is typically used to store a single + * piece of contact + * information (such as a phone number) and its + * associated metadata (such as whether it is a work or home number). * </p> * <h3>Data kinds</h3> * <p> - * Data is a generic table that can hold all kinds of data. Sync adapters - * and applications can introduce their own data kinds. The kind of data - * stored in a particular row is determined by the mime type in the row. - * Fields from {@link #DATA1} through {@link #DATA15} are generic columns - * whose specific use is determined by the kind of data stored in the row. + * Data is a generic table that can hold any kind of contact data. + * The kind of data stored in a given row is specified by the row's + * {@link #MIMETYPE} value, which determines the meaning of the + * generic columns {@link #DATA1} through + * {@link #DATA15}. * For example, if the data kind is - * {@link CommonDataKinds.Phone Phone.CONTENT_ITEM_TYPE}, then DATA1 stores the + * {@link CommonDataKinds.Phone Phone.CONTENT_ITEM_TYPE}, then the column + * {@link #DATA1} stores the * phone number, but if the data kind is - * {@link CommonDataKinds.Email Email.CONTENT_ITEM_TYPE}, then DATA1 stores the - * email address. + * {@link CommonDataKinds.Email Email.CONTENT_ITEM_TYPE}, then {@link #DATA1} + * stores the email address. + * Sync adapters and applications can introduce their own data kinds. * </p> * <p> - * ContactsContract defines a small number of common data kinds, e.g. + * ContactsContract defines a small number of pre-defined data kinds, e.g. * {@link CommonDataKinds.Phone}, {@link CommonDataKinds.Email} etc. As a * convenience, these classes define data kind specific aliases for DATA1 etc. * For example, {@link CommonDataKinds.Phone Phone.NUMBER} is the same as @@ -1799,8 +1839,8 @@ public final class ContactsContract { * By convention, {@link #DATA15} is used for storing BLOBs (binary data). * </p> * <p> - * Typically you should refrain from introducing new kinds of data for 3rd - * party account types. For example, if you add a data row for + * Typically you should refrain from introducing new kinds of data for an other + * party's account types. For example, if you add a data row for * "favorite song" to a raw contact owned by a Google account, it will not * get synced to the server, because the Google sync adapter does not know * how to handle this data kind. Thus new data kinds are typically @@ -1937,6 +1977,10 @@ public final class ContactsContract { * </dd> * </dl> * <h2>Columns</h2> + * <p> + * Many columns are available via a {@link Data#CONTENT_URI} query. For best performance you + * should explicitly specify a projection to only those columns that you need. + * </p> * <table class="jd-sumtable"> * <tr> * <th colspan='4'>Data</th> @@ -1946,7 +1990,7 @@ public final class ContactsContract { * <td style="width: 20em;">{@link #_ID}</td> * <td style="width: 5em;">read-only</td> * <td>Row ID. Sync adapter should try to preserve row IDs during updates. In other words, - * it would be a bad idea to delete and reinsert a data rows. A sync adapter should + * it would be a bad idea to delete and reinsert a data row. A sync adapter should * always do an update instead.</td> * </tr> * <tr> @@ -1978,21 +2022,15 @@ public final class ContactsContract { * <td>long</td> * <td>{@link #RAW_CONTACT_ID}</td> * <td>read/write-once</td> - * <td>A reference to the {@link RawContacts#_ID} that this data belongs to.</td> - * </tr> - * <tr> - * <td>long</td> - * <td>{@link #CONTACT_ID}</td> - * <td>read-only</td> - * <td>A reference to the {@link ContactsContract.Contacts#_ID} that this data row belongs - * to. It is obtained through a join with RawContacts.</td> + * <td>The id of the row in the {@link RawContacts} table that this data belongs to.</td> * </tr> * <tr> * <td>int</td> * <td>{@link #IS_PRIMARY}</td> * <td>read/write</td> * <td>Whether this is the primary entry of its kind for the raw contact it belongs to. - * "1" if true, "0" if false.</td> + * "1" if true, "0" if false. + * </td> * </tr> * <tr> * <td>int</td> @@ -2000,7 +2038,9 @@ public final class ContactsContract { * <td>read/write</td> * <td>Whether this is the primary entry of its kind for the aggregate * contact it belongs to. Any data record that is "super primary" must - * also be "primary".</td> + * also be "primary". For example, the super-primary entry may be + * interpreted as the default contact value of its kind (for example, + * the default phone number to use for the contact).</td> * </tr> * <tr> * <td>int</td> @@ -2029,7 +2069,19 @@ public final class ContactsContract { * {@link #DATA15} * </td> * <td>read/write</td> - * <td>Generic data columns, the meaning is {@link #MIMETYPE} specific.</td> + * <td> + * <p> + * Generic data columns. The meaning of each column is determined by the + * {@link #MIMETYPE}. By convention, {@link #DATA15} is used for storing + * BLOBs (binary data). + * </p> + * <p> + * Data columns whose meaning is not explicitly defined for a given MIMETYPE + * should not be used. There is no guarantee that any sync adapter will + * preserve them. Sync adapters themselves should not use such columns either, + * but should instead use {@link #SYNC1}-{@link #SYNC4}. + * </p> + * </td> * </tr> * <tr> * <td>Any type</td> @@ -2046,6 +2098,10 @@ public final class ContactsContract { * </tr> * </table> * + * <p> + * Some columns from the most recent associated status update are also available + * through an implicit join. + * </p> * <table class="jd-sumtable"> * <tr> * <th colspan='4'>Join with {@link StatusUpdates}</th> @@ -2098,18 +2154,26 @@ public final class ContactsContract { * </table> * * <p> - * Columns from the associated raw contact are also available through an - * implicit join. + * Some columns from the associated raw contact are also available through an + * implicit join. The other columns are excluded as uninteresting in this + * context. * </p> * * <table class="jd-sumtable"> * <tr> - * <th colspan='4'>Join with {@link RawContacts}</th> + * <th colspan='4'>Join with {@link ContactsContract.RawContacts}</th> * </tr> * <tr> - * <td style="width: 7em;">int</td> - * <td style="width: 20em;">{@link #AGGREGATION_MODE}</td> + * <td style="width: 7em;">long</td> + * <td style="width: 20em;">{@link #CONTACT_ID}</td> * <td style="width: 5em;">read-only</td> + * <td>The id of the row in the {@link Contacts} table that this data belongs + * to.</td> + * </tr> + * <tr> + * <td>int</td> + * <td>{@link #AGGREGATION_MODE}</td> + * <td>read-only</td> * <td>See {@link RawContacts}.</td> * </tr> * <tr> @@ -2121,13 +2185,18 @@ public final class ContactsContract { * </table> * * <p> - * Columns from the associated aggregated contact are also available through an - * implicit join. + * The ID column for the associated aggregated contact table + * {@link ContactsContract.Contacts} is available + * via the implicit join to the {@link RawContacts} table, see above. + * The remaining columns from this table are also + * available, through an implicit join. This + * facilitates lookup by + * the value of a single data element, such as the email address. * </p> * * <table class="jd-sumtable"> * <tr> - * <th colspan='4'>Join with {@link Contacts}</th> + * <th colspan='4'>Join with {@link ContactsContract.Contacts}</th> * </tr> * <tr> * <td style="width: 7em;">String</td> @@ -2234,24 +2303,30 @@ public final class ContactsContract { private Data() {} /** - * The content:// style URI for this table + * The content:// style URI for this table, which requests a directory + * of data rows matching the selection criteria. */ public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "data"); /** - * The MIME type of {@link #CONTENT_URI} providing a directory of data. + * The MIME type of the results from {@link #CONTENT_URI}. */ public static final String CONTENT_TYPE = "vnd.android.cursor.dir/data"; /** + * <p> * If {@link #FOR_EXPORT_ONLY} is explicitly set to "1", returned Cursor toward * Data.CONTENT_URI contains only exportable data. - * + * </p> + * <p> * This flag is useful (currently) only for vCard exporter in Contacts app, which * needs to exclude "un-exportable" data from available data to export, while * Contacts app itself has priviledge to access all data including "un-exportable" * ones and providers return all of them regardless of the callers' intention. - * <P>Type: INTEGER</p> + * </p> + * <p> + * Type: INTEGER + * </p> * * @hide Maybe available only in Eclair and not really ready for public use. * TODO: remove, or implement this feature completely. As of now (Eclair), @@ -2260,9 +2335,17 @@ public final class ContactsContract { public static final String FOR_EXPORT_ONLY = "for_export_only"; /** + * <p> * Build a {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI} * style {@link Uri} for the parent {@link android.provider.ContactsContract.Contacts} * entry of the given {@link ContactsContract.Data} entry. + * </p> + * <p> + * Returns the Uri for the contact in the first entry returned by + * {@link ContentResolver#query(Uri, String[], String, String[], String)} + * for the provided {@code dataUri}. If the query returns null or empty + * results, silently returns null. + * </p> */ public static Uri getContactLookupUri(ContentResolver resolver, Uri dataUri) { final Cursor cursor = resolver.query(dataUri, new String[] { @@ -2285,7 +2368,7 @@ public final class ContactsContract { /** * <p> - * Constants for the raw contacts entities table, which can be though of as + * Constants for the raw contacts entities table, which can be thought of as * an outer join of the raw_contacts table with the data table. It is a strictly * read-only table. * </p> diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java index 6d1fef6..1b938ee 100644 --- a/core/java/android/provider/MediaStore.java +++ b/core/java/android/provider/MediaStore.java @@ -96,14 +96,12 @@ public final class MediaStore { /** * The name of an Intent-extra used to control the UI of a ViewImage. * This is a boolean property that overrides the activity's default fullscreen state. - * @hide */ public static final String EXTRA_FULL_SCREEN = "android.intent.extra.fullScreen"; /** * The name of an Intent-extra used to control the UI of a ViewImage. * This is a boolean property that specifies whether or not to show action icons. - * @hide */ public static final String EXTRA_SHOW_ACTION_ICONS = "android.intent.extra.showActionIcons"; @@ -162,13 +160,11 @@ public final class MediaStore { /** * Specify the maximum allowed size. - * @hide */ public final static String EXTRA_SIZE_LIMIT = "android.intent.extra.sizeLimit"; /** * Specify the maximum allowed recording duration in seconds. - * @hide */ public final static String EXTRA_DURATION_LIMIT = "android.intent.extra.durationLimit"; diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 4c6db42..7db9fdc 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -2814,1002 +2814,207 @@ public final class Settings { "sync_min_gzip_bytes"; /** - * @hide - */ - public static final String[] SETTINGS_TO_BACKUP = { - ADB_ENABLED, - ALLOW_MOCK_LOCATION, - PARENTAL_CONTROL_ENABLED, - PARENTAL_CONTROL_REDIRECT_URL, - USB_MASS_STORAGE_ENABLED, - ACCESSIBILITY_ENABLED, - ENABLED_ACCESSIBILITY_SERVICES, - TTS_USE_DEFAULTS, - TTS_DEFAULT_RATE, - TTS_DEFAULT_PITCH, - TTS_DEFAULT_SYNTH, - TTS_DEFAULT_LANG, - TTS_DEFAULT_COUNTRY, - WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, - WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY, - WIFI_NUM_ALLOWED_CHANNELS, - WIFI_NUM_OPEN_NETWORKS_KEPT, - }; - - /** - * Helper method for determining if a location provider is enabled. - * @param cr the content resolver to use - * @param provider the location provider to query - * @return true if the provider is enabled - * - * @hide - */ - public static final boolean isLocationProviderEnabled(ContentResolver cr, String provider) { - String allowedProviders = Settings.Secure.getString(cr, LOCATION_PROVIDERS_ALLOWED); - if (allowedProviders != null) { - return (allowedProviders.equals(provider) || - allowedProviders.contains("," + provider + ",") || - allowedProviders.startsWith(provider + ",") || - allowedProviders.endsWith("," + provider)); - } - return false; - } - - /** - * Thread-safe method for enabling or disabling a single location provider. - * @param cr the content resolver to use - * @param provider the location provider to enable or disable - * @param enabled true if the provider should be enabled - * - * @hide - */ - public static final void setLocationProviderEnabled(ContentResolver cr, - String provider, boolean enabled) { - // to ensure thread safety, we write the provider name with a '+' or '-' - // and let the SettingsProvider handle it rather than reading and modifying - // the list of enabled providers. - if (enabled) { - provider = "+" + provider; - } else { - provider = "-" + provider; - } - putString(cr, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, provider); - } - } - - /** - * Gservices settings, containing the network names for Google's - * various services. This table holds simple name/addr pairs. - * Addresses can be accessed through the getString() method. - * - * TODO: This should move to partner/google/... somewhere. - * - * @hide - */ - public static final class Gservices extends NameValueTable { - public static final String SYS_PROP_SETTING_VERSION = "sys.settings_gservices_version"; - - /** - * Intent action broadcast when the Gservices table is updated by the server. - * This is broadcast once after settings change (so many values may have been updated). - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String CHANGED_ACTION = - "com.google.gservices.intent.action.GSERVICES_CHANGED"; - - /** - * Intent action to override Gservices for testing. (Requires WRITE_GSERVICES permission.) - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String OVERRIDE_ACTION = - "com.google.gservices.intent.action.GSERVICES_OVERRIDE"; - - /** - * Intent action to set Gservices with new values. (Requires WRITE_GSERVICES permission.) - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String UPDATE_ACTION = - "com.google.gservices.intent.action.GSERVICES_UPDATE"; - - private static volatile NameValueCache mNameValueCache = null; - private static final Object mNameValueCacheLock = new Object(); - - /** - * Look up a name in the database. - * @param resolver to access the database with - * @param name to look up in the table - * @return the corresponding value, or null if not present - */ - public static String getString(ContentResolver resolver, String name) { - synchronized (mNameValueCacheLock) { - if (mNameValueCache == null) { - mNameValueCache = new NameValueCache(SYS_PROP_SETTING_VERSION, CONTENT_URI); - } - return mNameValueCache.getString(resolver, name); - } - } - - /** - * Store a name/value pair into the database. - * @param resolver to access the database with - * @param name to store - * @param value to associate with the name - * @return true if the value was set, false on database errors - */ - public static boolean putString(ContentResolver resolver, - String name, String value) { - return putString(resolver, CONTENT_URI, name, value); - } - - /** - * Look up the value for name in the database, convert it to an int using Integer.parseInt - * and return it. If it is null or if a NumberFormatException is caught during the - * conversion then return defValue. - */ - public static int getInt(ContentResolver resolver, String name, int defValue) { - String valString = getString(resolver, name); - int value; - try { - value = valString != null ? Integer.parseInt(valString) : defValue; - } catch (NumberFormatException e) { - value = defValue; - } - return value; - } - - /** - * Look up the value for name in the database, convert it to a long using Long.parseLong - * and return it. If it is null or if a NumberFormatException is caught during the - * conversion then return defValue. - */ - public static long getLong(ContentResolver resolver, String name, long defValue) { - String valString = getString(resolver, name); - long value; - try { - value = valString != null ? Long.parseLong(valString) : defValue; - } catch (NumberFormatException e) { - value = defValue; - } - return value; - } - - /** - * Construct the content URI for a particular name/value pair, - * useful for monitoring changes with a ContentObserver. - * @param name to look up in the table - * @return the corresponding content URI, or null if not present - */ - public static Uri getUriFor(String name) { - return getUriFor(CONTENT_URI, name); - } - - /** - * The content:// style URL for this table - */ - public static final Uri CONTENT_URI = - Uri.parse("content://" + AUTHORITY + "/gservices"); - - /** - * MMS - URL to use for HTTP "x-wap-profile" header - */ - public static final String MMS_X_WAP_PROFILE_URL - = "mms_x_wap_profile_url"; - - /** - * YouTube - the flag to indicate whether to use proxy - */ - public static final String YOUTUBE_USE_PROXY - = "youtube_use_proxy"; - - /** - * MMS - maximum message size in bytes for a MMS message. - */ - public static final String MMS_MAXIMUM_MESSAGE_SIZE - = "mms_maximum_message_size"; - - /** - * Event tags from the kernel event log to upload during checkin. - */ - public static final String CHECKIN_EVENTS = "checkin_events"; - - /** - * Comma-separated list of service names to dump and upload during checkin. - */ - public static final String CHECKIN_DUMPSYS_LIST = "checkin_dumpsys_list"; - - /** - * Comma-separated list of packages to specify for each service that is - * dumped (currently only meaningful for user activity). - */ - public static final String CHECKIN_PACKAGE_LIST = "checkin_package_list"; - - /** - * The interval (in seconds) between periodic checkin attempts. - */ - public static final String CHECKIN_INTERVAL = "checkin_interval"; - - /** - * The interval (in seconds) between event log aggregation runs. - */ - public static final String AGGREGATION_INTERVAL_SECONDS = "aggregation_interval_seconds"; - - /** - * Boolean indicating if the market app should force market only checkins on - * install/uninstall. Any non-0 value is considered true. - */ - public static final String MARKET_FORCE_CHECKIN = "market_force_checkin"; - - /** - * The minimum version of the server that is required in order for the device to accept - * the server's recommendations about the initial sync settings to use. When this is unset, - * blank or can't be interpreted as an integer then we will not ask the server for a - * recommendation. - */ - public static final String GMAIL_CONFIG_INFO_MIN_SERVER_VERSION = - "gmail_config_info_min_server_version"; - - /** - * Controls whether Gmail offers a preview button for images. - */ - public static final String GMAIL_DISALLOW_IMAGE_PREVIEWS = "gmail_disallow_image_previews"; - - /** - * The maximal size in bytes allowed for attachments when composing messages in Gmail - */ - public static final String GMAIL_MAX_ATTACHMENT_SIZE = "gmail_max_attachment_size_bytes"; - - /** - * The timeout in milliseconds that Gmail uses when opening a connection and reading - * from it. A missing value or a value of -1 instructs Gmail to use the defaults provided - * by GoogleHttpClient. - */ - public static final String GMAIL_TIMEOUT_MS = "gmail_timeout_ms"; - - /** - * Controls whether Gmail will request an expedited sync when a message is sent. Value must - * be an integer where non-zero means true. Defaults to 1. - */ - public static final String GMAIL_SEND_IMMEDIATELY = "gmail_send_immediately"; - - /** - * Controls whether gmail buffers server responses. Possible values are "memory", for a - * memory-based buffer, or "file", for a temp-file-based buffer. All other values - * (including not set) disable buffering. - */ - public static final String GMAIL_BUFFER_SERVER_RESPONSE = "gmail_buffer_server_response"; - - /** - * The maximum size in bytes allowed for the provider to gzip a protocol buffer uploaded to - * the server. - */ - public static final String GMAIL_MAX_GZIP_SIZE = "gmail_max_gzip_size_bytes"; - - /** - * Controls whether Gmail will discard uphill operations that repeatedly fail. Value must be - * an integer where non-zero means true. Defaults to 1. This flag controls Donut devices. - */ - public static final String GMAIL_DISCARD_ERROR_UPHILL_OP = "gmail_discard_error_uphill_op"; - - /** - * Controls whether Gmail will discard uphill operations that repeatedly fail. Value must be - * an integer where non-zero means true. Defaults to 1. This flag controls Eclair and - * future devices. - */ - public static final String GMAIL_DISCARD_ERROR_UPHILL_OP_NEW = - "gmail_discard_error_uphill_op_new"; - - /** - * Controls how many attempts Gmail will try to upload an uphill operations before it - * abandons the operation. Defaults to 20. - */ - public static final String GMAIL_NUM_RETRY_UPHILL_OP = "gmail_num_retry_uphill_op"; - - /** - * How much time in seconds Gmail will try to upload an uphill operations before it - * abandons the operation. Defaults to 36400 (one day). - */ - public static final String GMAIL_WAIT_TIME_RETRY_UPHILL_OP = - "gmail_wait_time_retry_uphill_op"; - - /** - * Controls if Gmail should delay sending operations that have previously failed. - */ - public static final String GMAIL_DELAY_BAD_OP = "gmail_delay_bad_op"; - - /** - * Controls if the protocol buffer version of the protocol will use a multipart request for - * attachment uploads. Value must be an integer where non-zero means true. Defaults to 0. - */ - public static final String GMAIL_USE_MULTIPART_PROTOBUF = "gmail_use_multipart_protobuf"; - - /** - * the transcoder URL for mobile devices. - */ - public static final String TRANSCODER_URL = "mobile_transcoder_url"; - - /** - * URL that points to the privacy terms of the Google Talk service. - */ - public static final String GTALK_TERMS_OF_SERVICE_URL = "gtalk_terms_of_service_url"; - - /** - * Hostname of the GTalk server. - */ - public static final String GTALK_SERVICE_HOSTNAME = "gtalk_hostname"; - - /** - * Secure port of the GTalk server. - */ - public static final String GTALK_SERVICE_SECURE_PORT = "gtalk_secure_port"; - - /** - * The server configurable RMQ acking interval - */ - public static final String GTALK_SERVICE_RMQ_ACK_INTERVAL = "gtalk_rmq_ack_interval"; - - /** - * The minimum reconnect delay for short network outages or when the network is suspended - * due to phone use. - */ - public static final String GTALK_SERVICE_MIN_RECONNECT_DELAY_SHORT = - "gtalk_min_reconnect_delay_short"; - - /** - * The reconnect variant range for short network outages or when the network is suspended - * due to phone use. A random number between 0 and this constant is computed and - * added to {@link #GTALK_SERVICE_MIN_RECONNECT_DELAY_SHORT} to form the initial reconnect - * delay. - */ - public static final String GTALK_SERVICE_RECONNECT_VARIANT_SHORT = - "gtalk_reconnect_variant_short"; - - /** - * The minimum reconnect delay for long network outages - */ - public static final String GTALK_SERVICE_MIN_RECONNECT_DELAY_LONG = - "gtalk_min_reconnect_delay_long"; - - /** - * The reconnect variant range for long network outages. A random number between 0 and this - * constant is computed and added to {@link #GTALK_SERVICE_MIN_RECONNECT_DELAY_LONG} to - * form the initial reconnect delay. - */ - public static final String GTALK_SERVICE_RECONNECT_VARIANT_LONG = - "gtalk_reconnect_variant_long"; - - /** - * The maximum reconnect delay time, in milliseconds. - */ - public static final String GTALK_SERVICE_MAX_RECONNECT_DELAY = - "gtalk_max_reconnect_delay"; - - /** - * The network downtime that is considered "short" for the above calculations, - * in milliseconds. - */ - public static final String GTALK_SERVICE_SHORT_NETWORK_DOWNTIME = - "gtalk_short_network_downtime"; - - /** - * How frequently we send heartbeat pings to the GTalk server. Receiving a server packet - * will reset the heartbeat timer. The away heartbeat should be used when the user is - * logged into the GTalk app, but not actively using it. - */ - public static final String GTALK_SERVICE_AWAY_HEARTBEAT_INTERVAL_MS = - "gtalk_heartbeat_ping_interval_ms"; // keep the string backward compatible - - /** - * How frequently we send heartbeat pings to the GTalk server. Receiving a server packet - * will reset the heartbeat timer. The active heartbeat should be used when the user is - * actively using the GTalk app. - */ - public static final String GTALK_SERVICE_ACTIVE_HEARTBEAT_INTERVAL_MS = - "gtalk_active_heartbeat_ping_interval_ms"; - - /** - * How frequently we send heartbeat pings to the GTalk server. Receiving a server packet - * will reset the heartbeat timer. The sync heartbeat should be used when the user isn't - * logged into the GTalk app, but auto-sync is enabled. - */ - public static final String GTALK_SERVICE_SYNC_HEARTBEAT_INTERVAL_MS = - "gtalk_sync_heartbeat_ping_interval_ms"; - - /** - * How frequently we send heartbeat pings to the GTalk server. Receiving a server packet - * will reset the heartbeat timer. The no sync heartbeat should be used when the user isn't - * logged into the GTalk app, and auto-sync is not enabled. - */ - public static final String GTALK_SERVICE_NOSYNC_HEARTBEAT_INTERVAL_MS = - "gtalk_nosync_heartbeat_ping_interval_ms"; - - /** - * The maximum heartbeat interval used while on the WIFI network. - */ - public static final String GTALK_SERVICE_WIFI_MAX_HEARTBEAT_INTERVAL_MS = - "gtalk_wifi_max_heartbeat_ping_interval_ms"; - - /** - * How long we wait to receive a heartbeat ping acknowledgement (or another packet) - * from the GTalk server, before deeming the connection dead. - */ - public static final String GTALK_SERVICE_HEARTBEAT_ACK_TIMEOUT_MS = - "gtalk_heartbeat_ack_timeout_ms"; - - /** - * How long after screen is turned off before we consider the user to be idle. - */ - public static final String GTALK_SERVICE_IDLE_TIMEOUT_MS = - "gtalk_idle_timeout_ms"; - - /** - * By default, GTalkService will always connect to the server regardless of the auto-sync - * setting. However, if this parameter is true, then GTalkService will only connect - * if auto-sync is enabled. Using the GTalk app will trigger the connection too. - */ - public static final String GTALK_SERVICE_CONNECT_ON_AUTO_SYNC = - "gtalk_connect_on_auto_sync"; - - /** - * GTalkService holds a wakelock while broadcasting the intent for data message received. - * It then automatically release the wakelock after a timeout. This setting controls what - * the timeout should be. - */ - public static final String GTALK_DATA_MESSAGE_WAKELOCK_MS = - "gtalk_data_message_wakelock_ms"; - - /** - * The socket read timeout used to control how long ssl handshake wait for reads before - * timing out. This is needed so the ssl handshake doesn't hang for a long time in some - * circumstances. - */ - public static final String GTALK_SSL_HANDSHAKE_TIMEOUT_MS = - "gtalk_ssl_handshake_timeout_ms"; - - /** - * Compress the gtalk stream. - */ - public static final String GTALK_COMPRESS = "gtalk_compress"; - - /** - * This is the timeout for which Google Talk will send the message using bareJID. In a - * established chat between two XMPP endpoints, Google Talk uses fullJID in the format - * of user@domain/resource in order to send the message to the specific client. However, - * if Google Talk hasn't received a message from that client after some time, it would - * fall back to use the bareJID, which would broadcast the message to all clients for - * the other user. - */ - public static final String GTALK_USE_BARE_JID_TIMEOUT_MS = "gtalk_use_barejid_timeout_ms"; - - /** - * This is the threshold of retry number when there is an authentication expired failure - * for Google Talk. In some situation, e.g. when a Google Apps account is disabled chat - * service, the connection keeps failing. This threshold controls when we should stop - * the retrying. - */ - public static final String GTALK_MAX_RETRIES_FOR_AUTH_EXPIRED = - "gtalk_max_retries_for_auth_expired"; - - /** - * a boolean setting indicating whether the GTalkService should use RMQ2 protocol or not. - */ - public static final String GTALK_USE_RMQ2_PROTOCOL = - "gtalk_use_rmq2"; - - /** - * a boolean setting indicating whether the GTalkService should support both RMQ and - * RMQ2 protocols. This setting is true for the transitional period when we need to - * support both protocols. - */ - public static final String GTALK_SUPPORT_RMQ_AND_RMQ2_PROTOCOLS = - "gtalk_support_rmq_and_rmq2"; - - /** - * a boolean setting controlling whether the rmq2 protocol will include stream ids in - * the protobufs. This is used for debugging. - */ - public static final String GTALK_RMQ2_INCLUDE_STREAM_ID = - "gtalk_rmq2_include_stream_id"; - - /** - * when receiving a chat message from the server, the message could be an older message - * whose "time sent" is x seconds from now. If x is significant enough, we want to flag - * it so the UI can give it some special treatment when displaying the "time sent" for - * it. This setting is to control what x is. - */ - public static final String GTALK_OLD_CHAT_MESSAGE_THRESHOLD_IN_SEC = - "gtalk_old_chat_msg_threshold_in_sec"; - - /** - * a setting to control the max connection history record GTalkService stores. - */ - public static final String GTALK_MAX_CONNECTION_HISTORY_RECORDS = - "gtalk_max_conn_history_records"; - - /** - * This is gdata url to lookup album and picture info from picasa web. It also controls - * whether url scraping for picasa is enabled (NULL to disable). - */ - public static final String GTALK_PICASA_ALBUM_URL = - "gtalk_picasa_album_url"; - - /** - * This is the url to lookup picture info from flickr. It also controls - * whether url scraping for flickr is enabled (NULL to disable). - */ - public static final String GTALK_FLICKR_PHOTO_INFO_URL = - "gtalk_flickr_photo_info_url"; - - /** - * This is the url to lookup an actual picture from flickr. - */ - public static final String GTALK_FLICKR_PHOTO_URL = - "gtalk_flickr_photo_url"; - - /** - * This is the gdata url to lookup info on a youtube video. It also controls - * whether url scraping for youtube is enabled (NULL to disable). - */ - public static final String GTALK_YOUTUBE_VIDEO_URL = - "gtalk_youtube_video_url"; - - /** - * Enable/disable GTalk URL scraping for JPG images ("true" to enable). - */ - public static final String GTALK_URL_SCRAPING_FOR_JPG = - "gtalk_url_scraping_for_jpg"; - - /** - * Chat message lifetime (for pruning old chat messages). - */ - public static final String GTALK_CHAT_MESSAGE_LIFETIME = - "gtalk_chat_message_lifetime"; - - /** - * OTR message lifetime (for pruning old otr messages). - */ - public static final String GTALK_OTR_MESSAGE_LIFETIME = - "gtalk_otr_message_lifetime"; - - /** - * Chat expiration time, i.e., time since last message in the chat (for pruning old chats). - */ - public static final String GTALK_CHAT_EXPIRATION_TIME = - "gtalk_chat_expiration_time"; - - /** - * This is the url for getting the app token for server-to-device push messaging. - */ - public static final String PUSH_MESSAGING_REGISTRATION_URL = - "push_messaging_registration_url"; - - /** - * Use android://<it> routing infos for Google Sync Server subcriptions. - */ - public static final String GSYNC_USE_RMQ2_ROUTING_INFO = "gsync_use_rmq2_routing_info"; - - /** - * The hash value of the current provisioning settings - */ - public static final String PROVISIONING_DIGEST = "digest"; - - /** - * Provisioning keys to block from server update - */ - public static final String PROVISIONING_OVERRIDE = "override"; - - /** - * "Generic" service name for authentication requests. - */ - public static final String GOOGLE_LOGIN_GENERIC_AUTH_SERVICE - = "google_login_generic_auth_service"; - - /** - * Duration in milliseconds after setup at which market does not reconcile applications - * which are installed during restore. - */ - public static final String VENDING_RESTORE_WINDOW_MS = "vending_restore_window_ms"; - - - /** - * Frequency in milliseconds at which we should sync the locally installed Vending Machine - * content with the server. - */ - public static final String VENDING_SYNC_FREQUENCY_MS = "vending_sync_frequency_ms"; - - /** - * Support URL that is opened in a browser when user clicks on 'Help and Info' in Vending - * Machine. - */ - public static final String VENDING_SUPPORT_URL = "vending_support_url"; - - /** - * Indicates if Vending Machine requires a SIM to be in the phone to allow a purchase. - * - * true = SIM is required - * false = SIM is not required - */ - public static final String VENDING_REQUIRE_SIM_FOR_PURCHASE = - "vending_require_sim_for_purchase"; - - /** - * Indicates the Vending Machine backup state. It is set if the - * Vending application has been backed up at least once. - */ - public static final String VENDING_BACKUP_STATE = "vending_backup_state"; - - /** - * The current version id of the Vending Machine terms of service. - */ - public static final String VENDING_TOS_VERSION = "vending_tos_version"; - - /** - * URL that points to the terms of service for Vending Machine. - */ - public static final String VENDING_TOS_URL = "vending_tos_url"; - - /** - * URL to navigate to in browser (not Market) when the terms of service - * for Vending Machine could not be accessed due to bad network - * connection. - */ - public static final String VENDING_TOS_MISSING_URL = "vending_tos_missing_url"; - - /** - * Whether to use sierraqa instead of sierra tokens for the purchase flow in - * Vending Machine. - * - * true = use sierraqa - * false = use sierra (default) - */ - public static final String VENDING_USE_CHECKOUT_QA_SERVICE = - "vending_use_checkout_qa_service"; - - /** - * Default value to use for all/free/priced filter in Market. - * Valid values: ALL, FREE, PAID (case insensitive) - */ - public static final String VENDING_DEFAULT_FILTER = "vending_default_filter"; - /** - * Ranking type value to use for the first category tab (currently popular) - */ - public static final String VENDING_TAB_1_RANKING_TYPE = "vending_tab_1_ranking_type"; - - /** - * Title string to use for first category tab. - */ - public static final String VENDING_TAB_1_TITLE = "vending_tab_1_title"; - - /** - * Ranking type value to use for the second category tab (currently newest) - */ - public static final String VENDING_TAB_2_RANKING_TYPE = "vending_tab_2_ranking_type"; - - /** - * Title string to use for second category tab. - */ - public static final String VENDING_TAB_2_TITLE = "vending_tab_2_title"; - - /** - * Frequency in milliseconds at which we should request MCS heartbeats - * from the Vending Machine client. - */ - public static final String VENDING_HEARTBEAT_FREQUENCY_MS = - "vending_heartbeat_frequency_ms"; - - /** - * Frequency in milliseconds at which we should resend pending download - * requests to the API Server from the Vending Machine client. - */ - public static final String VENDING_PENDING_DOWNLOAD_RESEND_FREQUENCY_MS = - "vending_pd_resend_frequency_ms"; - - /** - * Time before an asset in the 'DOWNLOADING' state is considered ready - * for an install kick on the client. - */ - public static final String VENDING_DOWNLOADING_KICK_TIMEOUT_MS = - "vending_downloading_kick_ms"; - - /** - * Size of buffer in bytes for Vending to use when reading cache files. - */ - public static final String VENDING_DISK_INPUT_BUFFER_BYTES = - "vending_disk_input_buffer_bytes"; - - /** - * Size of buffer in bytes for Vending to use when writing cache files. - */ - public static final String VENDING_DISK_OUTPUT_BUFFER_BYTES = - "vending_disk_output_buffer_bytes"; - - /** - * Frequency in milliseconds at which we should cycle through the promoted applications - * on the home screen or the categories page. - */ - public static final String VENDING_PROMO_REFRESH_FREQUENCY_MS = - "vending_promo_refresh_freq_ms"; - - /** - * Frequency in milliseconds when we should refresh the provisioning information from - * the carrier backend. - */ - public static final String VENDING_CARRIER_PROVISIONING_REFRESH_FREQUENCY_MS = - "vending_carrier_ref_freq_ms"; - - /** - * Interval in milliseconds after which a failed provisioning request should be retried. - */ - public static final String VENDING_CARRIER_PROVISIONING_RETRY_MS = - "vending_carrier_prov_retry_ms"; - - /** - * Buffer in milliseconds for carrier credentials to be considered valid. - */ - public static final String VENDING_CARRIER_CREDENTIALS_BUFFER_MS = - "vending_carrier_cred_buf_ms"; - - /** - * Whether to turn on performance logging in the Market client. - */ - public static final String VENDING_LOG_PERFORMANCE = - "vending_log_perf"; - - /** - * URL that points to the legal terms of service to display in Settings. - * <p> - * This should be a https URL. For a pretty user-friendly URL, use - * {@link #SETTINGS_TOS_PRETTY_URL}. - */ - public static final String SETTINGS_TOS_URL = "settings_tos_url"; - - /** - * URL that points to the legal terms of service to display in Settings. - * <p> - * This should be a pretty http URL. For the URL the device will access - * via Settings, use {@link #SETTINGS_TOS_URL}. - */ - public static final String SETTINGS_TOS_PRETTY_URL = "settings_tos_pretty_url"; - - /** - * URL that points to the contributors to display in Settings. - * <p> - * This should be a https URL. For a pretty user-friendly URL, use - * {@link #SETTINGS_CONTRIBUTORS_PRETTY_URL}. - */ - public static final String SETTINGS_CONTRIBUTORS_URL = "settings_contributors_url"; - - /** - * URL that points to the contributors to display in Settings. - * <p> - * This should be a pretty http URL. For the URL the device will access - * via Settings, use {@link #SETTINGS_CONTRIBUTORS_URL}. - */ - public static final String SETTINGS_CONTRIBUTORS_PRETTY_URL = - "settings_contributors_pretty_url"; - - /** - * URL that points to the Terms Of Service for the device. - * <p> - * This should be a pretty http URL. - */ - public static final String SETUP_GOOGLE_TOS_URL = "setup_google_tos_url"; - - /** - * URL that points to the Android privacy policy for the device. - * <p> - * This should be a pretty http URL. - */ - public static final String SETUP_ANDROID_PRIVACY_URL = "setup_android_privacy_url"; - - /** - * URL that points to the Google privacy policy for the device. - * <p> - * This should be a pretty http URL. - */ - public static final String SETUP_GOOGLE_PRIVACY_URL = "setup_google_privacy_url"; - - /** - * Request an MSISDN token for various Google services. - */ - public static final String USE_MSISDN_TOKEN = "use_msisdn_token"; - - /** - * RSA public key used to encrypt passwords stored in the database. - */ - public static final String GLS_PUBLIC_KEY = "google_login_public_key"; - - /** - * Only check parental control status if this is set to "true". - */ - public static final String PARENTAL_CONTROL_CHECK_ENABLED = - "parental_control_check_enabled"; - - /** - * The list of applications we need to block if parental control is - * enabled. - */ - public static final String PARENTAL_CONTROL_APPS_LIST = - "parental_control_apps_list"; - - /** - * Duration in which parental control status is valid. - */ - public static final String PARENTAL_CONTROL_TIMEOUT_IN_MS = - "parental_control_timeout_in_ms"; - - /** - * When parental control is off, we expect to get this string from the - * litmus url. - */ - public static final String PARENTAL_CONTROL_EXPECTED_RESPONSE = - "parental_control_expected_response"; - - /** - * When the litmus url returns a 302, declare parental control to be on - * only if the redirect url matches this regular expression. - */ - public static final String PARENTAL_CONTROL_REDIRECT_REGEX = - "parental_control_redirect_regex"; - - /** - * Prefix for new Google services published by the checkin - * server. - */ - public static final String GOOGLE_SERVICES_PREFIX - = "google_services:"; - - /** - * List of test suites (local disk filename) for the automatic instrumentation test runner. - * The file format is similar to automated_suites.xml, see AutoTesterService. - * If this setting is missing or empty, the automatic test runner will not start. - */ - public static final String AUTOTEST_SUITES_FILE = "autotest_suites_file"; - - /** - * Interval between synchronous checkins forced by the automatic test runner. - * If you set this to a value smaller than CHECKIN_INTERVAL, then the test runner's - * frequent checkins will prevent asynchronous background checkins from interfering - * with any performance measurements. - */ - public static final String AUTOTEST_CHECKIN_SECONDS = "autotest_checkin_seconds"; - - /** - * Interval between reboots forced by the automatic test runner. - */ - public static final String AUTOTEST_REBOOT_SECONDS = "autotest_reboot_seconds"; - - - /** - * An email address that anr bugreports should be sent to. - */ - public static final String ANR_BUGREPORT_RECIPIENT = "anr_bugreport_recipient"; - - /** - * Flag for allowing service provider to use location information to improve products and - * services. - * Type: int ( 0 = disallow, 1 = allow ) - * @deprecated - */ - public static final String USE_LOCATION_FOR_SERVICES = "use_location"; - - /** * The number of promoted sources in GlobalSearch. + * @hide */ public static final String SEARCH_NUM_PROMOTED_SOURCES = "search_num_promoted_sources"; /** * The maximum number of suggestions returned by GlobalSearch. + * @hide */ public static final String SEARCH_MAX_RESULTS_TO_DISPLAY = "search_max_results_to_display"; /** * The number of suggestions GlobalSearch will ask each non-web search source for. + * @hide */ public static final String SEARCH_MAX_RESULTS_PER_SOURCE = "search_max_results_per_source"; /** * The number of suggestions the GlobalSearch will ask the web search source for. + * @hide */ public static final String SEARCH_WEB_RESULTS_OVERRIDE_LIMIT = "search_web_results_override_limit"; /** * The number of milliseconds that GlobalSearch will wait for suggestions from * promoted sources before continuing with all other sources. + * @hide */ public static final String SEARCH_PROMOTED_SOURCE_DEADLINE_MILLIS = "search_promoted_source_deadline_millis"; /** * The number of milliseconds before GlobalSearch aborts search suggesiton queries. + * @hide */ public static final String SEARCH_SOURCE_TIMEOUT_MILLIS = "search_source_timeout_millis"; /** * The maximum number of milliseconds that GlobalSearch shows the previous results * after receiving a new query. + * @hide */ public static final String SEARCH_PREFILL_MILLIS = "search_prefill_millis"; /** * The maximum age of log data used for shortcuts in GlobalSearch. + * @hide */ public static final String SEARCH_MAX_STAT_AGE_MILLIS = "search_max_stat_age_millis"; /** * The maximum age of log data used for source ranking in GlobalSearch. + * @hide */ public static final String SEARCH_MAX_SOURCE_EVENT_AGE_MILLIS = "search_max_source_event_age_millis"; /** * The minimum number of impressions needed to rank a source in GlobalSearch. + * @hide */ public static final String SEARCH_MIN_IMPRESSIONS_FOR_SOURCE_RANKING = "search_min_impressions_for_source_ranking"; /** * The minimum number of clicks needed to rank a source in GlobalSearch. + * @hide */ public static final String SEARCH_MIN_CLICKS_FOR_SOURCE_RANKING = "search_min_clicks_for_source_ranking"; /** * The maximum number of shortcuts shown by GlobalSearch. + * @hide */ public static final String SEARCH_MAX_SHORTCUTS_RETURNED = "search_max_shortcuts_returned"; /** * The size of the core thread pool for suggestion queries in GlobalSearch. + * @hide */ public static final String SEARCH_QUERY_THREAD_CORE_POOL_SIZE = "search_query_thread_core_pool_size"; /** * The maximum size of the thread pool for suggestion queries in GlobalSearch. + * @hide */ public static final String SEARCH_QUERY_THREAD_MAX_POOL_SIZE = "search_query_thread_max_pool_size"; /** * The size of the core thread pool for shortcut refreshing in GlobalSearch. + * @hide */ public static final String SEARCH_SHORTCUT_REFRESH_CORE_POOL_SIZE = "search_shortcut_refresh_core_pool_size"; /** * The maximum size of the thread pool for shortcut refreshing in GlobalSearch. + * @hide */ public static final String SEARCH_SHORTCUT_REFRESH_MAX_POOL_SIZE = "search_shortcut_refresh_max_pool_size"; /** * The maximun time that excess threads in the GlobalSeach thread pools will * wait before terminating. + * @hide */ public static final String SEARCH_THREAD_KEEPALIVE_SECONDS = "search_thread_keepalive_seconds"; /** * The maximum number of concurrent suggestion queries to each source. + * @hide */ public static final String SEARCH_PER_SOURCE_CONCURRENT_QUERY_LIMIT = "search_per_source_concurrent_query_limit"; /** - * Maximum size of /proc/last_kmsg content to upload after reboot. + * Whether or not alert sounds are played on MountService events. (0 = false, 1 = true) + * @hide */ - public static final String LAST_KMSG_KB = "last_kmsg_kb"; + public static final String MOUNT_PLAY_NOTIFICATION_SND = "mount_play_not_snd"; /** - * @deprecated + * Whether or not UMS auto-starts on UMS host detection. (0 = false, 1 = true) * @hide */ - @Deprecated // Obviated by NameValueCache: just fetch the value directly. - public static class QueryMap extends ContentQueryMap { + public static final String MOUNT_UMS_AUTOSTART = "mount_ums_autostart"; - public QueryMap(ContentResolver contentResolver, Cursor cursor, boolean keepUpdated, - Handler handlerForUpdateNotifications) { - super(cursor, NAME, keepUpdated, handlerForUpdateNotifications); - } + /** + * Whether or not a notification is displayed on UMS host detection. (0 = false, 1 = true) + * @hide + */ + public static final String MOUNT_UMS_PROMPT = "mount_ums_prompt"; - public QueryMap(ContentResolver contentResolver, boolean keepUpdated, - Handler handlerForUpdateNotifications) { - this(contentResolver, - contentResolver.query(CONTENT_URI, null, null, null, null), - keepUpdated, handlerForUpdateNotifications); - } + /** + * Whether or not a notification is displayed while UMS is enabled. (0 = false, 1 = true) + * @hide + */ + public static final String MOUNT_UMS_NOTIFY_ENABLED = "mount_ums_notify_enabled"; + + /** + * If nonzero, ANRs in invisible background processes bring up a dialog. + * Otherwise, the process will be silently killed. + * @hide + */ + public static final String ANR_SHOW_BACKGROUND = "anr_show_background"; - public String getString(String name) { - ContentValues cv = getValues(name); - if (cv == null) return null; - return cv.getAsString(VALUE); + /** + * @hide + */ + public static final String[] SETTINGS_TO_BACKUP = { + ADB_ENABLED, + ALLOW_MOCK_LOCATION, + PARENTAL_CONTROL_ENABLED, + PARENTAL_CONTROL_REDIRECT_URL, + USB_MASS_STORAGE_ENABLED, + ACCESSIBILITY_ENABLED, + ENABLED_ACCESSIBILITY_SERVICES, + TTS_USE_DEFAULTS, + TTS_DEFAULT_RATE, + TTS_DEFAULT_PITCH, + TTS_DEFAULT_SYNTH, + TTS_DEFAULT_LANG, + TTS_DEFAULT_COUNTRY, + WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, + WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY, + WIFI_NUM_ALLOWED_CHANNELS, + WIFI_NUM_OPEN_NETWORKS_KEPT, + MOUNT_PLAY_NOTIFICATION_SND, + MOUNT_UMS_AUTOSTART, + MOUNT_UMS_PROMPT, + MOUNT_UMS_NOTIFY_ENABLED + }; + + /** + * Helper method for determining if a location provider is enabled. + * @param cr the content resolver to use + * @param provider the location provider to query + * @return true if the provider is enabled + * + * @hide + */ + public static final boolean isLocationProviderEnabled(ContentResolver cr, String provider) { + String allowedProviders = Settings.Secure.getString(cr, LOCATION_PROVIDERS_ALLOWED); + if (allowedProviders != null) { + return (allowedProviders.equals(provider) || + allowedProviders.contains("," + provider + ",") || + allowedProviders.startsWith(provider + ",") || + allowedProviders.endsWith("," + provider)); } + return false; } + /** + * Thread-safe method for enabling or disabling a single location provider. + * @param cr the content resolver to use + * @param provider the location provider to enable or disable + * @param enabled true if the provider should be enabled + * + * @hide + */ + public static final void setLocationProviderEnabled(ContentResolver cr, + String provider, boolean enabled) { + // to ensure thread safety, we write the provider name with a '+' or '-' + // and let the SettingsProvider handle it rather than reading and modifying + // the list of enabled providers. + if (enabled) { + provider = "+" + provider; + } else { + provider = "-" + provider; + } + putString(cr, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, provider); + } } /** diff --git a/core/java/android/server/BluetoothA2dpService.java b/core/java/android/server/BluetoothA2dpService.java index e41f9de..22bb43c 100644 --- a/core/java/android/server/BluetoothA2dpService.java +++ b/core/java/android/server/BluetoothA2dpService.java @@ -100,7 +100,6 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub { setSinkPriority(device, BluetoothA2dp.PRIORITY_ON); } break; - case BluetoothDevice.BOND_BONDING: case BluetoothDevice.BOND_NONE: setSinkPriority(device, BluetoothA2dp.PRIORITY_UNDEFINED); break; @@ -407,7 +406,7 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub { mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); return Settings.Secure.getInt(mContext.getContentResolver(), Settings.Secure.getBluetoothA2dpSinkPriorityKey(device.getAddress()), - BluetoothA2dp.PRIORITY_OFF); + BluetoothA2dp.PRIORITY_UNDEFINED); } public synchronized boolean setSinkPriority(BluetoothDevice device, int priority) { @@ -466,10 +465,6 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub { checkSinkSuspendState(state); mTargetA2dpState = -1; - if (state == BluetoothA2dp.STATE_CONNECTING) { - mAudioManager.setParameters("A2dpSuspended=false"); - } - if (getSinkPriority(device) > BluetoothA2dp.PRIORITY_OFF && state == BluetoothA2dp.STATE_CONNECTING || state == BluetoothA2dp.STATE_CONNECTED) { diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java index 45719e4..fe3b149 100644 --- a/core/java/android/service/wallpaper/WallpaperService.java +++ b/core/java/android/service/wallpaper/WallpaperService.java @@ -434,9 +434,9 @@ public abstract class WallpaperService extends Service { } int myWidth = mSurfaceHolder.getRequestedWidth(); - if (myWidth <= 0) myWidth = ViewGroup.LayoutParams.FILL_PARENT; + if (myWidth <= 0) myWidth = ViewGroup.LayoutParams.MATCH_PARENT; int myHeight = mSurfaceHolder.getRequestedHeight(); - if (myHeight <= 0) myHeight = ViewGroup.LayoutParams.FILL_PARENT; + if (myHeight <= 0) myHeight = ViewGroup.LayoutParams.MATCH_PARENT; final boolean creating = !mCreated; final boolean formatChanged = mFormat != mSurfaceHolder.getRequestedFormat(); diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java index bd19f9e..bbbeb3f 100755 --- a/core/java/android/speech/tts/TextToSpeech.java +++ b/core/java/android/speech/tts/TextToSpeech.java @@ -129,8 +129,8 @@ public class TextToSpeech { * {@link TextToSpeech#synthesizeToFile(String, HashMap, String)} with the * {@link TextToSpeech.Engine#KEY_PARAM_UTTERANCE_ID} key. * @param utteranceId the identifier of the utterance. - */
- public void onUtteranceCompleted(String utteranceId);
+ */ + public void onUtteranceCompleted(String utteranceId); } @@ -286,6 +286,10 @@ public class TextToSpeech { */ public static final String KEY_PARAM_VARIANT = "variant"; /** + * {@hide} + */ + public static final String KEY_PARAM_ENGINE = "engine"; + /** * Parameter key to specify the audio stream type to be used when speaking text * or playing back a file. * @see TextToSpeech#speak(String, int, HashMap) @@ -327,10 +331,16 @@ public class TextToSpeech { * {@hide} */ protected static final int PARAM_POSITION_UTTERANCE_ID = 10; + + /** + * {@hide} + */ + protected static final int PARAM_POSITION_ENGINE = 12; + /** * {@hide} */ - protected static final int NB_CACHED_PARAMS = 6; + protected static final int NB_CACHED_PARAMS = 7; } /** @@ -373,6 +383,7 @@ public class TextToSpeech { mCachedParams[Engine.PARAM_POSITION_VARIANT] = Engine.KEY_PARAM_VARIANT; mCachedParams[Engine.PARAM_POSITION_STREAM] = Engine.KEY_PARAM_STREAM; mCachedParams[Engine.PARAM_POSITION_UTTERANCE_ID] = Engine.KEY_PARAM_UTTERANCE_ID; + mCachedParams[Engine.PARAM_POSITION_ENGINE] = Engine.KEY_PARAM_ENGINE; mCachedParams[Engine.PARAM_POSITION_RATE + 1] = String.valueOf(Engine.DEFAULT_RATE); @@ -381,10 +392,10 @@ public class TextToSpeech { mCachedParams[Engine.PARAM_POSITION_LANGUAGE + 1] = defaultLoc.getISO3Language(); mCachedParams[Engine.PARAM_POSITION_COUNTRY + 1] = defaultLoc.getISO3Country(); mCachedParams[Engine.PARAM_POSITION_VARIANT + 1] = defaultLoc.getVariant(); - mCachedParams[Engine.PARAM_POSITION_STREAM + 1] = String.valueOf(Engine.DEFAULT_STREAM); mCachedParams[Engine.PARAM_POSITION_UTTERANCE_ID + 1] = ""; + mCachedParams[Engine.PARAM_POSITION_ENGINE + 1] = Engine.DEFAULT_SYNTH; initTts(); } @@ -684,6 +695,10 @@ public class TextToSpeech { if (extra != null) { mCachedParams[Engine.PARAM_POSITION_UTTERANCE_ID + 1] = extra; } + extra = params.get(Engine.KEY_PARAM_ENGINE); + if (extra != null) { + mCachedParams[Engine.PARAM_POSITION_ENGINE + 1] = extra; + } } result = mITts.speak(mPackageName, text, queueMode, mCachedParams); } catch (RemoteException e) { @@ -819,7 +834,7 @@ public class TextToSpeech { mStarted = false; initTts(); } finally { - return result; + return result; } } } @@ -894,7 +909,7 @@ public class TextToSpeech { mStarted = false; initTts(); } finally { - return result; + return result; } } } @@ -943,7 +958,7 @@ public class TextToSpeech { mStarted = false; initTts(); } finally { - return result; + return result; } } } @@ -990,7 +1005,7 @@ public class TextToSpeech { mStarted = false; initTts(); } finally { - return result; + return result; } } } @@ -1046,7 +1061,7 @@ public class TextToSpeech { mStarted = false; initTts(); } finally { - return result; + return result; } } } @@ -1064,7 +1079,7 @@ public class TextToSpeech { return null; } try { - String[] locStrings = mITts.getLanguage(); + String[] locStrings = mITts.getLanguage(); if ((locStrings != null) && (locStrings.length == 3)) { return new Locale(locStrings[0], locStrings[1], locStrings[2]); } else { @@ -1131,7 +1146,7 @@ public class TextToSpeech { mStarted = false; initTts(); } finally { - return result; + return result; } } } @@ -1166,6 +1181,10 @@ public class TextToSpeech { if (extra != null) { mCachedParams[Engine.PARAM_POSITION_UTTERANCE_ID + 1] = extra; } + extra = params.get(Engine.KEY_PARAM_ENGINE); + if (extra != null) { + mCachedParams[Engine.PARAM_POSITION_ENGINE + 1] = extra; + } } if (mITts.synthesizeToFile(mPackageName, text, mCachedParams, filename)){ result = SUCCESS; @@ -1214,19 +1233,19 @@ public class TextToSpeech { * * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}. */ - public int setOnUtteranceCompletedListener(
- final OnUtteranceCompletedListener listener) {
+ public int setOnUtteranceCompletedListener( + final OnUtteranceCompletedListener listener) { synchronized (mStartLock) { int result = ERROR; if (!mStarted) { return result; } mITtscallback = new ITtsCallback.Stub() { - public void utteranceCompleted(String utteranceId) throws RemoteException {
- if (listener != null) {
- listener.onUtteranceCompleted(utteranceId);
- }
- }
+ public void utteranceCompleted(String utteranceId) throws RemoteException { + if (listener != null) { + listener.onUtteranceCompleted(utteranceId); + } + } }; try { result = mITts.registerCallback(mPackageName, mITtscallback); @@ -1251,7 +1270,7 @@ public class TextToSpeech { } finally { return result; } - }
+ } } /** @@ -1262,36 +1281,39 @@ public class TextToSpeech { * * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}. */ - public int setEngineByPackageName(String enginePackageName) {
- synchronized (mStartLock) {
- int result = TextToSpeech.ERROR;
- if (!mStarted) {
- return result;
- }
- try {
- result = mITts.setEngineByPackageName(enginePackageName);
- } catch (RemoteException e) {
- // TTS died; restart it.
- Log.e("TextToSpeech.java - setEngineByPackageName", "RemoteException");
- e.printStackTrace();
- mStarted = false;
- initTts();
- } catch (NullPointerException e) {
- // TTS died; restart it.
- Log.e("TextToSpeech.java - setEngineByPackageName", "NullPointerException");
- e.printStackTrace();
- mStarted = false;
- initTts();
- } catch (IllegalStateException e) {
- // TTS died; restart it.
- Log.e("TextToSpeech.java - setEngineByPackageName", "IllegalStateException");
- e.printStackTrace();
- mStarted = false;
- initTts();
- } finally {
- return result;
- }
- }
+ public int setEngineByPackageName(String enginePackageName) { + synchronized (mStartLock) { + int result = TextToSpeech.ERROR; + if (!mStarted) { + return result; + } + try { + result = mITts.setEngineByPackageName(enginePackageName); + if (result == TextToSpeech.SUCCESS){ + mCachedParams[Engine.PARAM_POSITION_ENGINE + 1] = enginePackageName; + } + } catch (RemoteException e) { + // TTS died; restart it. + Log.e("TextToSpeech.java - setEngineByPackageName", "RemoteException"); + e.printStackTrace(); + mStarted = false; + initTts(); + } catch (NullPointerException e) { + // TTS died; restart it. + Log.e("TextToSpeech.java - setEngineByPackageName", "NullPointerException"); + e.printStackTrace(); + mStarted = false; + initTts(); + } catch (IllegalStateException e) { + // TTS died; restart it. + Log.e("TextToSpeech.java - setEngineByPackageName", "IllegalStateException"); + e.printStackTrace(); + mStarted = false; + initTts(); + } finally { + return result; + } + } } } diff --git a/core/java/android/util/EventLog.java b/core/java/android/util/EventLog.java index a5029c0..b596d32 100644 --- a/core/java/android/util/EventLog.java +++ b/core/java/android/util/EventLog.java @@ -40,8 +40,6 @@ import java.util.regex.Pattern; * <p>Events use integer tag codes corresponding to /system/etc/event-log-tags. * They carry a payload of one or more int, long, or String values. The * event-log-tags file defines the payload contents for each type code. - * - * @pending */ public class EventLog { private static final String TAG = "EventLog"; diff --git a/core/java/android/util/EventLogTags.java b/core/java/android/util/EventLogTags.java index 075c84e..5cf5332 100644 --- a/core/java/android/util/EventLogTags.java +++ b/core/java/android/util/EventLogTags.java @@ -26,8 +26,8 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; /** - * to-be-deprecated: This class is no longer functional. - * Use {to-be-link android.util.EventLog} instead. + * @deprecated This class is no longer functional. + * Use {@link android.util.EventLog} instead. */ public class EventLogTags { public static class Description { diff --git a/core/java/android/util/Log.java b/core/java/android/util/Log.java index 7a959a6..75b1b90 100644 --- a/core/java/android/util/Log.java +++ b/core/java/android/util/Log.java @@ -234,7 +234,6 @@ public final class Log { * immediately with an error dialog. * @param tag Used to identify the source of a log message. * @param msg The message you would like logged. - * @pending */ public static int wtf(String tag, String msg) { return wtf(tag, msg, null); @@ -245,7 +244,6 @@ public final class Log { * Similar to {@link #wtf(String, String)}, with an exception to log. * @param tag Used to identify the source of a log message. * @param tr An exception to log. - * @pending */ public static int wtf(String tag, Throwable tr) { return wtf(tag, tr.getMessage(), tr); @@ -257,7 +255,6 @@ public final class Log { * @param tag Used to identify the source of a log message. * @param msg The message you would like logged. * @param tr An exception to log. May be null. - * @pending */ public static int wtf(String tag, String msg, Throwable tr) { tr = new TerribleFailure(msg, tr); diff --git a/core/java/android/view/TransformGestureDetector.java b/core/java/android/view/TransformGestureDetector.java new file mode 100644 index 0000000..196716a --- /dev/null +++ b/core/java/android/view/TransformGestureDetector.java @@ -0,0 +1,316 @@ +/* + * Copyright (C) 2010 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.view; + +import android.content.Context; +import android.util.Log; +import android.view.GestureDetector.SimpleOnGestureListener; + +/** + * Detects transformation gestures involving more than one pointer ("multitouch") + * using the supplied {@link MotionEvent}s. The {@link OnGestureListener} callback + * will notify users when a particular gesture event has occurred. This class + * should only be used with {@link MotionEvent}s reported via touch. + * + * To use this class: + * <ul> + * <li>Create an instance of the {@code TransformGestureDetector} for your + * {@link View} + * <li>In the {@link View#onTouchEvent(MotionEvent)} method ensure you call + * {@link #onTouchEvent(MotionEvent)}. The methods defined in your + * callback will be executed when the events occur. + * </ul> + * @hide Pending API approval + */ +public class TransformGestureDetector { + /** + * The listener for receiving notifications when gestures occur. + * If you want to listen for all the different gestures then implement + * this interface. If you only want to listen for a subset it might + * be easier to extend {@link SimpleOnGestureListener}. + * + * An application will receive events in the following order: + * One onTransformBegin() + * Zero or more onTransform() + * One onTransformEnd() or onTransformFling() + */ + public interface OnTransformGestureListener { + /** + * Responds to transformation events for a gesture in progress. + * Reported by pointer motion. + * + * @param detector The detector reporting the event - use this to + * retrieve extended info about event state. + * @return true if the event was handled, false otherwise. + */ + public boolean onTransform(TransformGestureDetector detector); + + /** + * Responds to the beginning of a transformation gesture. Reported by + * new pointers going down. + * + * @param detector The detector reporting the event - use this to + * retrieve extended info about event state. + * @return true if the event was handled, false otherwise. + */ + public boolean onTransformBegin(TransformGestureDetector detector); + + /** + * Responds to the end of a transformation gesture. Reported by existing + * pointers going up. If the end of a gesture would result in a fling, + * onTransformFling is called instead. + * + * @param detector The detector reporting the event - use this to + * retrieve extended info about event state. + * @return true if the event was handled, false otherwise. + */ + public boolean onTransformEnd(TransformGestureDetector detector); + + /** + * Responds to the end of a transformation gesture that begins a fling. + * Reported by existing pointers going up. If the end of a gesture + * would not result in a fling, onTransformEnd is called instead. + * + * @param detector The detector reporting the event - use this to + * retrieve extended info about event state. + * @return true if the event was handled, false otherwise. + */ + public boolean onTransformFling(TransformGestureDetector detector); + } + + private static final boolean DEBUG = false; + + private static final int INITIAL_EVENT_IGNORES = 2; + + private Context mContext; + private float mTouchSizeScale; + private OnTransformGestureListener mListener; + private int mVelocityTimeUnits; + private MotionEvent mInitialEvent; + + private MotionEvent mPrevEvent; + private MotionEvent mCurrEvent; + private VelocityTracker mVelocityTracker; + + private float mCenterX; + private float mCenterY; + private float mTransX; + private float mTransY; + private float mPrevFingerDiffX; + private float mPrevFingerDiffY; + private float mCurrFingerDiffX; + private float mCurrFingerDiffY; + private float mRotateDegrees; + private float mCurrLen; + private float mPrevLen; + private float mScaleFactor; + + // Units in pixels. Current value is pulled out of thin air for debugging only. + private float mPointerJumpLimit = 30; + + private int mEventIgnoreCount; + + public TransformGestureDetector(Context context, OnTransformGestureListener listener, + int velocityTimeUnits) { + mContext = context; + mListener = listener; + mTouchSizeScale = context.getResources().getDisplayMetrics().widthPixels/3; + mVelocityTimeUnits = velocityTimeUnits; + mEventIgnoreCount = INITIAL_EVENT_IGNORES; + } + + public TransformGestureDetector(Context context, OnTransformGestureListener listener) { + this(context, listener, 1000); + } + + public boolean onTouchEvent(MotionEvent event) { + final int action = event.getAction(); + boolean handled = true; + + if (mInitialEvent == null) { + // No transform gesture in progress + if ((action == MotionEvent.ACTION_POINTER_1_DOWN || + action == MotionEvent.ACTION_POINTER_2_DOWN) && + event.getPointerCount() >= 2) { + // We have a new multi-finger gesture + mInitialEvent = MotionEvent.obtain(event); + mPrevEvent = MotionEvent.obtain(event); + mVelocityTracker = VelocityTracker.obtain(); + handled = mListener.onTransformBegin(this); + } + } else { + // Transform gesture in progress - attempt to handle it + switch (action) { + case MotionEvent.ACTION_POINTER_1_UP: + case MotionEvent.ACTION_POINTER_2_UP: + // Gesture ended + handled = mListener.onTransformEnd(this); + + reset(); + break; + + case MotionEvent.ACTION_CANCEL: + handled = mListener.onTransformEnd(this); + + reset(); + break; + + case MotionEvent.ACTION_MOVE: + setContext(event); + + // Our first few events can be crazy from some touchscreens - drop them. + if (mEventIgnoreCount == 0) { + mVelocityTracker.addMovement(event); + handled = mListener.onTransform(this); + } else { + mEventIgnoreCount--; + } + + mPrevEvent.recycle(); + mPrevEvent = MotionEvent.obtain(event); + break; + } + } + return handled; + } + + private void setContext(MotionEvent curr) { + mCurrEvent = MotionEvent.obtain(curr); + + mRotateDegrees = -1; + mCurrLen = -1; + mPrevLen = -1; + mScaleFactor = -1; + + final MotionEvent prev = mPrevEvent; + + float px0 = prev.getX(0); + float py0 = prev.getY(0); + float px1 = prev.getX(1); + float py1 = prev.getY(1); + float cx0 = curr.getX(0); + float cy0 = curr.getY(0); + float cx1 = curr.getX(1); + float cy1 = curr.getY(1); + + // Some touchscreens do weird things with pointer values where points are + // too close along one axis. Try to detect this here and smooth things out. + // The main indicator is that we get the X or Y value from the other pointer. + final float dx0 = cx0 - px0; + final float dy0 = cy0 - py0; + final float dx1 = cx1 - px1; + final float dy1 = cy1 - py1; + + if (cx0 == cx1) { + if (Math.abs(dx0) > mPointerJumpLimit) { + cx0 = px0; + } else if (Math.abs(dx1) > mPointerJumpLimit) { + cx1 = px1; + } + } else if (cy0 == cy1) { + if (Math.abs(dy0) > mPointerJumpLimit) { + cy0 = py0; + } else if (Math.abs(dy1) > mPointerJumpLimit) { + cy1 = py1; + } + } + + final float pvx = px1 - px0; + final float pvy = py1 - py0; + final float cvx = cx1 - cx0; + final float cvy = cy1 - cy0; + mPrevFingerDiffX = pvx; + mPrevFingerDiffY = pvy; + mCurrFingerDiffX = cvx; + mCurrFingerDiffY = cvy; + + final float pmidx = px0 + pvx * 0.5f; + final float pmidy = py0 + pvy * 0.5f; + final float cmidx = cx0 + cvx * 0.5f; + final float cmidy = cy0 + cvy * 0.5f; + + mCenterX = cmidx; + mCenterY = cmidy; + mTransX = cmidx - pmidx; + mTransY = cmidy - pmidy; + } + + private void reset() { + if (mInitialEvent != null) { + mInitialEvent.recycle(); + mInitialEvent = null; + } + if (mPrevEvent != null) { + mPrevEvent.recycle(); + mPrevEvent = null; + } + if (mCurrEvent != null) { + mCurrEvent.recycle(); + mCurrEvent = null; + } + if (mVelocityTracker != null) { + mVelocityTracker.recycle(); + mVelocityTracker = null; + } + mEventIgnoreCount = INITIAL_EVENT_IGNORES; + } + + public float getCenterX() { + return mCenterX; + } + + public float getCenterY() { + return mCenterY; + } + + public float getTranslateX() { + return mTransX; + } + + public float getTranslateY() { + return mTransY; + } + + public float getCurrentSpan() { + if (mCurrLen == -1) { + final float cvx = mCurrFingerDiffX; + final float cvy = mCurrFingerDiffY; + mCurrLen = (float)Math.sqrt(cvx*cvx + cvy*cvy); + } + return mCurrLen; + } + + public float getPreviousSpan() { + if (mPrevLen == -1) { + final float pvx = mPrevFingerDiffX; + final float pvy = mPrevFingerDiffY; + mPrevLen = (float)Math.sqrt(pvx*pvx + pvy*pvy); + } + return mPrevLen; + } + + public float getScaleFactor() { + if (mScaleFactor == -1) { + mScaleFactor = getCurrentSpan() / getPreviousSpan(); + } + return mScaleFactor; + } + + public float getRotation() { + throw new UnsupportedOperationException(); + } +} diff --git a/core/java/android/view/VelocityTracker.java b/core/java/android/view/VelocityTracker.java index 5d89c46..9581080 100644 --- a/core/java/android/view/VelocityTracker.java +++ b/core/java/android/view/VelocityTracker.java @@ -55,12 +55,12 @@ public final class VelocityTracker implements Poolable<VelocityTracker> { } }, 2)); - final float mPastX[] = new float[NUM_PAST]; - final float mPastY[] = new float[NUM_PAST]; - final long mPastTime[] = new long[NUM_PAST]; + final float mPastX[][] = new float[MotionEvent.BASE_AVAIL_POINTERS][NUM_PAST]; + final float mPastY[][] = new float[MotionEvent.BASE_AVAIL_POINTERS][NUM_PAST]; + final long mPastTime[][] = new long[MotionEvent.BASE_AVAIL_POINTERS][NUM_PAST]; - float mYVelocity; - float mXVelocity; + float mYVelocity[] = new float[MotionEvent.BASE_AVAIL_POINTERS]; + float mXVelocity[] = new float[MotionEvent.BASE_AVAIL_POINTERS]; private VelocityTracker mNext; @@ -105,7 +105,9 @@ public final class VelocityTracker implements Poolable<VelocityTracker> { * Reset the velocity tracker back to its initial state. */ public void clear() { - mPastTime[0] = 0; + for (int i = 0; i < MotionEvent.BASE_AVAIL_POINTERS; i++) { + mPastTime[i][0] = 0; + } } /** @@ -120,18 +122,21 @@ public final class VelocityTracker implements Poolable<VelocityTracker> { public void addMovement(MotionEvent ev) { long time = ev.getEventTime(); final int N = ev.getHistorySize(); - for (int i=0; i<N; i++) { - addPoint(ev.getHistoricalX(i), ev.getHistoricalY(i), - ev.getHistoricalEventTime(i)); + final int pointerCount = ev.getPointerCount(); + for (int p = 0; p < pointerCount; p++) { + for (int i=0; i<N; i++) { + addPoint(p, ev.getHistoricalX(p, i), ev.getHistoricalY(p, i), + ev.getHistoricalEventTime(i)); + } + addPoint(p, ev.getX(p), ev.getY(p), time); } - addPoint(ev.getX(), ev.getY(), time); } - private void addPoint(float x, float y, long time) { + private void addPoint(int pos, float x, float y, long time) { int drop = -1; int i; if (localLOGV) Log.v(TAG, "Adding past y=" + y + " time=" + time); - final long[] pastTime = mPastTime; + final long[] pastTime = mPastTime[pos]; for (i=0; i<NUM_PAST; i++) { if (pastTime[i] == 0) { break; @@ -146,8 +151,8 @@ public final class VelocityTracker implements Poolable<VelocityTracker> { drop = 0; } if (drop == i) drop--; - final float[] pastX = mPastX; - final float[] pastY = mPastY; + final float[] pastX = mPastX[pos]; + final float[] pastY = mPastY[pos]; if (drop >= 0) { if (localLOGV) Log.v(TAG, "Dropping up to #" + drop); final int start = drop+1; @@ -190,44 +195,48 @@ public final class VelocityTracker implements Poolable<VelocityTracker> { * must be positive. */ public void computeCurrentVelocity(int units, float maxVelocity) { - final float[] pastX = mPastX; - final float[] pastY = mPastY; - final long[] pastTime = mPastTime; - - // Kind-of stupid. - final float oldestX = pastX[0]; - final float oldestY = pastY[0]; - final long oldestTime = pastTime[0]; - float accumX = 0; - float accumY = 0; - int N=0; - while (N < NUM_PAST) { - if (pastTime[N] == 0) { - break; + for (int pos = 0; pos < MotionEvent.BASE_AVAIL_POINTERS; pos++) { + final float[] pastX = mPastX[pos]; + final float[] pastY = mPastY[pos]; + final long[] pastTime = mPastTime[pos]; + + // Kind-of stupid. + final float oldestX = pastX[0]; + final float oldestY = pastY[0]; + final long oldestTime = pastTime[0]; + float accumX = 0; + float accumY = 0; + int N=0; + while (N < NUM_PAST) { + if (pastTime[N] == 0) { + break; + } + N++; } - N++; - } - // Skip the last received event, since it is probably pretty noisy. - if (N > 3) N--; - - for (int i=1; i < N; i++) { - final int dur = (int)(pastTime[i] - oldestTime); - if (dur == 0) continue; - float dist = pastX[i] - oldestX; - float vel = (dist/dur) * units; // pixels/frame. - if (accumX == 0) accumX = vel; - else accumX = (accumX + vel) * .5f; - - dist = pastY[i] - oldestY; - vel = (dist/dur) * units; // pixels/frame. - if (accumY == 0) accumY = vel; - else accumY = (accumY + vel) * .5f; + // Skip the last received event, since it is probably pretty noisy. + if (N > 3) N--; + + for (int i=1; i < N; i++) { + final int dur = (int)(pastTime[i] - oldestTime); + if (dur == 0) continue; + float dist = pastX[i] - oldestX; + float vel = (dist/dur) * units; // pixels/frame. + if (accumX == 0) accumX = vel; + else accumX = (accumX + vel) * .5f; + + dist = pastY[i] - oldestY; + vel = (dist/dur) * units; // pixels/frame. + if (accumY == 0) accumY = vel; + else accumY = (accumY + vel) * .5f; + } + mXVelocity[pos] = accumX < 0.0f ? Math.max(accumX, -maxVelocity) + : Math.min(accumX, maxVelocity); + mYVelocity[pos] = accumY < 0.0f ? Math.max(accumY, -maxVelocity) + : Math.min(accumY, maxVelocity); + + if (localLOGV) Log.v(TAG, "Y velocity=" + mYVelocity +" X velocity=" + + mXVelocity + " N=" + N); } - mXVelocity = accumX < 0.0f ? Math.max(accumX, -maxVelocity) : Math.min(accumX, maxVelocity); - mYVelocity = accumY < 0.0f ? Math.max(accumY, -maxVelocity) : Math.min(accumY, maxVelocity); - - if (localLOGV) Log.v(TAG, "Y velocity=" + mYVelocity +" X velocity=" - + mXVelocity + " N=" + N); } /** @@ -237,7 +246,7 @@ public final class VelocityTracker implements Poolable<VelocityTracker> { * @return The previously computed X velocity. */ public float getXVelocity() { - return mXVelocity; + return mXVelocity[0]; } /** @@ -247,6 +256,32 @@ public final class VelocityTracker implements Poolable<VelocityTracker> { * @return The previously computed Y velocity. */ public float getYVelocity() { - return mYVelocity; + return mYVelocity[0]; + } + + /** + * Retrieve the last computed X velocity. You must first call + * {@link #computeCurrentVelocity(int)} before calling this function. + * + * @param pos Which pointer's velocity to return. + * @return The previously computed X velocity. + * + * @hide Pending API approval + */ + public float getXVelocity(int pos) { + return mXVelocity[pos]; + } + + /** + * Retrieve the last computed Y velocity. You must first call + * {@link #computeCurrentVelocity(int)} before calling this function. + * + * @param pos Which pointer's velocity to return. + * @return The previously computed Y velocity. + * + * @hide Pending API approval + */ + public float getYVelocity(int pos) { + return mYVelocity[pos]; } } diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 5bd45a66a..df4cab0 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -379,7 +379,7 @@ import java.util.WeakHashMap; * dimension, it can specify one of: * <ul> * <li> an exact number - * <li>FILL_PARENT, which means the view wants to be as big as its parent + * <li>MATCH_PARENT, which means the view wants to be as big as its parent * (minus padding) * <li> WRAP_CONTENT, which means that the view wants to be just big enough to * enclose its content (plus padding). diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index 6646136..763f273 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -3070,7 +3070,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager if (childDimension >= 0) { resultSize = childDimension; resultMode = MeasureSpec.EXACTLY; - } else if (childDimension == LayoutParams.FILL_PARENT) { + } else if (childDimension == LayoutParams.MATCH_PARENT) { // Child wants to be our size. So be it. resultSize = size; resultMode = MeasureSpec.EXACTLY; @@ -3088,7 +3088,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager // Child wants a specific size... so be it resultSize = childDimension; resultMode = MeasureSpec.EXACTLY; - } else if (childDimension == LayoutParams.FILL_PARENT) { + } else if (childDimension == LayoutParams.MATCH_PARENT) { // Child wants to be our size, but our size is not fixed. // Constrain child to not be bigger than us. resultSize = size; @@ -3107,7 +3107,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager // Child wants a specific size... let him have it resultSize = childDimension; resultMode = MeasureSpec.EXACTLY; - } else if (childDimension == LayoutParams.FILL_PARENT) { + } else if (childDimension == LayoutParams.MATCH_PARENT) { // Child wants to be our size... find out how big it should // be resultSize = 0; @@ -3362,7 +3362,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager * for both width and height. For each dimension, it can specify one of: * <ul> * <li> an exact number - * <li>FILL_PARENT, which means the view wants to be as big as its parent + * <li>MATCH_PARENT, which means the view wants to be as big as its parent * (minus padding) * <li> WRAP_CONTENT, which means that the view wants to be just big enough * to enclose its content (plus padding) @@ -3376,14 +3376,22 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager */ public static class LayoutParams { /** - * Special value for the height or width requested by a View. - * FILL_PARENT means that the view wants to fill the available space - * within the parent, taking the parent's padding into account. + * This value has the same meaning as {@link #MATCH_PARENT} but has + * been deprecated. */ + @SuppressWarnings({"UnusedDeclaration"}) + @Deprecated public static final int FILL_PARENT = -1; /** * Special value for the height or width requested by a View. + * MATCH_PARENT means that the view wants to be as bigas its parent, + * minus the parent's padding, if any. + */ + public static final int MATCH_PARENT = -1; + + /** + * Special value for the height or width requested by a View. * WRAP_CONTENT means that the view wants to be just large enough to fit * its own internal content, taking its own padding into account. */ @@ -3391,20 +3399,20 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager /** * Information about how wide the view wants to be. Can be an exact - * size, or one of the constants FILL_PARENT or WRAP_CONTENT. + * size, or one of the constants MATCH_PARENT or WRAP_CONTENT. */ @ViewDebug.ExportedProperty(mapping = { - @ViewDebug.IntToString(from = FILL_PARENT, to = "FILL_PARENT"), + @ViewDebug.IntToString(from = MATCH_PARENT, to = "MATCH_PARENT"), @ViewDebug.IntToString(from = WRAP_CONTENT, to = "WRAP_CONTENT") }) public int width; /** * Information about how tall the view wants to be. Can be an exact - * size, or one of the constants FILL_PARENT or WRAP_CONTENT. + * size, or one of the constants MATCH_PARENT or WRAP_CONTENT. */ @ViewDebug.ExportedProperty(mapping = { - @ViewDebug.IntToString(from = FILL_PARENT, to = "FILL_PARENT"), + @ViewDebug.IntToString(from = MATCH_PARENT, to = "MATCH_PARENT"), @ViewDebug.IntToString(from = WRAP_CONTENT, to = "WRAP_CONTENT") }) public int height; @@ -3421,9 +3429,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager * * <ul> * <li><code>layout_width</code>: the width, either an exact value, - * {@link #WRAP_CONTENT} or {@link #FILL_PARENT}</li> + * {@link #WRAP_CONTENT} or {@link #MATCH_PARENT}</li> * <li><code>layout_height</code>: the height, either an exact value, - * {@link #WRAP_CONTENT} or {@link #FILL_PARENT}</li> + * {@link #WRAP_CONTENT} or {@link #MATCH_PARENT}</li> * </ul> * * @param c the application environment @@ -3442,9 +3450,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager * Creates a new set of layout parameters with the specified width * and height. * - * @param width the width, either {@link #FILL_PARENT}, + * @param width the width, either {@link #MATCH_PARENT}, * {@link #WRAP_CONTENT} or a fixed size in pixels - * @param height the height, either {@link #FILL_PARENT}, + * @param height the height, either {@link #MATCH_PARENT}, * {@link #WRAP_CONTENT} or a fixed size in pixels */ public LayoutParams(int width, int height) { @@ -3507,8 +3515,8 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager if (size == WRAP_CONTENT) { return "wrap-content"; } - if (size == FILL_PARENT) { - return "fill-parent"; + if (size == MATCH_PARENT) { + return "match-parent"; } return String.valueOf(size); } diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java index 47b976b..094b7dd 100644 --- a/core/java/android/view/ViewRoot.java +++ b/core/java/android/view/ViewRoot.java @@ -1167,7 +1167,7 @@ public final class ViewRoot extends Handler implements ViewParent, int measureSpec; switch (rootDimension) { - case ViewGroup.LayoutParams.FILL_PARENT: + case ViewGroup.LayoutParams.MATCH_PARENT: // Window can't resize. Force root view to be windowSize. measureSpec = MeasureSpec.makeMeasureSpec(windowSize, MeasureSpec.EXACTLY); break; diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java index 1932765..7dd5085 100644 --- a/core/java/android/view/Window.java +++ b/core/java/android/view/Window.java @@ -484,7 +484,7 @@ public abstract class Window { /** * Set the width and height layout parameters of the window. The default - * for both of these is FILL_PARENT; you can change them to WRAP_CONTENT to + * for both of these is MATCH_PARENT; you can change them to WRAP_CONTENT to * make a window that is not full-screen. * * @param width The desired layout width of the window. diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index fe329f2..8e15f89 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -771,26 +771,26 @@ public interface WindowManager extends ViewManager { public LayoutParams() { - super(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + super(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); type = TYPE_APPLICATION; format = PixelFormat.OPAQUE; } public LayoutParams(int _type) { - super(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + super(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); type = _type; format = PixelFormat.OPAQUE; } public LayoutParams(int _type, int _flags) { - super(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + super(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); type = _type; flags = _flags; format = PixelFormat.OPAQUE; } public LayoutParams(int _type, int _flags, int _format) { - super(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + super(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); type = _type; flags = _flags; format = _format; @@ -1036,9 +1036,9 @@ public interface WindowManager extends ViewManager { sb.append(','); sb.append(y); sb.append(")("); - sb.append((width==FILL_PARENT?"fill":(width==WRAP_CONTENT?"wrap":width))); + sb.append((width== MATCH_PARENT ?"fill":(width==WRAP_CONTENT?"wrap":width))); sb.append('x'); - sb.append((height==FILL_PARENT?"fill":(height==WRAP_CONTENT?"wrap":height))); + sb.append((height== MATCH_PARENT ?"fill":(height==WRAP_CONTENT?"wrap":height))); sb.append(")"); if (softInputMode != 0) { sb.append(" sim=#"); diff --git a/core/java/android/webkit/CallbackProxy.java b/core/java/android/webkit/CallbackProxy.java index fb369d3..6790c5d 100644 --- a/core/java/android/webkit/CallbackProxy.java +++ b/core/java/android/webkit/CallbackProxy.java @@ -90,7 +90,6 @@ class CallbackProxy extends Handler { private static final int JS_PROMPT = 114; private static final int JS_UNLOAD = 115; private static final int ASYNC_KEYEVENTS = 116; - private static final int TOO_MANY_REDIRECTS = 117; private static final int DOWNLOAD_FILE = 118; private static final int REPORT_ERROR = 119; private static final int RESEND_POST_DATA = 120; @@ -276,19 +275,6 @@ class CallbackProxy extends Handler { } break; - case TOO_MANY_REDIRECTS: - Message cancelMsg = - (Message) msg.getData().getParcelable("cancelMsg"); - Message continueMsg = - (Message) msg.getData().getParcelable("continueMsg"); - if (mWebViewClient != null) { - mWebViewClient.onTooManyRedirects(mWebView, cancelMsg, - continueMsg); - } else { - cancelMsg.sendToTarget(); - } - break; - case REPORT_ERROR: if (mWebViewClient != null) { int reasonCode = msg.arg1; @@ -790,19 +776,10 @@ class CallbackProxy extends Handler { sendMessage(msg); } + // Because this method is public and because CallbackProxy is mistakenly + // party of the public classes, we cannot remove this method. public void onTooManyRedirects(Message cancelMsg, Message continueMsg) { - // Do an unsynchronized quick check to avoid posting if no callback has - // been set. - if (mWebViewClient == null) { - cancelMsg.sendToTarget(); - return; - } - - Message msg = obtainMessage(TOO_MANY_REDIRECTS); - Bundle bundle = msg.getData(); - bundle.putParcelable("cancelMsg", cancelMsg); - bundle.putParcelable("continueMsg", continueMsg); - sendMessage(msg); + // deprecated. } public void onReceivedError(int errorCode, String description, diff --git a/core/java/android/webkit/DateSorter.java b/core/java/android/webkit/DateSorter.java index c46702e..16feaa9 100644 --- a/core/java/android/webkit/DateSorter.java +++ b/core/java/android/webkit/DateSorter.java @@ -38,7 +38,7 @@ public class DateSorter { /** must be >= 3 */ public static final int DAY_COUNT = 5; - private long [] mBins = new long[DAY_COUNT]; + private long [] mBins = new long[DAY_COUNT-1]; private String [] mLabels = new String[DAY_COUNT]; private static final int NUM_DAYS_AGO = 5; @@ -54,15 +54,13 @@ public class DateSorter { // Create the bins mBins[0] = c.getTimeInMillis(); // Today - c.roll(Calendar.DAY_OF_YEAR, -1); + c.add(Calendar.DAY_OF_YEAR, -1); mBins[1] = c.getTimeInMillis(); // Yesterday - c.roll(Calendar.DAY_OF_YEAR, -(NUM_DAYS_AGO - 1)); + c.add(Calendar.DAY_OF_YEAR, -(NUM_DAYS_AGO - 1)); mBins[2] = c.getTimeInMillis(); // Five days ago - c.roll(Calendar.DAY_OF_YEAR, NUM_DAYS_AGO); // move back to today - c.roll(Calendar.MONTH, -1); + c.add(Calendar.DAY_OF_YEAR, NUM_DAYS_AGO); // move back to today + c.add(Calendar.MONTH, -1); mBins[3] = c.getTimeInMillis(); // One month ago - c.roll(Calendar.MONTH, -1); - mBins[4] = c.getTimeInMillis(); // Over one month ago // build labels mLabels[0] = context.getText(com.android.internal.R.string.today).toString(); @@ -84,11 +82,11 @@ public class DateSorter { * date bin this date belongs to */ public int getIndex(long time) { - // Lame linear search - for (int i = 0; i < DAY_COUNT; i++) { + int lastDay = DAY_COUNT - 1; + for (int i = 0; i < lastDay; i++) { if (time > mBins[i]) return i; } - return DAY_COUNT - 1; + return lastDay; } /** @@ -96,6 +94,7 @@ public class DateSorter { * @return string label suitable for display to user */ public String getLabel(int index) { + if (index < 0 || index >= DAY_COUNT) return ""; return mLabels[index]; } @@ -105,17 +104,22 @@ public class DateSorter { * @return date boundary at given index */ public long getBoundary(int index) { + int lastDay = DAY_COUNT - 1; + // Error case + if (index < 0 || index > lastDay) index = 0; + // Since this provides a lower boundary on dates that will be included + // in the given bin, provide the smallest value + if (index == lastDay) return Long.MIN_VALUE; return mBins[index]; } /** * Calcuate 12:00am by zeroing out hour, minute, second, millisecond */ - private Calendar beginningOfDay(Calendar c) { + private void beginningOfDay(Calendar c) { c.set(Calendar.HOUR_OF_DAY, 0); c.set(Calendar.MINUTE, 0); c.set(Calendar.SECOND, 0); c.set(Calendar.MILLISECOND, 0); - return c; } } diff --git a/core/java/android/webkit/HTML5VideoViewProxy.java b/core/java/android/webkit/HTML5VideoViewProxy.java index 3e0be1c..429b335 100644 --- a/core/java/android/webkit/HTML5VideoViewProxy.java +++ b/core/java/android/webkit/HTML5VideoViewProxy.java @@ -48,6 +48,8 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.HashMap; import java.util.Map; +import java.util.Timer; +import java.util.TimerTask; /** * <p>Proxy for HTML5 video views. @@ -71,6 +73,9 @@ class HTML5VideoViewProxy extends Handler private static final int ENDED = 201; private static final int POSTER_FETCHED = 202; + // Timer thread -> UI thread + private static final int TIMEUPDATE = 300; + // The C++ MediaPlayerPrivateAndroid object. int mNativePointer; // The handler for WebCore thread messages; @@ -95,6 +100,22 @@ class HTML5VideoViewProxy extends Handler private static View mProgressView; // The container for the progress view and video view private static FrameLayout mLayout; + // The timer for timeupate events. + // See http://www.whatwg.org/specs/web-apps/current-work/#event-media-timeupdate + private static Timer mTimer; + private static final class TimeupdateTask extends TimerTask { + private HTML5VideoViewProxy mProxy; + + public TimeupdateTask(HTML5VideoViewProxy proxy) { + mProxy = proxy; + } + + public void run() { + mProxy.onTimeupdate(); + } + } + // The spec says the timer should fire every 250 ms or less. + private static final int TIMEUPDATE_PERIOD = 250; // ms private static final WebChromeClient.CustomViewCallback mCallback = new WebChromeClient.CustomViewCallback() { @@ -104,6 +125,8 @@ class HTML5VideoViewProxy extends Handler // which happens when the video view is detached from its parent // view. This happens in the WebChromeClient before this method // is invoked. + mTimer.cancel(); + mTimer = null; mCurrentProxy.playbackEnded(); mCurrentProxy = null; mLayout.removeView(mVideoView); @@ -118,11 +141,19 @@ class HTML5VideoViewProxy extends Handler public static void play(String url, int time, HTML5VideoViewProxy proxy, WebChromeClient client) { + if (mCurrentProxy == proxy) { + if (!mVideoView.isPlaying()) { + mVideoView.start(); + } + return; + } + if (mCurrentProxy != null) { // Some other video is already playing. Notify the caller that its playback ended. proxy.playbackEnded(); return; } + mCurrentProxy = proxy; // Create a FrameLayout that will contain the VideoView and the // progress view (if any). @@ -146,10 +177,23 @@ class HTML5VideoViewProxy extends Handler mProgressView.setVisibility(View.VISIBLE); } mLayout.setVisibility(View.VISIBLE); + mTimer = new Timer(); mVideoView.start(); client.onShowCustomView(mLayout, mCallback); } + public static boolean isPlaying(HTML5VideoViewProxy proxy) { + return (mCurrentProxy == proxy && mVideoView != null && mVideoView.isPlaying()); + } + + public static int getCurrentPosition() { + int currentPosMs = 0; + if (mVideoView != null) { + currentPosMs = mVideoView.getCurrentPosition(); + } + return currentPosMs; + } + public static void seek(int time, HTML5VideoViewProxy proxy) { if (mCurrentProxy == proxy && time >= 0 && mVideoView != null) { mVideoView.seekTo(time); @@ -159,10 +203,13 @@ class HTML5VideoViewProxy extends Handler public static void pause(HTML5VideoViewProxy proxy) { if (mCurrentProxy == proxy && mVideoView != null) { mVideoView.pause(); + mTimer.purge(); } } public static void onPrepared() { + mTimer.schedule(new TimeupdateTask(mCurrentProxy), TIMEUPDATE_PERIOD, TIMEUPDATE_PERIOD); + if (mProgressView == null || mLayout == null) { return; } @@ -203,7 +250,11 @@ class HTML5VideoViewProxy extends Handler sendMessage(obtainMessage(ENDED)); } - // Handler for the messages from WebCore thread to the UI thread. + public void onTimeupdate() { + sendMessage(obtainMessage(TIMEUPDATE)); + } + + // Handler for the messages from WebCore or Timer thread to the UI thread. @Override public void handleMessage(Message msg) { // This executes on the UI thread. @@ -241,6 +292,12 @@ class HTML5VideoViewProxy extends Handler } break; } + case TIMEUPDATE: { + if (VideoPlayer.isPlaying(this)) { + sendTimeupdate(); + } + break; + } } } @@ -410,6 +467,9 @@ class HTML5VideoViewProxy extends Handler Bitmap poster = (Bitmap) msg.obj; nativeOnPosterFetched(poster, mNativePointer); break; + case TIMEUPDATE: + nativeOnTimeupdate(msg.arg1, mNativePointer); + break; } } }; @@ -426,6 +486,12 @@ class HTML5VideoViewProxy extends Handler mWebCoreHandler.sendMessage(msg); } + private void sendTimeupdate() { + Message msg = Message.obtain(mWebCoreHandler, TIMEUPDATE); + msg.arg1 = VideoPlayer.getCurrentPosition(); + mWebCoreHandler.sendMessage(msg); + } + public Context getContext() { return mWebView.getContext(); } @@ -506,4 +572,5 @@ class HTML5VideoViewProxy extends Handler private native void nativeOnPrepared(int duration, int width, int height, int nativePointer); private native void nativeOnEnded(int nativePointer); private native void nativeOnPosterFetched(Bitmap poster, int nativePointer); + private native void nativeOnTimeupdate(int position, int nativePointer); } diff --git a/core/java/android/webkit/PluginFullScreenHolder.java b/core/java/android/webkit/PluginFullScreenHolder.java index 6a0b145..b641803 100644 --- a/core/java/android/webkit/PluginFullScreenHolder.java +++ b/core/java/android/webkit/PluginFullScreenHolder.java @@ -30,6 +30,7 @@ import android.util.Log; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; +import android.view.ViewGroup; class PluginFullScreenHolder extends Dialog { @@ -37,6 +38,7 @@ class PluginFullScreenHolder extends Dialog { private final WebView mWebView; private final int mNpp; + private View mContentView; private int mX; private int mY; private int mWidth; @@ -64,6 +66,12 @@ class PluginFullScreenHolder extends Dialog { } @Override + public void setContentView(View contentView) { + super.setContentView(contentView); + mContentView = contentView; + } + + @Override public void onBackPressed() { mWebView.mPrivateHandler.obtainMessage(WebView.HIDE_FULLSCREEN) .sendToTarget(); @@ -113,6 +121,11 @@ class PluginFullScreenHolder extends Dialog { @Override protected void onStop() { super.onStop(); + // manually remove the contentView's parent since the dialog does not + if (mContentView != null && mContentView.getParent() != null) { + ViewGroup vg = (ViewGroup) mContentView.getParent(); + vg.removeView(mContentView); + } mWebView.getWebViewCore().sendMessage( WebViewCore.EventHub.HIDE_FULLSCREEN, mNpp, 0); } diff --git a/core/java/android/webkit/PluginManager.java b/core/java/android/webkit/PluginManager.java index 141984a..cdcb662 100644 --- a/core/java/android/webkit/PluginManager.java +++ b/core/java/android/webkit/PluginManager.java @@ -21,6 +21,7 @@ import java.util.List; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; +import android.app.Service; import android.content.Context; import android.content.Intent; import android.content.pm.PackageInfo; @@ -31,8 +32,6 @@ import android.content.pm.Signature; import android.content.pm.PackageManager.NameNotFoundException; import android.os.SystemProperties; import android.util.Log; -import android.webkit.plugin.NativePlugin; -import android.webkit.plugin.WebkitPlugin; /** * Class for managing the relationship between the {@link WebView} and installed @@ -43,12 +42,6 @@ import android.webkit.plugin.WebkitPlugin; */ public class PluginManager { - private class PluginInfo { - public PackageInfo packageInfo; - public boolean isNative; - public Class<? extends WebkitPlugin> pluginClass; - } - /** * Service Action: A plugin wishes to be loaded in the WebView must provide * {@link android.content.IntentFilter IntentFilter} that accepts this @@ -75,7 +68,7 @@ public class PluginManager { private final Context mContext; - private ArrayList<PluginInfo> mPluginInfoCache; + private ArrayList<PackageInfo> mPackageInfoCache; // Only plugin matches one of the signatures in the list can be loaded // inside the WebView process @@ -87,7 +80,7 @@ public class PluginManager { private PluginManager(Context context) { mContext = context; - mPluginInfoCache = new ArrayList<PluginInfo>(); + mPackageInfoCache = new ArrayList<PackageInfo>(); } public static synchronized PluginManager getInstance(Context context) { @@ -122,10 +115,10 @@ public class PluginManager { PLUGIN_ACTION), PackageManager.GET_SERVICES | PackageManager.GET_META_DATA); - synchronized(mPluginInfoCache) { + synchronized(mPackageInfoCache) { // clear the list of existing packageInfo objects - mPluginInfoCache.clear(); + mPackageInfoCache.clear(); for (ResolveInfo info : plugins) { @@ -192,9 +185,6 @@ public class PluginManager { } } - PluginInfo pluginInfo = new PluginInfo(); - pluginInfo.packageInfo = pkgInfo; - // determine the type of plugin from the manifest if (serviceInfo.metaData == null) { Log.e(LOGTAG, "The plugin '" + serviceInfo.name + "' has no type defined"); @@ -202,9 +192,7 @@ public class PluginManager { } String pluginType = serviceInfo.metaData.getString(PLUGIN_TYPE); - if (TYPE_NATIVE.equals(pluginType)) { - pluginInfo.isNative = true; - } else { + if (!TYPE_NATIVE.equals(pluginType)) { Log.e(LOGTAG, "Unrecognized plugin type: " + pluginType); continue; } @@ -212,17 +200,11 @@ public class PluginManager { try { Class<?> cls = getPluginClass(serviceInfo.packageName, serviceInfo.name); - boolean classFound = false; - for(Class<?> implemented : cls.getInterfaces()) { - if (pluginInfo.isNative && implemented.equals(NativePlugin.class)) { - pluginInfo.pluginClass = cls.asSubclass(WebkitPlugin.class); - classFound = true; - break; - } - } + //TODO implement any requirements of the plugin class here! + boolean classFound = true; if (!classFound) { - Log.e(LOGTAG, "The plugin's class'" + serviceInfo.name + "' does not extend the appropriate interface."); + Log.e(LOGTAG, "The plugin's class' " + serviceInfo.name + "' does not extend the appropriate class."); continue; } @@ -235,7 +217,7 @@ public class PluginManager { } // if all checks have passed then make the plugin available - mPluginInfoCache.add(pluginInfo); + mPackageInfoCache.add(pkgInfo); directories.add(directory); } } @@ -252,9 +234,8 @@ public class PluginManager { } // must be synchronized to ensure the consistency of the cache - synchronized(mPluginInfoCache) { - for (PluginInfo pluginInfo : mPluginInfoCache) { - PackageInfo pkgInfo = pluginInfo.packageInfo; + synchronized(mPackageInfoCache) { + for (PackageInfo pkgInfo : mPackageInfoCache) { if (pluginLib.startsWith(pkgInfo.applicationInfo.dataDir)) { return pkgInfo.packageName; } @@ -270,39 +251,6 @@ public class PluginManager { } /* package */ - WebkitPlugin getPluginInstance(String pkgName, int npp) { - - // must be synchronized to ensure the consistency of the cache - synchronized(mPluginInfoCache) { - - // lookup plugin based on pkgName and instantiate if possible. - for (PluginInfo pluginInfo : mPluginInfoCache) { - - if (pluginInfo.packageInfo.packageName.equals(pkgName)) { - - try { - WebkitPlugin webkitPlugin = pluginInfo.pluginClass.newInstance(); - - if (pluginInfo.isNative) { - NativePlugin nativePlugin = (NativePlugin) webkitPlugin; - nativePlugin.initializePlugin(npp, mContext); - } - - return webkitPlugin; - } catch (Exception e) { - // Any number of things could have happened. Log the exception and - // return null. Careful not to use Log.e(LOGTAG, "String", e) - // because that reports the exception to the checkin service. - Log.e(LOGTAG, Log.getStackTraceString(e)); - } - break; - } - } - } - return null; - } - - /* package */ Class<?> getPluginClass(String packageName, String className) throws NameNotFoundException, ClassNotFoundException { Context pluginContext = mContext.createPackageContext(packageName, diff --git a/core/java/android/webkit/WebStorage.java b/core/java/android/webkit/WebStorage.java index a182287..cf71a84 100644 --- a/core/java/android/webkit/WebStorage.java +++ b/core/java/android/webkit/WebStorage.java @@ -389,8 +389,8 @@ public final class WebStorage { mOrigins = new HashMap<String, Origin>(); for (String origin : tmp) { Origin website = new Origin(origin, - nativeGetUsageForOrigin(origin), - nativeGetQuotaForOrigin(origin)); + nativeGetQuotaForOrigin(origin), + nativeGetUsageForOrigin(origin)); mOrigins.put(origin, website); } } diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index a6a48cb..c349606 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -25,11 +25,9 @@ import android.database.DataSetObserver; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; -import android.graphics.Paint; import android.graphics.Picture; import android.graphics.Point; import android.graphics.Rect; -import android.graphics.Region; import android.graphics.drawable.Drawable; import android.net.http.SslCertificate; import android.net.Uri; @@ -55,7 +53,6 @@ import android.view.VelocityTracker; import android.view.View; import android.view.ViewConfiguration; import android.view.ViewGroup; -import android.view.ViewParent; import android.view.ViewTreeObserver; import android.view.animation.AlphaAnimation; import android.view.inputmethod.InputMethodManager; @@ -203,6 +200,8 @@ public class WebView extends AbsoluteLayout implements ViewTreeObserver.OnGlobalFocusChangeListener, ViewGroup.OnHierarchyChangeListener { + // enable debug output for drag trackers + private static final boolean DEBUG_DRAG_TRACKER = false; // if AUTO_REDRAW_HACK is true, then the CALL key will toggle redrawing // the screen all-the-time. Good for profiling our drawing code static private final boolean AUTO_REDRAW_HACK = false; @@ -1847,7 +1846,7 @@ public class WebView extends AbsoluteLayout } if (null != v) { addView(v, new AbsoluteLayout.LayoutParams( - ViewGroup.LayoutParams.FILL_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, 0, 0)); if (mTitleShadow == null) { mTitleShadow = (Drawable) mContext.getResources().getDrawable( @@ -3193,14 +3192,17 @@ public class WebView extends AbsoluteLayout mWebViewCore.sendMessage(EventHub.SET_SELECTION, start, end); } - // Called by JNI when a touch event puts a textfield into focus. + /** + * Called in response to a message from webkit telling us that the soft + * keyboard should be launched. + */ private void displaySoftKeyboard(boolean isTextView) { InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE); if (isTextView) { - if (mWebTextView == null) return; - + rebuildWebTextView(); + if (!inEditingMode()) return; imm.showSoftInput(mWebTextView, 0); if (mInZoomOverview) { // if in zoom overview mode, call doDoubleTap() to bring it back @@ -3663,9 +3665,6 @@ public class WebView extends AbsoluteLayout nativeHideCursor(); } - /** - * @hide - */ public void emulateShiftHeld() { if (0 == mNativeClass) return; // client isn't initialized setUpSelectXY(); @@ -3893,7 +3892,9 @@ public class WebView extends AbsoluteLayout public void run() { // we always force, in case our height changed, in which case we // still want to send the notification over to webkit - setNewZoomScale(mActualScale, true); + if (mWebViewCore != null) { + setNewZoomScale(mActualScale, true); + } } }); } @@ -3970,7 +3971,7 @@ public class WebView extends AbsoluteLayout mMinDY = -viewTop; mMaxDY = docBottom - viewBottom; - if (DebugFlags.DRAG_TRACKER) { + if (DebugFlags.DRAG_TRACKER || DEBUG_DRAG_TRACKER) { Log.d(DebugFlags.DRAG_TRACKER_LOGTAG, " dragtracker y= " + y + " up/down= " + mMinDY + " " + mMaxDY); } @@ -4007,7 +4008,7 @@ public class WebView extends AbsoluteLayout if (mCurrStretchX != sx || mCurrStretchY != sy) { mCurrStretchX = sx; mCurrStretchY = sy; - if (DebugFlags.DRAG_TRACKER) { + if (DebugFlags.DRAG_TRACKER || DEBUG_DRAG_TRACKER) { Log.d(DebugFlags.DRAG_TRACKER_LOGTAG, "---- stretch " + sx + " " + sy); } @@ -4018,7 +4019,7 @@ public class WebView extends AbsoluteLayout } public void stopDrag() { - if (DebugFlags.DRAG_TRACKER) { + if (DebugFlags.DRAG_TRACKER || DEBUG_DRAG_TRACKER) { Log.d(DebugFlags.DRAG_TRACKER_LOGTAG, "----- stopDrag"); } mProxy.onStopDrag(); @@ -4055,7 +4056,7 @@ public class WebView extends AbsoluteLayout canvas.restoreToCount(count); return true; } - if (DebugFlags.DRAG_TRACKER) { + if (DebugFlags.DRAG_TRACKER || DEBUG_DRAG_TRACKER) { Log.d(DebugFlags.DRAG_TRACKER_LOGTAG, " -- draw false " + mCurrStretchX + " " + mCurrStretchY); } @@ -4070,7 +4071,7 @@ public class WebView extends AbsoluteLayout canvas.translate(-sx, -sy); drawContent(canvas); - if (DebugFlags.DRAG_TRACKER) { + if (DebugFlags.DRAG_TRACKER || DEBUG_DRAG_TRACKER) { Log.d(DebugFlags.DRAG_TRACKER_LOGTAG, "--- buildBitmap " + sx + " " + sy + " " + w + " " + h); } @@ -5107,10 +5108,6 @@ public class WebView extends AbsoluteLayout /*package*/ void centerKeyPressOnTextField() { mWebViewCore.sendMessage(EventHub.CLICK, nativeCursorFramePointer(), nativeCursorNodePointer()); - // Need to show the soft keyboard if it's not readonly. - if (!nativeCursorIsReadOnly()) { - displaySoftKeyboard(true); - } } private void doShortPress() { @@ -5132,12 +5129,12 @@ public class WebView extends AbsoluteLayout mWebViewCore.sendMessageAtFrontOfQueue(EventHub.VALID_NODE_BOUNDS, motionUpData); } else { - doMotionUp(contentX, contentY, false); + doMotionUp(contentX, contentY); } } - private void doMotionUp(int contentX, int contentY, boolean useNavCache) { - if (nativeMotionUp(contentX, contentY, useNavCache ? mNavSlop : 0)) { + private void doMotionUp(int contentX, int contentY) { + if (nativeMotionUp(contentX, contentY, mNavSlop)) { if (mLogEvent) { Checkin.updateStats(mContext.getContentResolver(), Checkin.Stats.Tag.BROWSER_SNAP_CENTER, 1, 0.0); @@ -5738,12 +5735,7 @@ public class WebView extends AbsoluteLayout if (msg.arg1 == 0) { hideSoftKeyboard(); } else { - displaySoftKeyboard(false); - if (DebugFlags.WEB_VIEW) { - Log.v(LOGTAG, "REQUEST_KEYBOARD" - + " focusCandidateIsPlugin=" - + nativeFocusCandidateIsPlugin()); - } + displaySoftKeyboard(1 == msg.arg2); } break; @@ -5771,7 +5763,7 @@ public class WebView extends AbsoluteLayout break; case DO_MOTION_UP: - doMotionUp(msg.arg1, msg.arg2, (Boolean) msg.obj); + doMotionUp(msg.arg1, msg.arg2); break; case SHOW_FULLSCREEN: @@ -6342,11 +6334,10 @@ public class WebView extends AbsoluteLayout private native void nativeCreate(int ptr); private native int nativeCursorFramePointer(); private native Rect nativeCursorNodeBounds(); - /* package */ native int nativeCursorNodePointer(); + private native int nativeCursorNodePointer(); /* package */ native boolean nativeCursorMatchesFocus(); private native boolean nativeCursorIntersects(Rect visibleRect); private native boolean nativeCursorIsAnchor(); - private native boolean nativeCursorIsReadOnly(); private native boolean nativeCursorIsTextInput(); private native Point nativeCursorPosition(); private native String nativeCursorText(); @@ -6374,13 +6365,12 @@ public class WebView extends AbsoluteLayout private native void nativeFindNext(boolean forward); /* package */ native int nativeFocusCandidateFramePointer(); private native boolean nativeFocusCandidateIsPassword(); - private native boolean nativeFocusCandidateIsPlugin(); private native boolean nativeFocusCandidateIsRtlText(); private native boolean nativeFocusCandidateIsTextInput(); /* package */ native int nativeFocusCandidateMaxLength(); /* package */ native String nativeFocusCandidateName(); private native Rect nativeFocusCandidateNodeBounds(); - /* package */ native int nativeFocusCandidatePointer(); + private native int nativeFocusCandidatePointer(); private native String nativeFocusCandidateText(); private native int nativeFocusCandidateTextSize(); /** diff --git a/core/java/android/webkit/WebViewClient.java b/core/java/android/webkit/WebViewClient.java index 032295d..02c7210 100644 --- a/core/java/android/webkit/WebViewClient.java +++ b/core/java/android/webkit/WebViewClient.java @@ -86,6 +86,8 @@ public class WebViewClient { * @param view The WebView that is initiating the callback. * @param cancelMsg The message to send if the host wants to cancel * @param continueMsg The message to send if the host wants to continue + * @deprecated This method is no longer called. When the WebView encounters + * a redirect loop, it will cancel the load. */ public void onTooManyRedirects(WebView view, Message cancelMsg, Message continueMsg) { diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java index 724493b..949b318 100644 --- a/core/java/android/webkit/WebViewCore.java +++ b/core/java/android/webkit/WebViewCore.java @@ -41,8 +41,6 @@ import android.view.KeyEvent; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; -import android.webkit.plugin.SurfaceDrawingModel; -import android.webkit.plugin.WebkitPlugin; import java.util.ArrayList; import java.util.Collection; @@ -1318,13 +1316,14 @@ final class WebViewCore { case VALID_NODE_BOUNDS: { MotionUpData motionUpData = (MotionUpData) msg.obj; - boolean result = nativeValidNodeAndBounds( + if (!nativeValidNodeAndBounds( motionUpData.mFrame, motionUpData.mNode, - motionUpData.mBounds); + motionUpData.mBounds)) { + nativeUpdateFrameCache(); + } Message message = mWebView.mPrivateHandler .obtainMessage(WebView.DO_MOTION_UP, - motionUpData.mX, motionUpData.mY, - new Boolean(result)); + motionUpData.mX, motionUpData.mY); mWebView.mPrivateHandler.sendMessageAtFrontOfQueue( message); break; @@ -2236,15 +2235,21 @@ final class WebViewCore { } // called by JNI - private void requestKeyboard(boolean showKeyboard) { + private void requestKeyboard(boolean showKeyboard, boolean isTextView) { if (mWebView != null) { Message.obtain(mWebView.mPrivateHandler, - WebView.REQUEST_KEYBOARD, showKeyboard ? 1 : 0, 0) + WebView.REQUEST_KEYBOARD, showKeyboard ? 1 : 0, + isTextView ? 1 : 0) .sendToTarget(); } } // called by JNI + private Context getContext() { + return mContext; + } + + // called by JNI private Class<?> getPluginClass(String libName, String clsName) { if (mWebView == null) { @@ -2271,40 +2276,17 @@ final class WebViewCore { return null; } - private WebkitPlugin createPluginJavaInstance(String libName, int npp) { - - if (mWebView == null) { - return null; - } - - PluginManager pluginManager = PluginManager.getInstance(null); - - String pkgName = pluginManager.getPluginsAPKName(libName); - if (pkgName == null) { - Log.w(LOGTAG, "Unable to resolve " + libName + " to a plugin APK"); - return null; - } - - return pluginManager.getPluginInstance(pkgName, npp); - } - // called by JNI. PluginWidget function to launch a full-screen view using a // View object provided by the plugin class. - private void showFullScreenPlugin(WebkitPlugin webkitPlugin, final int npp, - int x, int y, int width, int height) { - if (mWebView == null) { - return; - } + private void showFullScreenPlugin(ViewManager.ChildView childView, + final int npp, int x, int y, int width, int height) { - final SurfaceDrawingModel surface = webkitPlugin.getFullScreenSurface(); - if(surface == null) { - Log.e(LOGTAG, "Attempted to create an full-screen surface with a " + - "null drawing model"); + if (mWebView == null) { return; } PluginFullScreenData data = new PluginFullScreenData(); - data.mView = surface.getSurface(); + data.mView = childView.mView; data.mNpp = npp; data.mDocX = x; data.mDocY = y; @@ -2341,20 +2323,18 @@ final class WebViewCore { // called by JNI. PluginWidget functions for creating an embedded View for // the surface drawing model. - private ViewManager.ChildView createSurface(WebkitPlugin webkitPlugin, - int x, int y, int width, int height) { - + private ViewManager.ChildView addSurface(View pluginView, int x, int y, + int width, int height) { if (mWebView == null) { return null; } - SurfaceDrawingModel embeddedSurface = webkitPlugin.getEmbeddedSurface(); - if(embeddedSurface == null) { - Log.e(LOGTAG, "Attempted to create an embedded surface with a null drawing model"); + if (pluginView == null) { + Log.e(LOGTAG, "Attempted to add an empty plugin view to the view hierarchy"); return null; } - View pluginView = embeddedSurface.getSurface(); + // ensures the view system knows the view can redraw itself pluginView.setWillNotDraw(false); ViewManager.ChildView view = mWebView.mViewManager.createView(); diff --git a/core/java/android/webkit/plugin/NativePlugin.java b/core/java/android/webkit/plugin/NativePlugin.java deleted file mode 100644 index 5019c35..0000000 --- a/core/java/android/webkit/plugin/NativePlugin.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2009, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package android.webkit.plugin; - -import android.content.Context; - -/** - * - * @hide pending API solidification - */ -public interface NativePlugin extends WebkitPlugin { - - void initializePlugin(int npp, Context context); - -} diff --git a/core/java/android/webkit/plugin/SurfaceDrawingModel.java b/core/java/android/webkit/plugin/SurfaceDrawingModel.java deleted file mode 100644 index 93ba466..0000000 --- a/core/java/android/webkit/plugin/SurfaceDrawingModel.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2009, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package android.webkit.plugin; - -import android.view.View; - -/** - * - * @hide pending API solidification - */ -public interface SurfaceDrawingModel { - - public View getSurface(); - -} diff --git a/core/java/android/webkit/plugin/WebkitPlugin.java b/core/java/android/webkit/plugin/WebkitPlugin.java deleted file mode 100644 index 3d13c1c..0000000 --- a/core/java/android/webkit/plugin/WebkitPlugin.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2009, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package android.webkit.plugin; - -/** - * - * @hide pending API solidification - */ -public interface WebkitPlugin { - - SurfaceDrawingModel getEmbeddedSurface(); - SurfaceDrawingModel getFullScreenSurface(); - -} diff --git a/core/java/android/widget/AbsSpinner.java b/core/java/android/widget/AbsSpinner.java index 424a936..c939e3f 100644 --- a/core/java/android/widget/AbsSpinner.java +++ b/core/java/android/widget/AbsSpinner.java @@ -249,7 +249,7 @@ public abstract class AbsSpinner extends AdapterView<SpinnerAdapter> { @Override protected ViewGroup.LayoutParams generateDefaultLayoutParams() { return new ViewGroup.LayoutParams( - ViewGroup.LayoutParams.FILL_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); } diff --git a/core/java/android/widget/AbsoluteLayout.java b/core/java/android/widget/AbsoluteLayout.java index c77f7ae..b829655 100644 --- a/core/java/android/widget/AbsoluteLayout.java +++ b/core/java/android/widget/AbsoluteLayout.java @@ -161,9 +161,9 @@ public class AbsoluteLayout extends ViewGroup { * Creates a new set of layout parameters with the specified width, * height and location. * - * @param width the width, either {@link #FILL_PARENT}, + * @param width the width, either {@link #MATCH_PARENT}, {@link #WRAP_CONTENT} or a fixed size in pixels - * @param height the height, either {@link #FILL_PARENT}, + * @param height the height, either {@link #MATCH_PARENT}, {@link #WRAP_CONTENT} or a fixed size in pixels * @param x the X location of the child * @param y the Y location of the child diff --git a/core/java/android/widget/AutoCompleteTextView.java b/core/java/android/widget/AutoCompleteTextView.java index b455d47..bb9a672 100644 --- a/core/java/android/widget/AutoCompleteTextView.java +++ b/core/java/android/widget/AutoCompleteTextView.java @@ -172,7 +172,7 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe mDropDownAnchorId = a.getResourceId(R.styleable.AutoCompleteTextView_dropDownAnchor, View.NO_ID); - // For dropdown width, the developer can specify a specific width, or FILL_PARENT + // For dropdown width, the developer can specify a specific width, or MATCH_PARENT // (for full screen width) or WRAP_CONTENT (to match the width of the anchored view). mDropDownWidth = a.getLayoutDimension(R.styleable.AutoCompleteTextView_dropDownWidth, ViewGroup.LayoutParams.WRAP_CONTENT); @@ -240,7 +240,7 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe /** * <p>Returns the current width for the auto-complete drop down list. This can - * be a fixed width, or {@link ViewGroup.LayoutParams#FILL_PARENT} to fill the screen, or + * be a fixed width, or {@link ViewGroup.LayoutParams#MATCH_PARENT} to fill the screen, or * {@link ViewGroup.LayoutParams#WRAP_CONTENT} to fit the width of its anchor view.</p> * * @return the width for the drop down list @@ -253,7 +253,7 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe /** * <p>Sets the current width for the auto-complete drop down list. This can - * be a fixed width, or {@link ViewGroup.LayoutParams#FILL_PARENT} to fill the screen, or + * be a fixed width, or {@link ViewGroup.LayoutParams#MATCH_PARENT} to fill the screen, or * {@link ViewGroup.LayoutParams#WRAP_CONTENT} to fit the width of its anchor view.</p> * * @param width the width to use @@ -266,7 +266,7 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe /** * <p>Returns the current height for the auto-complete drop down list. This can - * be a fixed height, or {@link ViewGroup.LayoutParams#FILL_PARENT} to fill + * be a fixed height, or {@link ViewGroup.LayoutParams#MATCH_PARENT} to fill * the screen, or {@link ViewGroup.LayoutParams#WRAP_CONTENT} to fit the height * of the drop down's content.</p> * @@ -280,7 +280,7 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe /** * <p>Sets the current height for the auto-complete drop down list. This can - * be a fixed height, or {@link ViewGroup.LayoutParams#FILL_PARENT} to fill + * be a fixed height, or {@link ViewGroup.LayoutParams#MATCH_PARENT} to fill * the screen, or {@link ViewGroup.LayoutParams#WRAP_CONTENT} to fit the height * of the drop down's content.</p> * @@ -1129,7 +1129,7 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe boolean noInputMethod = isInputMethodNotNeeded(); if (mPopup.isShowing()) { - if (mDropDownWidth == ViewGroup.LayoutParams.FILL_PARENT) { + if (mDropDownWidth == ViewGroup.LayoutParams.MATCH_PARENT) { // The call to PopupWindow's update method below can accept -1 for any // value you do not want to update. widthSpec = -1; @@ -1139,19 +1139,19 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe widthSpec = mDropDownWidth; } - if (mDropDownHeight == ViewGroup.LayoutParams.FILL_PARENT) { + if (mDropDownHeight == ViewGroup.LayoutParams.MATCH_PARENT) { // The call to PopupWindow's update method below can accept -1 for any // value you do not want to update. - heightSpec = noInputMethod ? height : ViewGroup.LayoutParams.FILL_PARENT; + heightSpec = noInputMethod ? height : ViewGroup.LayoutParams.MATCH_PARENT; if (noInputMethod) { mPopup.setWindowLayoutMode( - mDropDownWidth == ViewGroup.LayoutParams.FILL_PARENT ? - ViewGroup.LayoutParams.FILL_PARENT : 0, 0); + mDropDownWidth == ViewGroup.LayoutParams.MATCH_PARENT ? + ViewGroup.LayoutParams.MATCH_PARENT : 0, 0); } else { mPopup.setWindowLayoutMode( - mDropDownWidth == ViewGroup.LayoutParams.FILL_PARENT ? - ViewGroup.LayoutParams.FILL_PARENT : 0, - ViewGroup.LayoutParams.FILL_PARENT); + mDropDownWidth == ViewGroup.LayoutParams.MATCH_PARENT ? + ViewGroup.LayoutParams.MATCH_PARENT : 0, + ViewGroup.LayoutParams.MATCH_PARENT); } } else if (mDropDownHeight == ViewGroup.LayoutParams.WRAP_CONTENT) { heightSpec = height; @@ -1164,8 +1164,8 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe mPopup.update(getDropDownAnchorView(), mDropDownHorizontalOffset, mDropDownVerticalOffset, widthSpec, heightSpec); } else { - if (mDropDownWidth == ViewGroup.LayoutParams.FILL_PARENT) { - widthSpec = ViewGroup.LayoutParams.FILL_PARENT; + if (mDropDownWidth == ViewGroup.LayoutParams.MATCH_PARENT) { + widthSpec = ViewGroup.LayoutParams.MATCH_PARENT; } else { if (mDropDownWidth == ViewGroup.LayoutParams.WRAP_CONTENT) { mPopup.setWidth(getDropDownAnchorView().getWidth()); @@ -1174,8 +1174,8 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe } } - if (mDropDownHeight == ViewGroup.LayoutParams.FILL_PARENT) { - heightSpec = ViewGroup.LayoutParams.FILL_PARENT; + if (mDropDownHeight == ViewGroup.LayoutParams.MATCH_PARENT) { + heightSpec = ViewGroup.LayoutParams.MATCH_PARENT; } else { if (mDropDownHeight == ViewGroup.LayoutParams.WRAP_CONTENT) { mPopup.setHeight(height); @@ -1295,7 +1295,7 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe hintContainer.setOrientation(LinearLayout.VERTICAL); LinearLayout.LayoutParams hintParams = new LinearLayout.LayoutParams( - ViewGroup.LayoutParams.FILL_PARENT, 0, 1.0f + ViewGroup.LayoutParams.MATCH_PARENT, 0, 1.0f ); hintContainer.addView(dropDownView, hintParams); hintContainer.addView(hintView); @@ -1331,7 +1331,7 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe final int maxHeight = mPopup.getMaxAvailableHeight( getDropDownAnchorView(), mDropDownVerticalOffset, ignoreBottomDecorations); - if (mDropDownAlwaysVisible || mDropDownHeight == ViewGroup.LayoutParams.FILL_PARENT) { + if (mDropDownAlwaysVisible || mDropDownHeight == ViewGroup.LayoutParams.MATCH_PARENT) { // getMaxAvailableHeight() subtracts the padding, so we put it back, // to get the available height for the whole window int padding = 0; diff --git a/core/java/android/widget/FrameLayout.java b/core/java/android/widget/FrameLayout.java index 3afd5d4..65a4673 100644 --- a/core/java/android/widget/FrameLayout.java +++ b/core/java/android/widget/FrameLayout.java @@ -164,12 +164,12 @@ public class FrameLayout extends ViewGroup { /** * Returns a set of layout parameters with a width of - * {@link android.view.ViewGroup.LayoutParams#FILL_PARENT}, - * and a height of {@link android.view.ViewGroup.LayoutParams#FILL_PARENT}. + * {@link android.view.ViewGroup.LayoutParams#MATCH_PARENT}, + * and a height of {@link android.view.ViewGroup.LayoutParams#MATCH_PARENT}. */ @Override protected LayoutParams generateDefaultLayoutParams() { - return new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); + return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); } /** @@ -467,9 +467,9 @@ public class FrameLayout extends ViewGroup { * Creates a new set of layout parameters with the specified width, height * and weight. * - * @param width the width, either {@link #FILL_PARENT}, + * @param width the width, either {@link #MATCH_PARENT}, * {@link #WRAP_CONTENT} or a fixed size in pixels - * @param height the height, either {@link #FILL_PARENT}, + * @param height the height, either {@link #MATCH_PARENT}, * {@link #WRAP_CONTENT} or a fixed size in pixels * @param gravity the gravity * diff --git a/core/java/android/widget/GridView.java b/core/java/android/widget/GridView.java index 2e91e52..30a38df 100644 --- a/core/java/android/widget/GridView.java +++ b/core/java/android/widget/GridView.java @@ -935,7 +935,7 @@ public class GridView extends AbsListView { AbsListView.LayoutParams p = (AbsListView.LayoutParams)child.getLayoutParams(); if (p == null) { - p = new AbsListView.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, + p = new AbsListView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, 0); child.setLayoutParams(p); } @@ -1254,7 +1254,7 @@ public class GridView extends AbsListView { // some up... AbsListView.LayoutParams p = (AbsListView.LayoutParams)child.getLayoutParams(); if (p == null) { - p = new AbsListView.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, + p = new AbsListView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, 0); } p.viewType = mAdapter.getItemViewType(position); diff --git a/core/java/android/widget/ImageButton.java b/core/java/android/widget/ImageButton.java index 2fc29bc..5c05170 100644 --- a/core/java/android/widget/ImageButton.java +++ b/core/java/android/widget/ImageButton.java @@ -57,6 +57,11 @@ import java.util.Map; * based on the state of the button and the corresponding images * defined in the XML.</p> * + * <p>The order of the {@code <item>} elements is important because they are + * evaluated in order. This is why the "normal" button image comes last, because + * it will only be applied after {@code android:state_pressed} and {@code + * android:state_focused} have both evaluated false.</p> + * * <p><strong>XML attributes</strong></p> * <p> * See {@link android.R.styleable#ImageView Button Attributes}, diff --git a/core/java/android/widget/LinearLayout.java b/core/java/android/widget/LinearLayout.java index f49079c..37372c5 100644 --- a/core/java/android/widget/LinearLayout.java +++ b/core/java/android/widget/LinearLayout.java @@ -378,7 +378,7 @@ public class LinearLayout extends ViewGroup { } boolean matchWidthLocally = false; - if (widthMode != MeasureSpec.EXACTLY && lp.width == LayoutParams.FILL_PARENT) { + if (widthMode != MeasureSpec.EXACTLY && lp.width == LayoutParams.MATCH_PARENT) { // The width of the linear layout will scale, and at least one // child said it wanted to match our width. Set a flag // indicating that we need to remeasure at least that view when @@ -391,7 +391,7 @@ public class LinearLayout extends ViewGroup { final int measuredWidth = child.getMeasuredWidth() + margin; maxWidth = Math.max(maxWidth, measuredWidth); - allFillParent = allFillParent && lp.width == LayoutParams.FILL_PARENT; + allFillParent = allFillParent && lp.width == LayoutParams.MATCH_PARENT; if (lp.weight > 0) { /* * Widths of weighted Views are bogus if we end up @@ -472,12 +472,12 @@ public class LinearLayout extends ViewGroup { maxWidth = Math.max(maxWidth, measuredWidth); boolean matchWidthLocally = widthMode != MeasureSpec.EXACTLY && - lp.width == LayoutParams.FILL_PARENT; + lp.width == LayoutParams.MATCH_PARENT; alternativeMaxWidth = Math.max(alternativeMaxWidth, matchWidthLocally ? margin : measuredWidth); - allFillParent = allFillParent && lp.width == LayoutParams.FILL_PARENT; + allFillParent = allFillParent && lp.width == LayoutParams.MATCH_PARENT; mTotalLength += child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin + getNextLocationOffset(child); @@ -515,7 +515,7 @@ public class LinearLayout extends ViewGroup { if (child.getVisibility() != GONE) { LinearLayout.LayoutParams lp = ((LinearLayout.LayoutParams)child.getLayoutParams()); - if (lp.width == LayoutParams.FILL_PARENT) { + if (lp.width == LayoutParams.MATCH_PARENT) { // Temporarily force children to reuse their old measured height // FIXME: this may not be right for something like wrapping text? int oldHeight = lp.height; @@ -629,7 +629,7 @@ public class LinearLayout extends ViewGroup { } boolean matchHeightLocally = false; - if (heightMode != MeasureSpec.EXACTLY && lp.height == LayoutParams.FILL_PARENT) { + if (heightMode != MeasureSpec.EXACTLY && lp.height == LayoutParams.MATCH_PARENT) { // The height of the linear layout will scale, and at least one // child said it wanted to match our height. Set a flag indicating that // we need to remeasure at least that view when we know our height. @@ -657,7 +657,7 @@ public class LinearLayout extends ViewGroup { maxHeight = Math.max(maxHeight, childHeight); - allFillParent = allFillParent && lp.height == LayoutParams.FILL_PARENT; + allFillParent = allFillParent && lp.height == LayoutParams.MATCH_PARENT; if (lp.weight > 0) { /* * Heights of weighted Views are bogus if we end up @@ -758,7 +758,7 @@ public class LinearLayout extends ViewGroup { lp.rightMargin + getNextLocationOffset(child); boolean matchHeightLocally = heightMode != MeasureSpec.EXACTLY && - lp.height == LayoutParams.FILL_PARENT; + lp.height == LayoutParams.MATCH_PARENT; final int margin = lp.topMargin + lp .bottomMargin; int childHeight = child.getMeasuredHeight() + margin; @@ -766,7 +766,7 @@ public class LinearLayout extends ViewGroup { alternativeMaxHeight = Math.max(alternativeMaxHeight, matchHeightLocally ? margin : childHeight); - allFillParent = allFillParent && lp.height == LayoutParams.FILL_PARENT; + allFillParent = allFillParent && lp.height == LayoutParams.MATCH_PARENT; if (baselineAligned) { final int childBaseline = child.getBaseline(); @@ -832,7 +832,7 @@ public class LinearLayout extends ViewGroup { if (child.getVisibility() != GONE) { LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) child.getLayoutParams(); - if (lp.height == LayoutParams.FILL_PARENT) { + if (lp.height == LayoutParams.MATCH_PARENT) { // Temporarily force children to reuse their old measured width // FIXME: this may not be right for something like wrapping text? int oldWidth = lp.width; @@ -1065,7 +1065,7 @@ public class LinearLayout extends ViewGroup { final LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) child.getLayoutParams(); - if (baselineAligned && lp.height != LayoutParams.FILL_PARENT) { + if (baselineAligned && lp.height != LayoutParams.MATCH_PARENT) { childBaseline = child.getBaseline(); } @@ -1199,7 +1199,7 @@ public class LinearLayout extends ViewGroup { /** * Returns a set of layout parameters with a width of - * {@link android.view.ViewGroup.LayoutParams#FILL_PARENT} + * {@link android.view.ViewGroup.LayoutParams#MATCH_PARENT} * and a height of {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT} * when the layout's orientation is {@link #VERTICAL}. When the orientation is * {@link #HORIZONTAL}, the width is set to {@link LayoutParams#WRAP_CONTENT} @@ -1210,7 +1210,7 @@ public class LinearLayout extends ViewGroup { if (mOrientation == HORIZONTAL) { return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); } else if (mOrientation == VERTICAL) { - return new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT); + return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); } return null; } @@ -1290,9 +1290,9 @@ public class LinearLayout extends ViewGroup { * Creates a new set of layout parameters with the specified width, height * and weight. * - * @param width the width, either {@link #FILL_PARENT}, + * @param width the width, either {@link #MATCH_PARENT}, * {@link #WRAP_CONTENT} or a fixed size in pixels - * @param height the height, either {@link #FILL_PARENT}, + * @param height the height, either {@link #MATCH_PARENT}, * {@link #WRAP_CONTENT} or a fixed size in pixels * @param weight the weight */ diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java index f4008f9..c63774a 100644 --- a/core/java/android/widget/ListView.java +++ b/core/java/android/widget/ListView.java @@ -1067,7 +1067,7 @@ public class ListView extends AbsListView { private void measureScrapChild(View child, int position, int widthMeasureSpec) { LayoutParams p = (LayoutParams) child.getLayoutParams(); if (p == null) { - p = new LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, + p = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, 0); child.setLayoutParams(p); } @@ -1702,7 +1702,7 @@ public class ListView extends AbsListView { // noinspection unchecked AbsListView.LayoutParams p = (AbsListView.LayoutParams) child.getLayoutParams(); if (p == null) { - p = new AbsListView.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, + p = new AbsListView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, 0); } p.viewType = mAdapter.getItemViewType(position); @@ -2388,7 +2388,7 @@ public class ListView extends AbsListView { ViewGroup.LayoutParams p = child.getLayoutParams(); if (p == null) { p = new ViewGroup.LayoutParams( - ViewGroup.LayoutParams.FILL_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); } diff --git a/core/java/android/widget/MediaController.java b/core/java/android/widget/MediaController.java index 446a992..c246c247 100644 --- a/core/java/android/widget/MediaController.java +++ b/core/java/android/widget/MediaController.java @@ -167,8 +167,8 @@ public class MediaController extends FrameLayout { mAnchor = view; FrameLayout.LayoutParams frameParams = new FrameLayout.LayoutParams( - ViewGroup.LayoutParams.FILL_PARENT, - ViewGroup.LayoutParams.FILL_PARENT + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT ); removeAllViews(); diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java index e4cc609..d20ab3b 100644 --- a/core/java/android/widget/PopupWindow.java +++ b/core/java/android/widget/PopupWindow.java @@ -569,7 +569,7 @@ public class PopupWindow { * the current width or height is requested as an explicit size from * the window manager. You can supply * {@link ViewGroup.LayoutParams#WRAP_CONTENT} or - * {@link ViewGroup.LayoutParams#FILL_PARENT} to have that measure + * {@link ViewGroup.LayoutParams#MATCH_PARENT} to have that measure * spec supplied instead, replacing the absolute width and height that * has been set in the popup.</p> * @@ -578,11 +578,11 @@ public class PopupWindow { * * @param widthSpec an explicit width measure spec mode, either * {@link ViewGroup.LayoutParams#WRAP_CONTENT}, - * {@link ViewGroup.LayoutParams#FILL_PARENT}, or 0 to use the absolute + * {@link ViewGroup.LayoutParams#MATCH_PARENT}, or 0 to use the absolute * width. * @param heightSpec an explicit height measure spec mode, either * {@link ViewGroup.LayoutParams#WRAP_CONTENT}, - * {@link ViewGroup.LayoutParams#FILL_PARENT}, or 0 to use the absolute + * {@link ViewGroup.LayoutParams#MATCH_PARENT}, or 0 to use the absolute * height. */ public void setWindowLayoutMode(int widthSpec, int heightSpec) { @@ -785,7 +785,7 @@ public class PopupWindow { if (mBackground != null) { final ViewGroup.LayoutParams layoutParams = mContentView.getLayoutParams(); - int height = ViewGroup.LayoutParams.FILL_PARENT; + int height = ViewGroup.LayoutParams.MATCH_PARENT; if (layoutParams != null && layoutParams.height == ViewGroup.LayoutParams.WRAP_CONTENT) { height = ViewGroup.LayoutParams.WRAP_CONTENT; @@ -795,7 +795,7 @@ public class PopupWindow { // within another view that owns the background drawable PopupViewContainer popupViewContainer = new PopupViewContainer(mContext); PopupViewContainer.LayoutParams listParams = new PopupViewContainer.LayoutParams( - ViewGroup.LayoutParams.FILL_PARENT, height + ViewGroup.LayoutParams.MATCH_PARENT, height ); popupViewContainer.setBackgroundDrawable(mBackground); popupViewContainer.addView(mContentView, listParams); diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java index 533c607..1aa1df3 100644 --- a/core/java/android/widget/RelativeLayout.java +++ b/core/java/android/widget/RelativeLayout.java @@ -291,6 +291,8 @@ public class RelativeLayout extends ViewGroup { } } + // TODO: we need to find another way to implement RelativeLayout + // This implementation cannot handle every case @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (mDirtyHierarchy) { @@ -438,6 +440,10 @@ public class RelativeLayout extends ViewGroup { final int[] rules = params.getRules(); if (rules[CENTER_IN_PARENT] != 0 || rules[CENTER_HORIZONTAL] != 0) { centerHorizontal(child, params, width); + } else if (rules[ALIGN_PARENT_RIGHT] != 0) { + final int childWidth = child.getMeasuredWidth(); + params.mLeft = width - mPaddingRight - childWidth; + params.mRight = params.mLeft + childWidth; } } } @@ -464,6 +470,10 @@ public class RelativeLayout extends ViewGroup { final int[] rules = params.getRules(); if (rules[CENTER_IN_PARENT] != 0 || rules[CENTER_VERTICAL] != 0) { centerVertical(child, params, height); + } else if (rules[ALIGN_PARENT_BOTTOM] != 0) { + final int childHeight = child.getMeasuredHeight(); + params.mTop = height - mPaddingBottom - childHeight; + params.mBottom = params.mTop + childHeight; } } } @@ -560,7 +570,7 @@ public class RelativeLayout extends ViewGroup { mPaddingLeft, mPaddingRight, myWidth); int childHeightMeasureSpec; - if (params.width == LayoutParams.FILL_PARENT) { + if (params.width == LayoutParams.MATCH_PARENT) { childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(myHeight, MeasureSpec.EXACTLY); } else { childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(myHeight, MeasureSpec.AT_MOST); @@ -622,7 +632,7 @@ public class RelativeLayout extends ViewGroup { // We can grow in this dimension. childSpecSize = childSize; } - } else if (childSize == LayoutParams.FILL_PARENT) { + } else if (childSize == LayoutParams.MATCH_PARENT) { // Child wanted to be as big as possible. Give all availble // space childSpecMode = MeasureSpec.EXACTLY; @@ -673,7 +683,7 @@ public class RelativeLayout extends ViewGroup { params.mRight = params.mLeft + child.getMeasuredWidth(); } } - return false; + return rules[ALIGN_PARENT_RIGHT] != 0; } private boolean positionChildVertical(View child, LayoutParams params, int myHeight, @@ -702,7 +712,7 @@ public class RelativeLayout extends ViewGroup { params.mBottom = params.mTop + child.getMeasuredHeight(); } } - return false; + return rules[ALIGN_PARENT_BOTTOM] != 0; } private void applyHorizontalSizeRules(LayoutParams childParams, int myWidth) { diff --git a/core/java/android/widget/SlidingDrawer.java b/core/java/android/widget/SlidingDrawer.java index f706744..11d72de 100644 --- a/core/java/android/widget/SlidingDrawer.java +++ b/core/java/android/widget/SlidingDrawer.java @@ -43,7 +43,7 @@ import android.view.accessibility.AccessibilityEvent; * SlidingDrawer should be used as an overlay inside layouts. This means SlidingDrawer * should only be used inside of a FrameLayout or a RelativeLayout for instance. The * size of the SlidingDrawer defines how much space the content will occupy once slid - * out so SlidingDrawer should usually use fill_parent for both its dimensions. + * out so SlidingDrawer should usually use match_parent for both its dimensions. * * Inside an XML layout, SlidingDrawer must define the id of the handle and of the * content: @@ -51,8 +51,8 @@ import android.view.accessibility.AccessibilityEvent; * <pre class="prettyprint"> * <SlidingDrawer * android:id="@+id/drawer" - * android:layout_width="fill_parent" - * android:layout_height="fill_parent" + * android:layout_width="match_parent" + * android:layout_height="match_parent" * * android:handle="@+id/handle" * android:content="@+id/content"> @@ -64,8 +64,8 @@ import android.view.accessibility.AccessibilityEvent; * * <GridView * android:id="@id/content" - * android:layout_width="fill_parent" - * android:layout_height="fill_parent" /> + * android:layout_width="match_parent" + * android:layout_height="match_parent" /> * * </SlidingDrawer> * </pre> diff --git a/core/java/android/widget/TabHost.java b/core/java/android/widget/TabHost.java index 412f817..78e2fee 100644 --- a/core/java/android/widget/TabHost.java +++ b/core/java/android/widget/TabHost.java @@ -327,8 +327,8 @@ mTabHost.addTab(TAB_TAG_1, "Hello, world!", "Tab 1"); .addView( mCurrentView, new ViewGroup.LayoutParams( - ViewGroup.LayoutParams.FILL_PARENT, - ViewGroup.LayoutParams.FILL_PARENT)); + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT)); } if (!mTabWidget.hasFocus()) { diff --git a/core/java/android/widget/TabWidget.java b/core/java/android/widget/TabWidget.java index c12d098..aa47e6d 100644 --- a/core/java/android/widget/TabWidget.java +++ b/core/java/android/widget/TabWidget.java @@ -16,8 +16,6 @@ package android.widget; -import com.android.internal.R; - import android.content.Context; import android.content.res.Resources; import android.content.res.TypedArray; @@ -26,7 +24,6 @@ import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.os.Build; import android.util.AttributeSet; -import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.view.View.OnFocusChangeListener; @@ -313,7 +310,7 @@ public class TabWidget extends LinearLayout implements OnFocusChangeListener { if (child.getLayoutParams() == null) { final LinearLayout.LayoutParams lp = new LayoutParams( 0, - ViewGroup.LayoutParams.FILL_PARENT, 1.0f); + ViewGroup.LayoutParams.MATCH_PARENT, 1.0f); lp.setMargins(0, 0, 0, 0); child.setLayoutParams(lp); } @@ -328,7 +325,7 @@ public class TabWidget extends LinearLayout implements OnFocusChangeListener { ImageView divider = new ImageView(mContext); final LinearLayout.LayoutParams lp = new LayoutParams( mDividerDrawable.getIntrinsicWidth(), - LayoutParams.FILL_PARENT); + LayoutParams.MATCH_PARENT); lp.setMargins(0, 0, 0, 0); divider.setLayoutParams(lp); divider.setBackgroundDrawable(mDividerDrawable); diff --git a/core/java/android/widget/TableLayout.java b/core/java/android/widget/TableLayout.java index afa2f3b..66500a3 100644 --- a/core/java/android/widget/TableLayout.java +++ b/core/java/android/widget/TableLayout.java @@ -52,7 +52,7 @@ import java.util.regex.Pattern; * {@link #setColumnCollapsed(int,boolean) setColumnCollapsed()}.</p> * * <p>The children of a TableLayout cannot specify the <code>layout_width</code> - * attribute. Width is always <code>FILL_PARENT</code>. However, the + * attribute. Width is always <code>MATCH_PARENT</code>. However, the * <code>layout_height</code> attribute can be defined by a child; default value * is {@link android.widget.TableLayout.LayoutParams#WRAP_CONTENT}. If the child * is a {@link android.widget.TableRow}, then the height is always @@ -621,7 +621,7 @@ public class TableLayout extends LinearLayout { /** * Returns a set of layout parameters with a width of - * {@link android.view.ViewGroup.LayoutParams#FILL_PARENT}, + * {@link android.view.ViewGroup.LayoutParams#MATCH_PARENT}, * and a height of {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT}. */ @Override @@ -647,7 +647,7 @@ public class TableLayout extends LinearLayout { /** * <p>This set of layout parameters enforces the width of each child to be - * {@link #FILL_PARENT} and the height of each child to be + * {@link #MATCH_PARENT} and the height of each child to be * {@link #WRAP_CONTENT}, but only if the height is not specified.</p> */ @SuppressWarnings({"UnusedDeclaration"}) @@ -663,14 +663,14 @@ public class TableLayout extends LinearLayout { * {@inheritDoc} */ public LayoutParams(int w, int h) { - super(FILL_PARENT, h); + super(MATCH_PARENT, h); } /** * {@inheritDoc} */ public LayoutParams(int w, int h, float initWeight) { - super(FILL_PARENT, h, initWeight); + super(MATCH_PARENT, h, initWeight); } /** @@ -679,7 +679,7 @@ public class TableLayout extends LinearLayout { * {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT}.</p> */ public LayoutParams() { - super(FILL_PARENT, WRAP_CONTENT); + super(MATCH_PARENT, WRAP_CONTENT); } /** @@ -698,7 +698,7 @@ public class TableLayout extends LinearLayout { /** * <p>Fixes the row's width to - * {@link android.view.ViewGroup.LayoutParams#FILL_PARENT}; the row's + * {@link android.view.ViewGroup.LayoutParams#MATCH_PARENT}; the row's * height is fixed to * {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT} if no layout * height is specified.</p> @@ -710,7 +710,7 @@ public class TableLayout extends LinearLayout { @Override protected void setBaseAttributes(TypedArray a, int widthAttr, int heightAttr) { - this.width = FILL_PARENT; + this.width = MATCH_PARENT; if (a.hasValue(heightAttr)) { this.height = a.getLayoutDimension(heightAttr, "layout_height"); } else { diff --git a/core/java/android/widget/TableRow.java b/core/java/android/widget/TableRow.java index 5628cab..abf08bf 100644 --- a/core/java/android/widget/TableRow.java +++ b/core/java/android/widget/TableRow.java @@ -35,7 +35,7 @@ import android.view.ViewDebug; * <p>The children of a TableRow do not need to specify the * <code>layout_width</code> and <code>layout_height</code> attributes in the * XML file. TableRow always enforces those values to be respectively - * {@link android.widget.TableLayout.LayoutParams#FILL_PARENT} and + * {@link android.widget.TableLayout.LayoutParams#MATCH_PARENT} and * {@link android.widget.TableLayout.LayoutParams#WRAP_CONTENT}.</p> * * <p> @@ -299,7 +299,7 @@ public class TableRow extends LinearLayout { case LayoutParams.WRAP_CONTENT: spec = getChildMeasureSpec(widthMeasureSpec, 0, LayoutParams.WRAP_CONTENT); break; - case LayoutParams.FILL_PARENT: + case LayoutParams.MATCH_PARENT: spec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); break; default: @@ -351,7 +351,7 @@ public class TableRow extends LinearLayout { /** * Returns a set of layout parameters with a width of - * {@link android.view.ViewGroup.LayoutParams#FILL_PARENT}, + * {@link android.view.ViewGroup.LayoutParams#MATCH_PARENT}, * a height of {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT} and no spanning. */ @Override @@ -451,7 +451,7 @@ public class TableRow extends LinearLayout { * {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT}.</p> */ public LayoutParams() { - super(FILL_PARENT, WRAP_CONTENT); + super(MATCH_PARENT, WRAP_CONTENT); column = -1; span = 1; } @@ -459,7 +459,7 @@ public class TableRow extends LinearLayout { /** * <p>Puts the view in the specified column.</p> * - * <p>Sets the child width to {@link android.view.ViewGroup.LayoutParams#FILL_PARENT} + * <p>Sets the child width to {@link android.view.ViewGroup.LayoutParams#MATCH_PARENT} * and the child height to * {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT}.</p> * @@ -490,7 +490,7 @@ public class TableRow extends LinearLayout { if (a.hasValue(widthAttr)) { width = a.getLayoutDimension(widthAttr, "layout_width"); } else { - width = FILL_PARENT; + width = MATCH_PARENT; } // We don't want to force users to specify a layout_height diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 455b593..12e8e29 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -4992,7 +4992,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener final int height = mLayoutParams.height; // If the size of the view does not depend on the size of the text, try to // start the marquee immediately - if (height != LayoutParams.WRAP_CONTENT && height != LayoutParams.FILL_PARENT) { + if (height != LayoutParams.WRAP_CONTENT && height != LayoutParams.MATCH_PARENT) { startMarquee(); } else { // Defer the start of the marquee until we know our width (see setFrame()) @@ -5307,7 +5307,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (desiredHeight != this.getHeight()) { sizeChanged = true; } - } else if (mLayoutParams.height == LayoutParams.FILL_PARENT) { + } else if (mLayoutParams.height == LayoutParams.MATCH_PARENT) { if (mDesiredHeightAtMeasure >= 0) { int desiredHeight = getDesiredHeight(); @@ -5354,7 +5354,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (mEllipsize != TextUtils.TruncateAt.MARQUEE) { // In a fixed-height view, so use our new text layout. if (mLayoutParams.height != LayoutParams.WRAP_CONTENT && - mLayoutParams.height != LayoutParams.FILL_PARENT) { + mLayoutParams.height != LayoutParams.MATCH_PARENT) { invalidate(); return; } diff --git a/core/java/android/widget/ViewSwitcher.java b/core/java/android/widget/ViewSwitcher.java index 0dcaf95..71ae624 100644 --- a/core/java/android/widget/ViewSwitcher.java +++ b/core/java/android/widget/ViewSwitcher.java @@ -80,7 +80,7 @@ public class ViewSwitcher extends ViewAnimator { View child = mFactory.makeView(); LayoutParams lp = (LayoutParams) child.getLayoutParams(); if (lp == null) { - lp = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT); + lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); } addView(child, lp); return child; diff --git a/core/java/android/widget/ZoomButtonsController.java b/core/java/android/widget/ZoomButtonsController.java index e55fbb8..bea009c 100644 --- a/core/java/android/widget/ZoomButtonsController.java +++ b/core/java/android/widget/ZoomButtonsController.java @@ -247,7 +247,7 @@ public class ZoomButtonsController implements View.OnTouchListener { LayoutParams.FLAG_LAYOUT_NO_LIMITS | LayoutParams.FLAG_ALT_FOCUSABLE_IM; lp.height = LayoutParams.WRAP_CONTENT; - lp.width = LayoutParams.FILL_PARENT; + lp.width = LayoutParams.MATCH_PARENT; lp.type = LayoutParams.TYPE_APPLICATION_PANEL; lp.format = PixelFormat.TRANSLUCENT; lp.windowAnimations = com.android.internal.R.style.Animation_ZoomButtons; diff --git a/core/java/com/android/internal/app/AlertController.java b/core/java/com/android/internal/app/AlertController.java index 57dbb44..f56b15c 100644 --- a/core/java/com/android/internal/app/AlertController.java +++ b/core/java/com/android/internal/app/AlertController.java @@ -16,7 +16,7 @@ package com.android.internal.app; -import static android.view.ViewGroup.LayoutParams.FILL_PARENT; +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; @@ -361,7 +361,7 @@ public class AlertController { if (mView != null) { customPanel = (FrameLayout) mWindow.findViewById(R.id.customPanel); FrameLayout custom = (FrameLayout) mWindow.findViewById(R.id.custom); - custom.addView(mView, new LayoutParams(FILL_PARENT, FILL_PARENT)); + custom.addView(mView, new LayoutParams(MATCH_PARENT, MATCH_PARENT)); if (mViewSpacingSpecified) { custom.setPadding(mViewSpacingLeft, mViewSpacingTop, mViewSpacingRight, mViewSpacingBottom); @@ -391,7 +391,7 @@ public class AlertController { if (mCustomTitleView != null) { // Add the custom title view directly to the topPanel layout LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams( - LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT); + LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT); topPanel.addView(mCustomTitleView, lp); @@ -460,8 +460,8 @@ public class AlertController { if (mListView != null) { contentPanel.removeView(mWindow.findViewById(R.id.scrollView)); contentPanel.addView(mListView, - new LinearLayout.LayoutParams(FILL_PARENT, FILL_PARENT)); - contentPanel.setLayoutParams(new LinearLayout.LayoutParams(FILL_PARENT, 0, 1.0f)); + new LinearLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT)); + contentPanel.setLayoutParams(new LinearLayout.LayoutParams(MATCH_PARENT, 0, 1.0f)); } else { contentPanel.setVisibility(View.GONE); } @@ -657,8 +657,8 @@ public class AlertController { ViewGroup parent = (ViewGroup) mWindow.findViewById(R.id.parentPanel); parent.removeView(buttonPanel); AbsListView.LayoutParams params = new AbsListView.LayoutParams( - AbsListView.LayoutParams.FILL_PARENT, - AbsListView.LayoutParams.FILL_PARENT); + AbsListView.LayoutParams.MATCH_PARENT, + AbsListView.LayoutParams.MATCH_PARENT); buttonPanel.setLayoutParams(params); mListView.addFooterView(buttonPanel); */ diff --git a/core/java/com/android/internal/app/ExternalMediaFormatActivity.java b/core/java/com/android/internal/app/ExternalMediaFormatActivity.java index 000f6c4..2b07ae6 100644 --- a/core/java/com/android/internal/app/ExternalMediaFormatActivity.java +++ b/core/java/com/android/internal/app/ExternalMediaFormatActivity.java @@ -102,7 +102,7 @@ public class ExternalMediaFormatActivity extends AlertActivity implements Dialog .getService("mount")); if (mountService != null) { try { - mountService.formatMedia(Environment.getExternalStorageDirectory().toString()); + mountService.formatVolume(Environment.getExternalStorageDirectory().toString()); } catch (RemoteException e) { } } diff --git a/core/java/com/android/internal/view/menu/IconMenuItemView.java b/core/java/com/android/internal/view/menu/IconMenuItemView.java index 66e15c1..3c5b422 100644 --- a/core/java/com/android/internal/view/menu/IconMenuItemView.java +++ b/core/java/com/android/internal/view/menu/IconMenuItemView.java @@ -254,7 +254,7 @@ public final class IconMenuItemView extends TextView implements MenuView.ItemVie if (lp == null) { // Default layout parameters lp = new IconMenuView.LayoutParams( - IconMenuView.LayoutParams.FILL_PARENT, IconMenuView.LayoutParams.FILL_PARENT); + IconMenuView.LayoutParams.MATCH_PARENT, IconMenuView.LayoutParams.MATCH_PARENT); } // Set the desired width of item diff --git a/core/java/com/android/internal/widget/ContactHeaderWidget.java b/core/java/com/android/internal/widget/ContactHeaderWidget.java index 19debec..33fd936 100644 --- a/core/java/com/android/internal/widget/ContactHeaderWidget.java +++ b/core/java/com/android/internal/widget/ContactHeaderWidget.java @@ -119,12 +119,12 @@ public class ContactHeaderWidget extends FrameLayout implements View.OnClickList int CONTACT_STATUS_RES_PACKAGE = 8; int CONTACT_STATUS_LABEL = 9; } - + private interface PhotoQuery { String[] COLUMNS = new String[] { Photo.PHOTO }; - + int PHOTO = 0; } @@ -241,13 +241,13 @@ public class ContactHeaderWidget extends FrameLayout implements View.OnClickList case TOKEN_PHOTO_QUERY: { //Set the photo Bitmap photoBitmap = null; - if (cursor != null && cursor.moveToFirst() + if (cursor != null && cursor.moveToFirst() && !cursor.isNull(PhotoQuery.PHOTO)) { byte[] photoData = cursor.getBlob(PhotoQuery.PHOTO); photoBitmap = BitmapFactory.decodeByteArray(photoData, 0, photoData.length, null); } - + if (photoBitmap == null) { photoBitmap = loadPlaceholderPhoto(null); } @@ -261,7 +261,7 @@ public class ContactHeaderWidget extends FrameLayout implements View.OnClickList case TOKEN_CONTACT_INFO: { if (cursor != null && cursor.moveToFirst()) { bindContactInfo(cursor); - Uri lookupUri = Contacts.getLookupUri(cursor.getLong(ContactQuery._ID), + Uri lookupUri = Contacts.getLookupUri(cursor.getLong(ContactQuery._ID), cursor.getString(ContactQuery.LOOKUP_KEY)); startPhotoQuery(cursor.getLong(ContactQuery.PHOTO_ID), lookupUri); invalidate(); @@ -277,6 +277,7 @@ public class ContactHeaderWidget extends FrameLayout implements View.OnClickList } else { String phoneNumber = (String) cookie; setDisplayName(phoneNumber, null); + setSocialSnippet(null); mPhotoView.assignContactFromPhone(phoneNumber, true); } break; @@ -290,6 +291,7 @@ public class ContactHeaderWidget extends FrameLayout implements View.OnClickList } else { String emailAddress = (String) cookie; setDisplayName(emailAddress, null); + setSocialSnippet(null); mPhotoView.assignContactFromEmail(emailAddress, true); } break; @@ -374,6 +376,7 @@ public class ContactHeaderWidget extends FrameLayout implements View.OnClickList public void setSocialSnippet(CharSequence snippet) { if (snippet == null) { mStatusView.setVisibility(View.GONE); + mStatusAttributionView.setVisibility(View.GONE); } else { mStatusView.setText(snippet); mStatusView.setVisibility(View.VISIBLE); @@ -446,7 +449,9 @@ public class ContactHeaderWidget extends FrameLayout implements View.OnClickList * */ public void wipeClean() { + setDisplayName(null, null); setPhoto(null); + setSocialSnippet(null); mContactUri = null; mExcludeMimes = null; } @@ -457,11 +462,11 @@ public class ContactHeaderWidget extends FrameLayout implements View.OnClickList } protected void startPhotoQuery(long photoId, Uri lookupKey) { - mQueryHandler.startQuery(TOKEN_PHOTO_QUERY, lookupKey, + mQueryHandler.startQuery(TOKEN_PHOTO_QUERY, lookupKey, ContentUris.withAppendedId(Data.CONTENT_URI, photoId), PhotoQuery.COLUMNS, null, null, null); } - + /** * Bind the contact details provided by the given {@link Cursor}. */ diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java index 58056bd..3c5a753 100644 --- a/core/java/com/android/internal/widget/LockPatternUtils.java +++ b/core/java/com/android/internal/widget/LockPatternUtils.java @@ -38,8 +38,9 @@ import java.util.List; public class LockPatternUtils { private static final String TAG = "LockPatternUtils"; - + private static final String LOCK_PATTERN_FILE = "/system/gesture.key"; + private static final String LOCK_PASSWORD_FILE = "/system/password.key"; /** * The maximum number of incorrect attempts before the user is prevented @@ -70,20 +71,32 @@ public class LockPatternUtils { public static final int MIN_LOCK_PATTERN_SIZE = 4; /** + * Type of password being stored. + * pattern = pattern screen + * pin = digit-only password + * password = alphanumeric password + */ + public static final int MODE_PATTERN = 0; + public static final int MODE_PIN = 1; + public static final int MODE_PASSWORD = 2; + + /** * The minimum number of dots the user must include in a wrong pattern * attempt for it to be counted against the counts that affect * {@link #FAILED_ATTEMPTS_BEFORE_TIMEOUT} and {@link #FAILED_ATTEMPTS_BEFORE_RESET} */ - public static final int MIN_PATTERN_REGISTER_FAIL = 3; + public static final int MIN_PATTERN_REGISTER_FAIL = 3; private final static String LOCKOUT_PERMANENT_KEY = "lockscreen.lockedoutpermanently"; private final static String LOCKOUT_ATTEMPT_DEADLINE = "lockscreen.lockoutattemptdeadline"; - private final static String PATTERN_EVER_CHOSEN = "lockscreen.patterneverchosen"; + private final static String PATTERN_EVER_CHOSEN_KEY = "lockscreen.patterneverchosen"; + public final static String PASSWORD_TYPE_KEY = "lockscreen.password_type"; private final ContentResolver mContentResolver; private static String sLockPatternFilename; - + private static String sLockPasswordFilename; + /** * @param contentResolver Used to look up and save settings. */ @@ -91,16 +104,19 @@ public class LockPatternUtils { mContentResolver = contentResolver; // Initialize the location of gesture lock file if (sLockPatternFilename == null) { - sLockPatternFilename = android.os.Environment.getDataDirectory() + sLockPatternFilename = android.os.Environment.getDataDirectory() .getAbsolutePath() + LOCK_PATTERN_FILE; + sLockPasswordFilename = android.os.Environment.getDataDirectory() + .getAbsolutePath() + LOCK_PASSWORD_FILE; } + } /** * Check to see if a pattern matches the saved pattern. If no pattern exists, * always returns true. * @param pattern The pattern to check. - * @return Whether the pattern matchees the stored one. + * @return Whether the pattern matches the stored one. */ public boolean checkPattern(List<LockPatternView.Cell> pattern) { try { @@ -122,13 +138,40 @@ public class LockPatternUtils { } /** - * Check to see if the user has stored a lock pattern. - * @return Whether a saved pattern exists. + * Check to see if a password matches the saved password. If no password exists, + * always returns true. + * @param password The password to check. + * @return Whether the password matches the stored one. */ - public boolean savedPatternExists() { + public boolean checkPassword(String password) { + try { + // Read all the bytes from the file + RandomAccessFile raf = new RandomAccessFile(sLockPasswordFilename, "r"); + final byte[] stored = new byte[(int) raf.length()]; + int got = raf.read(stored, 0, stored.length); + raf.close(); + if (got <= 0) { + return true; + } + // Compare the hash from the file with the entered password's hash + return Arrays.equals(stored, LockPatternUtils.passwordToHash(password)); + } catch (FileNotFoundException fnfe) { + return true; + } catch (IOException ioe) { + return true; + } + } + + /** + * Checks to see if the given file exists and contains any data. Returns true if it does, + * false otherwise. + * @param filename + * @return true if file exists and is non-empty. + */ + private boolean nonEmptyFileExists(String filename) { try { // Check if we can read a byte from the file - RandomAccessFile raf = new RandomAccessFile(sLockPatternFilename, "r"); + RandomAccessFile raf = new RandomAccessFile(filename, "r"); byte first = raf.readByte(); raf.close(); return true; @@ -140,13 +183,29 @@ public class LockPatternUtils { } /** + * Check to see if the user has stored a lock pattern. + * @return Whether a saved pattern exists. + */ + public boolean savedPatternExists() { + return nonEmptyFileExists(sLockPatternFilename); + } + + /** + * Check to see if the user has stored a lock pattern. + * @return Whether a saved pattern exists. + */ + public boolean savedPasswordExists() { + return nonEmptyFileExists(sLockPasswordFilename); + } + + /** * Return true if the user has ever chosen a pattern. This is true even if the pattern is * currently cleared. * * @return True if the user has ever chosen a pattern. */ public boolean isPatternEverChosen() { - return getBoolean(PATTERN_EVER_CHOSEN); + return getBoolean(PATTERN_EVER_CHOSEN_KEY); } /** @@ -166,7 +225,8 @@ public class LockPatternUtils { raf.write(hash, 0, hash.length); } raf.close(); - setBoolean(PATTERN_EVER_CHOSEN, true); + setBoolean(PATTERN_EVER_CHOSEN_KEY, true); + setLong(PASSWORD_TYPE_KEY, MODE_PATTERN); } catch (FileNotFoundException fnfe) { // Cant do much, unless we want to fail over to using the settings provider Log.e(TAG, "Unable to save lock pattern to " + sLockPatternFilename); @@ -177,6 +237,38 @@ public class LockPatternUtils { } /** + * Save a lock password. + * @param password The password to save + */ + public void saveLockPassword(String password) { + // Compute the hash + boolean numericHint = password != null ? TextUtils.isDigitsOnly(password) : false; + final byte[] hash = LockPatternUtils.passwordToHash(password); + try { + // Write the hash to file + RandomAccessFile raf = new RandomAccessFile(sLockPasswordFilename, "rw"); + // Truncate the file if pattern is null, to clear the lock + if (password == null) { + raf.setLength(0); + } else { + raf.write(hash, 0, hash.length); + } + raf.close(); + setLong(PASSWORD_TYPE_KEY, numericHint ? MODE_PIN : MODE_PASSWORD); + } catch (FileNotFoundException fnfe) { + // Cant do much, unless we want to fail over to using the settings provider + Log.e(TAG, "Unable to save lock pattern to " + sLockPasswordFilename); + } catch (IOException ioe) { + // Cant do much + Log.e(TAG, "Unable to save lock pattern to " + sLockPasswordFilename); + } + } + + public int getPasswordMode() { + return (int) getLong(PASSWORD_TYPE_KEY, MODE_PATTERN); + } + + /** * Deserialize a pattern. * @param string The pattern serialized with {@link #patternToString} * @return The pattern. @@ -210,7 +302,7 @@ public class LockPatternUtils { } return new String(res); } - + /* * Generate an SHA-1 hash for the pattern. Not the most secure, but it is * at least a second level of protection. First level is that the file @@ -218,11 +310,11 @@ public class LockPatternUtils { * @param pattern the gesture pattern. * @return the hash of the pattern in a byte array. */ - static byte[] patternToHash(List<LockPatternView.Cell> pattern) { + private static byte[] patternToHash(List<LockPatternView.Cell> pattern) { if (pattern == null) { return null; } - + final int patternSize = pattern.size(); byte[] res = new byte[patternSize]; for (int i = 0; i < patternSize; i++) { @@ -238,11 +330,55 @@ public class LockPatternUtils { } } + /* + * Generate a hash for the given password. To avoid brute force attacks, we use a salted hash. + * Not the most secure, but it is at least a second level of protection. First level is that + * the file is in a location only readable by the system process. + * @param password the gesture pattern. + * @return the hash of the pattern in a byte array. + */ + public static byte[] passwordToHash(String password) { + if (password == null) { + return null; + } + String algo = null; + byte[] hashed = null; + try { + long salt = 0x2374868151054924L; // TODO: make this unique to device + byte[] saltedPassword = (password + Long.toString(salt)).getBytes(); + byte[] sha1 = MessageDigest.getInstance(algo = "SHA-1").digest(saltedPassword); + byte[] md5 = MessageDigest.getInstance(algo = "MD5").digest(saltedPassword); + hashed = (toHex(sha1) + toHex(md5)).getBytes(); + } catch (NoSuchAlgorithmException e) { + Log.w(TAG, "Failed to encode string because of missing algorithm: " + algo); + } + return hashed; + } + + private static String toHex(byte[] ary) { + final String hex = "0123456789ABCDEF"; + String ret = ""; + for (int i = 0; i < ary.length; i++) { + ret += hex.charAt((ary[i] >> 4) & 0xf); + ret += hex.charAt(ary[i] & 0xf); + } + return ret; + } + + /** + * @return Whether the lock password is enabled. + */ + public boolean isLockPasswordEnabled() { + long mode = getLong(PASSWORD_TYPE_KEY, 0); + return savedPasswordExists() && (mode == MODE_PASSWORD || mode == MODE_PIN); + } + /** * @return Whether the lock pattern is enabled. */ public boolean isLockPatternEnabled() { - return getBoolean(Settings.System.LOCK_PATTERN_ENABLED); + return getBoolean(Settings.System.LOCK_PATTERN_ENABLED) + && getLong(PASSWORD_TYPE_KEY, MODE_PATTERN) == MODE_PATTERN; } /** @@ -361,5 +497,10 @@ public class LockPatternUtils { android.provider.Settings.System.putLong(mContentResolver, systemSettingKey, value); } - + public boolean isSecure() { + long mode = getPasswordMode(); + boolean secure = mode == MODE_PATTERN && isLockPatternEnabled() && savedPatternExists() + || (mode == MODE_PIN || mode == MODE_PASSWORD) && savedPasswordExists(); + return secure; + } } diff --git a/core/java/com/android/internal/widget/SlidingTab.java b/core/java/com/android/internal/widget/SlidingTab.java index f07b2f1..adafbb4 100644 --- a/core/java/com/android/internal/widget/SlidingTab.java +++ b/core/java/com/android/internal/widget/SlidingTab.java @@ -23,8 +23,6 @@ import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Rect; import android.graphics.drawable.Drawable; -import android.os.Handler; -import android.os.Message; import android.os.Vibrator; import android.util.AttributeSet; import android.util.Log; @@ -34,7 +32,6 @@ import android.view.View; import android.view.ViewGroup; import android.view.animation.AlphaAnimation; import android.view.animation.Animation; -import android.view.animation.AnimationSet; import android.view.animation.LinearInterpolator; import android.view.animation.TranslateAnimation; import android.view.animation.Animation.AnimationListener; @@ -214,7 +211,7 @@ public class SlidingTab extends ViewGroup { // Create hint TextView text = new TextView(parent.getContext()); text.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, - LayoutParams.FILL_PARENT)); + LayoutParams.MATCH_PARENT)); text.setBackgroundResource(barId); text.setTextAppearance(parent.getContext(), R.style.TextAppearance_SlidingTabNormal); // hint.setSingleLine(); // Hmm.. this causes the text to disappear off-screen diff --git a/core/java/com/google/android/util/GoogleWebContentHelper.java b/core/java/com/google/android/util/GoogleWebContentHelper.java deleted file mode 100644 index 8291e29..0000000 --- a/core/java/com/google/android/util/GoogleWebContentHelper.java +++ /dev/null @@ -1,281 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.android.util; - -import android.content.ContentResolver; -import android.content.Context; -import android.net.http.SslError; -import android.os.Message; -import android.provider.Settings; -import android.text.TextUtils; -import android.view.KeyEvent; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.webkit.HttpAuthHandler; -import android.webkit.SslErrorHandler; -import android.webkit.WebSettings; -import android.webkit.WebView; -import android.webkit.WebViewClient; -import android.widget.TextView; - -import java.util.Locale; - -/** - * Helper to display Google web content, and fallback on a static message if the - * web content is unreachable. For example, this can be used to display - * "Legal terms". - * <p> - * The typical usage pattern is to have two Gservices settings defined: - * <ul> - * <li>A secure URL that will be displayed on the device. This should be HTTPS - * so hotspots won't intercept it giving us a false positive that the page - * loaded successfully. - * <li>A pretty human-readable URL that will be displayed to the user in case we - * cannot reach the above URL. - * </ul> - * <p> - * The typical call sequence is {@link #setUrlsFromGservices(String, String)}, - * {@link #setUnsuccessfulMessage(String)}, and {@link #loadUrl()}. At some - * point, you'll want to display the layout via {@link #getLayout()}. - */ -public class GoogleWebContentHelper { - - private Context mContext; - - private String mSecureUrl; - private String mPrettyUrl; - - private String mUnsuccessfulMessage; - - private ViewGroup mLayout; - private WebView mWebView; - private View mProgressBar; - private TextView mTextView; - - private boolean mReceivedResponse; - - public GoogleWebContentHelper(Context context) { - mContext = context; - } - - /** - * Fetches the URLs from Gservices. - * - * @param secureSetting The setting key whose value contains the HTTPS URL. - * @param prettySetting The setting key whose value contains the pretty URL. - * @return This {@link GoogleWebContentHelper} so methods can be chained. - */ - public GoogleWebContentHelper setUrlsFromGservices(String secureSetting, String prettySetting) { - ContentResolver contentResolver = mContext.getContentResolver(); - mSecureUrl = fillUrl(Settings.Gservices.getString(contentResolver, secureSetting), - mContext); - mPrettyUrl = fillUrl(Settings.Gservices.getString(contentResolver, prettySetting), - mContext); - return this; - } - - /** - * Fetch directly from provided urls. - * - * @param secureUrl The HTTPS URL. - * @param prettyUrl The pretty URL. - * @return This {@link GoogleWebContentHelper} so methods can be chained. - */ - public GoogleWebContentHelper setUrls(String secureUrl, String prettyUrl) { - mSecureUrl = fillUrl(secureUrl, mContext); - mPrettyUrl = fillUrl(prettyUrl, mContext); - return this; - } - - - /** - * Sets the message that will be shown if we are unable to load the page. - * <p> - * This should be called after {@link #setUrlsFromGservices(String, String)} - * . - * - * @param message The message to load. The first argument, according to - * {@link java.util.Formatter}, will be substituted with the pretty - * URL. - * @return This {@link GoogleWebContentHelper} so methods can be chained. - */ - public GoogleWebContentHelper setUnsuccessfulMessage(String message) { - Locale locale = mContext.getResources().getConfiguration().locale; - mUnsuccessfulMessage = String.format(locale, message, mPrettyUrl); - return this; - } - - /** - * Begins loading the secure URL. - * - * @return This {@link GoogleWebContentHelper} so methods can be chained. - */ - public GoogleWebContentHelper loadUrl() { - ensureViews(); - mWebView.loadUrl(mSecureUrl); - return this; - } - - /** - * Loads data into the webview and also provides a failback url - * @return This {@link GoogleWebContentHelper} so methods can be chained. - */ - public GoogleWebContentHelper loadDataWithFailUrl(String base, String data, - String mimeType, String encoding, String failUrl) { - ensureViews(); - mWebView.loadDataWithBaseURL(base, data, mimeType, encoding, failUrl); - return this; - } - - /** - * Helper to handle the back key. Returns true if the back key was handled, - * otherwise returns false. - * @param event the key event sent to {@link Activity#dispatchKeyEvent()} - */ - public boolean handleKey(KeyEvent event) { - if (event.getKeyCode() == KeyEvent.KEYCODE_BACK - && event.getAction() == KeyEvent.ACTION_DOWN) { - if (mWebView.canGoBack()) { - mWebView.goBack(); - return true; - } - } - return false; - } - - /** - * Returns the layout containing the web view, progress bar, and text view. - * This class takes care of setting each one's visibility based on current - * state. - * - * @return The layout you should display. - */ - public ViewGroup getLayout() { - ensureViews(); - return mLayout; - } - - private synchronized void ensureViews() { - if (mLayout == null) { - initializeViews(); - } - } - - /** - * Fills the URL with the locale. - * - * @param url The URL in Formatter style for the extra info to be filled in. - * @return The filled URL. - */ - private static String fillUrl(String url, Context context) { - - if (TextUtils.isEmpty(url)) { - return ""; - } - - /* We add another layer of indirection here to allow mcc's to fill - * in Locales for TOS. TODO - REMOVE when needed locales supported - * natively (when not shipping devices to country X without support - * for their locale). - */ - String localeReplacement = context. - getString(com.android.internal.R.string.locale_replacement); - if (localeReplacement != null && localeReplacement.length() != 0) { - url = String.format(url, localeReplacement); - } - - Locale locale = Locale.getDefault(); - String tmp = locale.getLanguage() + "_" + locale.getCountry().toLowerCase(); - return String.format(url, tmp); - } - - private void initializeViews() { - - LayoutInflater inflater = - (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - - mLayout = (ViewGroup) inflater.inflate( - com.android.internal.R.layout.google_web_content_helper_layout, null); - - mWebView = (WebView) mLayout.findViewById(com.android.internal.R.id.web); - mWebView.setWebViewClient(new MyWebViewClient()); - WebSettings settings = mWebView.getSettings(); - settings.setCacheMode(WebSettings.LOAD_NO_CACHE); - - mProgressBar = mLayout.findViewById(com.android.internal.R.id.progressContainer); - TextView message = (TextView) mProgressBar.findViewById(com.android.internal.R.id.message); - message.setText(com.android.internal.R.string.googlewebcontenthelper_loading); - - mTextView = (TextView) mLayout.findViewById(com.android.internal.R.id.text); - mTextView.setText(mUnsuccessfulMessage); - } - - private synchronized void handleWebViewCompletion(boolean success) { - - if (mReceivedResponse) { - return; - } else { - mReceivedResponse = true; - } - - // In both cases, remove the progress bar - ((ViewGroup) mProgressBar.getParent()).removeView(mProgressBar); - - // Remove the view that isn't relevant - View goneView = success ? mTextView : mWebView; - ((ViewGroup) goneView.getParent()).removeView(goneView); - - // Show the next view, which depends on success - View visibleView = success ? mWebView : mTextView; - visibleView.setVisibility(View.VISIBLE); - } - - private class MyWebViewClient extends WebViewClient { - - @Override - public void onPageFinished(WebView view, String url) { - handleWebViewCompletion(true); - } - - @Override - public void onReceivedError(WebView view, int errorCode, - String description, String failingUrl) { - handleWebViewCompletion(false); - } - - @Override - public void onReceivedHttpAuthRequest(WebView view, - HttpAuthHandler handler, String host, String realm) { - handleWebViewCompletion(false); - } - - @Override - public void onReceivedSslError(WebView view, SslErrorHandler handler, - SslError error) { - handleWebViewCompletion(false); - } - - @Override - public void onTooManyRedirects(WebView view, Message cancelMsg, - Message continueMsg) { - handleWebViewCompletion(false); - } - - } - -} |
