summaryrefslogtreecommitdiffstats
path: root/core/java/android
diff options
context:
space:
mode:
Diffstat (limited to 'core/java/android')
-rw-r--r--core/java/android/accounts/AccountManagerService.java18
-rw-r--r--core/java/android/annotation/SdkConstant.java2
-rw-r--r--core/java/android/app/Activity.java4
-rw-r--r--core/java/android/app/ActivityManager.java45
-rw-r--r--core/java/android/app/ActivityManagerNative.java62
-rw-r--r--core/java/android/app/AlertDialog.java2
-rw-r--r--core/java/android/app/ApplicationContext.java38
-rw-r--r--core/java/android/app/ApplicationErrorReport.java1
-rw-r--r--core/java/android/app/Dialog.java4
-rw-r--r--core/java/android/app/ExpandableListActivity.java18
-rw-r--r--core/java/android/app/IActivityController.aidl2
-rw-r--r--core/java/android/app/IActivityManager.java14
-rw-r--r--core/java/android/app/ListActivity.java18
-rw-r--r--core/java/android/app/SearchDialog.java23
-rw-r--r--core/java/android/app/SearchManager.java29
-rw-r--r--core/java/android/app/SearchSourceSelector.java197
-rw-r--r--core/java/android/appwidget/AppWidgetHostView.java4
-rw-r--r--core/java/android/bluetooth/BluetoothA2dp.java2
-rw-r--r--core/java/android/bluetooth/BluetoothHeadset.java2
-rw-r--r--core/java/android/bluetooth/package.html90
-rw-r--r--core/java/android/content/ContentResolver.java44
-rw-r--r--core/java/android/content/Context.java6
-rw-r--r--core/java/android/content/EventLogTags.logtags10
-rw-r--r--core/java/android/content/Intent.java2
-rw-r--r--core/java/android/content/SyncManager.java4
-rw-r--r--core/java/android/content/SyncStorageEngine.java9
-rw-r--r--core/java/android/content/package.html14
-rw-r--r--core/java/android/content/pm/ApplicationInfo.java10
-rw-r--r--core/java/android/content/pm/PackageManager.java12
-rw-r--r--core/java/android/content/pm/PackageParser.java6
-rw-r--r--core/java/android/content/res/ColorStateList.java2
-rw-r--r--core/java/android/database/sqlite/SQLiteCursor.java12
-rw-r--r--core/java/android/database/sqlite/SQLiteDatabase.java1
-rw-r--r--core/java/android/ddm/DdmHandleHello.java4
-rw-r--r--core/java/android/hardware/SensorManager.java6
-rw-r--r--core/java/android/inputmethodservice/InputMethodService.java20
-rwxr-xr-xcore/java/android/inputmethodservice/KeyboardView.java12
-rw-r--r--core/java/android/net/MobileDataStateTracker.java23
-rw-r--r--core/java/android/net/SSLCertificateSocketFactory.java5
-rw-r--r--core/java/android/net/Uri.java61
-rw-r--r--core/java/android/net/http/CertificateChainValidator.java4
-rw-r--r--core/java/android/net/http/DomainNameChecker.java280
-rw-r--r--core/java/android/os/AsyncTask.java2
-rw-r--r--core/java/android/os/Build.java14
-rw-r--r--core/java/android/os/Debug.java10
-rw-r--r--core/java/android/os/Environment.java64
-rw-r--r--core/java/android/os/FileObserver.java4
-rw-r--r--core/java/android/os/FileUtils.java8
-rw-r--r--core/java/android/os/ICheckinService.aidl3
-rw-r--r--core/java/android/os/IMountService.aidl50
-rw-r--r--core/java/android/os/IPowerManager.aidl1
-rw-r--r--core/java/android/os/MemoryFile.java13
-rw-r--r--core/java/android/os/MessageQueue.java4
-rw-r--r--core/java/android/os/Power.java18
-rw-r--r--core/java/android/os/PowerManager.java3
-rw-r--r--core/java/android/os/RecoverySystem.java418
-rw-r--r--core/java/android/pim/vcard/VCardComposer.java52
-rw-r--r--core/java/android/pim/vcard/VCardParser_V21.java4
-rw-r--r--core/java/android/preference/EditTextPreference.java3
-rw-r--r--core/java/android/provider/Calendar.java53
-rw-r--r--core/java/android/provider/ContactsContract.java282
-rw-r--r--core/java/android/provider/MediaStore.java16
-rw-r--r--core/java/android/provider/Settings.java1154
-rw-r--r--core/java/android/server/BluetoothA2dpService.java16
-rw-r--r--core/java/android/server/BluetoothEventLoop.java15
-rw-r--r--core/java/android/server/BluetoothService.java19
-rw-r--r--core/java/android/service/wallpaper/WallpaperService.java4
-rwxr-xr-xcore/java/android/speech/tts/ITts.aidl4
-rwxr-xr-xcore/java/android/speech/tts/TextToSpeech.java100
-rw-r--r--core/java/android/text/method/ArrowKeyMovementMethod.java72
-rw-r--r--core/java/android/util/EventLog.java294
-rw-r--r--core/java/android/util/EventLogTags.java56
-rw-r--r--core/java/android/util/Log.java52
-rw-r--r--core/java/android/view/TransformGestureDetector.java316
-rw-r--r--core/java/android/view/VelocityTracker.java139
-rw-r--r--core/java/android/view/View.java105
-rw-r--r--core/java/android/view/ViewConfiguration.java4
-rw-r--r--core/java/android/view/ViewDebug.java4
-rw-r--r--core/java/android/view/ViewGroup.java42
-rw-r--r--core/java/android/view/ViewRoot.java2
-rw-r--r--core/java/android/view/ViewStub.java8
-rw-r--r--core/java/android/view/Window.java2
-rw-r--r--core/java/android/view/WindowManager.java12
-rw-r--r--core/java/android/view/WindowManagerPolicy.java13
-rwxr-xr-xcore/java/android/view/WindowOrientationListener.java132
-rw-r--r--core/java/android/webkit/CallbackProxy.java29
-rw-r--r--core/java/android/webkit/HTML5VideoViewProxy.java69
-rw-r--r--core/java/android/webkit/WebStorage.java4
-rw-r--r--core/java/android/webkit/WebView.java67
-rw-r--r--core/java/android/webkit/WebViewClient.java2
-rw-r--r--core/java/android/webkit/WebViewCore.java22
-rw-r--r--core/java/android/widget/AbsListView.java25
-rw-r--r--core/java/android/widget/AbsSeekBar.java37
-rw-r--r--core/java/android/widget/AbsSpinner.java2
-rw-r--r--core/java/android/widget/AbsoluteLayout.java4
-rw-r--r--core/java/android/widget/AutoCompleteTextView.java42
-rw-r--r--core/java/android/widget/FrameLayout.java10
-rw-r--r--core/java/android/widget/GridView.java12
-rw-r--r--core/java/android/widget/ImageButton.java7
-rw-r--r--core/java/android/widget/ImageView.java12
-rw-r--r--core/java/android/widget/LinearLayout.java36
-rw-r--r--core/java/android/widget/ListView.java35
-rw-r--r--core/java/android/widget/MediaController.java4
-rw-r--r--core/java/android/widget/PopupWindow.java10
-rw-r--r--core/java/android/widget/RelativeLayout.java21
-rw-r--r--core/java/android/widget/RemoteViews.java40
-rw-r--r--core/java/android/widget/SimpleAdapter.java18
-rw-r--r--core/java/android/widget/SimpleCursorAdapter.java31
-rw-r--r--core/java/android/widget/SlidingDrawer.java10
-rw-r--r--core/java/android/widget/TabHost.java4
-rw-r--r--core/java/android/widget/TabWidget.java7
-rw-r--r--core/java/android/widget/TableLayout.java16
-rw-r--r--core/java/android/widget/TableRow.java12
-rw-r--r--core/java/android/widget/TextView.java11
-rw-r--r--core/java/android/widget/ViewSwitcher.java2
-rw-r--r--core/java/android/widget/ZoomButtonsController.java2
116 files changed, 2930 insertions, 2382 deletions
diff --git a/core/java/android/accounts/AccountManagerService.java b/core/java/android/accounts/AccountManagerService.java
index de01153..d5a9b02 100644
--- a/core/java/android/accounts/AccountManagerService.java
+++ b/core/java/android/accounts/AccountManagerService.java
@@ -38,6 +38,7 @@ import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Binder;
import android.os.Bundle;
+import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
@@ -52,6 +53,7 @@ import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
+import java.io.File;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -153,8 +155,7 @@ public class AccountManagerService
new AtomicReference<AccountManagerService>();
private static final boolean isDebuggableMonkeyBuild =
- SystemProperties.getBoolean("ro.monkey", false)
- && SystemProperties.getBoolean("ro.debuggable", false);
+ SystemProperties.getBoolean("ro.monkey", false);
private static final Account[] EMPTY_ACCOUNT_ARRAY = new Account[]{};
static {
@@ -1351,9 +1352,20 @@ public class AccountManagerService
}
}
+ private static String getDatabaseName() {
+ if(Environment.isEncryptedFilesystemEnabled()) {
+ // Hard-coded path in case of encrypted file system
+ return Environment.getSystemSecureDirectory().getPath() + File.separator + DATABASE_NAME;
+ } else {
+ // Regular path in case of non-encrypted file system
+ return DATABASE_NAME;
+ }
+ }
+
private class DatabaseHelper extends SQLiteOpenHelper {
+
public DatabaseHelper(Context context) {
- super(context, DATABASE_NAME, null, DATABASE_VERSION);
+ super(context, AccountManagerService.getDatabaseName(), null, DATABASE_VERSION);
}
@Override
diff --git a/core/java/android/annotation/SdkConstant.java b/core/java/android/annotation/SdkConstant.java
index 6ac70f0..0a53186 100644
--- a/core/java/android/annotation/SdkConstant.java
+++ b/core/java/android/annotation/SdkConstant.java
@@ -29,7 +29,7 @@ import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.SOURCE)
public @interface SdkConstant {
public static enum SdkConstantType {
- ACTIVITY_INTENT_ACTION, BROADCAST_INTENT_ACTION, SERVICE_ACTION, INTENT_CATEGORY;
+ ACTIVITY_INTENT_ACTION, BROADCAST_INTENT_ACTION, SERVICE_ACTION, INTENT_CATEGORY, FEATURE;
}
SdkConstantType value();
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 676d6d5..932ad53 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -606,7 +606,7 @@ public class ActivityManager {
public int uid;
/**
- * The tag that was provided when the process crashed.
+ * The activity name associated with the error, if known. May be null.
*/
public String tag;
@@ -622,7 +622,6 @@ public class ActivityManager {
/**
* The stack trace where the error originated. May be null.
- * @pending
*/
public String stackTrace;
@@ -891,6 +890,38 @@ public class ActivityManager {
}
/**
+ * @deprecated This is now just a wrapper for
+ * {@link #killBackgroundProcesses(String)}; the previous behavior here
+ * is no longer available to applications because it allows them to
+ * break other applications by removing their alarms, stopping their
+ * services, etc.
+ */
+ @Deprecated
+ public void restartPackage(String packageName) {
+ killBackgroundProcesses(packageName);
+ }
+
+ /**
+ * Have the system immediately kill all background processes associated
+ * with the given package. This is the same as the kernel killing those
+ * processes to reclaim memory; the system will take care of restarting
+ * these processes in the future as needed.
+ *
+ * <p>You must hold the permission
+ * {@link android.Manifest.permission#KILL_BACKGROUND_PROCESSES} to be able to
+ * call this method.
+ *
+ * @param packageName The name of the package whose processes are to
+ * be killed.
+ */
+ public void killBackgroundProcesses(String packageName) {
+ try {
+ ActivityManagerNative.getDefault().killBackgroundProcesses(packageName);
+ } catch (RemoteException e) {
+ }
+ }
+
+ /**
* Have the system perform a force stop of everything associated with
* the given application package. All processes that share its uid
* will be killed, all services it has running stopped, all activities
@@ -899,14 +930,18 @@ public class ActivityManager {
* be stopped, notifications removed, etc.
*
* <p>You must hold the permission
- * {@link android.Manifest.permission#RESTART_PACKAGES} to be able to
+ * {@link android.Manifest.permission#FORCE_STOP_PACKAGES} to be able to
* call this method.
*
* @param packageName The name of the package to be stopped.
+ *
+ * @hide This is not available to third party applications due to
+ * it allowing them to break other applications by stopping their
+ * services, removing their alarms, etc.
*/
- public void restartPackage(String packageName) {
+ public void forceStopPackage(String packageName) {
try {
- ActivityManagerNative.getDefault().restartPackage(packageName);
+ ActivityManagerNative.getDefault().forceStopPackage(packageName);
} catch (RemoteException e) {
}
}
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index a0498aa..09b88ee 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -979,13 +979,23 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
return true;
}
- case HANDLE_APPLICATION_ERROR_TRANSACTION: {
+ case HANDLE_APPLICATION_CRASH_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ IBinder app = data.readStrongBinder();
+ ApplicationErrorReport.CrashInfo ci = new ApplicationErrorReport.CrashInfo(data);
+ handleApplicationCrash(app, ci);
+ reply.writeNoException();
+ return true;
+ }
+
+ case HANDLE_APPLICATION_WTF_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
IBinder app = data.readStrongBinder();
String tag = data.readString();
ApplicationErrorReport.CrashInfo ci = new ApplicationErrorReport.CrashInfo(data);
- handleApplicationError(app, tag, ci);
+ boolean res = handleApplicationWtf(app, tag, ci);
reply.writeNoException();
+ reply.writeInt(res ? 1 : 0);
return true;
}
@@ -997,10 +1007,18 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
return true;
}
- case RESTART_PACKAGE_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
+ case KILL_BACKGROUND_PROCESSES_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
String packageName = data.readString();
- restartPackage(packageName);
+ killBackgroundProcesses(packageName);
+ reply.writeNoException();
+ return true;
+ }
+
+ case FORCE_STOP_PACKAGE_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ String packageName = data.readString();
+ forceStopPackage(packageName);
reply.writeNoException();
return true;
}
@@ -2337,7 +2355,20 @@ class ActivityManagerProxy implements IActivityManager
/* this base class version is never called */
return true;
}
- public void handleApplicationError(IBinder app, String tag,
+ public void handleApplicationCrash(IBinder app,
+ ApplicationErrorReport.CrashInfo crashInfo) throws RemoteException
+ {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ data.writeStrongBinder(app);
+ crashInfo.writeToParcel(data, 0);
+ mRemote.transact(HANDLE_APPLICATION_CRASH_TRANSACTION, data, reply, 0);
+ reply.readException();
+ reply.recycle();
+ data.recycle();
+ }
+ public boolean handleApplicationWtf(IBinder app, String tag,
ApplicationErrorReport.CrashInfo crashInfo) throws RemoteException
{
Parcel data = Parcel.obtain();
@@ -2346,10 +2377,12 @@ class ActivityManagerProxy implements IActivityManager
data.writeStrongBinder(app);
data.writeString(tag);
crashInfo.writeToParcel(data, 0);
- mRemote.transact(HANDLE_APPLICATION_ERROR_TRANSACTION, data, reply, 0);
+ mRemote.transact(HANDLE_APPLICATION_WTF_TRANSACTION, data, reply, 0);
reply.readException();
+ boolean res = reply.readInt() != 0;
reply.recycle();
data.recycle();
+ return res;
}
public void signalPersistentProcesses(int sig) throws RemoteException {
@@ -2363,12 +2396,23 @@ class ActivityManagerProxy implements IActivityManager
reply.recycle();
}
- public void restartPackage(String packageName) throws RemoteException {
+ public void killBackgroundProcesses(String packageName) throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ data.writeString(packageName);
+ mRemote.transact(KILL_BACKGROUND_PROCESSES_TRANSACTION, data, reply, 0);
+ reply.readException();
+ data.recycle();
+ reply.recycle();
+ }
+
+ public void forceStopPackage(String packageName) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeString(packageName);
- mRemote.transact(RESTART_PACKAGE_TRANSACTION, data, reply, 0);
+ mRemote.transact(FORCE_STOP_PACKAGE_TRANSACTION, data, reply, 0);
reply.readException();
data.recycle();
reply.recycle();
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/ApplicationContext.java b/core/java/android/app/ApplicationContext.java
index de370d2..d89b877 100644
--- a/core/java/android/app/ApplicationContext.java
+++ b/core/java/android/app/ApplicationContext.java
@@ -466,14 +466,7 @@ class ApplicationContext extends Context {
@Override
public SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory) {
- File dir = getDatabasesDir();
- if (!dir.isDirectory() && dir.mkdir()) {
- FileUtils.setPermissions(dir.getPath(),
- FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
- -1, -1);
- }
-
- File f = makeFilename(dir, name);
+ File f = validateFilePath(name, true);
SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(f, factory);
setFilePermissionsFromMode(f.getPath(), mode, 0);
return db;
@@ -482,7 +475,7 @@ class ApplicationContext extends Context {
@Override
public boolean deleteDatabase(String name) {
try {
- File f = makeFilename(getDatabasesDir(), name);
+ File f = validateFilePath(name, false);
return f.delete();
} catch (Exception e) {
}
@@ -491,7 +484,7 @@ class ApplicationContext extends Context {
@Override
public File getDatabasePath(String name) {
- return makeFilename(getDatabasesDir(), name);
+ return validateFilePath(name, false);
}
@Override
@@ -1454,12 +1447,35 @@ class ApplicationContext extends Context {
FileUtils.setPermissions(name, perms, -1, -1);
}
+ private File validateFilePath(String name, boolean createDirectory) {
+ File dir;
+ File f;
+
+ if (name.charAt(0) == File.separatorChar) {
+ String dirPath = name.substring(0, name.lastIndexOf(File.separatorChar));
+ dir = new File(dirPath);
+ name = name.substring(name.lastIndexOf(File.separatorChar));
+ f = new File(dir, name);
+ } else {
+ dir = getDatabasesDir();
+ f = makeFilename(dir, name);
+ }
+
+ if (createDirectory && !dir.isDirectory() && dir.mkdir()) {
+ FileUtils.setPermissions(dir.getPath(),
+ FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
+ -1, -1);
+ }
+
+ return f;
+ }
+
private File makeFilename(File base, String name) {
if (name.indexOf(File.separatorChar) < 0) {
return new File(base, name);
}
throw new IllegalArgumentException(
- "File " + name + " contains a path separator");
+ "File " + name + " contains a path separator");
}
// ----------------------------------------------------------------------
diff --git a/core/java/android/app/ApplicationErrorReport.java b/core/java/android/app/ApplicationErrorReport.java
index e89b3ad0..a4b692f 100644
--- a/core/java/android/app/ApplicationErrorReport.java
+++ b/core/java/android/app/ApplicationErrorReport.java
@@ -195,6 +195,7 @@ public class ApplicationErrorReport implements Parcelable {
StringWriter sw = new StringWriter();
tr.printStackTrace(new PrintWriter(sw));
stackTrace = sw.toString();
+ exceptionMessage = tr.getMessage();
// Populate fields with the "root cause" exception
while (tr.getCause() != null) {
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;
* &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
* &lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
* android:orientation=&quot;vertical&quot;
- * android:layout_width=&quot;fill_parent&quot;
- * android:layout_height=&quot;fill_parent&quot;
+ * android:layout_width=&quot;match_parent&quot;
+ * android:layout_height=&quot;match_parent&quot;
* android:paddingLeft=&quot;8dp&quot;
* android:paddingRight=&quot;8dp&quot;&gt;
*
* &lt;ExpandableListView android:id=&quot;@id/android:list&quot;
- * android:layout_width=&quot;fill_parent&quot;
- * android:layout_height=&quot;fill_parent&quot;
+ * android:layout_width=&quot;match_parent&quot;
+ * android:layout_height=&quot;match_parent&quot;
* android:background=&quot;#00FF00&quot;
* android:layout_weight=&quot;1&quot;
* android:drawSelectorOnTop=&quot;false&quot;/&gt;
*
* &lt;TextView android:id=&quot;@id/android:empty&quot;
- * android:layout_width=&quot;fill_parent&quot;
- * android:layout_height=&quot;fill_parent&quot;
+ * android:layout_width=&quot;match_parent&quot;
+ * android:layout_height=&quot;match_parent&quot;
* android:background=&quot;#FF0000&quot;
* android:text=&quot;No data&quot;/&gt;
* &lt;/LinearLayout&gt;
@@ -114,19 +114,19 @@ import java.util.Map;
* <pre>
* &lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
* &lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- * android:layout_width=&quot;fill_parent&quot;
+ * android:layout_width=&quot;match_parent&quot;
* android:layout_height=&quot;wrap_content&quot;
* android:orientation=&quot;vertical&quot;&gt;
*
* &lt;TextView android:id=&quot;@+id/text1&quot;
* android:textSize=&quot;16sp&quot;
* android:textStyle=&quot;bold&quot;
- * android:layout_width=&quot;fill_parent&quot;
+ * android:layout_width=&quot;match_parent&quot;
* android:layout_height=&quot;wrap_content&quot;/&gt;
*
* &lt;TextView android:id=&quot;@+id/text2&quot;
* android:textSize=&quot;16sp&quot;
- * android:layout_width=&quot;fill_parent&quot;
+ * android:layout_width=&quot;match_parent&quot;
* android:layout_height=&quot;wrap_content&quot;/&gt;
* &lt;/LinearLayout&gt;
* </pre>
diff --git a/core/java/android/app/IActivityController.aidl b/core/java/android/app/IActivityController.aidl
index 804dd61..c76a517 100644
--- a/core/java/android/app/IActivityController.aidl
+++ b/core/java/android/app/IActivityController.aidl
@@ -44,7 +44,7 @@ interface IActivityController
* it immediately.
*/
boolean appCrashed(String processName, int pid,
- String tag, String shortMsg, String longMsg,
+ String shortMsg, String longMsg,
long timeMillis, String stackTrace);
/**
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index c890c4c..016d465 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -216,7 +216,8 @@ public interface IActivityManager extends IInterface {
public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) throws RemoteException;
- public void restartPackage(final String packageName) throws RemoteException;
+ public void killBackgroundProcesses(final String packageName) throws RemoteException;
+ public void forceStopPackage(final String packageName) throws RemoteException;
// Note: probably don't want to allow applications access to these.
public void goingToSleep() throws RemoteException;
@@ -242,8 +243,9 @@ public interface IActivityManager extends IInterface {
// Special low-level communication with activity manager.
public void startRunning(String pkg, String cls, String action,
String data) throws RemoteException;
-
- public void handleApplicationError(IBinder app, String tag,
+ public void handleApplicationCrash(IBinder app,
+ ApplicationErrorReport.CrashInfo crashInfo) throws RemoteException;
+ public boolean handleApplicationWtf(IBinder app, String tag,
ApplicationErrorReport.CrashInfo crashInfo) throws RemoteException;
/*
@@ -349,7 +351,7 @@ public interface IActivityManager extends IInterface {
// Please keep these transaction codes the same -- they are also
// sent by C++ code.
int START_RUNNING_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION;
- int HANDLE_APPLICATION_ERROR_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+1;
+ int HANDLE_APPLICATION_CRASH_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+1;
int START_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+2;
int UNHANDLED_BACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+3;
int OPEN_CONTENT_URI_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+4;
@@ -423,7 +425,7 @@ public interface IActivityManager extends IInterface {
int GET_MEMORY_INFO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+75;
int GET_PROCESSES_IN_ERROR_STATE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+76;
int CLEAR_APP_DATA_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+77;
- int RESTART_PACKAGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+78;
+ int FORCE_STOP_PACKAGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+78;
int KILL_PIDS_FOR_MEMORY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+79;
int GET_SERVICES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+80;
int REPORT_PSS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+81;
@@ -446,4 +448,6 @@ public interface IActivityManager extends IInterface {
int KILL_APPLICATION_PROCESS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+98;
int START_ACTIVITY_INTENT_SENDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+99;
int OVERRIDE_PENDING_TRANSITION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+100;
+ int HANDLE_APPLICATION_WTF_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+101;
+ int KILL_BACKGROUND_PROCESSES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+102;
}
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;
* &lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
* &lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
* android:orientation=&quot;vertical&quot;
- * android:layout_width=&quot;fill_parent&quot;
- * android:layout_height=&quot;fill_parent&quot;
+ * android:layout_width=&quot;match_parent&quot;
+ * android:layout_height=&quot;match_parent&quot;
* android:paddingLeft=&quot;8dp&quot;
* android:paddingRight=&quot;8dp&quot;&gt;
*
* &lt;ListView android:id=&quot;@id/android:list&quot;
- * android:layout_width=&quot;fill_parent&quot;
- * android:layout_height=&quot;fill_parent&quot;
+ * android:layout_width=&quot;match_parent&quot;
+ * android:layout_height=&quot;match_parent&quot;
* android:background=&quot;#00FF00&quot;
* android:layout_weight=&quot;1&quot;
* android:drawSelectorOnTop=&quot;false&quot;/&gt;
*
* &lt;TextView id=&quot;@id/android:empty&quot;
- * android:layout_width=&quot;fill_parent&quot;
- * android:layout_height=&quot;fill_parent&quot;
+ * android:layout_width=&quot;match_parent&quot;
+ * android:layout_height=&quot;match_parent&quot;
* android:background=&quot;#FF0000&quot;
* android:text=&quot;No data&quot;/&gt;
* &lt;/LinearLayout&gt;
@@ -100,19 +100,19 @@ import android.widget.ListView;
* <pre>
* &lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
* &lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- * android:layout_width=&quot;fill_parent&quot;
+ * android:layout_width=&quot;match_parent&quot;
* android:layout_height=&quot;wrap_content&quot;
* android:orientation=&quot;vertical&quot;&gt;
*
* &lt;TextView android:id=&quot;@+id/text1&quot;
* android:textSize=&quot;16sp&quot;
* android:textStyle=&quot;bold&quot;
- * android:layout_width=&quot;fill_parent&quot;
+ * android:layout_width=&quot;match_parent&quot;
* android:layout_height=&quot;wrap_content&quot;/&gt;
*
* &lt;TextView android:id=&quot;@+id/text2&quot;
* android:textSize=&quot;16sp&quot;
- * android:layout_width=&quot;fill_parent&quot;
+ * android:layout_width=&quot;match_parent&quot;
* android:layout_height=&quot;wrap_content&quot;/&gt;
* &lt;/LinearLayout&gt;
* </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/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java
index fda9b81..7e5f858 100644
--- a/core/java/android/bluetooth/BluetoothA2dp.java
+++ b/core/java/android/bluetooth/BluetoothA2dp.java
@@ -83,6 +83,8 @@ public final class BluetoothA2dp {
/** Default priority for a2dp devices that should not allow incoming
* connections */
public static final int PRIORITY_OFF = 0;
+ /** Default priority when not set or when the device is unpaired */
+ public static final int PRIORITY_UNDEFINED = -1;
private final IBluetoothA2dp mService;
private final Context mContext;
diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java
index 5eb655a..b792965 100644
--- a/core/java/android/bluetooth/BluetoothHeadset.java
+++ b/core/java/android/bluetooth/BluetoothHeadset.java
@@ -109,6 +109,8 @@ public final class BluetoothHeadset {
/** Default priority for headsets that should not be auto-connected
* and not allow incoming connections. */
public static final int PRIORITY_OFF = 0;
+ /** Default priority when not set or when the device is unpaired */
+ public static final int PRIORITY_UNDEFINED = -1;
/** The voice dialer 'works' but the user experience is poor. The voice
* recognizer has trouble dealing with the 8kHz SCO signal, and it still
diff --git a/core/java/android/bluetooth/package.html b/core/java/android/bluetooth/package.html
index 4f0755e..5ff240c 100644
--- a/core/java/android/bluetooth/package.html
+++ b/core/java/android/bluetooth/package.html
@@ -12,96 +12,16 @@ devices, connecting with devices, and managing data transfer between devices.
<li>Transfer data to and from other devices</li>
</ul>
-<p class="note"><strong>Note:</strong>
+<p>
To perform Bluetooth communication using these APIs, an application must
declare the {@link android.Manifest.permission#BLUETOOTH} permission. Some
-additional functionality, such as requesting device discovery and
-pairing also requires the {@link android.Manifest.permission#BLUETOOTH_ADMIN}
+additional functionality, such as requesting device discovery,
+also requires the {@link android.Manifest.permission#BLUETOOTH_ADMIN}
permission.
</p>
-<h3>Overview</h3>
-
-<p>Here's a basic introduction to the Bluetooth classes:</p>
-<dl>
- <dt>{@link android.bluetooth.BluetoothAdapter}</dt>
- <dd>This represents the local Bluetooth adapter, which is essentially the
- entry-point to performing any interaction with Bluetooth. With it, you can
- discover other Bluetooth devices, query a list of bonded (paired) devices,
- initialize a {@link android.bluetooth.BluetoothDevice} using a known MAC
- address, and create a {@link android.bluetooth.BluetoothServerSocket} to
- listen for communications from other devices.</dd>
-
- <dt>{@link android.bluetooth.BluetoothDevice}</dt>
- <dd>This represents a remote Bluetooth device. Use this to request a
- connection with a remote device through a
- {@link android.bluetooth.BluetoothSocket}
- or query information about the device such as its name, address, class, and
- bonding state.</dd>
-
- <dt>{@link android.bluetooth.BluetoothSocket}</dt>
- <dd>This represents the interface for a Bluetooth socket
- (similar to a TCP client-side {@link java.net.Socket}). This is the
- connection point that allows an app to transfer data with another Bluetooth
- device via {@link java.io.InputStream} and {@link java.io.OutputStream}.</dd>
- <dt>{@link android.bluetooth.BluetoothServerSocket}</dt>
-
- <dd>This represents an open server socket that listens for incoming requests
- (similar to a TCP server-side {@link java.net.ServerSocket}).
- When attempting to connect two Android devices, one device will need to open
- a server socket with this class. When a connection is accepted, a new
- {@link android.bluetooth.BluetoothSocket} will be returned,
- which can be used to manage the connection and transfer data.</dd>
-
- <dt>{@link android.bluetooth.BluetoothClass}</dt>
- <dd>This represents the Bluetooth class for a device which describes general
- characteristics and capabilities of a device. This class and its subclasses
- don't provide any actual functionality. The sub-classes are entirely composed
- of constants for the device and service class definitions.</dd>
-</dl>
-
-
-<h3>Example Procedure</h3>
-
-<p>For example, here's an pseudo-code procedure for discovering and
-connecting a remote device, and transfering data:</p>
-
-<ol>
- <li>Register a {@link android.content.BroadcastReceiver} that accepts the
- {@link android.bluetooth.BluetoothDevice#ACTION_FOUND} Intent.</li>
- <li>Call {@link android.bluetooth.BluetoothAdapter#getDefaultAdapter} to
- retrieve the Android system's local
- {@link android.bluetooth.BluetoothAdapter}.</li>
- <li>Call {@link android.bluetooth.BluetoothAdapter#startDiscovery()
- BluetoothAdapter.startDiscovery()} to scan for local devices. This is where
- the BroadcastReceiver comes in; Android now scans for devices and will
- broadcast the {@link android.bluetooth.BluetoothDevice#ACTION_FOUND} Intent
- for each remote device discovered. The
- {@link android.content.BroadcastReceiver}
- you created will receive each Intent.</li>
- <li>The {@link android.bluetooth.BluetoothDevice#ACTION_FOUND} Intent
- includes the {@link android.bluetooth.BluetoothDevice#EXTRA_DEVICE}
- Parcelable extra, which is a {@link android.bluetooth.BluetoothDevice}
- object. Extract this from the Intent and call
- {@link android.bluetooth.BluetoothDevice#createRfcommSocketToServiceRecord(java.util.UUID)
- BluetoothDevice.createRfcommSocketToServiceRecord()}
- to open a {@link android.bluetooth.BluetoothSocket} with a chosen
- remote device.</li>
- <li>Call {@link android.bluetooth.BluetoothSocket#connect()
- BluetoothSocket.connect()} to connect with the remote device.</li>
- <li>When successfully connected, call
- {@link android.bluetooth.BluetoothSocket#getInputStream()
- BluetoothSocket.getInputStream()} and/or
- {@link android.bluetooth.BluetoothSocket#getOutputStream()
- BluetoothSocket.getOutputStream()} to retreive an
- {@link java.io.InputStream} and {@link java.io.OutputStream}, respectively,
- which are hooked into the socket.</li>
- <li>Use {@link java.io.InputStream#read(byte[]) InputStream.read()} and
- {@link java.io.OutputStream#write(byte[]) OutputStream.write()} to transfer
- data.</li>
-</ol>
-
-
+<p>For a detailed guide to using the Bluetooth APIs, see the <a
+href="{@docRoot}guide/topics/wireless/bluetooth.html">Bluetooth Dev Guide topic</a>.</p>
<p class="note"><strong>Note:</strong>
Not all Android devices are guaranteed to have Bluetooth functionality.</p>
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/Context.java b/core/java/android/content/Context.java
index 2ab5357..0fafe5d 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -1314,7 +1314,7 @@ public abstract class Context {
/**
* Use with {@link #getSystemService} to retrieve a
- * {@blink android.appwidget.AppWidgetManager} for accessing AppWidgets.
+ * {@link android.appwidget.AppWidgetManager} for accessing AppWidgets.
*
* @hide
* @see #getSystemService
@@ -1323,7 +1323,7 @@ public abstract class Context {
/**
* Use with {@link #getSystemService} to retrieve an
- * {@blink android.backup.IBackupManager IBackupManager} for communicating
+ * {@link android.backup.IBackupManager IBackupManager} for communicating
* with the backup mechanism.
* @hide
*
@@ -1333,7 +1333,7 @@ public abstract class Context {
/**
* Use with {@link #getSystemService} to retrieve a
- * {@blink android.os.DropBox DropBox} instance for recording
+ * {@link android.os.DropBoxManager} instance for recording
* diagnostic logs.
* @see #getSystemService
*/
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/Intent.java b/core/java/android/content/Intent.java
index ec1252a..bf37b62 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -575,7 +575,7 @@ import java.util.Set;
* {@link #setFlags} and {@link #addFlags}. See {@link #setFlags} for a list
* of all possible flags.
*/
-public class Intent implements Parcelable {
+public class Intent implements Parcelable, Cloneable {
// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
// Standard intent activity actions (see action variable).
diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java
index d436365..a9c61dc 100644
--- a/core/java/android/content/SyncManager.java
+++ b/core/java/android/content/SyncManager.java
@@ -859,8 +859,8 @@ class SyncManager implements OnAccountsUpdateListener {
}
// Cap the delay
- long maxSyncRetryTimeInSeconds = Settings.Gservices.getLong(mContext.getContentResolver(),
- Settings.Gservices.SYNC_MAX_RETRY_DELAY_IN_SECONDS,
+ long maxSyncRetryTimeInSeconds = Settings.Secure.getLong(mContext.getContentResolver(),
+ Settings.Secure.SYNC_MAX_RETRY_DELAY_IN_SECONDS,
DEFAULT_MAX_SYNC_RETRY_TIME_IN_SECONDS);
if (newDelayInMs > maxSyncRetryTimeInSeconds * 1000) {
newDelayInMs = maxSyncRetryTimeInSeconds * 1000;
diff --git a/core/java/android/content/SyncStorageEngine.java b/core/java/android/content/SyncStorageEngine.java
index d1fdfaf..4c53201 100644
--- a/core/java/android/content/SyncStorageEngine.java
+++ b/core/java/android/content/SyncStorageEngine.java
@@ -25,7 +25,6 @@ import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
import android.accounts.Account;
-import android.backup.IBackupManager;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
@@ -37,7 +36,7 @@ import android.os.Message;
import android.os.Parcel;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
-import android.os.ServiceManager;
+import android.os.SystemProperties;
import android.util.Log;
import android.util.SparseArray;
import android.util.Xml;
@@ -258,7 +257,9 @@ public class SyncStorageEngine extends Handler {
mCal = Calendar.getInstance(TimeZone.getTimeZone("GMT+0"));
- File dataDir = Environment.getDataDirectory();
+ // This call will return the correct directory whether Encrypted File Systems is
+ // enabled or not.
+ File dataDir = Environment.getSecureDataDirectory();
File systemDir = new File(dataDir, "system");
File syncDir = new File(systemDir, "sync");
mAccountInfoFile = new AtomicFile(new File(syncDir, "accounts.xml"));
@@ -511,7 +512,7 @@ public class SyncStorageEngine extends Handler {
SyncStatusInfo status = getOrCreateSyncStatusLocked(authority.ident);
status.pending = true;
- status.initialize = op.extras != null &&
+ status.initialize = op.extras != null &&
op.extras.containsKey(ContentResolver.SYNC_EXTRAS_INITIALIZE) &&
op.extras.getBoolean(ContentResolver.SYNC_EXTRAS_INITIALIZE);
}
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>
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;root&gt;
&lt;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!" /&gt;
&lt;/root&gt;
@@ -447,7 +447,7 @@ one of those resources:</p>
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;root&gt;
&lt;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!" /&gt;
&lt;/root&gt;
@@ -463,7 +463,7 @@ reference a system resource, you would need to write:</p>
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;root&gt;
&lt;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!" /&gt;
&lt;/root&gt;
@@ -476,7 +476,7 @@ strings in a layout file so that they can be localized:</p>
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;root&gt;
&lt;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" /&gt;
&lt;/root&gt;
@@ -509,7 +509,7 @@ one of the standard colors defined in the base system theme:</p>
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;root&gt;
&lt;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" /&gt;
&lt;/root&gt;
@@ -637,10 +637,10 @@ new style resource with the desired values:</p>
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;root&gt;
&lt;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!" /&gt;
&lt;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." /&gt;
&lt;/root&gt;</pre>
<h4>&nbsp;</h4>
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 1800c30..3dea286 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -208,6 +208,16 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
public static final int FLAG_RESTORE_NEEDS_APPLICATION = 1<<16;
/**
+ * Value for {@link #flags}: this is true if the application has set
+ * its android:neverEncrypt to true, false otherwise. It is used to specify
+ * that this package specifically "opts-out" of a secured file system solution,
+ * and will always store its data in-the-clear.
+ *
+ * {@hide}
+ */
+ public static final int FLAG_NEVER_ENCRYPT = 1<<17;
+
+ /**
* Flags associated with the application. Any combination of
* {@link #FLAG_SYSTEM}, {@link #FLAG_DEBUGGABLE}, {@link #FLAG_HAS_CODE},
* {@link #FLAG_PERSISTENT}, {@link #FLAG_FACTORY_TEST}, and
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 03d2a6d..53a966d 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -16,6 +16,8 @@
package android.content.pm;
+import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -518,30 +520,35 @@ public abstract class PackageManager {
* {@link #hasSystemFeature}: The device has a camera facing away
* from the screen.
*/
+ @SdkConstant(SdkConstantType.FEATURE)
public static final String FEATURE_CAMERA = "android.hardware.camera";
/**
* Feature for {@link #getSystemAvailableFeatures} and
* {@link #hasSystemFeature}: The device's camera supports auto-focus.
*/
+ @SdkConstant(SdkConstantType.FEATURE)
public static final String FEATURE_CAMERA_AUTOFOCUS = "android.hardware.camera.autofocus";
/**
* Feature for {@link #getSystemAvailableFeatures} and
* {@link #hasSystemFeature}: The device's camera supports flash.
*/
+ @SdkConstant(SdkConstantType.FEATURE)
public static final String FEATURE_CAMERA_FLASH = "android.hardware.camera.flash";
/**
* Feature for {@link #getSystemAvailableFeatures} and
* {@link #hasSystemFeature}: The device includes a light sensor.
*/
+ @SdkConstant(SdkConstantType.FEATURE)
public static final String FEATURE_SENSOR_LIGHT = "android.hardware.sensor.light";
/**
* Feature for {@link #getSystemAvailableFeatures} and
* {@link #hasSystemFeature}: The device includes a proximity sensor.
*/
+ @SdkConstant(SdkConstantType.FEATURE)
public static final String FEATURE_SENSOR_PROXIMITY = "android.hardware.sensor.proximity";
/**
@@ -549,30 +556,35 @@ public abstract class PackageManager {
* {@link #hasSystemFeature}: The device has a telephony radio with data
* communication support.
*/
+ @SdkConstant(SdkConstantType.FEATURE)
public static final String FEATURE_TELEPHONY = "android.hardware.telephony";
/**
* Feature for {@link #getSystemAvailableFeatures} and
* {@link #hasSystemFeature}: The device has a CDMA telephony stack.
*/
+ @SdkConstant(SdkConstantType.FEATURE)
public static final String FEATURE_TELEPHONY_CDMA = "android.hardware.telephony.cdma";
/**
* Feature for {@link #getSystemAvailableFeatures} and
* {@link #hasSystemFeature}: The device has a GSM telephony stack.
*/
+ @SdkConstant(SdkConstantType.FEATURE)
public static final String FEATURE_TELEPHONY_GSM = "android.hardware.telephony.gsm";
/**
* Feature for {@link #getSystemAvailableFeatures} and
* {@link #hasSystemFeature}: The device's touch screen supports multitouch.
*/
+ @SdkConstant(SdkConstantType.FEATURE)
public static final String FEATURE_TOUCHSCREEN_MULTITOUCH = "android.hardware.touchscreen.multitouch";
/**
* Feature for {@link #getSystemAvailableFeatures} and
* {@link #hasSystemFeature}: The device supports live wallpapers.
*/
+ @SdkConstant(SdkConstantType.FEATURE)
public static final String FEATURE_LIVE_WALLPAPER = "android.software.live_wallpaper";
/**
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 0754cbf..ad99f54 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -1399,6 +1399,12 @@ public class PackageParser {
ai.flags |= ApplicationInfo.FLAG_TEST_ONLY;
}
+ if (sa.getBoolean(
+ com.android.internal.R.styleable.AndroidManifestApplication_neverEncrypt,
+ false)) {
+ ai.flags |= ApplicationInfo.FLAG_NEVER_ENCRYPT;
+ }
+
String str;
str = sa.getNonResourceString(
com.android.internal.R.styleable.AndroidManifestApplication_permission);
diff --git a/core/java/android/content/res/ColorStateList.java b/core/java/android/content/res/ColorStateList.java
index 453a83d..70baaef 100644
--- a/core/java/android/content/res/ColorStateList.java
+++ b/core/java/android/content/res/ColorStateList.java
@@ -44,7 +44,7 @@ import java.util.Arrays;
* &lt;selector xmlns:android="http://schemas.android.com/apk/res/android"&gt;
* &lt;item android:state_focused="true" android:color="@color/testcolor1"/&gt;
* &lt;item android:state_pressed="true" android:state_enabled="false" android:color="@color/testcolor2" /&gt;
- * &lt;item android:state_enabled="false" android:colore="@color/testcolor3" /&gt;
+ * &lt;item android:state_enabled="false" android:color="@color/testcolor3" /&gt;
* &lt;item android:state_active="true" android:color="@color/testcolor4" /&gt;
* &lt;item android:color="@color/testcolor5"/&gt;
* &lt;/selector&gt;
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/ddm/DdmHandleHello.java b/core/java/android/ddm/DdmHandleHello.java
index c5d591f..0603ca5 100644
--- a/core/java/android/ddm/DdmHandleHello.java
+++ b/core/java/android/ddm/DdmHandleHello.java
@@ -152,8 +152,8 @@ public class DdmHandleHello extends ChunkHandler {
"hprof-heap-dump", "method-trace-profiling"
};
- if (Config.LOGD)
- Log.d("ddm-heap", "Got feature list request");
+ if (Config.LOGV)
+ Log.v("ddm-heap", "Got feature list request");
int size = 4 + 4 * features.length;
for (int i = features.length-1; i >= 0; i--)
diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java
index 271f973..0c6bb1a 100644
--- a/core/java/android/hardware/SensorManager.java
+++ b/core/java/android/hardware/SensorManager.java
@@ -364,7 +364,7 @@ public class SensorManager
final float[] values = new float[3];
final int[] status = new int[1];
final long timestamp[] = new long[1];
- Process.setThreadPriority(Process.THREAD_PRIORITY_DISPLAY);
+ Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_DISPLAY);
if (!open()) {
return;
@@ -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 6978974..5d5bd9c 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);
}
}
@@ -1056,8 +1056,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(
@@ -1086,7 +1086,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));
}
@@ -1099,7 +1099,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/inputmethodservice/KeyboardView.java b/core/java/android/inputmethodservice/KeyboardView.java
index 76131fc..b0c3909 100755
--- a/core/java/android/inputmethodservice/KeyboardView.java
+++ b/core/java/android/inputmethodservice/KeyboardView.java
@@ -1118,6 +1118,11 @@ public class KeyboardView extends View implements View.OnClickListener {
if (action == MotionEvent.ACTION_DOWN) mSwipeTracker.clear();
mSwipeTracker.addMovement(me);
+ // Ignore all motion events until a DOWN.
+ if (mAbortKey && action != MotionEvent.ACTION_DOWN) {
+ return true;
+ }
+
if (mGestureDetector.onTouchEvent(me)) {
showPreview(NOT_A_KEY);
mHandler.removeMessages(MSG_REPEAT);
@@ -1150,9 +1155,14 @@ public class KeyboardView extends View implements View.OnClickListener {
mKeys[keyIndex].codes[0] : 0);
if (mCurrentKey >= 0 && mKeys[mCurrentKey].repeatable) {
mRepeatKeyIndex = mCurrentKey;
- repeatKey();
Message msg = mHandler.obtainMessage(MSG_REPEAT);
mHandler.sendMessageDelayed(msg, REPEAT_START_DELAY);
+ repeatKey();
+ // Delivering the key could have caused an abort
+ if (mAbortKey) {
+ mRepeatKeyIndex = NOT_A_KEY;
+ break;
+ }
}
if (mCurrentKey != NOT_A_KEY) {
Message msg = mHandler.obtainMessage(MSG_LONGPRESS, me);
diff --git a/core/java/android/net/MobileDataStateTracker.java b/core/java/android/net/MobileDataStateTracker.java
index 538e51a..b254961 100644
--- a/core/java/android/net/MobileDataStateTracker.java
+++ b/core/java/android/net/MobileDataStateTracker.java
@@ -60,12 +60,11 @@ public class MobileDataStateTracker extends NetworkStateTracker {
* @param apnType the Phone apnType
* @param tag the name of this network
*/
- public MobileDataStateTracker(Context context, Handler target,
- int netType, String apnType, String tag) {
+ public MobileDataStateTracker(Context context, Handler target, int netType, String tag) {
super(context, target, netType,
TelephonyManager.getDefault().getNetworkType(), tag,
TelephonyManager.getDefault().getNetworkTypeName());
- mApnType = apnType;
+ mApnType = networkTypeToApnType(netType);
mPhoneService = null;
if(netType == ConnectivityManager.TYPE_MOBILE) {
mEnabled = true;
@@ -501,4 +500,22 @@ public class MobileDataStateTracker extends NetworkStateTracker {
+ " APN type \"" + apnType + "\"");
return Phone.APN_REQUEST_FAILED;
}
+
+ public static String networkTypeToApnType(int netType) {
+ switch(netType) {
+ case ConnectivityManager.TYPE_MOBILE:
+ return Phone.APN_TYPE_DEFAULT; // TODO - use just one of these
+ case ConnectivityManager.TYPE_MOBILE_MMS:
+ return Phone.APN_TYPE_MMS;
+ case ConnectivityManager.TYPE_MOBILE_SUPL:
+ return Phone.APN_TYPE_SUPL;
+ case ConnectivityManager.TYPE_MOBILE_DUN:
+ return Phone.APN_TYPE_DUN;
+ case ConnectivityManager.TYPE_MOBILE_HIPRI:
+ return Phone.APN_TYPE_HIPRI;
+ default:
+ Log.e(TAG, "Error mapping networkType " + netType + " to apnType.");
+ return null;
+ }
+ }
}
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/Uri.java b/core/java/android/net/Uri.java
index 9a1b65d..f2ea539 100644
--- a/core/java/android/net/Uri.java
+++ b/core/java/android/net/Uri.java
@@ -1567,51 +1567,40 @@ public abstract class Uri implements Parcelable, Comparable<Uri> {
if (isOpaque()) {
throw new UnsupportedOperationException(NOT_HIERARCHICAL);
}
+ if (key == null) {
+ throw new NullPointerException("key");
+ }
- String query = getEncodedQuery();
-
+ final String query = getEncodedQuery();
if (query == null) {
return null;
}
- String encodedKey;
- try {
- encodedKey = URLEncoder.encode(key, DEFAULT_ENCODING);
- } catch (UnsupportedEncodingException e) {
- throw new AssertionError(e);
- }
-
- String prefix = encodedKey + "=";
+ final String encodedKey = encode(key, null);
+ final int encodedKeyLength = encodedKey.length();
- if (query.length() < prefix.length()) {
- return null;
- }
+ int encodedKeySearchIndex = 0;
+ final int encodedKeySearchEnd = query.length() - (encodedKeyLength + 1);
- int start;
- if (query.startsWith(prefix)) {
- // It's the first parameter.
- start = prefix.length();
- } else {
- // It must be later in the query string.
- prefix = "&" + prefix;
- start = query.indexOf(prefix);
-
- if (start == -1) {
- // Not found.
- return null;
+ while (encodedKeySearchIndex <= encodedKeySearchEnd) {
+ int keyIndex = query.indexOf(encodedKey, encodedKeySearchIndex);
+ if (keyIndex == -1) {
+ break;
+ }
+ final int equalsIndex = keyIndex + encodedKeyLength;
+ if (query.charAt(equalsIndex) != '=') {
+ encodedKeySearchIndex = equalsIndex + 1;
+ continue;
+ }
+ if (keyIndex == 0 || query.charAt(keyIndex - 1) == '&') {
+ int end = query.indexOf('&', equalsIndex);
+ if (end == -1) {
+ end = query.length();
+ }
+ return decode(query.substring(equalsIndex + 1, end));
}
-
- start += prefix.length();
- }
-
- // Find end of value.
- int end = query.indexOf('&', start);
- if (end == -1) {
- end = query.length();
}
-
- String value = query.substring(start, end);
- return decode(value);
+ return null;
}
/** Identifies a null parcelled Uri. */
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/AsyncTask.java b/core/java/android/os/AsyncTask.java
index 7d2c698..d28148c 100644
--- a/core/java/android/os/AsyncTask.java
+++ b/core/java/android/os/AsyncTask.java
@@ -82,7 +82,7 @@ import java.util.concurrent.atomic.AtomicInteger;
* <li><code>Result</code>, the type of the result of the background
* computation.</li>
* </ol>
- * <p>Not all types are always used by am asynchronous task. To mark a type as unused,
+ * <p>Not all types are always used by an asynchronous task. To mark a type as unused,
* simply use the type {@link Void}:</p>
* <pre>
* private class MyTask extends AsyncTask&lt;Void, Void, Void&gt; { ... }
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index e9353d8..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");
@@ -41,6 +41,9 @@ public class Build {
/** The name of the instruction set (CPU type + ABI convention) of native code. */
public static final String CPU_ABI = getString("ro.product.cpu.abi");
+ /** The name of the second instruction set (CPU type + ABI convention) of native code. */
+ public static final String CPU_ABI2 = getString("ro.product.cpu.abi2");
+
/** The manufacturer of the product/hardware. */
public static final String MANUFACTURER = getString("ro.product.manufacturer");
@@ -50,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/Debug.java b/core/java/android/os/Debug.java
index b4f64b6..b33e8be 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -753,6 +753,16 @@ href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Lo
}
/**
+ * Dumps the contents of VM reference tables (e.g. JNI locals and
+ * globals) to the log file.
+ *
+ * @hide
+ */
+ public static final void dumpReferenceTables() {
+ VMDebug.dumpReferenceTables();
+ }
+
+ /**
* API for gathering and querying instruction counts.
*
* Example usage:
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index f761e8e..9491bd4 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -18,6 +18,8 @@ package android.os;
import java.io.File;
+import android.os.IMountService;
+
/**
* Provides access to environment variables.
*/
@@ -26,6 +28,10 @@ public class Environment {
private static final File ROOT_DIRECTORY
= getDirectory("ANDROID_ROOT", "/system");
+ private static final String SYSTEM_PROPERTY_EFS_ENABLED = "persist.security.efs.enabled";
+
+ private static IMountService mMntSvc = null;
+
/**
* Gets the Android root directory.
*/
@@ -33,9 +39,55 @@ public class Environment {
return ROOT_DIRECTORY;
}
+ /**
+ * Gets the system directory available for secure storage.
+ * If Encrypted File system is enabled, it returns an encrypted directory (/data/secure/system).
+ * Otherwise, it returns the unencrypted /data/system directory.
+ * @return File object representing the secure storage system directory.
+ * @hide
+ */
+ public static File getSystemSecureDirectory() {
+ if (isEncryptedFilesystemEnabled()) {
+ return new File(SECURE_DATA_DIRECTORY, "system");
+ } else {
+ return new File(DATA_DIRECTORY, "system");
+ }
+ }
+
+ /**
+ * Gets the data directory for secure storage.
+ * If Encrypted File system is enabled, it returns an encrypted directory (/data/secure).
+ * Otherwise, it returns the unencrypted /data directory.
+ * @return File object representing the data directory for secure storage.
+ * @hide
+ */
+ public static File getSecureDataDirectory() {
+ if (isEncryptedFilesystemEnabled()) {
+ return SECURE_DATA_DIRECTORY;
+ } else {
+ return DATA_DIRECTORY;
+ }
+ }
+
+ /**
+ * Returns whether the Encrypted File System feature is enabled on the device or not.
+ * @return <code>true</code> if Encrypted File System feature is enabled, <code>false</code>
+ * if disabled.
+ * @hide
+ */
+ public static boolean isEncryptedFilesystemEnabled() {
+ return SystemProperties.getBoolean(SYSTEM_PROPERTY_EFS_ENABLED, false);
+ }
+
private static final File DATA_DIRECTORY
= getDirectory("ANDROID_DATA", "/data");
+ /**
+ * @hide
+ */
+ private static final File SECURE_DATA_DIRECTORY
+ = getDirectory("ANDROID_SECURE_DATA", "/data/secure");
+
private static final File EXTERNAL_STORAGE_DIRECTORY
= getDirectory("EXTERNAL_STORAGE", "/sdcard");
@@ -119,9 +171,19 @@ public class Environment {
/**
* Gets the current state of the external storage device.
+ * Note: This call should be deprecated as it doesn't support
+ * multiple volumes.
*/
public static String getExternalStorageState() {
- return SystemProperties.get("EXTERNAL_STORAGE_STATE", MEDIA_REMOVED);
+ try {
+ if (mMntSvc == null) {
+ mMntSvc = IMountService.Stub.asInterface(ServiceManager
+ .getService("mount"));
+ }
+ return mMntSvc.getVolumeState(getExternalStorageDirectory().toString());
+ } catch (Exception rex) {
+ return Environment.MEDIA_REMOVED;
+ }
}
static File getDirectory(String variableName, String defaultPath) {
diff --git a/core/java/android/os/FileObserver.java b/core/java/android/os/FileObserver.java
index 38d252e..3457815 100644
--- a/core/java/android/os/FileObserver.java
+++ b/core/java/android/os/FileObserver.java
@@ -103,9 +103,7 @@ public abstract class FileObserver {
try {
observer.onEvent(mask, path);
} catch (Throwable throwable) {
- Log.e(LOG_TAG, "Unhandled throwable " + throwable.toString() +
- " (returned by observer " + observer + ")", throwable);
- RuntimeInit.crash("FileObserver", throwable);
+ Log.wtf(LOG_TAG, "Unhandled exception in FileObserver " + observer, throwable);
}
}
}
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/ICheckinService.aidl b/core/java/android/os/ICheckinService.aidl
index 619079a..e5609b0 100644
--- a/core/java/android/os/ICheckinService.aidl
+++ b/core/java/android/os/ICheckinService.aidl
@@ -29,6 +29,9 @@ interface ICheckinService {
/** Reboot into the recovery system and wipe all user data. */
void masterClear();
+ /** Reboot into the recovery system, wipe all user data and enable Encrypted File Systems. */
+ void masterClearAndToggleEFS(boolean efsEnabled);
+
/**
* Determine if the device is under parental control. Return null if
* we are unable to check the parental control status.
diff --git a/core/java/android/os/IMountService.aidl b/core/java/android/os/IMountService.aidl
index 96d44b6..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,14 +65,46 @@ interface IMountService
void setPlayNotificationSounds(boolean value);
/**
- * Returns true if USB Mass Storage is automatically started
- * when a UMS host is detected.
+ * Gets the state of an volume via it's mountpoint.
*/
- boolean getAutoStartUms();
+ String getVolumeState(String mountPoint);
+
+ /*
+ * Creates a secure container with the specified parameters.
+ * On success, the filesystem container-path is returned.
+ */
+ String createSecureContainer(String id, int sizeMb, String fstype, String key, int ownerUid);
+
+ /*
+ * Finalize a container which has just been created and populated.
+ * After finalization, the container is immutable.
+ */
+ void finalizeSecureContainer(String id);
+
+ /*
+ * Destroy a secure container, and free up all resources associated with it.
+ * NOTE: Ensure all references are released prior to deleting.
+ */
+ void destroySecureContainer(String id);
+
+ /*
+ * Mount a secure container with the specified key and owner UID.
+ * On success, the filesystem container-path is returned.
+ */
+ String mountSecureContainer(String id, String key, int ownerUid);
+
+ /*
+ * Returns the filesystem path of a mounted secure container.
+ */
+ String getSecureContainerPath(String id);
+
+ /**
+ * Gets an Array of currently known secure container IDs
+ */
+ String[] getSecureContainerList();
/**
- * Sets whether or not USB Mass Storage is automatically started
- * when a UMS host is detected.
+ * Shuts down the MountService and gracefully unmounts all external media.
*/
- void setAutoStartUms(boolean value);
+ void shutdown();
}
diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl
index 0afc537..23762ca 100644
--- a/core/java/android/os/IPowerManager.aidl
+++ b/core/java/android/os/IPowerManager.aidl
@@ -31,6 +31,7 @@ interface IPowerManager
void preventScreenOn(boolean prevent);
boolean isScreenOn();
void reboot(String reason);
+ void crash(String message);
// sets the brightness of the backlights (screen, keyboard, button) 0-255
void setBacklightBrightness(int brightness);
diff --git a/core/java/android/os/MemoryFile.java b/core/java/android/os/MemoryFile.java
index 03542dd..9742b05 100644
--- a/core/java/android/os/MemoryFile.java
+++ b/core/java/android/os/MemoryFile.java
@@ -52,7 +52,7 @@ public class MemoryFile
private static native void native_write(FileDescriptor fd, int address, byte[] buffer,
int srcOffset, int destOffset, int count, boolean isUnpinned) throws IOException;
private static native void native_pin(FileDescriptor fd, boolean pin) throws IOException;
- private static native int native_get_mapped_size(FileDescriptor fd) throws IOException;
+ private static native int native_get_size(FileDescriptor fd) throws IOException;
private FileDescriptor mFD; // ashmem file descriptor
private int mAddress; // address of ashmem memory
@@ -300,20 +300,19 @@ public class MemoryFile
* @hide
*/
public static boolean isMemoryFile(FileDescriptor fd) throws IOException {
- return (native_get_mapped_size(fd) >= 0);
+ return (native_get_size(fd) >= 0);
}
/**
- * Returns the size of the memory file, rounded up to a page boundary, that
- * the file descriptor refers to, or -1 if the file descriptor does not
- * refer to a memory file.
+ * Returns the size of the memory file that the file descriptor refers to,
+ * or -1 if the file descriptor does not refer to a memory file.
*
* @throws IOException If <code>fd</code> is not a valid file descriptor.
*
* @hide
*/
- public static int getMappedSize(FileDescriptor fd) throws IOException {
- return native_get_mapped_size(fd);
+ public static int getSize(FileDescriptor fd) throws IOException {
+ return native_get_size(fd);
}
/**
diff --git a/core/java/android/os/MessageQueue.java b/core/java/android/os/MessageQueue.java
index caf0923..bc653d6 100644
--- a/core/java/android/os/MessageQueue.java
+++ b/core/java/android/os/MessageQueue.java
@@ -115,9 +115,7 @@ public class MessageQueue {
didIdle = true;
keep = ((IdleHandler)idler).queueIdle();
} catch (Throwable t) {
- Log.e("MessageQueue",
- "IdleHandler threw exception", t);
- RuntimeInit.crash("MessageQueue", t);
+ Log.wtf("MessageQueue", "IdleHandler threw exception", t);
}
if (!keep) {
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/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 293dabc..e4eaf45 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -326,12 +326,11 @@ public class PowerManager
{
synchronized (mToken) {
if (mHeld) {
+ Log.wtf(TAG, "WakeLock finalized while still held: " + mTag);
try {
mService.releaseWakeLock(mToken, 0);
} catch (RemoteException e) {
}
- RuntimeInit.crash(TAG, new Exception(
- "WakeLock finalized while still held: "+mTag));
}
}
}
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
new file mode 100644
index 0000000..3dd3918
--- /dev/null
+++ b/core/java/android/os/RecoverySystem.java
@@ -0,0 +1,418 @@
+/*
+ * 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.os;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.security.GeneralSecurityException;
+import java.security.PublicKey;
+import java.security.Signature;
+import java.security.SignatureException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+import android.content.Context;
+import android.util.Log;
+
+import org.apache.harmony.security.asn1.BerInputStream;
+import org.apache.harmony.security.pkcs7.ContentInfo;
+import org.apache.harmony.security.pkcs7.SignedData;
+import org.apache.harmony.security.pkcs7.SignerInfo;
+import org.apache.harmony.security.provider.cert.X509CertImpl;
+
+/**
+ * RecoverySystem contains methods for interacting with the Android
+ * recovery system (the separate partition that can be used to install
+ * system updates, wipe user data, etc.)
+ */
+public class RecoverySystem {
+ private static final String TAG = "RecoverySystem";
+
+ /**
+ * Default location of zip file containing public keys (X509
+ * certs) authorized to sign OTA updates.
+ */
+ private static final File DEFAULT_KEYSTORE =
+ new File("/system/etc/security/otacerts.zip");
+
+ /** Send progress to listeners no more often than this (in ms). */
+ private static final long PUBLISH_PROGRESS_INTERVAL_MS = 500;
+
+ /** Used to communicate with recovery. See bootable/recovery/recovery.c. */
+ private static File RECOVERY_DIR = new File("/cache/recovery");
+ private static File COMMAND_FILE = new File(RECOVERY_DIR, "command");
+ private static File LOG_FILE = new File(RECOVERY_DIR, "log");
+
+ // Length limits for reading files.
+ private static int LOG_FILE_MAX_LENGTH = 8 * 1024;
+
+ /**
+ * Interface definition for a callback to be invoked regularly as
+ * verification proceeds.
+ */
+ public interface ProgressListener {
+ /**
+ * Called periodically as the verification progresses.
+ *
+ * @param progress the approximate percentage of the
+ * verification that has been completed, ranging from 0
+ * to 100 (inclusive).
+ */
+ public void onProgress(int progress);
+ }
+
+ /** @return the set of certs that can be used to sign an OTA package. */
+ private static HashSet<Certificate> getTrustedCerts(File keystore)
+ throws IOException, GeneralSecurityException {
+ HashSet<Certificate> trusted = new HashSet<Certificate>();
+ if (keystore == null) {
+ keystore = DEFAULT_KEYSTORE;
+ }
+ ZipFile zip = new ZipFile(keystore);
+ try {
+ CertificateFactory cf = CertificateFactory.getInstance("X.509");
+ Enumeration<? extends ZipEntry> entries = zip.entries();
+ while (entries.hasMoreElements()) {
+ ZipEntry entry = entries.nextElement();
+ trusted.add(cf.generateCertificate(zip.getInputStream(entry)));
+ }
+ } finally {
+ zip.close();
+ }
+ return trusted;
+ }
+
+ /**
+ * Verify the cryptographic signature of a system update package
+ * before installing it. Note that the package is also verified
+ * separately by the installer once the device is rebooted into
+ * the recovery system. This function will return only if the
+ * package was successfully verified; otherwise it will throw an
+ * exception.
+ *
+ * Verification of a package can take significant time, so this
+ * function should not be called from a UI thread.
+ *
+ * @param packageFile the package to be verified
+ * @param listener an object to receive periodic progress
+ * updates as verification proceeds. May be null.
+ * @param deviceCertsZipFile the zip file of certificates whose
+ * public keys we will accept. Verification succeeds if the
+ * package is signed by the private key corresponding to any
+ * public key in this file. May be null to use the system default
+ * file (currently "/system/etc/security/otacerts.zip").
+ *
+ * @throws IOException if there were any errors reading the
+ * package or certs files.
+ * @throws GeneralSecurityException if verification failed
+ */
+ public static void verifyPackage(File packageFile,
+ ProgressListener listener,
+ File deviceCertsZipFile)
+ throws IOException, GeneralSecurityException {
+ long fileLen = packageFile.length();
+
+ RandomAccessFile raf = new RandomAccessFile(packageFile, "r");
+ try {
+ int lastPercent = 0;
+ long lastPublishTime = System.currentTimeMillis();
+ if (listener != null) {
+ listener.onProgress(lastPercent);
+ }
+
+ raf.seek(fileLen - 6);
+ byte[] footer = new byte[6];
+ raf.readFully(footer);
+
+ if (footer[2] != (byte)0xff || footer[3] != (byte)0xff) {
+ throw new SignatureException("no signature in file (no footer)");
+ }
+
+ int commentSize = (footer[4] & 0xff) | ((footer[5] & 0xff) << 8);
+ int signatureStart = (footer[0] & 0xff) | ((footer[1] & 0xff) << 8);
+ Log.v(TAG, String.format("comment size %d; signature start %d",
+ commentSize, signatureStart));
+
+ byte[] eocd = new byte[commentSize + 22];
+ raf.seek(fileLen - (commentSize + 22));
+ raf.readFully(eocd);
+
+ // Check that we have found the start of the
+ // end-of-central-directory record.
+ if (eocd[0] != (byte)0x50 || eocd[1] != (byte)0x4b ||
+ eocd[2] != (byte)0x05 || eocd[3] != (byte)0x06) {
+ throw new SignatureException("no signature in file (bad footer)");
+ }
+
+ for (int i = 4; i < eocd.length-3; ++i) {
+ if (eocd[i ] == (byte)0x50 && eocd[i+1] == (byte)0x4b &&
+ eocd[i+2] == (byte)0x05 && eocd[i+3] == (byte)0x06) {
+ throw new SignatureException("EOCD marker found after start of EOCD");
+ }
+ }
+
+ // The following code is largely copied from
+ // JarUtils.verifySignature(). We could just *call* that
+ // method here if that function didn't read the entire
+ // input (ie, the whole OTA package) into memory just to
+ // compute its message digest.
+
+ BerInputStream bis = new BerInputStream(
+ new ByteArrayInputStream(eocd, commentSize+22-signatureStart, signatureStart));
+ ContentInfo info = (ContentInfo)ContentInfo.ASN1.decode(bis);
+ SignedData signedData = info.getSignedData();
+ if (signedData == null) {
+ throw new IOException("signedData is null");
+ }
+ Collection encCerts = signedData.getCertificates();
+ if (encCerts.isEmpty()) {
+ throw new IOException("encCerts is empty");
+ }
+ // Take the first certificate from the signature (packages
+ // should contain only one).
+ Iterator it = encCerts.iterator();
+ X509Certificate cert = null;
+ if (it.hasNext()) {
+ cert = new X509CertImpl((org.apache.harmony.security.x509.Certificate)it.next());
+ } else {
+ throw new SignatureException("signature contains no certificates");
+ }
+
+ List sigInfos = signedData.getSignerInfos();
+ SignerInfo sigInfo;
+ if (!sigInfos.isEmpty()) {
+ sigInfo = (SignerInfo)sigInfos.get(0);
+ } else {
+ throw new IOException("no signer infos!");
+ }
+
+ // Check that the public key of the certificate contained
+ // in the package equals one of our trusted public keys.
+
+ HashSet<Certificate> trusted = getTrustedCerts(
+ deviceCertsZipFile == null ? DEFAULT_KEYSTORE : deviceCertsZipFile);
+
+ PublicKey signatureKey = cert.getPublicKey();
+ boolean verified = false;
+ for (Certificate c : trusted) {
+ if (c.getPublicKey().equals(signatureKey)) {
+ verified = true;
+ break;
+ }
+ }
+ if (!verified) {
+ throw new SignatureException("signature doesn't match any trusted key");
+ }
+
+ // The signature cert matches a trusted key. Now verify that
+ // the digest in the cert matches the actual file data.
+
+ // The verifier in recovery *only* handles SHA1withRSA
+ // signatures. SignApk.java always uses SHA1withRSA, no
+ // matter what the cert says to use. Ignore
+ // cert.getSigAlgName(), and instead use whatever
+ // algorithm is used by the signature (which should be
+ // SHA1withRSA).
+
+ String da = sigInfo.getdigestAlgorithm();
+ String dea = sigInfo.getDigestEncryptionAlgorithm();
+ String alg = null;
+ if (da == null || dea == null) {
+ // fall back to the cert algorithm if the sig one
+ // doesn't look right.
+ alg = cert.getSigAlgName();
+ } else {
+ alg = da + "with" + dea;
+ }
+ Signature sig = Signature.getInstance(alg);
+ sig.initVerify(cert);
+
+ // The signature covers all of the OTA package except the
+ // archive comment and its 2-byte length.
+ long toRead = fileLen - commentSize - 2;
+ long soFar = 0;
+ raf.seek(0);
+ byte[] buffer = new byte[4096];
+ while (soFar < toRead) {
+ int size = buffer.length;
+ if (soFar + size > toRead) {
+ size = (int)(toRead - soFar);
+ }
+ int read = raf.read(buffer, 0, size);
+ sig.update(buffer, 0, read);
+ soFar += read;
+
+ if (listener != null) {
+ long now = System.currentTimeMillis();
+ int p = (int)(soFar * 100 / toRead);
+ if (p > lastPercent &&
+ now - lastPublishTime > PUBLISH_PROGRESS_INTERVAL_MS) {
+ lastPercent = p;
+ lastPublishTime = now;
+ listener.onProgress(lastPercent);
+ }
+ }
+ }
+ if (listener != null) {
+ listener.onProgress(100);
+ }
+
+ if (!sig.verify(sigInfo.getEncryptedDigest())) {
+ throw new SignatureException("signature digest verification failed");
+ }
+ } finally {
+ raf.close();
+ }
+ }
+
+ /**
+ * Reboots the device in order to install the given update
+ * package.
+ * Requires the {@link android.Manifest.permission#REBOOT}
+ * and {@link android.Manifest.permission#ACCESS_CACHE_FILESYSTEM}
+ * permissions.
+ *
+ * @param context the Context to use
+ * @param packageFile the update package to install. Currently
+ * must be on the /cache or /data partitions.
+ *
+ * @throws IOException if writing the recovery command file
+ * fails, or if the reboot itself fails.
+ */
+ public static void installPackage(Context context, File packageFile)
+ throws IOException {
+ String filename = packageFile.getCanonicalPath();
+
+ if (filename.startsWith("/cache/")) {
+ filename = "CACHE:" + filename.substring(7);
+ } else if (filename.startsWith("/data/")) {
+ filename = "DATA:" + filename.substring(6);
+ } else {
+ throw new IllegalArgumentException(
+ "Must start with /cache or /data: " + filename);
+ }
+ Log.w(TAG, "!!! REBOOTING TO INSTALL " + filename + " !!!");
+ String arg = "--update_package=" + filename;
+ bootCommand(context, arg);
+ }
+
+ /**
+ * Reboots the device and wipes the user data partition. This is
+ * sometimes called a "factory reset", which is something of a
+ * misnomer because the system partition is not restored to its
+ * factory state.
+ * Requires the {@link android.Manifest.permission#REBOOT}
+ * and {@link android.Manifest.permission#ACCESS_CACHE_FILESYSTEM}
+ * permissions.
+ *
+ * @param context the Context to use
+ *
+ * @throws IOException if writing the recovery command file
+ * fails, or if the reboot itself fails.
+ */
+ public static void rebootWipeUserData(Context context)
+ throws IOException {
+ bootCommand(context, "--wipe_data");
+ }
+
+ /**
+ * Reboot into the recovery system to wipe the /data partition and toggle
+ * Encrypted File Systems on/off.
+ * @param extras to add to the RECOVERY_COMPLETED intent after rebooting.
+ * @throws IOException if something goes wrong.
+ *
+ * @hide
+ */
+ public static void rebootToggleEFS(Context context, boolean efsEnabled)
+ throws IOException {
+ if (efsEnabled) {
+ bootCommand(context, "--set_encrypted_filesystem=on");
+ } else {
+ bootCommand(context, "--set_encrypted_filesystem=off");
+ }
+ }
+
+ /**
+ * Reboot into the recovery system with the supplied argument.
+ * @param arg to pass to the recovery utility.
+ * @throws IOException if something goes wrong.
+ */
+ private static void bootCommand(Context context, String arg) throws IOException {
+ RECOVERY_DIR.mkdirs(); // In case we need it
+ COMMAND_FILE.delete(); // In case it's not writable
+ LOG_FILE.delete();
+
+ FileWriter command = new FileWriter(COMMAND_FILE);
+ try {
+ command.write(arg);
+ command.write("\n");
+ } finally {
+ command.close();
+ }
+
+ // Having written the command file, go ahead and reboot
+ PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+ pm.reboot("recovery");
+
+ throw new IOException("Reboot failed (no permissions?)");
+ }
+
+ /**
+ * Called after booting to process and remove recovery-related files.
+ * @return the log file from recovery, or null if none was found.
+ *
+ * @hide
+ */
+ public static String handleAftermath() {
+ // Record the tail of the LOG_FILE
+ String log = null;
+ try {
+ log = FileUtils.readTextFile(LOG_FILE, -LOG_FILE_MAX_LENGTH, "...\n");
+ } catch (FileNotFoundException e) {
+ Log.i(TAG, "No recovery log file");
+ } catch (IOException e) {
+ Log.e(TAG, "Error reading recovery log", e);
+ }
+
+ // Delete everything in RECOVERY_DIR
+ String[] names = RECOVERY_DIR.list();
+ for (int i = 0; names != null && i < names.length; i++) {
+ File f = new File(RECOVERY_DIR, names[i]);
+ if (!f.delete()) {
+ Log.e(TAG, "Can't delete: " + f);
+ } else {
+ Log.i(TAG, "Deleted: " + f);
+ }
+ }
+
+ return log;
+ }
+
+ private void RecoverySystem() { } // Do not instantiate
+}
diff --git a/core/java/android/pim/vcard/VCardComposer.java b/core/java/android/pim/vcard/VCardComposer.java
index 4eaea6a..389c9f4 100644
--- a/core/java/android/pim/vcard/VCardComposer.java
+++ b/core/java/android/pim/vcard/VCardComposer.java
@@ -54,6 +54,7 @@ import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
+import java.lang.reflect.Method;
import java.nio.charset.UnsupportedCharsetException;
import java.util.ArrayList;
import java.util.Arrays;
@@ -197,7 +198,7 @@ public class VCardComposer {
if (mIsDoCoMo) {
try {
// Create one empty entry.
- mWriter.write(createOneEntryInternal("-1"));
+ mWriter.write(createOneEntryInternal("-1", null));
} catch (IOException e) {
Log.e(LOG_TAG,
"IOException occurred during exportOneContactData: "
@@ -428,6 +429,14 @@ public class VCardComposer {
}
public boolean createOneEntry() {
+ return createOneEntry(null);
+ }
+
+ /**
+ * @param getEntityIteratorMethod For Dependency Injection.
+ * @hide just for testing.
+ */
+ public boolean createOneEntry(Method getEntityIteratorMethod) {
if (mCursor == null || mCursor.isAfterLast()) {
mErrorReason = FAILURE_REASON_NOT_INITIALIZED;
return false;
@@ -439,7 +448,8 @@ public class VCardComposer {
vcard = createOneCallLogEntryInternal();
} else {
if (mIdColumn >= 0) {
- vcard = createOneEntryInternal(mCursor.getString(mIdColumn));
+ vcard = createOneEntryInternal(mCursor.getString(mIdColumn),
+ getEntityIteratorMethod);
} else {
Log.e(LOG_TAG, "Incorrect mIdColumn: " + mIdColumn);
return true;
@@ -475,7 +485,8 @@ public class VCardComposer {
return true;
}
- private String createOneEntryInternal(final String contactId) {
+ private String createOneEntryInternal(final String contactId,
+ Method getEntityIteratorMethod) {
final Map<String, List<ContentValues>> contentValuesListMap =
new HashMap<String, List<ContentValues>>();
// The resolver may return the entity iterator with no data. It is possiible.
@@ -484,13 +495,34 @@ public class VCardComposer {
boolean dataExists = false;
EntityIterator entityIterator = null;
try {
- final Uri uri = RawContacts.CONTENT_URI.buildUpon()
- .appendEncodedPath(contactId)
- .appendEncodedPath(RawContacts.Entity.CONTENT_DIRECTORY)
- .appendQueryParameter(Data.FOR_EXPORT_ONLY, "1")
- .build();
- entityIterator = RawContacts.newEntityIterator(mContentResolver.query(
- uri, null, null, null, null));
+
+ if (getEntityIteratorMethod != null) {
+ try {
+ final Uri uri = RawContacts.CONTENT_URI.buildUpon()
+ .appendQueryParameter(Data.FOR_EXPORT_ONLY, "1")
+ .build();
+ final String selection = Data.CONTACT_ID + "=?";
+ final String[] selectionArgs = new String[] {contactId};
+ entityIterator = (EntityIterator)getEntityIteratorMethod.invoke(null,
+ mContentResolver, uri, selection, selectionArgs, null);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ } else {
+ final Uri uri = RawContacts.CONTENT_URI.buildUpon()
+ .appendEncodedPath(contactId)
+ .appendEncodedPath(RawContacts.Entity.CONTENT_DIRECTORY)
+ .appendQueryParameter(Data.FOR_EXPORT_ONLY, "1")
+ .build();
+ entityIterator = RawContacts.newEntityIterator(mContentResolver.query(
+ uri, null, null, null, null));
+ }
+
+ if (entityIterator == null) {
+ Log.e(LOG_TAG, "EntityIterator is null");
+ return "";
+ }
+
dataExists = entityIterator.hasNext();
while (entityIterator.hasNext()) {
Entity entity = entityIterator.next();
diff --git a/core/java/android/pim/vcard/VCardParser_V21.java b/core/java/android/pim/vcard/VCardParser_V21.java
index e7c19cf..c2928cb 100644
--- a/core/java/android/pim/vcard/VCardParser_V21.java
+++ b/core/java/android/pim/vcard/VCardParser_V21.java
@@ -110,11 +110,11 @@ public class VCardParser_V21 extends VCardParser {
private long mTimeHandleBase64;
public VCardParser_V21() {
- this(VCardConfig.PARSE_TYPE_UNKNOWN);
+ this(null);
}
public VCardParser_V21(VCardSourceDetector detector) {
- this(detector.getEstimatedType());
+ this(detector != null ? detector.getEstimatedType() : VCardConfig.PARSE_TYPE_UNKNOWN);
}
public VCardParser_V21(int parseType) {
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 b74564a..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,58 +1049,39 @@ public final class Calendar {
public static final String MAX_INSTANCE = "maxInstance";
/**
- * The minimum Julian day in the BusyBits table.
+ * The minimum Julian day in the EventDays table.
* <P>Type: INTEGER</P>
*/
- public static final String MIN_BUSYBITS = "minBusyBits";
+ public static final String MIN_EVENTDAYS = "minEventDays";
/**
- * The maximum Julian day in the BusyBits table.
+ * The maximum Julian day in the EventDays table.
* <P>Type: INTEGER</P>
*/
- public static final String MAX_BUSYBITS = "maxBusyBits";
+ public static final String MAX_EVENTDAYS = "maxEventDays";
}
public static final class CalendarMetaData implements CalendarMetaDataColumns {
}
- public interface BusyBitsColumns {
+ public interface EventDaysColumns {
/**
- * The Julian day number.
+ * The Julian starting day number.
* <P>Type: INTEGER (int)</P>
*/
- public static final String DAY = "day";
+ public static final String STARTDAY = "startDay";
+ public static final String ENDDAY = "endDay";
- /**
- * 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";
}
- 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;
+ public static final class EventDays implements EventDaysColumns {
+ public static final Uri CONTENT_URI = Uri.parse("content://calendar/instances/groupbyday");
- // The number of intervals in a day
- public static final int INTERVALS_PER_DAY = 24 * 60 / MINUTES_PER_BUSY_INTERVAL;
+ public static final String[] PROJECTION = { STARTDAY, ENDDAY };
+ public static final String SELECTION = "selected==1";
/**
- * Retrieves the busy bits for the Julian days starting at "startDay"
+ * Retrieves the days with events for the Julian days starting at "startDay"
* for "numDays".
*
* @param cr the ContentResolver
@@ -1116,8 +1097,8 @@ public final class Calendar {
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 cr.query(builder.build(), PROJECTION, SELECTION,
+ null /* selection args */, STARTDAY);
}
}
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index ed9198e..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;
@@ -35,6 +35,7 @@ import android.graphics.Rect;
import android.net.Uri;
import android.os.RemoteException;
import android.text.TextUtils;
+import android.util.DisplayMetrics;
import android.util.Pair;
import android.view.View;
@@ -52,49 +53,50 @@ import java.io.InputStream;
* ContactsContract defines an extensible database of contact-related
* information. Contact information is stored in a three-tier data model:
* </p>
- * <blockquote>
- * <p>
+ * <ul>
+ * <li>
* The {@link Data} table contains all kinds of personal data: phone numbers,
* email addresses etc. The list of data kinds that can be stored in this table
* is open-ended. There is a predefined set of common kinds, but any application
* can add its own data kinds.
- * </p>
- * <p>
+ * </li>
+ * <li>
* A row in the {@link RawContacts} table represents a set of Data describing a
- * person and associated with a single account.
- * </p>
- * <p>
+ * 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
* RawContacts presumably describing the same person.
- * </p>
- * </blockquote>
+ * </li>
+ * </ul>
* <p>
* Other tables include:
* </p>
- * <blockquote>
- * <p>
+ * <ul>
+ * <li>
* {@link Groups}, which contains information about raw contact groups - the
* current API does not support the notion of groups spanning multiple accounts.
- * </p>
- * <p>
+ * </li>
+ * <li>
* {@link StatusUpdates}, which contains social status updates including IM
* availability.
- * </p>
- * <p>
+ * </li>
+ * <li>
* {@link AggregationExceptions}, which is used for manual aggregation and
* disaggregation of raw contacts
- * </p>
- * <p>
+ * </li>
+ * <li>
* {@link Settings}, which contains visibility and sync settings for accounts
* and groups.
- * </p>
- * <p>
+ * </li>
+ * <li>
* {@link SyncState}, which contains free-form data maintained on behalf of sync
* adapters
- * </p>
- * <p>
- * {@link PhoneLookup}, which is used for quick caller-ID lookup</id>
- * </blockquote>
+ * </li>
+ * <li>
+ * {@link PhoneLookup}, which is used for quick caller-ID lookup</li>
+ * </ul>
*/
@SuppressWarnings("unused")
public final class ContactsContract {
@@ -244,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
@@ -270,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
@@ -294,7 +304,7 @@ public final class ContactsContract {
* The display name for the contact.
* <P>Type: TEXT</P>
*/
- public static final String DISPLAY_NAME = "display_name";
+ public static final String DISPLAY_NAME = ContactNameColumns.DISPLAY_NAME_PRIMARY;
/**
* Reference to the row in the RawContacts table holding the contact name.
@@ -440,6 +450,8 @@ public final class ContactsContract {
}
/**
+ * Contact name and contact name metadata columns in the RawContacts table.
+ *
* @see Contacts
* @see RawContacts
* @hide
@@ -456,13 +468,13 @@ public final class ContactsContract {
* The default text shown as the contact's display name. It is based on
* available data, see {@link #DISPLAY_NAME_SOURCE}.
*/
- public static final String DISPLAY_NAME = "display_name";
+ public static final String DISPLAY_NAME_PRIMARY = "display_name";
/**
* Alternative representation of the display name. If display name is
* based on the structured name and the structured name follows
* the Western full name style, then this field contains the "family name first"
- * version of the full name. Otherwise, it is the same as {@link #DISPLAY_NAME}.
+ * version of the full name. Otherwise, it is the same as DISPLAY_NAME_PRIMARY.
*/
public static final String DISPLAY_NAME_ALTERNATIVE = "display_name_alt";
@@ -483,7 +495,7 @@ public final class ContactsContract {
* the sort key is the name's Pinyin spelling; for Japanese names
* it is the Hiragana version of the phonetic name.
*/
- public static final String SORT_KEY = "sort_key";
+ public static final String SORT_KEY_PRIMARY = "sort_key";
/**
* Sort key based on the alternative representation of the full name,
@@ -562,7 +574,7 @@ public final class ContactsContract {
* </tr>
* <tr>
* <td>String</td>
- * <td>{@link #DISPLAY_NAME}</td>
+ * <td>DISPLAY_NAME_PRIMARY</td>
* <td>read-only</td>
* <td>The display name for the contact. It is the display name
* contributed by the raw contact referred to by the NAME_RAW_CONTACT_ID
@@ -692,7 +704,7 @@ public final class ContactsContract {
* </table>
*/
public static class Contacts implements BaseColumns, ContactsColumns,
- ContactOptionsColumns, ContactStatusColumns {
+ ContactOptionsColumns, ContactNameColumns, ContactStatusColumns {
/**
* This utility class cannot be instantiated
*/
@@ -1519,6 +1531,7 @@ public final class ContactsContract {
super(cursor);
}
+ @Override
public android.content.Entity getEntityAndIncrementCursor(Cursor cursor)
throws RemoteException {
final int columnRawContactId = cursor.getColumnIndexOrThrow(RawContacts._ID);
@@ -1614,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;
/**
@@ -1633,6 +1666,7 @@ public final class ContactsContract {
/**
* @deprecated use {@link #STATUS}
*/
+ @Deprecated
public static final String PRESENCE_CUSTOM_STATUS = STATUS;
/**
@@ -1689,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";
@@ -1738,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. */
@@ -1757,30 +1794,35 @@ public final class ContactsContract {
* @see ContactsContract.Data
*/
protected interface DataColumnsWithJoins extends BaseColumns, DataColumns, StatusColumns,
- RawContactsColumns, ContactsColumns, ContactOptionsColumns, ContactStatusColumns {
-
+ RawContactsColumns, ContactsColumns, ContactNameColumns, ContactOptionsColumns,
+ ContactStatusColumns {
}
/**
* <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
@@ -1797,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
@@ -1935,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>
@@ -1944,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>
@@ -1976,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>
@@ -1998,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>
@@ -2027,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>
@@ -2044,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>
@@ -2096,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>
@@ -2119,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>
@@ -2232,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),
@@ -2258,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[] {
@@ -2283,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>
@@ -3039,7 +3124,7 @@ public final class ContactsContract {
/**
* The alphabet used for capturing the phonetic name.
- * See {@link ContactsContract.PhoneticNameStyle}.
+ * See ContactsContract.PhoneticNameStyle.
* @hide
*/
public static final String PHONETIC_NAME_STYLE = DATA11;
@@ -3922,6 +4007,12 @@ public final class ContactsContract {
* <td>{@link #DATA9}</td>
* <td></td>
* </tr>
+ * <tr>
+ * <td>String</td>
+ * <td>PHONETIC_NAME_STYLE</td>
+ * <td>{@link #DATA10}</td>
+ * <td></td>
+ * </tr>
* </table>
*/
public static final class Organization implements DataColumnsWithJoins, CommonColumns {
@@ -3979,6 +4070,13 @@ public final class ContactsContract {
public static final String OFFICE_LOCATION = DATA9;
/**
+ * The alphabet used for capturing the phonetic name.
+ * See {@link ContactsContract.PhoneticNameStyle}.
+ * @hide
+ */
+ public static final String PHONETIC_NAME_STYLE = DATA10;
+
+ /**
* Return the string resource that best describes the given
* {@link #TYPE}. Will always return a valid resource.
*/
@@ -4599,6 +4697,7 @@ public final class ContactsContract {
super(cursor);
}
+ @Override
public Entity getEntityAndIncrementCursor(Cursor cursor) throws RemoteException {
// we expect the cursor is already at the row we need to read from
final ContentValues values = new ContentValues();
@@ -4881,8 +4980,10 @@ public final class ContactsContract {
/**
* Extra used to specify pivot dialog location in screen coordinates.
+ * @deprecated Use {@link Intent#setSourceBounds(Rect)} instead.
* @hide
*/
+ @Deprecated
public static final String EXTRA_TARGET_RECT = "target_rect";
/**
@@ -4942,15 +5043,17 @@ public final class ContactsContract {
*/
public static void showQuickContact(Context context, View target, Uri lookupUri, int mode,
String[] excludeMimes) {
- // Find location and bounds of target view
- final int[] location = new int[2];
- target.getLocationOnScreen(location);
+ // Find location and bounds of target view, adjusting based on the
+ // assumed local density.
+ final float appScale = context.getResources().getCompatibilityInfo().applicationScale;
+ final int[] pos = new int[2];
+ target.getLocationOnScreen(pos);
final Rect rect = new Rect();
- rect.left = location[0];
- rect.top = location[1];
- rect.right = rect.left + target.getWidth();
- rect.bottom = rect.top + target.getHeight();
+ rect.left = (int) (pos[0] * appScale + 0.5f);
+ rect.top = (int) (pos[1] * appScale + 0.5f);
+ rect.right = (int) ((pos[0] + target.getWidth()) * appScale + 0.5f);
+ rect.bottom = (int) ((pos[1] + target.getHeight()) * appScale + 0.5f);
// Trigger with obtained rectangle
showQuickContact(context, rect, lookupUri, mode, excludeMimes);
@@ -4967,8 +5070,11 @@ public final class ContactsContract {
* @param target Specific {@link Rect} that this dialog should be
* centered around, in screen coordinates. In particular, if
* the dialog has a "callout" arrow, it will be pointed and
- * centered around this {@link Rect}.
- * @param lookupUri A {@link ContactsContract.Contacts#CONTENT_LOOKUP_URI} style
+ * centered around this {@link Rect}. If you are running at a
+ * non-native density, you need to manually adjust using
+ * {@link DisplayMetrics#density} before calling.
+ * @param lookupUri A
+ * {@link ContactsContract.Contacts#CONTENT_LOOKUP_URI} style
* {@link Uri} that describes a specific contact to feature
* in this dialog.
* @param mode Any of {@link #MODE_SMALL}, {@link #MODE_MEDIUM}, or
@@ -4987,7 +5093,7 @@ public final class ContactsContract {
| Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
intent.setData(lookupUri);
- intent.putExtra(EXTRA_TARGET_RECT, target);
+ intent.setSourceBounds(target);
intent.putExtra(EXTRA_MODE, mode);
intent.putExtra(EXTRA_EXCLUDE_MIMES, excludeMimes);
context.startActivity(intent);
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index ae53dbe2..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";
@@ -179,6 +175,13 @@ public final class MediaStore {
public final static String EXTRA_OUTPUT = "output";
/**
+ * The string that is used when a media attribute is not known. For example,
+ * if an audio file does not have any meta data, the artist and album columns
+ * will be set to this value.
+ */
+ public static final String UNKNOWN_STRING = "<unknown>";
+
+ /**
* Common fields for most MediaProvider tables
*/
@@ -844,7 +847,6 @@ public final class MediaStore {
* The position, in ms, playback was at when playback for this file
* was last stopped.
* <P>Type: INTEGER (long)</P>
- * @hide
*/
public static final String BOOKMARK = "bookmark";
@@ -923,7 +925,6 @@ public final class MediaStore {
/**
* Non-zero if the audio file is a podcast
* <P>Type: INTEGER (boolean)</P>
- * @hide
*/
public static final String IS_PODCAST = "is_podcast";
@@ -964,7 +965,7 @@ public final class MediaStore {
public static String keyFor(String name) {
if (name != null) {
boolean sortfirst = false;
- if (name.equals(android.media.MediaFile.UNKNOWN_STRING)) {
+ if (name.equals(UNKNOWN_STRING)) {
return "\001";
}
// Check if the first character is \001. We use this to
@@ -1258,7 +1259,6 @@ public final class MediaStore {
* @param from The position of the item to move
* @param to The position to move the item to
* @return true on success
- * @hide
*/
public static final boolean moveItem(ContentResolver res,
long playlistId, int from, int to) {
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 8dc7a55..7db9fdc 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1453,7 +1453,6 @@ public final class Settings {
*/
public static final String[] SETTINGS_TO_BACKUP = {
STAY_ON_WHILE_PLUGGED_IN,
- END_BUTTON_BEHAVIOR,
WIFI_SLEEP_POLICY,
WIFI_USE_STATIC_IP,
WIFI_STATIC_IP,
@@ -2453,234 +2452,9 @@ public final class Settings {
public static final String LAST_SETUP_SHOWN = "last_setup_shown";
/**
- * @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";
-
- /**
* How frequently (in seconds) to check the memory status of the
* device.
+ * @hide
*/
public static final String MEMCHECK_INTERVAL = "memcheck_interval";
@@ -2688,6 +2462,7 @@ public final class Settings {
* Max frequency (in seconds) to log memory check stats, in realtime
* seconds. This allows for throttling of logs when the device is
* running for large amounts of time.
+ * @hide
*/
public static final String MEMCHECK_LOG_REALTIME_INTERVAL =
"memcheck_log_realtime_interval";
@@ -2695,6 +2470,7 @@ public final class Settings {
/**
* Boolean indicating whether rebooting due to system memory checks
* is enabled.
+ * @hide
*/
public static final String MEMCHECK_SYSTEM_ENABLED = "memcheck_system_enabled";
@@ -2702,12 +2478,14 @@ public final class Settings {
* How many bytes the system process must be below to avoid scheduling
* a soft reboot. This reboot will happen when it is next determined
* to be a good time.
+ * @hide
*/
public static final String MEMCHECK_SYSTEM_SOFT_THRESHOLD = "memcheck_system_soft";
/**
* How many bytes the system process must be below to avoid scheduling
* a hard reboot. This reboot will happen immediately.
+ * @hide
*/
public static final String MEMCHECK_SYSTEM_HARD_THRESHOLD = "memcheck_system_hard";
@@ -2715,18 +2493,21 @@ public final class Settings {
* How many bytes the phone process must be below to avoid scheduling
* a soft restart. This restart will happen when it is next determined
* to be a good time.
+ * @hide
*/
public static final String MEMCHECK_PHONE_SOFT_THRESHOLD = "memcheck_phone_soft";
/**
* How many bytes the phone process must be below to avoid scheduling
* a hard restart. This restart will happen immediately.
+ * @hide
*/
public static final String MEMCHECK_PHONE_HARD_THRESHOLD = "memcheck_phone_hard";
/**
* Boolean indicating whether restarting the phone process due to
* memory checks is enabled.
+ * @hide
*/
public static final String MEMCHECK_PHONE_ENABLED = "memcheck_phone_enabled";
@@ -2734,6 +2515,7 @@ public final class Settings {
* First time during the day it is okay to kill processes
* or reboot the device due to low memory situations. This number is
* in seconds since midnight.
+ * @hide
*/
public static final String MEMCHECK_EXEC_START_TIME = "memcheck_exec_start_time";
@@ -2741,6 +2523,7 @@ public final class Settings {
* Last time during the day it is okay to kill processes
* or reboot the device due to low memory situations. This number is
* in seconds since midnight.
+ * @hide
*/
public static final String MEMCHECK_EXEC_END_TIME = "memcheck_exec_end_time";
@@ -2748,6 +2531,7 @@ public final class Settings {
* How long the screen must have been off in order to kill processes
* or reboot. This number is in seconds. A value of -1 means to
* entirely disregard whether the screen is on.
+ * @hide
*/
public static final String MEMCHECK_MIN_SCREEN_OFF = "memcheck_min_screen_off";
@@ -2756,6 +2540,7 @@ public final class Settings {
* or reboot. This number is in seconds. Note: this value must be
* smaller than {@link #MEMCHECK_RECHECK_INTERVAL} or else it will
* always see an alarm scheduled within its time.
+ * @hide
*/
public static final String MEMCHECK_MIN_ALARM = "memcheck_min_alarm";
@@ -2765,12 +2550,14 @@ public final class Settings {
* this value must be larger than {@link #MEMCHECK_MIN_ALARM} or else
* the alarm to schedule the recheck will always appear within the
* minimum "do not execute now" time.
+ * @hide
*/
public static final String MEMCHECK_RECHECK_INTERVAL = "memcheck_recheck_interval";
/**
* How frequently (in DAYS) to reboot the device. If 0, no reboots
* will occur.
+ * @hide
*/
public static final String REBOOT_INTERVAL = "reboot_interval";
@@ -2778,6 +2565,7 @@ public final class Settings {
* First time during the day it is okay to force a reboot of the
* device (if REBOOT_INTERVAL is set). This number is
* in seconds since midnight.
+ * @hide
*/
public static final String REBOOT_START_TIME = "reboot_start_time";
@@ -2786,692 +2574,117 @@ public final class Settings {
* a reboot can be executed. If 0, a reboot will always be executed at
* exactly the given time. Otherwise, it will only be executed if
* the device is idle within the window.
+ * @hide
*/
public static final String REBOOT_WINDOW = "reboot_window";
/**
- * 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://&lt;it&gt; routing infos for Google Sync Server subcriptions.
- */
- public static final String GSYNC_USE_RMQ2_ROUTING_INFO = "gsync_use_rmq2_routing_info";
-
- /**
- * Enable use of ssl session caching.
- * 'db' - save each session in a (per process) database
- * 'file' - save each session in a (per process) file
- * not set or any other value - normal java in-memory caching
- */
- public static final String SSL_SESSION_CACHE = "ssl_session_cache";
-
- /**
- * How many bytes long a message has to be, in order to be gzipped.
- */
- public static final String SYNC_MIN_GZIP_BYTES =
- "sync_min_gzip_bytes";
-
- /**
- * 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}.
+ * Threshold values for the duration and level of a discharge cycle, under
+ * which we log discharge cycle info.
+ * @hide
*/
- public static final String SETTINGS_CONTRIBUTORS_PRETTY_URL =
- "settings_contributors_pretty_url";
+ public static final String BATTERY_DISCHARGE_DURATION_THRESHOLD =
+ "battery_discharge_duration_threshold";
+ /** @hide */
+ public static final String BATTERY_DISCHARGE_THRESHOLD = "battery_discharge_threshold";
/**
- * URL that points to the Terms Of Service for the device.
- * <p>
- * This should be a pretty http URL.
+ * Flag for allowing ActivityManagerService to send ACTION_APP_ERROR intents
+ * on application crashes and ANRs. If this is disabled, the crash/ANR dialog
+ * will never display the "Report" button.
+ * Type: int ( 0 = disallow, 1 = allow )
+ * @hide
*/
- public static final String SETUP_GOOGLE_TOS_URL = "setup_google_tos_url";
+ public static final String SEND_ACTION_APP_ERROR = "send_action_app_error";
/**
- * URL that points to the Android privacy policy for the device.
- * <p>
- * This should be a pretty http URL.
+ * Nonzero causes Log.wtf() to crash.
+ * @hide
*/
- public static final String SETUP_ANDROID_PRIVACY_URL = "setup_android_privacy_url";
+ public static final String WTF_IS_FATAL = "wtf_is_fatal";
/**
- * URL that points to the Google privacy policy for the device.
- * <p>
- * This should be a pretty http URL.
+ * Maximum age of entries kept by {@link android.os.IDropBox}.
+ * @hide
*/
- public static final String SETUP_GOOGLE_PRIVACY_URL = "setup_google_privacy_url";
-
+ public static final String DROPBOX_AGE_SECONDS =
+ "dropbox_age_seconds";
/**
- * Request an MSISDN token for various Google services.
+ * Maximum amount of disk space used by {@link android.os.IDropBox} no matter what.
+ * @hide
*/
- public static final String USE_MSISDN_TOKEN = "use_msisdn_token";
-
+ public static final String DROPBOX_QUOTA_KB =
+ "dropbox_quota_kb";
/**
- * RSA public key used to encrypt passwords stored in the database.
+ * Percent of free disk (excluding reserve) which {@link android.os.IDropBox} will use.
+ * @hide
*/
- public static final String GLS_PUBLIC_KEY = "google_login_public_key";
-
+ public static final String DROPBOX_QUOTA_PERCENT =
+ "dropbox_quota_percent";
/**
- * Only check parental control status if this is set to "true".
+ * Percent of total disk which {@link android.os.IDropBox} will never dip into.
+ * @hide
*/
- public static final String PARENTAL_CONTROL_CHECK_ENABLED =
- "parental_control_check_enabled";
-
+ public static final String DROPBOX_RESERVE_PERCENT =
+ "dropbox_reserve_percent";
/**
- * The list of applications we need to block if parental control is
- * enabled.
+ * Prefix for per-tag dropbox disable/enable settings.
+ * @hide
*/
- public static final String PARENTAL_CONTROL_APPS_LIST =
- "parental_control_apps_list";
+ public static final String DROPBOX_TAG_PREFIX =
+ "dropbox:";
- /**
- * 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.
+ * Screen timeout in milliseconds corresponding to the
+ * PowerManager's POKE_LOCK_SHORT_TIMEOUT flag (i.e. the fastest
+ * possible screen timeout behavior.)
+ * @hide
*/
- public static final String PARENTAL_CONTROL_EXPECTED_RESPONSE =
- "parental_control_expected_response";
+ public static final String SHORT_KEYLIGHT_DELAY_MS =
+ "short_keylight_delay_ms";
/**
- * When the litmus url returns a 302, declare parental control to be on
- * only if the redirect url matches this regular expression.
+ * The interval in minutes after which the amount of free storage left on the
+ * device is logged to the event log
+ * @hide
*/
- public static final String PARENTAL_CONTROL_REDIRECT_REGEX =
- "parental_control_redirect_regex";
+ public static final String SYS_FREE_STORAGE_LOG_INTERVAL =
+ "sys_free_storage_log_interval";
/**
* Threshold for the amount of change in disk free space required to report the amount of
* free space. Used to prevent spamming the logs when the disk free space isn't changing
* frequently.
+ * @hide
*/
public static final String DISK_FREE_CHANGE_REPORTING_THRESHOLD =
"disk_free_change_reporting_threshold";
- /**
- * Prefix for new Google services published by the checkin
- * server.
- */
- public static final String GOOGLE_SERVICES_PREFIX
- = "google_services:";
-
- /**
- * The maximum reconnect delay for short network outages or when the network is suspended
- * due to phone use.
- */
- public static final String SYNC_MAX_RETRY_DELAY_IN_SECONDS =
- "sync_max_retry_delay_in_seconds";
/**
* Minimum percentage of free storage on the device that is used to determine if
* the device is running low on storage.
* Say this value is set to 10, the device is considered running low on storage
* if 90% or more of the device storage is filled up.
+ * @hide
*/
public static final String SYS_STORAGE_THRESHOLD_PERCENTAGE =
"sys_storage_threshold_percentage";
/**
- * The interval in minutes after which the amount of free storage left on the
- * device is logged to the event log
- */
- public static final String SYS_FREE_STORAGE_LOG_INTERVAL =
- "sys_free_storage_log_interval";
-
- /**
- * The interval in milliseconds at which to check the number of SMS sent
- * out without asking for use permit, to limit the un-authorized SMS
- * usage.
- */
- public static final String SMS_OUTGOING_CHECK_INTERVAL_MS =
- "sms_outgoing_check_interval_ms";
-
- /**
- * The number of outgoing SMS sent without asking for user permit
- * (of {@link #SMS_OUTGOING_CHECK_INTERVAL_MS}
+ * The interval in milliseconds after which Wi-Fi is considered idle.
+ * When idle, it is possible for the device to be switched from Wi-Fi to
+ * the mobile data network.
+ * @hide
*/
- public static final String SMS_OUTGOING_CEHCK_MAX_COUNT =
- "sms_outgoing_check_max_count";
+ public static final String WIFI_IDLE_MS = "wifi_idle_ms";
/**
* The interval in milliseconds at which to check packet counts on the
* mobile data interface when screen is on, to detect possible data
* connection problems.
+ * @hide
*/
public static final String PDP_WATCHDOG_POLL_INTERVAL_MS =
"pdp_watchdog_poll_interval_ms";
@@ -3480,6 +2693,7 @@ public final class Settings {
* The interval in milliseconds at which to check packet counts on the
* mobile data interface when screen is off, to detect possible data
* connection problems.
+ * @hide
*/
public static final String PDP_WATCHDOG_LONG_POLL_INTERVAL_MS =
"pdp_watchdog_long_poll_interval_ms";
@@ -3488,6 +2702,7 @@ public final class Settings {
* The interval in milliseconds at which to check packet counts on the
* mobile data interface after {@link #PDP_WATCHDOG_TRIGGER_PACKET_COUNT}
* outgoing packets has been reached without incoming packets.
+ * @hide
*/
public static final String PDP_WATCHDOG_ERROR_POLL_INTERVAL_MS =
"pdp_watchdog_error_poll_interval_ms";
@@ -3496,6 +2711,7 @@ public final class Settings {
* The number of outgoing packets sent without seeing an incoming packet
* that triggers a countdown (of {@link #PDP_WATCHDOG_ERROR_POLL_COUNT}
* device is logged to the event log
+ * @hide
*/
public static final String PDP_WATCHDOG_TRIGGER_PACKET_COUNT =
"pdp_watchdog_trigger_packet_count";
@@ -3504,6 +2720,7 @@ public final class Settings {
* The number of polls to perform (at {@link #PDP_WATCHDOG_ERROR_POLL_INTERVAL_MS})
* after hitting {@link #PDP_WATCHDOG_TRIGGER_PACKET_COUNT} before
* attempting data connection recovery.
+ * @hide
*/
public static final String PDP_WATCHDOG_ERROR_POLL_COUNT =
"pdp_watchdog_error_poll_count";
@@ -3511,6 +2728,7 @@ public final class Settings {
/**
* The number of failed PDP reset attempts before moving to something more
* drastic: re-registering to the network.
+ * @hide
*/
public static final String PDP_WATCHDOG_MAX_PDP_RESET_FAIL_COUNT =
"pdp_watchdog_max_pdp_reset_fail_count";
@@ -3518,12 +2736,14 @@ public final class Settings {
/**
* Address to ping as a last sanity check before attempting any recovery.
* Unset or set to "0.0.0.0" to skip this check.
+ * @hide
*/
public static final String PDP_WATCHDOG_PING_ADDRESS = "pdp_watchdog_ping_address";
/**
* The "-w deadline" parameter for the ping, ie, the max time in
* seconds to spend pinging.
+ * @hide
*/
public static final String PDP_WATCHDOG_PING_DEADLINE = "pdp_watchdog_ping_deadline";
@@ -3532,231 +2752,269 @@ public final class Settings {
* after the first registration mismatch of gprs and voice service,
* to detect possible data network registration problems.
*
+ * @hide
*/
public static final String GPRS_REGISTER_CHECK_PERIOD_MS =
"gprs_register_check_period_ms";
/**
- * The interval in milliseconds after which Wi-Fi is considered idle.
- * When idle, it is possible for the device to be switched from Wi-Fi to
- * the mobile data network.
- */
- public static final String WIFI_IDLE_MS = "wifi_idle_ms";
-
- /**
- * Screen timeout in milliseconds corresponding to the
- * PowerManager's POKE_LOCK_SHORT_TIMEOUT flag (i.e. the fastest
- * possible screen timeout behavior.)
+ * The length of time in milli-seconds that automatic small adjustments to
+ * SystemClock are ignored if NITZ_UPDATE_DIFF is not exceeded.
+ * @hide
*/
- public static final String SHORT_KEYLIGHT_DELAY_MS =
- "short_keylight_delay_ms";
+ public static final String NITZ_UPDATE_SPACING = "nitz_update_spacing";
/**
- * 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.
+ * If the NITZ_UPDATE_DIFF time is exceeded then an automatic adjustment
+ * to SystemClock will be allowed even if NITZ_UPDATE_SPACING has not been
+ * exceeded.
+ * @hide
*/
- public static final String AUTOTEST_SUITES_FILE = "autotest_suites_file";
+ public static final String NITZ_UPDATE_DIFF = "nitz_update_diff";
/**
- * 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.
+ * The maximum reconnect delay for short network outages or when the network is suspended
+ * due to phone use.
+ * @hide
*/
- public static final String AUTOTEST_CHECKIN_SECONDS = "autotest_checkin_seconds";
+ public static final String SYNC_MAX_RETRY_DELAY_IN_SECONDS =
+ "sync_max_retry_delay_in_seconds";
/**
- * Interval between reboots forced by the automatic test runner.
+ * The interval in milliseconds at which to check the number of SMS sent
+ * out without asking for use permit, to limit the un-authorized SMS
+ * usage.
+ * @hide
*/
- public static final String AUTOTEST_REBOOT_SECONDS = "autotest_reboot_seconds";
-
+ public static final String SMS_OUTGOING_CHECK_INTERVAL_MS =
+ "sms_outgoing_check_interval_ms";
/**
- * Threshold values for the duration and level of a discharge cycle, under
- * which we log discharge cycle info.
+ * The number of outgoing SMS sent without asking for user permit
+ * (of {@link #SMS_OUTGOING_CHECK_INTERVAL_MS}
+ * @hide
*/
- public static final String BATTERY_DISCHARGE_DURATION_THRESHOLD =
- "battery_discharge_duration_threshold";
- public static final String BATTERY_DISCHARGE_THRESHOLD = "battery_discharge_threshold";
+ public static final String SMS_OUTGOING_CHECK_MAX_COUNT =
+ "sms_outgoing_check_max_count";
/**
- * An email address that anr bugreports should be sent to.
+ * Enable use of ssl session caching.
+ * 'db' - save each session in a (per process) database
+ * 'file' - save each session in a (per process) file
+ * not set or any other value - normal java in-memory caching
+ * @hide
*/
- public static final String ANR_BUGREPORT_RECIPIENT = "anr_bugreport_recipient";
+ public static final String SSL_SESSION_CACHE = "ssl_session_cache";
/**
- * Flag for allowing service provider to use location information to improve products and
- * services.
- * Type: int ( 0 = disallow, 1 = allow )
- * @deprecated
+ * How many bytes long a message has to be, in order to be gzipped.
+ * @hide
*/
- public static final String USE_LOCATION_FOR_SERVICES = "use_location";
+ public static final String SYNC_MIN_GZIP_BYTES =
+ "sync_min_gzip_bytes";
/**
* 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";
- /**
- * Flag for allowing ActivityManagerService to send ACTION_APP_ERROR intents
- * on application crashes and ANRs. If this is disabled, the crash/ANR dialog
- * will never display the "Report" button.
- * Type: int ( 0 = disallow, 1 = allow )
- */
- public static final String SEND_ACTION_APP_ERROR = "send_action_app_error";
/**
- * 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";
/**
- * Maximum age of entries kept by {@link android.os.IDropBox}.
- */
- public static final String DROPBOX_AGE_SECONDS =
- "dropbox_age_seconds";
- /**
- * Maximum amount of disk space used by {@link android.os.IDropBox} no matter what.
- */
- public static final String DROPBOX_QUOTA_KB =
- "dropbox_quota_kb";
- /**
- * Percent of free disk (excluding reserve) which {@link android.os.IDropBox} will use.
+ * Whether or not UMS auto-starts on UMS host detection. (0 = false, 1 = true)
+ * @hide
*/
- public static final String DROPBOX_QUOTA_PERCENT =
- "dropbox_quota_percent";
+ public static final String MOUNT_UMS_AUTOSTART = "mount_ums_autostart";
+
/**
- * Percent of total disk which {@link android.os.IDropBox} will never dip into.
+ * Whether or not a notification is displayed on UMS host detection. (0 = false, 1 = true)
+ * @hide
*/
- public static final String DROPBOX_RESERVE_PERCENT =
- "dropbox_reserve_percent";
+ public static final String MOUNT_UMS_PROMPT = "mount_ums_prompt";
+
/**
- * Prefix for per-tag dropbox disable/enable settings.
+ * Whether or not a notification is displayed while UMS is enabled. (0 = false, 1 = true)
+ * @hide
*/
- public static final String DROPBOX_TAG_PREFIX =
- "dropbox:";
+ public static final String MOUNT_UMS_NOTIFY_ENABLED = "mount_ums_notify_enabled";
/**
- * The length of time in milli-seconds that automatic small adjustments to
- * SystemClock are ignored if NITZ_UPDATE_DIFF is not exceeded.
+ * If nonzero, ANRs in invisible background processes bring up a dialog.
+ * Otherwise, the process will be silently killed.
+ * @hide
*/
- public static final String NITZ_UPDATE_SPACING = "nitz_update_spacing";
+ public static final String ANR_SHOW_BACKGROUND = "anr_show_background";
/**
- * If the NITZ_UPDATE_DIFF time is exceeded then an automatic adjustment
- * to SystemClock will be allowed even if NITZ_UPDATE_SPACING has not been
- * exceeded.
+ * @hide
*/
- public static final String NITZ_UPDATE_DIFF = "nitz_update_diff";
+ 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
+ };
/**
- * @deprecated
+ * 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
*/
- @Deprecated // Obviated by NameValueCache: just fetch the value directly.
- public static class QueryMap extends ContentQueryMap {
-
- public QueryMap(ContentResolver contentResolver, Cursor cursor, boolean keepUpdated,
- Handler handlerForUpdateNotifications) {
- super(cursor, NAME, keepUpdated, handlerForUpdateNotifications);
- }
-
- public QueryMap(ContentResolver contentResolver, boolean keepUpdated,
- Handler handlerForUpdateNotifications) {
- this(contentResolver,
- contentResolver.query(CONTENT_URI, null, null, null, null),
- keepUpdated, handlerForUpdateNotifications);
+ 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;
+ }
- public String getString(String name) {
- ContentValues cv = getValues(name);
- if (cv == null) return null;
- return cv.getAsString(VALUE);
+ /**
+ * 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 03dcf00..22bb43c 100644
--- a/core/java/android/server/BluetoothA2dpService.java
+++ b/core/java/android/server/BluetoothA2dpService.java
@@ -96,11 +96,12 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub {
BluetoothDevice.ERROR);
switch(bondState) {
case BluetoothDevice.BOND_BONDED:
- setSinkPriority(device, BluetoothA2dp.PRIORITY_ON);
+ if (getSinkPriority(device) == BluetoothA2dp.PRIORITY_UNDEFINED) {
+ setSinkPriority(device, BluetoothA2dp.PRIORITY_ON);
+ }
break;
- case BluetoothDevice.BOND_BONDING:
case BluetoothDevice.BOND_NONE:
- setSinkPriority(device, BluetoothA2dp.PRIORITY_OFF);
+ setSinkPriority(device, BluetoothA2dp.PRIORITY_UNDEFINED);
break;
}
} else if (action.equals(BluetoothDevice.ACTION_ACL_CONNECTED)) {
@@ -405,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) {
@@ -464,11 +465,8 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub {
checkSinkSuspendState(state);
mTargetA2dpState = -1;
- if (state == BluetoothA2dp.STATE_CONNECTING) {
- mAudioManager.setParameters("A2dpSuspended=false");
- }
-
- if (state == BluetoothA2dp.STATE_CONNECTING ||
+ if (getSinkPriority(device) > BluetoothA2dp.PRIORITY_OFF &&
+ state == BluetoothA2dp.STATE_CONNECTING ||
state == BluetoothA2dp.STATE_CONNECTED) {
// We have connected or attempting to connect.
// Bump priority
diff --git a/core/java/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java
index 0d0d245..b28cf43 100644
--- a/core/java/android/server/BluetoothEventLoop.java
+++ b/core/java/android/server/BluetoothEventLoop.java
@@ -21,14 +21,15 @@ import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothUuid;
-import android.os.ParcelUuid;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.Message;
+import android.os.ParcelUuid;
import android.util.Log;
import java.util.HashMap;
+import java.util.Set;
/**
* TODO: Move this to
@@ -553,7 +554,7 @@ class BluetoothEventLoop {
if (mBluetoothService.isEnabled() &&
(BluetoothUuid.isAudioSource(uuid) || BluetoothUuid.isAvrcpTarget(uuid)
|| BluetoothUuid.isAdvAudioDist(uuid)) &&
- (a2dp.getNonDisconnectedSinks().size() == 0)) {
+ !isOtherSinkInNonDisconnectingState(address)) {
BluetoothDevice device = mAdapter.getRemoteDevice(address);
authorized = a2dp.getSinkPriority(device) > BluetoothA2dp.PRIORITY_OFF;
if (authorized) {
@@ -568,6 +569,16 @@ class BluetoothEventLoop {
return authorized;
}
+ boolean isOtherSinkInNonDisconnectingState(String address) {
+ BluetoothA2dp a2dp = new BluetoothA2dp(mContext);
+ Set<BluetoothDevice> devices = a2dp.getNonDisconnectedSinks();
+ if (devices.size() == 0) return false;
+ for(BluetoothDevice dev: devices) {
+ if (!dev.getAddress().equals(address)) return true;
+ }
+ return false;
+ }
+
private void onAgentCancel() {
Intent intent = new Intent(BluetoothDevice.ACTION_PAIRING_CANCEL);
mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM);
diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java
index b590449..dfb775f 100644
--- a/core/java/android/server/BluetoothService.java
+++ b/core/java/android/server/BluetoothService.java
@@ -74,6 +74,7 @@ public class BluetoothService extends IBluetooth.Stub {
private int mNativeData;
private BluetoothEventLoop mEventLoop;
private boolean mIsAirplaneSensitive;
+ private boolean mIsAirplaneToggleable;
private int mBluetoothState;
private boolean mRestart = false; // need to call enable() after disable()
private boolean mIsDiscovering;
@@ -370,7 +371,7 @@ public class BluetoothService extends IBluetooth.Stub {
"Need BLUETOOTH_ADMIN permission");
// Airplane mode can prevent Bluetooth radio from being turned on.
- if (mIsAirplaneSensitive && isAirplaneModeOn()) {
+ if (mIsAirplaneSensitive && isAirplaneModeOn() && !mIsAirplaneToggleable) {
return false;
}
if (mBluetoothState != BluetoothAdapter.STATE_OFF) {
@@ -545,7 +546,7 @@ public class BluetoothService extends IBluetooth.Stub {
mEventLoop.onPropertyChanged(propVal);
}
- if (mIsAirplaneSensitive && isAirplaneModeOn()) {
+ if (mIsAirplaneSensitive && isAirplaneModeOn() && !mIsAirplaneToggleable) {
disable(false);
}
@@ -1597,10 +1598,17 @@ public class BluetoothService extends IBluetooth.Stub {
};
private void registerForAirplaneMode(IntentFilter filter) {
- String airplaneModeRadios = Settings.System.getString(mContext.getContentResolver(),
+ final ContentResolver resolver = mContext.getContentResolver();
+ final String airplaneModeRadios = Settings.System.getString(resolver,
Settings.System.AIRPLANE_MODE_RADIOS);
- mIsAirplaneSensitive = airplaneModeRadios == null
- ? true : airplaneModeRadios.contains(Settings.System.RADIO_BLUETOOTH);
+ final String toggleableRadios = Settings.System.getString(resolver,
+ Settings.System.AIRPLANE_MODE_TOGGLEABLE_RADIOS);
+
+ mIsAirplaneSensitive = airplaneModeRadios == null ? true :
+ airplaneModeRadios.contains(Settings.System.RADIO_BLUETOOTH);
+ mIsAirplaneToggleable = toggleableRadios == null ? false :
+ toggleableRadios.contains(Settings.System.RADIO_BLUETOOTH);
+
if (mIsAirplaneSensitive) {
filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
}
@@ -1661,6 +1669,7 @@ public class BluetoothService extends IBluetooth.Stub {
}
pw.println("mIsAirplaneSensitive = " + mIsAirplaneSensitive);
+ pw.println("mIsAirplaneToggleable = " + mIsAirplaneToggleable);
pw.println("Local address = " + getAddress());
pw.println("Local name = " + getName());
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/ITts.aidl b/core/java/android/speech/tts/ITts.aidl
index 1812188..2ed660a 100755
--- a/core/java/android/speech/tts/ITts.aidl
+++ b/core/java/android/speech/tts/ITts.aidl
@@ -59,5 +59,7 @@ interface ITts {
int unregisterCallback(in String callingApp, ITtsCallback cb);
- int playSilence(in String callingApp, in long duration, in int queueMode, in String[] params);
+ int playSilence(in String callingApp, in long duration, in int queueMode, in String[] params);
+
+ int setEngineByPackageName(in String enginePackageName);
}
diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index 3f369dd..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,50 @@ public class TextToSpeech {
} finally {
return result;
}
- }
+ }
+ }
+
+ /**
+ * Sets the speech synthesis engine to be used by its packagename.
+ *
+ * @param enginePackageName
+ * The packagename for the synthesis engine (ie, "com.svox.pico")
+ *
+ * @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);
+ 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/text/method/ArrowKeyMovementMethod.java b/core/java/android/text/method/ArrowKeyMovementMethod.java
index 0d04b13..7b307f8 100644
--- a/core/java/android/text/method/ArrowKeyMovementMethod.java
+++ b/core/java/android/text/method/ArrowKeyMovementMethod.java
@@ -247,10 +247,11 @@ implements MovementMethod
KeyEvent.META_SHIFT_ON) == 1) ||
(MetaKeyKeyListener.getMetaState(buffer,
MetaKeyKeyListener.META_SELECTING) != 0);
+ int x = (int) event.getX();
+ int y = (int) event.getY();
+ int offset = getOffset(x, y, widget);
+
if (cap) {
- int x = (int) event.getX();
- int y = (int) event.getY();
- int offset = getOffset(x, y, widget);
buffer.setSpan(LAST_TAP_DOWN, offset, offset,
Spannable.SPAN_POINT_POINT);
@@ -260,6 +261,30 @@ implements MovementMethod
// without this, users would get booted out of select
// mode once the view detected it needed to scroll.
widget.getParent().requestDisallowInterceptTouchEvent(true);
+ } else {
+ OnePointFiveTapState[] tap = buffer.getSpans(0, buffer.length(),
+ OnePointFiveTapState.class);
+
+ if (tap.length > 0) {
+ if (event.getEventTime() - tap[0].mWhen <=
+ ViewConfiguration.getDoubleTapTimeout() &&
+ sameWord(buffer, offset, Selection.getSelectionEnd(buffer))) {
+
+ tap[0].active = true;
+ MetaKeyKeyListener.startSelecting(widget, buffer);
+ widget.getParent().requestDisallowInterceptTouchEvent(true);
+ buffer.setSpan(LAST_TAP_DOWN, offset, offset,
+ Spannable.SPAN_POINT_POINT);
+ }
+
+ tap[0].mWhen = event.getEventTime();
+ } else {
+ OnePointFiveTapState newtap = new OnePointFiveTapState();
+ newtap.mWhen = event.getEventTime();
+ newtap.active = false;
+ buffer.setSpan(newtap, 0, buffer.length(),
+ Spannable.SPAN_INCLUSIVE_INCLUSIVE);
+ }
}
} else if (event.getAction() == MotionEvent.ACTION_MOVE ) {
boolean cap = (MetaKeyKeyListener.getMetaState(buffer,
@@ -287,7 +312,7 @@ implements MovementMethod
// user started the selection)
int lastDownOffset = buffer.getSpanStart(LAST_TAP_DOWN);
- // Compute the selection boundries
+ // Compute the selection boundaries
int spanstart;
int spanend;
if (offset >= lastDownOffset) {
@@ -324,6 +349,19 @@ implements MovementMethod
// XXX should do the same adjust for x as we do for the line.
+ OnePointFiveTapState[] onepointfivetap = buffer.getSpans(0, buffer.length(),
+ OnePointFiveTapState.class);
+ if (onepointfivetap.length > 0 && onepointfivetap[0].active &&
+ Selection.getSelectionStart(buffer) == Selection.getSelectionEnd(buffer)) {
+ // If we've set select mode, because there was a onepointfivetap,
+ // but there was no ensuing swipe gesture, undo the select mode
+ // and remove reference to the last onepointfivetap.
+ MetaKeyKeyListener.stopSelecting(widget, buffer);
+ for (int i=0; i < onepointfivetap.length; i++) {
+ buffer.removeSpan(onepointfivetap[i]);
+ }
+ buffer.removeSpan(LAST_TAP_DOWN);
+ }
boolean cap = (MetaKeyKeyListener.getMetaState(buffer,
KeyEvent.META_SHIFT_ON) == 1) ||
(MetaKeyKeyListener.getMetaState(buffer,
@@ -335,10 +373,10 @@ implements MovementMethod
if (tap.length > 0) {
if (event.getEventTime() - tap[0].mWhen <=
- ViewConfiguration.getDoubleTapTimeout()) {
- if (sameWord(buffer, off, Selection.getSelectionEnd(buffer))) {
- doubletap = true;
- }
+ ViewConfiguration.getDoubleTapTimeout() &&
+ sameWord(buffer, off, Selection.getSelectionEnd(buffer))) {
+
+ doubletap = true;
}
tap[0].mWhen = event.getEventTime();
@@ -351,6 +389,11 @@ implements MovementMethod
if (cap) {
buffer.removeSpan(LAST_TAP_DOWN);
+ if (onepointfivetap.length > 0 && onepointfivetap[0].active) {
+ // If we selecting something with the onepointfivetap-and
+ // swipe gesture, stop it on finger up.
+ MetaKeyKeyListener.stopSelecting(widget, buffer);
+ }
} else if (doubletap) {
Selection.setSelection(buffer,
findWordStart(buffer, off),
@@ -373,6 +416,19 @@ implements MovementMethod
long mWhen;
}
+ /* We check for a onepointfive tap. This is similar to
+ * doubletap gesture (where a finger goes down, up, down, up, in a short
+ * time period), except in the onepointfive tap, a users finger only needs
+ * to go down, up, down in a short time period. We detect this type of tap
+ * to implement the onepointfivetap-and-swipe selection gesture.
+ * This gesture allows users to select a segment of text without going
+ * through the "select text" option in the context menu.
+ */
+ private static class OnePointFiveTapState implements NoCopySpan {
+ long mWhen;
+ boolean active;
+ }
+
private static boolean sameWord(CharSequence text, int one, int two) {
int start = findWordStart(text, one);
int end = findWordEnd(text, one);
diff --git a/core/java/android/util/EventLog.java b/core/java/android/util/EventLog.java
index 81dd96e..b596d32 100644
--- a/core/java/android/util/EventLog.java
+++ b/core/java/android/util/EventLog.java
@@ -16,134 +16,41 @@
package android.util;
-import com.google.android.collect.Lists;
-
+import java.io.BufferedReader;
+import java.io.FileReader;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
+import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
-import java.util.ArrayList;
import java.util.Collection;
-import java.util.List;
+import java.util.HashMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
/**
- * {@hide}
- * Dynamically defined (in terms of event types), space efficient (i.e. "tight") event logging
- * to help instrument code for large scale stability and performance monitoring.
- *
- * Note that this class contains all static methods. This is done for efficiency reasons.
- *
- * Events for the event log are self-describing binary data structures. They start with a 20 byte
- * header (generated automatically) which contains all of the following in order:
- *
- * <ul>
- * <li> Payload length: 2 bytes - length of the non-header portion </li>
- * <li> Padding: 2 bytes - no meaning at this time </li>
- * <li> Timestamp:
- * <ul>
- * <li> Seconds: 4 bytes - seconds since Epoch </li>
- * <li> Nanoseconds: 4 bytes - plus extra nanoseconds </li>
- * </ul></li>
- * <li> Process ID: 4 bytes - matching {@link android.os.Process#myPid} </li>
- * <li> Thread ID: 4 bytes - matching {@link android.os.Process#myTid} </li>
- * </li>
- * </ul>
+ * Access to the system diagnostic event record. System diagnostic events are
+ * used to record certain system-level events (such as garbage collection,
+ * activity manager state, system watchdogs, and other low level activity),
+ * which may be automatically collected and analyzed during system development.
*
- * The above is followed by a payload, comprised of the following:
- * <ul>
- * <li> Tag: 4 bytes - unique integer used to identify a particular event. This number is also
- * used as a key to map to a string that can be displayed by log reading tools.
- * </li>
- * <li> Type: 1 byte - can be either {@link #INT}, {@link #LONG}, {@link #STRING},
- * or {@link #LIST}. </li>
- * <li> Event log value: the size and format of which is one of:
- * <ul>
- * <li> INT: 4 bytes </li>
- * <li> LONG: 8 bytes </li>
- * <li> STRING:
- * <ul>
- * <li> Size of STRING: 4 bytes </li>
- * <li> The string: n bytes as specified in the size fields above. </li>
- * </ul></li>
- * <li> {@link List LIST}:
- * <ul>
- * <li> Num items: 1 byte </li>
- * <li> N value payloads, where N is the number of items specified above. </li>
- * </ul></li>
- * </ul>
- * </li>
- * <li> '\n': 1 byte - an automatically generated newline, used to help detect and recover from log
- * corruption and enable standard unix tools like grep, tail and wc to operate
- * on event logs. </li>
- * </ul>
+ * <p>This is <b>not</b> the main "logcat" debugging log ({@link android.util.Log})!
+ * These diagnostic events are for system integrators, not application authors.
*
- * Note that all output is done in the endian-ness of the device (as determined
- * by {@link ByteOrder#nativeOrder()}).
+ * <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.
*/
-
public class EventLog {
+ private static final String TAG = "EventLog";
- // Value types
- public static final byte INT = 0;
- public static final byte LONG = 1;
- public static final byte STRING = 2;
- public static final byte LIST = 3;
+ private static final String TAGS_FILE = "/system/etc/event-log-tags";
+ private static final String COMMENT_PATTERN = "^\\s*(#.*)?$";
+ private static final String TAG_PATTERN = "^\\s*(\\d+)\\s+(\\w+)\\s*(\\(.*\\))?\\s*$";
+ private static HashMap<String, Integer> sTagCodes = null;
+ private static HashMap<Integer, String> sTagNames = null;
- /**
- * An immutable tuple used to log a heterogeneous set of loggable items.
- * The items can be Integer, Long, String, or {@link List}.
- * The maximum number of items is 127
- */
- public static final class List {
- private Object[] mItems;
-
- /**
- * Get a particular tuple item
- * @param pos The position of the item in the tuple
- */
- public final Object getItem(int pos) {
- return mItems[pos];
- }
-
- /**
- * Get the number of items in the tuple.
- */
- public final byte getNumItems() {
- return (byte) mItems.length;
- }
-
- /**
- * Create a new tuple.
- * @param items The items to create the tuple with, as varargs.
- * @throws IllegalArgumentException if the arguments are too few (0),
- * too many, or aren't loggable types.
- */
- public List(Object... items) throws IllegalArgumentException {
- if (items.length > Byte.MAX_VALUE) {
- throw new IllegalArgumentException(
- "A List must have fewer than "
- + Byte.MAX_VALUE + " items in it.");
- }
- for (int i = 0; i < items.length; i++) {
- final Object item = items[i];
- if (item == null) {
- // Would be nice to be able to write null strings...
- items[i] = "";
- } else if (!(item instanceof List ||
- item instanceof String ||
- item instanceof Integer ||
- item instanceof Long)) {
- throw new IllegalArgumentException(
- "Attempt to create a List with illegal item type.");
- }
- }
- this.mItems = items;
- }
- }
-
- /**
- * A previously logged event read from the logs.
- */
+ /** A previously logged event read from the logs. */
public static final class Event {
private final ByteBuffer mBuffer;
@@ -158,77 +65,84 @@ public class EventLog {
private static final int TAG_OFFSET = 20;
private static final int DATA_START = 24;
+ // Value types
+ private static final byte INT_TYPE = 0;
+ private static final byte LONG_TYPE = 1;
+ private static final byte STRING_TYPE = 2;
+ private static final byte LIST_TYPE = 3;
+
/** @param data containing event, read from the system */
- public Event(byte[] data) {
+ /*package*/ Event(byte[] data) {
mBuffer = ByteBuffer.wrap(data);
mBuffer.order(ByteOrder.nativeOrder());
}
+ /** @return the process ID which wrote the log entry */
public int getProcessId() {
return mBuffer.getInt(PROCESS_OFFSET);
}
+ /** @return the thread ID which wrote the log entry */
public int getThreadId() {
return mBuffer.getInt(THREAD_OFFSET);
}
+ /** @return the wall clock time when the entry was written */
public long getTimeNanos() {
return mBuffer.getInt(SECONDS_OFFSET) * 1000000000l
+ mBuffer.getInt(NANOSECONDS_OFFSET);
}
+ /** @return the type tag code of the entry */
public int getTag() {
return mBuffer.getInt(TAG_OFFSET);
}
- /** @return one of Integer, Long, String, or List. */
+ /** @return one of Integer, Long, String, null, or Object[] of same. */
public synchronized Object getData() {
- mBuffer.limit(PAYLOAD_START + mBuffer.getShort(LENGTH_OFFSET));
- mBuffer.position(DATA_START); // Just after the tag.
- return decodeObject();
- }
-
- public byte[] getRawData() {
- return mBuffer.array();
+ try {
+ mBuffer.limit(PAYLOAD_START + mBuffer.getShort(LENGTH_OFFSET));
+ mBuffer.position(DATA_START); // Just after the tag.
+ return decodeObject();
+ } catch (IllegalArgumentException e) {
+ Log.wtf(TAG, "Illegal entry payload: tag=" + getTag(), e);
+ return null;
+ } catch (BufferUnderflowException e) {
+ Log.wtf(TAG, "Truncated entry payload: tag=" + getTag(), e);
+ return null;
+ }
}
/** @return the loggable item at the current position in mBuffer. */
private Object decodeObject() {
- if (mBuffer.remaining() < 1) return null;
- switch (mBuffer.get()) {
- case INT:
- if (mBuffer.remaining() < 4) return null;
+ byte type = mBuffer.get();
+ switch (type) {
+ case INT_TYPE:
return (Integer) mBuffer.getInt();
- case LONG:
- if (mBuffer.remaining() < 8) return null;
+ case LONG_TYPE:
return (Long) mBuffer.getLong();
- case STRING:
+ case STRING_TYPE:
try {
- if (mBuffer.remaining() < 4) return null;
int length = mBuffer.getInt();
- if (length < 0 || mBuffer.remaining() < length) return null;
int start = mBuffer.position();
mBuffer.position(start + length);
return new String(mBuffer.array(), start, length, "UTF-8");
} catch (UnsupportedEncodingException e) {
- throw new RuntimeException(e); // UTF-8 is guaranteed.
+ Log.wtf(TAG, "UTF-8 is not supported", e);
+ return null;
}
- case LIST:
- if (mBuffer.remaining() < 1) return null;
+ case LIST_TYPE:
int length = mBuffer.get();
- if (length < 0) return null;
+ if (length < 0) length += 256; // treat as signed byte
Object[] array = new Object[length];
- for (int i = 0; i < length; ++i) {
- array[i] = decodeObject();
- if (array[i] == null) return null;
- }
- return new List(array);
+ for (int i = 0; i < length; ++i) array[i] = decodeObject();
+ return array;
default:
- return null;
+ throw new IllegalArgumentException("Unknown entry type: " + type);
}
}
}
@@ -236,46 +150,36 @@ public class EventLog {
// We assume that the native methods deal with any concurrency issues.
/**
- * Send an event log message.
- * @param tag An event identifer
+ * Record an event log message.
+ * @param tag The event type tag code
* @param value A value to log
* @return The number of bytes written
*/
public static native int writeEvent(int tag, int value);
/**
- * Send an event log message.
- * @param tag An event identifer
+ * Record an event log message.
+ * @param tag The event type tag code
* @param value A value to log
* @return The number of bytes written
*/
public static native int writeEvent(int tag, long value);
/**
- * Send an event log message.
- * @param tag An event identifer
+ * Record an event log message.
+ * @param tag The event type tag code
* @param str A value to log
* @return The number of bytes written
*/
public static native int writeEvent(int tag, String str);
/**
- * Send an event log message.
- * @param tag An event identifer
- * @param list A {@link List} to log
- * @return The number of bytes written
- */
- public static native int writeEvent(int tag, List list);
-
- /**
- * Send an event log message.
- * @param tag An event identifer
+ * Record an event log message.
+ * @param tag The event type tag code
* @param list A list of values to log
* @return The number of bytes written
*/
- public static int writeEvent(int tag, Object... list) {
- return writeEvent(tag, new List(list));
- }
+ public static native int writeEvent(int tag, Object... list);
/**
* Read events from the log, filtered by type.
@@ -287,11 +191,65 @@ public class EventLog {
throws IOException;
/**
- * Read events from a file.
- * @param path to read from
- * @param output container to add events into
- * @throws IOException if something goes wrong reading events
+ * Get the name associated with an event type tag code.
+ * @param tag code to look up
+ * @return the name of the tag, or null if no tag has that number
*/
- public static native void readEvents(String path, Collection<Event> output)
- throws IOException;
+ public static String getTagName(int tag) {
+ readTagsFile();
+ return sTagNames.get(tag);
+ }
+
+ /**
+ * Get the event type tag code associated with an event name.
+ * @param name of event to look up
+ * @return the tag code, or -1 if no tag has that name
+ */
+ public static int getTagCode(String name) {
+ readTagsFile();
+ Integer code = sTagCodes.get(name);
+ return code != null ? code : -1;
+ }
+
+ /**
+ * Read TAGS_FILE, populating sTagCodes and sTagNames, if not already done.
+ */
+ private static synchronized void readTagsFile() {
+ if (sTagCodes != null && sTagNames != null) return;
+
+ sTagCodes = new HashMap<String, Integer>();
+ sTagNames = new HashMap<Integer, String>();
+
+ Pattern comment = Pattern.compile(COMMENT_PATTERN);
+ Pattern tag = Pattern.compile(TAG_PATTERN);
+ BufferedReader reader = null;
+ String line;
+
+ try {
+ reader = new BufferedReader(new FileReader(TAGS_FILE), 256);
+ while ((line = reader.readLine()) != null) {
+ if (comment.matcher(line).matches()) continue;
+
+ Matcher m = tag.matcher(line);
+ if (!m.matches()) {
+ Log.wtf(TAG, "Bad entry in " + TAGS_FILE + ": " + line);
+ continue;
+ }
+
+ try {
+ int num = Integer.parseInt(m.group(1));
+ String name = m.group(2);
+ sTagCodes.put(name, num);
+ sTagNames.put(num, name);
+ } catch (NumberFormatException e) {
+ Log.wtf(TAG, "Error in " + TAGS_FILE + ": " + line, e);
+ }
+ }
+ } catch (IOException e) {
+ Log.wtf(TAG, "Error reading " + TAGS_FILE, e);
+ // Leave the maps existing but unpopulated
+ } finally {
+ try { if (reader != null) reader.close(); } catch (IOException e) {}
+ }
+ }
}
diff --git a/core/java/android/util/EventLogTags.java b/core/java/android/util/EventLogTags.java
index be905e3..5cf5332 100644
--- a/core/java/android/util/EventLogTags.java
+++ b/core/java/android/util/EventLogTags.java
@@ -25,16 +25,14 @@ import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-/** Parsed representation of /etc/event-log-tags. */
+/**
+ * @deprecated This class is no longer functional.
+ * Use {@link android.util.EventLog} instead.
+ */
public class EventLogTags {
- private final static String TAG = "EventLogTags";
-
- private final static String TAGS_FILE = "/etc/event-log-tags";
-
public static class Description {
public final int mTag;
public final String mName;
- // TODO: Parse parameter descriptions when anyone has a use for them.
Description(int tag, String name) {
mTag = tag;
@@ -42,49 +40,11 @@ public class EventLogTags {
}
}
- private final static Pattern COMMENT_PATTERN = Pattern.compile(
- "^\\s*(#.*)?$");
-
- private final static Pattern TAG_PATTERN = Pattern.compile(
- "^\\s*(\\d+)\\s+(\\w+)\\s*(\\(.*\\))?\\s*$");
+ public EventLogTags() throws IOException {}
- private final HashMap<String, Description> mNameMap =
- new HashMap<String, Description>();
-
- private final HashMap<Integer, Description> mTagMap =
- new HashMap<Integer, Description>();
-
- public EventLogTags() throws IOException {
- this(new BufferedReader(new FileReader(TAGS_FILE), 256));
- }
+ public EventLogTags(BufferedReader input) throws IOException {}
- public EventLogTags(BufferedReader input) throws IOException {
- String line;
- while ((line = input.readLine()) != null) {
- Matcher m = COMMENT_PATTERN.matcher(line);
- if (m.matches()) continue;
+ public Description get(String name) { return null; }
- m = TAG_PATTERN.matcher(line);
- if (m.matches()) {
- try {
- int tag = Integer.parseInt(m.group(1));
- Description d = new Description(tag, m.group(2));
- mNameMap.put(d.mName, d);
- mTagMap.put(d.mTag, d);
- } catch (NumberFormatException e) {
- Log.e(TAG, "Error in event log tags entry: " + line, e);
- }
- } else {
- Log.e(TAG, "Can't parse event log tags entry: " + line);
- }
- }
- }
-
- public Description get(String name) {
- return mNameMap.get(name);
- }
-
- public Description get(int tag) {
- return mTagMap.get(tag);
- }
+ public Description get(int tag) { return null; }
}
diff --git a/core/java/android/util/Log.java b/core/java/android/util/Log.java
index e95d0be..75b1b90 100644
--- a/core/java/android/util/Log.java
+++ b/core/java/android/util/Log.java
@@ -81,6 +81,13 @@ public final class Log {
*/
public static final int ASSERT = 7;
+ /**
+ * Exception class used to capture a stack trace in {@link #wtf()}.
+ */
+ private static class TerribleFailure extends Exception {
+ TerribleFailure(String msg, Throwable cause) { super(msg, cause); }
+ }
+
private Log() {
}
@@ -170,24 +177,24 @@ public final class Log {
/**
* Checks to see whether or not a log for the specified tag is loggable at the specified level.
- *
+ *
* The default level of any tag is set to INFO. This means that any level above and including
* INFO will be logged. Before you make any calls to a logging method you should check to see
* if your tag should be logged. You can change the default level by setting a system property:
* 'setprop log.tag.&lt;YOUR_LOG_TAG> &lt;LEVEL>'
- * Where level is either VERBOSE, DEBUG, INFO, WARN, ERROR, ASSERT, or SUPPRESS. SUPRESS will
+ * Where level is either VERBOSE, DEBUG, INFO, WARN, ERROR, ASSERT, or SUPPRESS. SUPPRESS will
* turn off all logging for your tag. You can also create a local.prop file that with the
* following in it:
* 'log.tag.&lt;YOUR_LOG_TAG>=&lt;LEVEL>'
* and place that in /data/local.prop.
- *
+ *
* @param tag The tag to check.
* @param level The level to check.
* @return Whether or not that this is allowed to be logged.
* @throws IllegalArgumentException is thrown if the tag.length() > 23.
*/
public static native boolean isLoggable(String tag, int level);
-
+
/*
* Send a {@link #WARN} log message and log the exception.
* @param tag Used to identify the source of a log message. It usually identifies
@@ -220,6 +227,43 @@ public final class Log {
}
/**
+ * What a Terrible Failure: Report a condition that should never happen.
+ * The error will always be logged at level ASSERT with the call stack.
+ * Depending on system configuration, a report may be added to the
+ * {@link android.os.DropBoxManager} and/or the process may be terminated
+ * immediately with an error dialog.
+ * @param tag Used to identify the source of a log message.
+ * @param msg The message you would like logged.
+ */
+ public static int wtf(String tag, String msg) {
+ return wtf(tag, msg, null);
+ }
+
+ /**
+ * What a Terrible Failure: Report an exception that should never happen.
+ * 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.
+ */
+ public static int wtf(String tag, Throwable tr) {
+ return wtf(tag, tr.getMessage(), tr);
+ }
+
+ /**
+ * What a Terrible Failure: Report an exception that should never happen.
+ * Similar to {@link #wtf(String, Throwable)}, with a message as well.
+ * @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.
+ */
+ public static int wtf(String tag, String msg, Throwable tr) {
+ tr = new TerribleFailure(msg, tr);
+ int bytes = println(ASSERT, tag, getStackTraceString(tr));
+ RuntimeInit.wtf(tag, tr);
+ return bytes;
+ }
+
+ /**
* Handy function to get a loggable stack trace from a Throwable
* @param tr An exception to log
*/
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 788f04a..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).
@@ -1494,6 +1494,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
* @hide
*/
static final int OPAQUE_MASK = 0x01800000;
+
+ /**
+ * Indicates a prepressed state;
+ * the short time between ACTION_DOWN and recognizing
+ * a 'real' press. Prepressed is used to recognize quick taps
+ * even when they are shorter than ViewConfiguration.getTapTimeout().
+ *
+ * @hide
+ */
+ private static final int PREPRESSED = 0x02000000;
/**
* The parent this view is attached to.
@@ -1722,6 +1732,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
private int mNextFocusDownId = View.NO_ID;
private CheckForLongPress mPendingCheckForLongPress;
+ private CheckForTap mPendingCheckForTap = null;
+
private UnsetPressedState mUnsetPressedState;
/**
@@ -1762,6 +1774,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
* Special tree observer used when mAttachInfo is null.
*/
private ViewTreeObserver mFloatingTreeObserver;
+
+ /**
+ * Cache the touch slop from the context that created the view.
+ */
+ private int mTouchSlop;
// Used for debug only
static long sInstanceCount = 0;
@@ -1777,6 +1794,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
mResources = context != null ? context.getResources() : null;
mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED;
++sInstanceCount;
+ mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
}
/**
@@ -2726,7 +2744,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
setPressed(false);
if (!mHasPerformedLongPress) {
- cancelLongPress();
+ removeLongPressCallback();
}
}
}
@@ -3748,7 +3766,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
if (imm != null && (mPrivateFlags & FOCUSED) != 0) {
imm.focusOut(this);
}
- cancelLongPress();
+ removeLongPressCallback();
onFocusLost();
} else if (imm != null && (mPrivateFlags & FOCUSED) != 0) {
imm.focusIn(this);
@@ -3951,7 +3969,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
(event.getRepeatCount() == 0)) {
setPressed(true);
if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
- postCheckForLongClick();
+ postCheckForLongClick(0);
}
return true;
}
@@ -3994,7 +4012,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
if (!mHasPerformedLongPress) {
// This is a tap, so remove the longpress check
- cancelLongPress();
+ removeLongPressCallback();
result = performClick();
}
@@ -4174,7 +4192,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
(viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) {
switch (event.getAction()) {
case MotionEvent.ACTION_UP:
- if ((mPrivateFlags & PRESSED) != 0) {
+ boolean prepressed = (mPrivateFlags & PREPRESSED) != 0;
+ if ((mPrivateFlags & PRESSED) != 0 || prepressed) {
// take focus if we don't have it already and we should in
// touch mode.
boolean focusTaken = false;
@@ -4184,7 +4203,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
if (!mHasPerformedLongPress) {
// This is a tap, so remove the longpress check
- cancelLongPress();
+ removeLongPressCallback();
// Only perform take click actions if we were in the pressed state
if (!focusTaken) {
@@ -4196,24 +4215,31 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
mUnsetPressedState = new UnsetPressedState();
}
- if (!post(mUnsetPressedState)) {
+ if (prepressed) {
+ mPrivateFlags |= PRESSED;
+ refreshDrawableState();
+ postDelayed(mUnsetPressedState,
+ ViewConfiguration.getPressedStateDuration());
+ } else if (!post(mUnsetPressedState)) {
// If the post failed, unpress right now
mUnsetPressedState.run();
}
+ removeTapCallback();
}
break;
case MotionEvent.ACTION_DOWN:
- mPrivateFlags |= PRESSED;
- refreshDrawableState();
- if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
- postCheckForLongClick();
+ if (mPendingCheckForTap == null) {
+ mPendingCheckForTap = new CheckForTap();
}
+ mPrivateFlags |= PREPRESSED;
+ postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
break;
case MotionEvent.ACTION_CANCEL:
mPrivateFlags &= ~PRESSED;
refreshDrawableState();
+ removeTapCallback();
break;
case MotionEvent.ACTION_MOVE:
@@ -4221,25 +4247,19 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
final int y = (int) event.getY();
// Be lenient about moving outside of buttons
- int slop = ViewConfiguration.get(mContext).getScaledTouchSlop();
+ int slop = mTouchSlop;
if ((x < 0 - slop) || (x >= getWidth() + slop) ||
(y < 0 - slop) || (y >= getHeight() + slop)) {
// Outside button
+ removeTapCallback();
if ((mPrivateFlags & PRESSED) != 0) {
- // Remove any future long press checks
- cancelLongPress();
+ // Remove any future long press/tap checks
+ removeLongPressCallback();
// Need to switch from pressed to not pressed
mPrivateFlags &= ~PRESSED;
refreshDrawableState();
}
- } else {
- // Inside button
- if ((mPrivateFlags & PRESSED) == 0) {
- // Need to switch from not pressed to pressed
- mPrivateFlags |= PRESSED;
- refreshDrawableState();
- }
}
break;
}
@@ -4250,15 +4270,32 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
}
/**
+ * Remove the longpress detection timer.
+ */
+ private void removeLongPressCallback() {
+ if (mPendingCheckForLongPress != null) {
+ removeCallbacks(mPendingCheckForLongPress);
+ }
+ }
+
+ /**
+ * Remove the tap detection timer.
+ */
+ private void removeTapCallback() {
+ if (mPendingCheckForTap != null) {
+ mPrivateFlags &= ~PREPRESSED;
+ removeCallbacks(mPendingCheckForTap);
+ }
+ }
+
+ /**
* Cancels a pending long press. Your subclass can use this if you
* want the context menu to come up if the user presses and holds
* at the same place, but you don't want it to come up if they press
* and then move around enough to cause scrolling.
*/
public void cancelLongPress() {
- if (mPendingCheckForLongPress != null) {
- removeCallbacks(mPendingCheckForLongPress);
- }
+ removeLongPressCallback();
}
/**
@@ -5759,7 +5796,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
* @see #onAttachedToWindow()
*/
protected void onDetachedFromWindow() {
- cancelLongPress();
+ removeLongPressCallback();
destroyDrawingCache();
}
@@ -8420,14 +8457,15 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
}
}
- private void postCheckForLongClick() {
+ private void postCheckForLongClick(int delayOffset) {
mHasPerformedLongPress = false;
if (mPendingCheckForLongPress == null) {
mPendingCheckForLongPress = new CheckForLongPress();
}
mPendingCheckForLongPress.rememberWindowAttachCount();
- postDelayed(mPendingCheckForLongPress, ViewConfiguration.getLongPressTimeout());
+ postDelayed(mPendingCheckForLongPress,
+ ViewConfiguration.getLongPressTimeout() - delayOffset);
}
private static int[] stateSetUnion(final int[] stateSet1,
@@ -8604,6 +8642,17 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
mOriginalWindowAttachCount = mWindowAttachCount;
}
}
+
+ private final class CheckForTap implements Runnable {
+ public void run() {
+ mPrivateFlags &= ~PREPRESSED;
+ mPrivateFlags |= PRESSED;
+ refreshDrawableState();
+ if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
+ postCheckForLongClick(ViewConfiguration.getTapTimeout());
+ }
+ }
+ }
/**
* Interface definition for a callback to be invoked when a key event is
diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java
index 993048f..2344c42 100644
--- a/core/java/android/view/ViewConfiguration.java
+++ b/core/java/android/view/ViewConfiguration.java
@@ -49,7 +49,7 @@ public class ViewConfiguration {
* Defines the duration in milliseconds of the pressed state in child
* components.
*/
- private static final int PRESSED_STATE_DURATION = 85;
+ private static final int PRESSED_STATE_DURATION = 125;
/**
* Defines the duration in milliseconds before a press turns into
@@ -69,7 +69,7 @@ public class ViewConfiguration {
* is a tap or a scroll. If the user does not move within this interval, it is
* considered to be a tap.
*/
- private static final int TAP_TIMEOUT = 100;
+ private static final int TAP_TIMEOUT = 115;
/**
* Defines the duration in milliseconds we will wait to see if a touch event
diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java
index 2fd974e..3ebe1c2 100644
--- a/core/java/android/view/ViewDebug.java
+++ b/core/java/android/view/ViewDebug.java
@@ -702,7 +702,7 @@ public class ViewDebug {
if (parameter.indexOf('@') != -1) {
final String[] ids = parameter.split("@");
final String className = ids[0];
- final int hashCode = Integer.parseInt(ids[1], 16);
+ final int hashCode = (int) Long.parseLong(ids[1], 16);
View view = root.getRootView();
if (view instanceof ViewGroup) {
@@ -910,7 +910,7 @@ public class ViewDebug {
private static void dump(View root, OutputStream clientStream) throws IOException {
BufferedWriter out = null;
try {
- out = new BufferedWriter(new OutputStreamWriter(clientStream), 32 * 1024);
+ out = new BufferedWriter(new OutputStreamWriter(clientStream, "utf-8"), 32 * 1024);
View view = root.getRootView();
if (view instanceof ViewGroup) {
ViewGroup group = (ViewGroup) view;
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/ViewStub.java b/core/java/android/view/ViewStub.java
index 703a38f..d5e9af4 100644
--- a/core/java/android/view/ViewStub.java
+++ b/core/java/android/view/ViewStub.java
@@ -207,9 +207,11 @@ public final class ViewStub extends View {
} else {
throw new IllegalStateException("setVisibility called on un-referenced view");
}
- } else if (visibility == VISIBLE || visibility == INVISIBLE) {
+ } else {
super.setVisibility(visibility);
- inflate();
+ if (visibility == VISIBLE || visibility == INVISIBLE) {
+ inflate();
+ }
}
}
@@ -244,7 +246,7 @@ public final class ViewStub extends View {
parent.addView(view, index);
}
- mInflatedViewRef = new WeakReference(view);
+ mInflatedViewRef = new WeakReference<View>(view);
if (mInflateListener != null) {
mInflateListener.onInflate(this, view);
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/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 5d3840a..bbe9c1f 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -662,6 +662,14 @@ public interface WindowManagerPolicy {
public boolean finishAnimationLw();
/**
+ * Return true if it is okay to perform animations for an app transition
+ * that is about to occur. You may return false for this if, for example,
+ * the lock screen is currently displayed so the switch should happen
+ * immediately.
+ */
+ public boolean allowAppAnimationsLw();
+
+ /**
* Called after the screen turns off.
*
* @param why {@link #OFF_BECAUSE_OF_USER} or
@@ -675,6 +683,11 @@ public interface WindowManagerPolicy {
public void screenTurnedOn();
/**
+ * Return whether the screen is currently on.
+ */
+ public boolean isScreenOn();
+
+ /**
* Perform any initial processing of a low-level input event before the
* window manager handles special keys and generates a high-level event
* that is dispatched to the application.
diff --git a/core/java/android/view/WindowOrientationListener.java b/core/java/android/view/WindowOrientationListener.java
index 13606e7..2aba60b 100755
--- a/core/java/android/view/WindowOrientationListener.java
+++ b/core/java/android/view/WindowOrientationListener.java
@@ -33,13 +33,12 @@ import android.util.Log;
public abstract class WindowOrientationListener {
private static final String TAG = "WindowOrientationListener";
private static final boolean DEBUG = false;
- private static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
+ private static final boolean localLOGV = DEBUG || Config.DEBUG;
private SensorManager mSensorManager;
private boolean mEnabled = false;
private int mRate;
private Sensor mSensor;
- private SensorEventListener mSensorEventListener;
- private int mSensorRotation = -1;
+ private SensorEventListenerImpl mSensorEventListener;
/**
* Creates a new WindowOrientationListener.
@@ -80,7 +79,6 @@ public abstract class WindowOrientationListener {
}
if (mEnabled == false) {
if (localLOGV) Log.d(TAG, "WindowOrientationListener enabled");
- mSensorRotation = -1;
mSensorManager.registerListener(mSensorEventListener, mSensor, mRate);
mEnabled = true;
}
@@ -96,23 +94,22 @@ public abstract class WindowOrientationListener {
}
if (mEnabled == true) {
if (localLOGV) Log.d(TAG, "WindowOrientationListener disabled");
- mSensorRotation = -1;
mSensorManager.unregisterListener(mSensorEventListener);
mEnabled = false;
}
}
public int getCurrentRotation() {
- return mSensorRotation;
+ if (mEnabled) {
+ return mSensorEventListener.getCurrentRotation();
+ }
+ return -1;
}
class SensorEventListenerImpl implements SensorEventListener {
private static final int _DATA_X = 0;
private static final int _DATA_Y = 1;
private static final int _DATA_Z = 2;
- // Angle around x-axis thats considered almost perfect vertical to hold
- // the device
- private static final int PIVOT = 20;
// Angle around x-asis that's considered almost too vertical. Beyond
// this angle will not result in any orientation changes. f phone faces uses,
// the device is leaning backward.
@@ -121,30 +118,61 @@ public abstract class WindowOrientationListener {
// angle will not result in any orientation changes. If phone faces uses,
// the device is leaning forward.
private static final int PIVOT_LOWER = -10;
- // Upper threshold limit for switching from portrait to landscape
- private static final int PL_UPPER = 295;
- // Lower threshold limit for switching from landscape to portrait
- private static final int LP_LOWER = 320;
- // Lower threshold limt for switching from portrait to landscape
- private static final int PL_LOWER = 270;
- // Upper threshold limit for switching from landscape to portrait
- private static final int LP_UPPER = 359;
- // Minimum angle which is considered landscape
- private static final int LANDSCAPE_LOWER = 235;
- // Minimum angle which is considered portrait
- private static final int PORTRAIT_LOWER = 60;
-
- // Internal value used for calculating linear variant
- private static final float PL_LF_UPPER =
- ((float)(PL_UPPER-PL_LOWER))/((float)(PIVOT_UPPER-PIVOT));
- private static final float PL_LF_LOWER =
- ((float)(PL_UPPER-PL_LOWER))/((float)(PIVOT-PIVOT_LOWER));
- // Internal value used for calculating linear variant
- private static final float LP_LF_UPPER =
- ((float)(LP_UPPER - LP_LOWER))/((float)(PIVOT_UPPER-PIVOT));
- private static final float LP_LF_LOWER =
- ((float)(LP_UPPER - LP_LOWER))/((float)(PIVOT-PIVOT_LOWER));
+ static final int ROTATION_0 = 0;
+ static final int ROTATION_90 = 1;
+ static final int ROTATION_180 = 2;
+ static final int ROTATION_270 = 3;
+ int mRotation = ROTATION_0;
+
+ // Threshold values defined for device rotation positions
+ // follow order ROTATION_0 .. ROTATION_270
+ final int THRESHOLDS[][][] = new int[][][] {
+ {{60, 135}, {135, 225}, {225, 300}},
+ {{0, 45}, {45, 135}, {135, 210}, {330, 360}},
+ {{0, 45}, {45, 120}, {240, 315}, {315, 360}},
+ {{0, 30}, {150, 225}, {225, 315}, {315, 360}}
+ };
+
+ // Transform rotation ranges based on THRESHOLDS. This
+ // has to be in step with THESHOLDS
+ final int ROTATE_TO[][] = new int[][] {
+ {ROTATION_270, ROTATION_180, ROTATION_90},
+ {ROTATION_0, ROTATION_270, ROTATION_180, ROTATION_0},
+ {ROTATION_0, ROTATION_270, ROTATION_90, ROTATION_0},
+ {ROTATION_0, ROTATION_180, ROTATION_90, ROTATION_0}
+ };
+
+ // Mapping into actual Surface rotation values
+ final int TRANSFORM_ROTATIONS[] = new int[]{Surface.ROTATION_0,
+ Surface.ROTATION_90, Surface.ROTATION_180, Surface.ROTATION_270};
+
+ int getCurrentRotation() {
+ return TRANSFORM_ROTATIONS[mRotation];
+ }
+ private void calculateNewRotation(int orientation, int zyangle) {
+ if (localLOGV) Log.i(TAG, orientation + ", " + zyangle + ", " + mRotation);
+ int rangeArr[][] = THRESHOLDS[mRotation];
+ int row = -1;
+ for (int i = 0; i < rangeArr.length; i++) {
+ if ((orientation >= rangeArr[i][0]) && (orientation < rangeArr[i][1])) {
+ row = i;
+ break;
+ }
+ }
+ if (row != -1) {
+ // Find new rotation based on current rotation value.
+ // This also takes care of irregular rotations as well.
+ int rotation = ROTATE_TO[mRotation][row];
+ if (localLOGV) Log.i(TAG, " new rotation = " + rotation);
+ if (rotation != mRotation) {
+ mRotation = rotation;
+ // Trigger orientation change
+ onOrientationChanged(TRANSFORM_ROTATIONS[rotation]);
+ }
+ }
+ }
+
public void onSensorChanged(SensorEvent event) {
float[] values = event.values;
float X = values[_DATA_X];
@@ -153,53 +181,19 @@ public abstract class WindowOrientationListener {
float OneEightyOverPi = 57.29577957855f;
float gravity = (float) Math.sqrt(X*X+Y*Y+Z*Z);
float zyangle = (float)Math.asin(Z/gravity)*OneEightyOverPi;
- int rotation = -1;
if ((zyangle <= PIVOT_UPPER) && (zyangle >= PIVOT_LOWER)) {
// Check orientation only if the phone is flat enough
// Don't trust the angle if the magnitude is small compared to the y value
float angle = (float)Math.atan2(Y, -X) * OneEightyOverPi;
- int orientation = 90 - (int)Math.round(angle);
+ int orientation = 90 - Math.round(angle);
// normalize to 0 - 359 range
while (orientation >= 360) {
orientation -= 360;
- }
+ }
while (orientation < 0) {
orientation += 360;
}
- // Orientation values between LANDSCAPE_LOWER and PL_LOWER
- // are considered landscape.
- // Ignore orientation values between 0 and LANDSCAPE_LOWER
- // For orientation values between LP_UPPER and PL_LOWER,
- // the threshold gets set linearly around PIVOT.
- if ((orientation >= PL_LOWER) && (orientation <= LP_UPPER)) {
- float threshold;
- float delta = zyangle - PIVOT;
- if (mSensorRotation == Surface.ROTATION_90) {
- if (delta < 0) {
- // Delta is negative
- threshold = LP_LOWER - (LP_LF_LOWER * delta);
- } else {
- threshold = LP_LOWER + (LP_LF_UPPER * delta);
- }
- rotation = (orientation >= threshold) ? Surface.ROTATION_0 : Surface.ROTATION_90;
- } else {
- if (delta < 0) {
- // Delta is negative
- threshold = PL_UPPER+(PL_LF_LOWER * delta);
- } else {
- threshold = PL_UPPER-(PL_LF_UPPER * delta);
- }
- rotation = (orientation <= threshold) ? Surface.ROTATION_90: Surface.ROTATION_0;
- }
- } else if ((orientation >= LANDSCAPE_LOWER) && (orientation < LP_LOWER)) {
- rotation = Surface.ROTATION_90;
- } else if ((orientation >= PL_UPPER) || (orientation <= PORTRAIT_LOWER)) {
- rotation = Surface.ROTATION_0;
- }
- if ((rotation != -1) && (rotation != mSensorRotation)) {
- mSensorRotation = rotation;
- onOrientationChanged(mSensorRotation);
- }
+ calculateNewRotation(orientation, Math.round(zyangle));
}
}
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/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/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 6368dac..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;
@@ -486,7 +485,7 @@ public class WebView extends AbsoluteLayout
static final int MOVE_OUT_OF_PLUGIN = 19;
static final int CLEAR_TEXT_ENTRY = 20;
static final int UPDATE_TEXT_SELECTION_MSG_ID = 21;
- static final int UPDATE_CLIPBOARD = 22;
+
static final int LONG_PRESS_CENTER = 23;
static final int PREVENT_TOUCH_ID = 24;
static final int WEBCORE_NEED_TOUCH_EVENTS = 25;
@@ -523,7 +522,7 @@ public class WebView extends AbsoluteLayout
"MOVE_OUT_OF_PLUGIN", // = 19;
"CLEAR_TEXT_ENTRY", // = 20;
"UPDATE_TEXT_SELECTION_MSG_ID", // = 21;
- "UPDATE_CLIPBOARD", // = 22;
+ "22", // = 22;
"LONG_PRESS_CENTER", // = 23;
"PREVENT_TOUCH_ID", // = 24;
"WEBCORE_NEED_TOUCH_EVENTS", // = 25;
@@ -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(
@@ -3666,9 +3665,6 @@ public class WebView extends AbsoluteLayout
nativeHideCursor();
}
- /**
- * @hide
- */
public void emulateShiftHeld() {
if (0 == mNativeClass) return; // client isn't initialized
setUpSelectXY();
@@ -3677,14 +3673,22 @@ public class WebView extends AbsoluteLayout
private boolean commitCopy() {
boolean copiedSomething = false;
if (mExtendSelection) {
- // copy region so core operates on copy without touching orig.
- Region selection = new Region(nativeGetSelection());
- if (selection.isEmpty() == false) {
+ String selection = nativeGetSelection();
+ if (selection != "") {
+ if (DebugFlags.WEB_VIEW) {
+ Log.v(LOGTAG, "commitCopy \"" + selection + "\"");
+ }
Toast.makeText(mContext
, com.android.internal.R.string.text_copied
, Toast.LENGTH_SHORT).show();
- mWebViewCore.sendMessage(EventHub.GET_SELECTION, selection);
copiedSomething = true;
+ try {
+ IClipboard clip = IClipboard.Stub.asInterface(
+ ServiceManager.getService("clipboard"));
+ clip.setClipboardText(selection);
+ } catch (android.os.RemoteException e) {
+ Log.e(LOGTAG, "Clipboard failed", e);
+ }
}
mExtendSelection = false;
}
@@ -3888,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);
+ }
}
});
}
@@ -3965,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);
}
@@ -4002,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);
}
@@ -4013,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();
@@ -4050,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);
}
@@ -4065,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);
}
@@ -5123,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);
@@ -5681,19 +5687,6 @@ public class WebView extends AbsoluteLayout
mWebTextView.setAdapterCustom(adapter);
}
break;
- case UPDATE_CLIPBOARD:
- String str = (String) msg.obj;
- if (DebugFlags.WEB_VIEW) {
- Log.v(LOGTAG, "UPDATE_CLIPBOARD " + str);
- }
- try {
- IClipboard clip = IClipboard.Stub.asInterface(
- ServiceManager.getService("clipboard"));
- clip.setClipboardText(str);
- } catch (android.os.RemoteException e) {
- Log.e(LOGTAG, "Clipboard failed", e);
- }
- break;
case RESUME_WEBCORE_UPDATE:
WebViewCore.resumeUpdate(mWebViewCore);
break;
@@ -5770,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:
@@ -6388,7 +6381,7 @@ public class WebView extends AbsoluteLayout
private native boolean nativeFocusIsPlugin();
/* package */ native int nativeFocusNodePointer();
private native Rect nativeGetCursorRingBounds();
- private native Region nativeGetSelection();
+ private native String nativeGetSelection();
private native boolean nativeHasCursorNode();
private native boolean nativeHasFocusNode();
private native void nativeHideCursor();
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 885dda9..949b318 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -545,8 +545,6 @@ final class WebViewCore {
*/
private native void nativeSetSelection(int start, int end);
- private native String nativeGetSelection(Region sel);
-
// Register a scheme to be treated as local scheme so that it can access
// local asset files for resources
private native void nativeRegisterURLSchemeAsLocal(String scheme);
@@ -776,7 +774,7 @@ final class WebViewCore {
"SET_BACKGROUND_COLOR", // = 126;
"SET_MOVE_FOCUS", // = 127
"SAVE_DOCUMENT_STATE", // = 128;
- "GET_SELECTION", // = 129;
+ "129", // = 129;
"WEBKIT_DRAW", // = 130;
"SYNC_SCROLL", // = 131;
"POST_URL", // = 132;
@@ -829,7 +827,7 @@ final class WebViewCore {
static final int SET_BACKGROUND_COLOR = 126;
static final int SET_MOVE_FOCUS = 127;
static final int SAVE_DOCUMENT_STATE = 128;
- static final int GET_SELECTION = 129;
+
static final int WEBKIT_DRAW = 130;
static final int SYNC_SCROLL = 131;
static final int POST_URL = 132;
@@ -1266,13 +1264,6 @@ final class WebViewCore {
nativeSetBackgroundColor(msg.arg1);
break;
- case GET_SELECTION:
- String str = nativeGetSelection((Region) msg.obj);
- Message.obtain(mWebView.mPrivateHandler
- , WebView.UPDATE_CLIPBOARD, str)
- .sendToTarget();
- break;
-
case DUMP_DOMTREE:
nativeDumpDomTree(msg.arg1 == 1);
break;
@@ -1325,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;
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 92ff315..e241c77 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -127,11 +127,6 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
static final int TOUCH_MODE_FLING = 4;
/**
- * Indicates that the user is currently dragging the fast scroll thumb
- */
- static final int TOUCH_MODE_FAST_SCROLL = 5;
-
- /**
* Regular layout - usually an unsolicited layout from the view system
*/
static final int LAYOUT_NORMAL = 0;
@@ -440,6 +435,8 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
private Runnable mClearScrollingCache;
private int mMinimumVelocity;
private int mMaximumVelocity;
+
+ final boolean[] mIsScrap = new boolean[1];
/**
* Interface definition for a callback to be invoked when the list or grid
@@ -1239,9 +1236,13 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
* converting an old view or making a new one.
*
* @param position The position to display
+ * @param isScrap Array of at least 1 boolean, the first entry will become true if
+ * the returned view was taken from the scrap heap, false if otherwise.
+ *
* @return A view displaying the data associated with the specified position
*/
- View obtainView(int position) {
+ View obtainView(int position, boolean[] isScrap) {
+ isScrap[0] = false;
View scrapView;
scrapView = mRecycler.getScrapView(position);
@@ -1269,6 +1270,8 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
ViewDebug.trace(scrapView, ViewDebug.RecyclerTraceType.MOVE_TO_SCRAP_HEAP,
position, -1);
}
+ } else {
+ isScrap[0] = true;
}
} else {
child = mAdapter.getView(position, null, this);
@@ -1543,6 +1546,9 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
// Dismiss the popup in case onSaveInstanceState() was not invoked
dismissPopup();
+ // Detach any view left in the scrap heap
+ mRecycler.clear();
+
final ViewTreeObserver treeObserver = getViewTreeObserver();
if (treeObserver != null) {
treeObserver.removeOnTouchModeChangeListener(this);
@@ -1636,6 +1642,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
if (mDataChanged) return;
if (mAdapter != null && mItemCount > 0 &&
+ mClickMotionPosition != INVALID_POSITION &&
mClickMotionPosition < mAdapter.getCount() && sameWindow()) {
performItemClick(mChild, mClickMotionPosition, getAdapter().getItemId(
mClickMotionPosition));
@@ -2969,7 +2976,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
break;
case KeyEvent.KEYCODE_SPACE:
// Only send spaces once we are filtered
- okToSend = mFiltered = true;
+ okToSend = mFiltered;
break;
}
@@ -3594,12 +3601,12 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
for (int i = 0; i < count; ++i) {
final View victim = activeViews[i];
if (victim != null) {
- int whichScrap = ((AbsListView.LayoutParams)
- victim.getLayoutParams()).viewType;
+ int whichScrap = ((AbsListView.LayoutParams) victim.getLayoutParams()).viewType;
activeViews[i] = null;
if (whichScrap == AdapterView.ITEM_VIEW_TYPE_IGNORE) {
+ removeDetachedView(victim, false);
// Do not move views that should be ignored
continue;
}
diff --git a/core/java/android/widget/AbsSeekBar.java b/core/java/android/widget/AbsSeekBar.java
index d25530b..d6dd872 100644
--- a/core/java/android/widget/AbsSeekBar.java
+++ b/core/java/android/widget/AbsSeekBar.java
@@ -26,7 +26,6 @@ import android.view.KeyEvent;
import android.view.MotionEvent;
public abstract class AbsSeekBar extends ProgressBar {
-
private Drawable mThumb;
private int mThumbOffset;
@@ -66,8 +65,9 @@ public abstract class AbsSeekBar extends ProgressBar {
Drawable thumb = a.getDrawable(com.android.internal.R.styleable.SeekBar_thumb);
setThumb(thumb); // will guess mThumbOffset if thumb != null...
// ...but allow layout to override this
- int thumbOffset =
- a.getDimensionPixelOffset(com.android.internal.R.styleable.SeekBar_thumbOffset, getThumbOffset());
+ int thumbOffset = a.getDimensionPixelOffset(
+ com.android.internal.R.styleable.SeekBar_thumbOffset, getThumbOffset());
+ setThumbOffset(thumbOffset);
a.recycle();
a = context.obtainStyledAttributes(attrs,
@@ -91,7 +91,7 @@ public abstract class AbsSeekBar extends ProgressBar {
// Assuming the thumb drawable is symmetric, set the thumb offset
// such that the thumb will hang halfway off either edge of the
// progress bar.
- mThumbOffset = (int)thumb.getIntrinsicWidth() / 2;
+ mThumbOffset = thumb.getIntrinsicWidth() / 2;
}
mThumb = thumb;
invalidate();
@@ -368,20 +368,21 @@ public abstract class AbsSeekBar extends ProgressBar {
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
- int progress = getProgress();
-
- switch (keyCode) {
- case KeyEvent.KEYCODE_DPAD_LEFT:
- if (progress <= 0) break;
- setProgress(progress - mKeyProgressIncrement, true);
- onKeyChange();
- return true;
-
- case KeyEvent.KEYCODE_DPAD_RIGHT:
- if (progress >= getMax()) break;
- setProgress(progress + mKeyProgressIncrement, true);
- onKeyChange();
- return true;
+ if (isEnabled()) {
+ int progress = getProgress();
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_DPAD_LEFT:
+ if (progress <= 0) break;
+ setProgress(progress - mKeyProgressIncrement, true);
+ onKeyChange();
+ return true;
+
+ case KeyEvent.KEYCODE_DPAD_RIGHT:
+ if (progress >= getMax()) break;
+ setProgress(progress + mKeyProgressIncrement, true);
+ onKeyChange();
+ return true;
+ }
}
return super.onKeyDown(keyCode, event);
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 ce985e3..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;
@@ -1485,8 +1485,8 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe
* @return the view for the specified item
*/
@Override
- protected View obtainView(int position) {
- View view = super.obtainView(position);
+ View obtainView(int position, boolean[] isScrap) {
+ View view = super.obtainView(position, isScrap);
if (view instanceof TextView) {
((TextView) view).setHorizontallyScrolling(true);
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 ffe9908..30a38df 100644
--- a/core/java/android/widget/GridView.java
+++ b/core/java/android/widget/GridView.java
@@ -931,11 +931,11 @@ public class GridView extends AbsListView {
mItemCount = mAdapter == null ? 0 : mAdapter.getCount();
final int count = mItemCount;
if (count > 0) {
- final View child = obtainView(0);
+ final View child = obtainView(0, mIsScrap);
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);
}
@@ -1203,7 +1203,7 @@ public class GridView extends AbsListView {
View child;
if (!mDataChanged) {
- // Try to use an exsiting view for this position
+ // Try to use an existing view for this position
child = mRecycler.getActiveView(position);
if (child != null) {
// Found it -- we're using an existing child
@@ -1215,10 +1215,10 @@ public class GridView extends AbsListView {
// Make a new view for this position, or convert an unused view if
// possible
- child = obtainView(position);
+ child = obtainView(position, mIsScrap);
// This needs to be positioned and measured
- setupChild(child, position, y, flow, childrenLeft, selected, false, where);
+ setupChild(child, position, y, flow, childrenLeft, selected, mIsScrap[0], where);
return child;
}
@@ -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 d417e40..5c05170 100644
--- a/core/java/android/widget/ImageButton.java
+++ b/core/java/android/widget/ImageButton.java
@@ -44,11 +44,11 @@ import java.util.Map;
* <pre>
* &lt;?xml version="1.0" encoding="utf-8"?&gt;
* &lt;selector xmlns:android="http://schemas.android.com/apk/res/android"&gt;
- * &lt;item android:drawable="@drawable/button_normal" /&gt; &lt;!-- default --&gt;
* &lt;item android:state_pressed="true"
* android:drawable="@drawable/button_pressed" /&gt; &lt;!-- pressed --&gt;
* &lt;item android:state_focused="true"
* android:drawable="@drawable/button_focused" /&gt; &lt;!-- focused --&gt;
+ * &lt;item android:drawable="@drawable/button_normal" /&gt; &lt;!-- default --&gt;
* &lt;/selector&gt;</pre>
*
* <p>Save the XML file in your project {@code res/drawable/} folder and then
@@ -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 &lt;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/ImageView.java b/core/java/android/widget/ImageView.java
index 8f24041..3853359 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -491,8 +491,16 @@ public class ImageView extends View {
}
} else if (mUri != null) {
String scheme = mUri.getScheme();
- if (ContentResolver.SCHEME_CONTENT.equals(scheme)
- || ContentResolver.SCHEME_ANDROID_RESOURCE.equals(scheme)
+ if (ContentResolver.SCHEME_ANDROID_RESOURCE.equals(scheme)) {
+ try {
+ // Load drawable through Resources, to get the source density information
+ ContentResolver.OpenResourceIdResult r =
+ mContext.getContentResolver().getResourceId(mUri);
+ d = r.r.getDrawable(r.id);
+ } catch (Exception e) {
+ Log.w("ImageView", "Unable to open content: " + mUri, e);
+ }
+ } else if (ContentResolver.SCHEME_CONTENT.equals(scheme)
|| ContentResolver.SCHEME_FILE.equals(scheme)) {
try {
d = Drawable.createFromStream(
diff --git a/core/java/android/widget/LinearLayout.java b/core/java/android/widget/LinearLayout.java
index 6cc794b..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;
@@ -991,6 +991,9 @@ public class LinearLayout extends ViewGroup {
case Gravity.RIGHT:
childLeft = childRight - childWidth - lp.rightMargin;
break;
+ default:
+ childLeft = paddingLeft;
+ break;
}
@@ -1062,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();
}
@@ -1102,6 +1105,9 @@ public class LinearLayout extends ViewGroup {
childTop -= (maxDescent[INDEX_BOTTOM] - descent);
}
break;
+ default:
+ childTop = paddingTop;
+ break;
}
childLeft += lp.leftMargin;
@@ -1193,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}
@@ -1204,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;
}
@@ -1284,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 b574d45..c63774a 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -1033,7 +1033,7 @@ public class ListView extends AbsListView {
mItemCount = mAdapter == null ? 0 : mAdapter.getCount();
if (mItemCount > 0 && (widthMode == MeasureSpec.UNSPECIFIED ||
heightMode == MeasureSpec.UNSPECIFIED)) {
- final View child = obtainView(0);
+ final View child = obtainView(0, mIsScrap);
measureScrapChild(child, 0, widthMeasureSpec);
@@ -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);
}
@@ -1142,9 +1142,10 @@ public class ListView extends AbsListView {
endPosition = (endPosition == NO_POSITION) ? adapter.getCount() - 1 : endPosition;
final AbsListView.RecycleBin recycleBin = mRecycler;
final boolean recyle = recycleOnMeasure();
+ final boolean[] isScrap = mIsScrap;
for (i = startPosition; i <= endPosition; ++i) {
- child = obtainView(i);
+ child = obtainView(i, isScrap);
measureScrapChild(child, i, widthMeasureSpec);
@@ -1665,10 +1666,10 @@ public class ListView extends AbsListView {
}
// Make a new view for this position, or convert an unused view if possible
- child = obtainView(position);
+ child = obtainView(position, mIsScrap);
// This needs to be positioned and measured
- setupChild(child, position, y, flow, childrenLeft, selected, false);
+ setupChild(child, position, y, flow, childrenLeft, selected, mIsScrap[0]);
return child;
}
@@ -1701,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);
@@ -2387,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);
}
@@ -2823,17 +2824,19 @@ public class ListView extends AbsListView {
private View addViewAbove(View theView, int position) {
int abovePosition = position - 1;
- View view = obtainView(abovePosition);
+ View view = obtainView(abovePosition, mIsScrap);
int edgeOfNewChild = theView.getTop() - mDividerHeight;
- setupChild(view, abovePosition, edgeOfNewChild, false, mListPadding.left, false, false);
+ setupChild(view, abovePosition, edgeOfNewChild, false, mListPadding.left,
+ false, mIsScrap[0]);
return view;
}
private View addViewBelow(View theView, int position) {
int belowPosition = position + 1;
- View view = obtainView(belowPosition);
+ View view = obtainView(belowPosition, mIsScrap);
int edgeOfNewChild = theView.getBottom() + mDividerHeight;
- setupChild(view, belowPosition, edgeOfNewChild, true, mListPadding.left, false, false);
+ setupChild(view, belowPosition, edgeOfNewChild, true, mListPadding.left,
+ false, mIsScrap[0]);
return view;
}
@@ -3080,13 +3083,19 @@ public class ListView extends AbsListView {
if (gainFocus && previouslyFocusedRect != null) {
previouslyFocusedRect.offset(mScrollX, mScrollY);
+ final ListAdapter adapter = mAdapter;
+ final int firstPosition = mFirstPosition;
+ // Don't cache the result of getChildCount here, it could change in layoutChildren.
+ if (adapter.getCount() < getChildCount() + firstPosition) {
+ mLayoutMode = LAYOUT_NORMAL;
+ layoutChildren();
+ }
+
// figure out which item should be selected based on previously
// focused rect
Rect otherRect = mTempRect;
int minDistance = Integer.MAX_VALUE;
final int childCount = getChildCount();
- final int firstPosition = mFirstPosition;
- final ListAdapter adapter = mAdapter;
for (int i = 0; i < childCount; i++) {
// only consider selectable views
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 e19a93d..1aa1df3 100644
--- a/core/java/android/widget/RelativeLayout.java
+++ b/core/java/android/widget/RelativeLayout.java
@@ -45,8 +45,7 @@ import java.util.ArrayList;
/**
* A Layout where the positions of the children can be described in relation to each other or to the
- * parent. For the sake of efficiency, the relations between views are evaluated in one pass, so if
- * view Y is dependent on the position of view X, make sure the view X comes first in the layout.
+ * parent.
*
* <p>
* Note that you cannot have a circular dependency between the size of the RelativeLayout and the
@@ -292,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) {
@@ -439,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;
}
}
}
@@ -465,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;
}
}
}
@@ -561,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);
@@ -623,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;
@@ -674,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,
@@ -703,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/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index b847e57..3003580 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -26,6 +26,7 @@ import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.net.Uri;
+import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
@@ -37,7 +38,6 @@ import android.view.ViewGroup;
import android.view.LayoutInflater.Filter;
import android.view.View.OnClickListener;
-import java.lang.Class;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -137,11 +137,21 @@ public class RemoteViews implements Parcelable, Filter {
if (target != null && pendingIntent != null) {
OnClickListener listener = new OnClickListener() {
public void onClick(View v) {
- int[] pos = new int[2];
+ // Find target view location in screen coordinates and
+ // fill into PendingIntent before sending.
+ final float appScale = v.getContext().getResources()
+ .getCompatibilityInfo().applicationScale;
+ final int[] pos = new int[2];
v.getLocationOnScreen(pos);
- Intent intent = new Intent();
- intent.setSourceBounds(new Rect(pos[0], pos[1],
- pos[0]+v.getWidth(), pos[1]+v.getHeight()));
+
+ 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);
+
+ final Intent intent = new Intent();
+ intent.setSourceBounds(rect);
try {
// TODO: Unregister this handler if PendingIntent.FLAG_ONE_SHOT?
v.getContext().startIntentSender(
@@ -273,6 +283,7 @@ public class RemoteViews implements Parcelable, Filter {
static final int CHAR_SEQUENCE = 10;
static final int URI = 11;
static final int BITMAP = 12;
+ static final int BUNDLE = 13;
int viewId;
String methodName;
@@ -332,6 +343,9 @@ public class RemoteViews implements Parcelable, Filter {
case BITMAP:
this.value = Bitmap.CREATOR.createFromParcel(in);
break;
+ case BUNDLE:
+ this.value = in.readBundle();
+ break;
default:
break;
}
@@ -384,6 +398,9 @@ public class RemoteViews implements Parcelable, Filter {
case BITMAP:
((Bitmap)this.value).writeToParcel(out, flags);
break;
+ case BUNDLE:
+ out.writeBundle((Bundle) this.value);
+ break;
default:
break;
}
@@ -415,6 +432,8 @@ public class RemoteViews implements Parcelable, Filter {
return Uri.class;
case BITMAP:
return Bitmap.class;
+ case BUNDLE:
+ return Bundle.class;
default:
return null;
}
@@ -876,6 +895,17 @@ public class RemoteViews implements Parcelable, Filter {
}
/**
+ * Call a method taking one Bundle on a view in the layout for this RemoteViews.
+ *
+ * @param viewId The id of the view whose text should change
+ * @param methodName The name of the method to call.
+ * @param value The value to pass to the method.
+ */
+ public void setBundle(int viewId, String methodName, Bundle value) {
+ addAction(new ReflectionAction(viewId, methodName, ReflectionAction.BUNDLE, value));
+ }
+
+ /**
* Inflates the view hierarchy represented by this object and applies
* all of the actions.
*
diff --git a/core/java/android/widget/SimpleAdapter.java b/core/java/android/widget/SimpleAdapter.java
index 9dd4d15..479965a 100644
--- a/core/java/android/widget/SimpleAdapter.java
+++ b/core/java/android/widget/SimpleAdapter.java
@@ -25,7 +25,6 @@ import android.net.Uri;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
-import java.util.WeakHashMap;
/**
* An easy adapter to map static data to views defined in an XML file. You can specify the data
@@ -58,7 +57,6 @@ public class SimpleAdapter extends BaseAdapter implements Filterable {
private int mResource;
private int mDropDownResource;
private LayoutInflater mInflater;
- private final WeakHashMap<View, View[]> mHolders = new WeakHashMap<View, View[]>();
private SimpleFilter mFilter;
private ArrayList<Map<String, ?>> mUnfilteredData;
@@ -121,16 +119,6 @@ public class SimpleAdapter extends BaseAdapter implements Filterable {
View v;
if (convertView == null) {
v = mInflater.inflate(resource, parent, false);
-
- final int[] to = mTo;
- final int count = to.length;
- final View[] holder = new View[count];
-
- for (int i = 0; i < count; i++) {
- holder[i] = v.findViewById(to[i]);
- }
-
- mHolders.put(v, holder);
} else {
v = convertView;
}
@@ -162,13 +150,12 @@ public class SimpleAdapter extends BaseAdapter implements Filterable {
}
final ViewBinder binder = mViewBinder;
- final View[] holder = mHolders.get(view);
final String[] from = mFrom;
final int[] to = mTo;
final int count = to.length;
for (int i = 0; i < count; i++) {
- final View v = holder[i];
+ final View v = view.findViewById(to[i]);
if (v != null) {
final Object data = dataSet.get(from[i]);
String text = data == null ? "" : data.toString();
@@ -187,7 +174,8 @@ public class SimpleAdapter extends BaseAdapter implements Filterable {
((Checkable) v).setChecked((Boolean) data);
} else {
throw new IllegalStateException(v.getClass().getName() +
- " should be bound to a Boolean, not a " + data.getClass());
+ " should be bound to a Boolean, not a " +
+ (data == null ? "<unknown type>" : data.getClass()));
}
} else if (v instanceof TextView) {
// Note: keep the instanceof TextView check at the bottom of these
diff --git a/core/java/android/widget/SimpleCursorAdapter.java b/core/java/android/widget/SimpleCursorAdapter.java
index 436b79b..7d3459e 100644
--- a/core/java/android/widget/SimpleCursorAdapter.java
+++ b/core/java/android/widget/SimpleCursorAdapter.java
@@ -20,9 +20,6 @@ import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.view.View;
-import android.view.ViewGroup;
-
-import java.util.WeakHashMap;
/**
* An easy adapter to map columns from a cursor to TextViews or ImageViews
@@ -66,7 +63,6 @@ public class SimpleCursorAdapter extends ResourceCursorAdapter {
private CursorToStringConverter mCursorToStringConverter;
private ViewBinder mViewBinder;
private String[] mOriginalFrom;
- private final WeakHashMap<View, View[]> mHolders = new WeakHashMap<View, View[]>();
/**
* Constructor.
@@ -91,29 +87,6 @@ public class SimpleCursorAdapter extends ResourceCursorAdapter {
findColumns(from);
}
- @Override
- public View newView(Context context, Cursor cursor, ViewGroup parent) {
- return generateViewHolder(super.newView(context, cursor, parent));
- }
-
- @Override
- public View newDropDownView(Context context, Cursor cursor, ViewGroup parent) {
- return generateViewHolder(super.newDropDownView(context, cursor, parent));
- }
-
- private View generateViewHolder(View v) {
- final int[] to = mTo;
- final int count = to.length;
- final View[] holder = new View[count];
-
- for (int i = 0; i < count; i++) {
- holder[i] = v.findViewById(to[i]);
- }
- mHolders.put(v, holder);
-
- return v;
- }
-
/**
* Binds all of the field names passed into the "to" parameter of the
* constructor with their corresponding cursor columns as specified in the
@@ -140,13 +113,13 @@ public class SimpleCursorAdapter extends ResourceCursorAdapter {
*/
@Override
public void bindView(View view, Context context, Cursor cursor) {
- final View[] holder = mHolders.get(view);
final ViewBinder binder = mViewBinder;
final int count = mTo.length;
final int[] from = mFrom;
+ final int[] to = mTo;
for (int i = 0; i < count; i++) {
- final View v = holder[i];
+ final View v = view.findViewById(to[i]);
if (v != null) {
boolean bound = false;
if (binder != null) {
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">
* &lt;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"&gt;
@@ -64,8 +64,8 @@ import android.view.accessibility.AccessibilityEvent;
*
* &lt;GridView
* android:id="@id/content"
- * android:layout_width="fill_parent"
- * android:layout_height="fill_parent" /&gt;
+ * android:layout_width="match_parent"
+ * android:layout_height="match_parent" /&gt;
*
* &lt;/SlidingDrawer&gt;
* </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 201cc0c..12e8e29 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -4531,6 +4531,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
// Now use the delta to determine the actual amount of text
// we need.
partialEndOffset += delta;
+ if (partialStartOffset > N) {
+ partialStartOffset = N;
+ } else if (partialStartOffset < 0) {
+ partialStartOffset = 0;
+ }
if (partialEndOffset > N) {
partialEndOffset = N;
} else if (partialEndOffset < 0) {
@@ -4987,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())
@@ -5302,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();
@@ -5349,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;