summaryrefslogtreecommitdiffstats
path: root/core/java/android
diff options
context:
space:
mode:
Diffstat (limited to 'core/java/android')
-rw-r--r--core/java/android/app/ActivityManager.java19
-rw-r--r--core/java/android/app/ActivityManagerNative.java49
-rw-r--r--core/java/android/app/ActivityThread.java22
-rw-r--r--core/java/android/app/IActivityManager.java15
-rw-r--r--core/java/android/app/IApplicationThread.java1
-rw-r--r--core/java/android/app/IBackupAgent.aidl19
-rw-r--r--core/java/android/app/backup/BackupAgent.java32
-rw-r--r--core/java/android/app/backup/FullBackup.java110
-rw-r--r--core/java/android/app/backup/FullBackupAgent.java42
-rw-r--r--core/java/android/app/backup/IBackupManager.aidl8
-rw-r--r--core/java/android/content/res/CompatibilityInfo.java13
-rw-r--r--core/java/android/database/sqlite/SQLiteQueryBuilder.java70
-rw-r--r--core/java/android/net/ConnectivityManager.java36
-rw-r--r--core/java/android/net/IConnectivityManager.aidl4
-rw-r--r--core/java/android/net/INetworkPolicyListener.aidl24
-rw-r--r--core/java/android/net/INetworkPolicyManager.aidl7
-rw-r--r--core/java/android/net/NetworkInfo.java22
-rw-r--r--core/java/android/net/NetworkPolicyManager.java38
-rw-r--r--core/java/android/view/View.java41
-rw-r--r--core/java/android/webkit/HTML5VideoFullScreen.java3
-rw-r--r--core/java/android/webkit/HTML5VideoInline.java49
-rw-r--r--core/java/android/webkit/HTML5VideoView.java12
-rw-r--r--core/java/android/webkit/HTML5VideoViewProxy.java16
-rw-r--r--core/java/android/webkit/ZoomManager.java16
-rw-r--r--core/java/android/widget/SearchView.java5
-rw-r--r--core/java/android/widget/TextView.java14
26 files changed, 570 insertions, 117 deletions
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index ef2e54a..a6658cc 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -138,6 +138,25 @@ public class ActivityManager {
}
}
+ /** @hide */
+ public boolean getPackageAskScreenCompat(String packageName) {
+ try {
+ return ActivityManagerNative.getDefault().getPackageAskScreenCompat(packageName);
+ } catch (RemoteException e) {
+ // System dead, we will be dead too soon!
+ return false;
+ }
+ }
+
+ /** @hide */
+ public void setPackageAskScreenCompat(String packageName, boolean ask) {
+ try {
+ ActivityManagerNative.getDefault().setPackageAskScreenCompat(packageName, ask);
+ } catch (RemoteException e) {
+ // System dead, we will be dead too soon!
+ }
+ }
+
/**
* Return the approximate per-application memory class of the current
* device. This gives you an idea of how hard a memory limit you should
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 2a0d798..85f40c9 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1483,6 +1483,26 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
return true;
}
+ case GET_PACKAGE_ASK_SCREEN_COMPAT_TRANSACTION:
+ {
+ data.enforceInterface(IActivityManager.descriptor);
+ String pkg = data.readString();
+ boolean ask = getPackageAskScreenCompat(pkg);
+ reply.writeNoException();
+ reply.writeInt(ask ? 1 : 0);
+ return true;
+ }
+
+ case SET_PACKAGE_ASK_SCREEN_COMPAT_TRANSACTION:
+ {
+ data.enforceInterface(IActivityManager.descriptor);
+ String pkg = data.readString();
+ boolean ask = data.readInt() != 0;
+ setPackageAskScreenCompat(pkg, ask);
+ reply.writeNoException();
+ return true;
+ }
+
}
return super.onTransact(code, data, reply, flags);
@@ -3254,7 +3274,8 @@ class ActivityManagerProxy implements IActivityManager
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
- mRemote.transact(SET_PACKAGE_SCREEN_COMPAT_MODE_TRANSACTION, data, reply, 0);
+ data.writeString(packageName);
+ mRemote.transact(GET_PACKAGE_SCREEN_COMPAT_MODE_TRANSACTION, data, reply, 0);
reply.readException();
int mode = reply.readInt();
reply.recycle();
@@ -3275,6 +3296,32 @@ class ActivityManagerProxy implements IActivityManager
data.recycle();
}
+ public boolean getPackageAskScreenCompat(String packageName) throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ data.writeString(packageName);
+ mRemote.transact(GET_PACKAGE_ASK_SCREEN_COMPAT_TRANSACTION, data, reply, 0);
+ reply.readException();
+ boolean ask = reply.readInt() != 0;
+ reply.recycle();
+ data.recycle();
+ return ask;
+ }
+
+ public void setPackageAskScreenCompat(String packageName, boolean ask)
+ throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ data.writeString(packageName);
+ data.writeInt(ask ? 1 : 0);
+ mRemote.transact(SET_PACKAGE_ASK_SCREEN_COMPAT_TRANSACTION, data, reply, 0);
+ reply.readException();
+ reply.recycle();
+ data.recycle();
+ }
+
public boolean switchUser(int userid) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 85e59b3..955cef2 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -1980,7 +1980,8 @@ public final class ActivityThread {
BackupAgent agent = null;
String classname = data.appInfo.backupAgentName;
- if (data.backupMode == IApplicationThread.BACKUP_MODE_FULL) {
+ if (data.backupMode == IApplicationThread.BACKUP_MODE_FULL
+ || data.backupMode == IApplicationThread.BACKUP_MODE_RESTORE_FULL) {
classname = "android.app.backup.FullBackupAgent";
if ((data.appInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
// system packages can supply their own full-backup agent
@@ -2011,7 +2012,8 @@ public final class ActivityThread {
// If this is during restore, fail silently; otherwise go
// ahead and let the user see the crash.
Slog.e(TAG, "Agent threw during creation: " + e);
- if (data.backupMode != IApplicationThread.BACKUP_MODE_RESTORE) {
+ if (data.backupMode != IApplicationThread.BACKUP_MODE_RESTORE
+ && data.backupMode != IApplicationThread.BACKUP_MODE_RESTORE_FULL) {
throw e;
}
// falling through with 'binder' still null
@@ -3658,12 +3660,16 @@ public final class ActivityThread {
Application app = data.info.makeApplication(data.restrictedBackupMode, null);
mInitialApplication = app;
- List<ProviderInfo> providers = data.providers;
- if (providers != null) {
- installContentProviders(app, providers);
- // For process that contains content providers, we want to
- // ensure that the JIT is enabled "at some point".
- mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
+ // don't bring up providers in restricted mode; they may depend on the
+ // app's custom Application class
+ if (!data.restrictedBackupMode){
+ List<ProviderInfo> providers = data.providers;
+ if (providers != null) {
+ installContentProviders(app, providers);
+ // For process that contains content providers, we want to
+ // ensure that the JIT is enabled "at some point".
+ mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
+ }
}
try {
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 1f53c0e..e2588cf 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -347,6 +347,9 @@ public interface IActivityManager extends IInterface {
public int getPackageScreenCompatMode(String packageName) throws RemoteException;
public void setPackageScreenCompatMode(String packageName, int mode)
throws RemoteException;
+ public boolean getPackageAskScreenCompat(String packageName) throws RemoteException;
+ public void setPackageAskScreenCompat(String packageName, boolean ask)
+ throws RemoteException;
// Multi-user APIs
public boolean switchUser(int userid) throws RemoteException;
@@ -577,9 +580,11 @@ public interface IActivityManager extends IInterface {
int SET_FRONT_ACTIVITY_SCREEN_COMPAT_MODE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+124;
int GET_PACKAGE_SCREEN_COMPAT_MODE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+125;
int SET_PACKAGE_SCREEN_COMPAT_MODE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+126;
- int SWITCH_USER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+127;
- int REMOVE_SUB_TASK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+128;
- int REMOVE_TASK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+129;
- int REGISTER_PROCESS_OBSERVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+130;
- int UNREGISTER_PROCESS_OBSERVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+131;
+ int GET_PACKAGE_ASK_SCREEN_COMPAT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+127;
+ int SET_PACKAGE_ASK_SCREEN_COMPAT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+128;
+ int SWITCH_USER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+129;
+ int REMOVE_SUB_TASK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+130;
+ int REMOVE_TASK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+131;
+ int REGISTER_PROCESS_OBSERVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+132;
+ int UNREGISTER_PROCESS_OBSERVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+133;
}
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index 8c31559..05a68a8 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -68,6 +68,7 @@ public interface IApplicationThread extends IInterface {
static final int BACKUP_MODE_INCREMENTAL = 0;
static final int BACKUP_MODE_FULL = 1;
static final int BACKUP_MODE_RESTORE = 2;
+ static final int BACKUP_MODE_RESTORE_FULL = 3;
void scheduleCreateBackupAgent(ApplicationInfo app, CompatibilityInfo compatInfo,
int backupMode) throws RemoteException;
void scheduleDestroyBackupAgent(ApplicationInfo app, CompatibilityInfo compatInfo)
diff --git a/core/java/android/app/IBackupAgent.aidl b/core/java/android/app/IBackupAgent.aidl
index 52fc623..8af78fa 100644
--- a/core/java/android/app/IBackupAgent.aidl
+++ b/core/java/android/app/IBackupAgent.aidl
@@ -79,4 +79,23 @@ oneway interface IBackupAgent {
*/
void doRestore(in ParcelFileDescriptor data, int appVersionCode,
in ParcelFileDescriptor newState, int token, IBackupManager callbackBinder);
+
+ /**
+ * Restore a single "file" to the application. The file was typically obtained from
+ * a full-backup dataset. The agent reads 'size' bytes of file content
+ * from the provided file descriptor.
+ *
+ * @param data Read-only pipe delivering the file content itself.
+ *
+ * @param size Size of the file being restored.
+ * @param type Type of file system entity, e.g. FullBackup.TYPE_DIRECTORY.
+ * @param domain Name of the file's semantic domain to which the 'path' argument is a
+ * relative path. e.g. FullBackup.DATABASE_TREE_TOKEN.
+ * @param path Relative path of the file within its semantic domain.
+ * @param mode Access mode of the file system entity, e.g. 0660.
+ * @param mtime Last modification time of the file system entity.
+ */
+ void doRestoreFile(in ParcelFileDescriptor data, long size,
+ int type, String domain, String path, long mode, long mtime,
+ int token, IBackupManager callbackBinder);
}
diff --git a/core/java/android/app/backup/BackupAgent.java b/core/java/android/app/backup/BackupAgent.java
index dc60e24..17f8adb 100644
--- a/core/java/android/app/backup/BackupAgent.java
+++ b/core/java/android/app/backup/BackupAgent.java
@@ -179,10 +179,18 @@ public abstract class BackupAgent extends ContextWrapper {
throws IOException;
/**
+ * @hide
+ */
+ public void onRestoreFile(ParcelFileDescriptor data, long size,
+ int type, String domain, String path, long mode, long mtime)
+ throws IOException {
+ // empty stub implementation
+ }
+
+ /**
* Package-private, used only for dispatching an extra step during full backup
*/
void onSaveApk(BackupDataOutput data) {
- if (DEBUG) Log.v(TAG, "--- base onSaveApk() ---");
}
// ----- Core implementation -----
@@ -203,6 +211,7 @@ public abstract class BackupAgent extends ContextWrapper {
private class BackupServiceBinder extends IBackupAgent.Stub {
private static final String TAG = "BackupServiceBinder";
+ @Override
public void doBackup(ParcelFileDescriptor oldState,
ParcelFileDescriptor data,
ParcelFileDescriptor newState,
@@ -236,6 +245,7 @@ public abstract class BackupAgent extends ContextWrapper {
}
}
+ @Override
public void doRestore(ParcelFileDescriptor data, int appVersionCode,
ParcelFileDescriptor newState,
int token, IBackupManager callbackBinder) throws RemoteException {
@@ -261,5 +271,25 @@ public abstract class BackupAgent extends ContextWrapper {
}
}
}
+
+ @Override
+ public void doRestoreFile(ParcelFileDescriptor data, long size,
+ int type, String domain, String path, long mode, long mtime,
+ int token, IBackupManager callbackBinder) throws RemoteException {
+ long ident = Binder.clearCallingIdentity();
+ try {
+Log.d(TAG, "doRestoreFile() => onRestoreFile()");
+ BackupAgent.this.onRestoreFile(data, size, type, domain, path, mode, mtime);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ try {
+ callbackBinder.opComplete(token);
+ } catch (RemoteException e) {
+ // we'll time out anyway, so we're safe
+ }
+ }
+ }
}
}
diff --git a/core/java/android/app/backup/FullBackup.java b/core/java/android/app/backup/FullBackup.java
index 9850566..dfb0dd7 100644
--- a/core/java/android/app/backup/FullBackup.java
+++ b/core/java/android/app/backup/FullBackup.java
@@ -16,6 +16,17 @@
package android.app.backup;
+import android.os.ParcelFileDescriptor;
+import android.util.Log;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import libcore.io.ErrnoException;
+import libcore.io.Libcore;
+
/**
* Global constant definitions et cetera related to the full-backup-to-fd
* binary format.
@@ -23,18 +34,95 @@ package android.app.backup;
* @hide
*/
public class FullBackup {
- public static String APK_TREE_TOKEN = "a";
- public static String OBB_TREE_TOKEN = "obb";
- public static String ROOT_TREE_TOKEN = "r";
- public static String DATA_TREE_TOKEN = "f";
- public static String DATABASE_TREE_TOKEN = "db";
- public static String SHAREDPREFS_TREE_TOKEN = "sp";
- public static String CACHE_TREE_TOKEN = "c";
-
- public static String FULL_BACKUP_INTENT_ACTION = "fullback";
- public static String FULL_RESTORE_INTENT_ACTION = "fullrest";
- public static String CONF_TOKEN_INTENT_EXTRA = "conftoken";
+ static final String TAG = "FullBackup";
+
+ public static final String APK_TREE_TOKEN = "a";
+ public static final String OBB_TREE_TOKEN = "obb";
+ public static final String ROOT_TREE_TOKEN = "r";
+ public static final String DATA_TREE_TOKEN = "f";
+ public static final String DATABASE_TREE_TOKEN = "db";
+ public static final String SHAREDPREFS_TREE_TOKEN = "sp";
+ public static final String CACHE_TREE_TOKEN = "c";
+ public static final String SHARED_STORAGE_TOKEN = "shared";
+
+ public static final String APPS_PREFIX = "apps/";
+ public static final String SHARED_PREFIX = "shared/";
+
+ public static final String FULL_BACKUP_INTENT_ACTION = "fullback";
+ public static final String FULL_RESTORE_INTENT_ACTION = "fullrest";
+ public static final String CONF_TOKEN_INTENT_EXTRA = "conftoken";
+
+ public static final int TYPE_EOF = 0;
+ public static final int TYPE_FILE = 1;
+ public static final int TYPE_DIRECTORY = 2;
+ public static final int TYPE_SYMLINK = 3;
static public native int backupToTar(String packageName, String domain,
String linkdomain, String rootpath, String path, BackupDataOutput output);
+
+ static public void restoreToFile(ParcelFileDescriptor data,
+ long size, int type, long mode, long mtime, File outFile) throws IOException {
+ if (type == FullBackup.TYPE_DIRECTORY) {
+ // Canonically a directory has no associated content, so we don't need to read
+ // anything from the pipe in this case. Just create the directory here and
+ // drop down to the final metadata adjustment.
+ if (outFile != null) outFile.mkdirs();
+ } else {
+ FileOutputStream out = null;
+
+ // Pull the data from the pipe, copying it to the output file, until we're done
+ try {
+ if (outFile != null) {
+ File parent = outFile.getParentFile();
+ if (!parent.exists()) {
+ // in practice this will only be for the default semantic directories,
+ // and using the default mode for those is appropriate.
+ // TODO: support the edge case of apps that have adjusted the
+ // permissions on these core directories
+ parent.mkdirs();
+ }
+ out = new FileOutputStream(outFile);
+ }
+ } catch (IOException e) {
+ Log.e(TAG, "Unable to create/open file " + outFile.getPath(), e);
+ }
+
+ byte[] buffer = new byte[32 * 1024];
+ final long origSize = size;
+ FileInputStream in = new FileInputStream(data.getFileDescriptor());
+ while (size > 0) {
+ int toRead = (size > buffer.length) ? buffer.length : (int)size;
+ int got = in.read(buffer, 0, toRead);
+ if (got <= 0) {
+ Log.w(TAG, "Incomplete read: expected " + size + " but got "
+ + (origSize - size));
+ break;
+ }
+ if (out != null) {
+ try {
+ out.write(buffer, 0, got);
+ } catch (IOException e) {
+ // Problem writing to the file. Quit copying data and delete
+ // the file, but of course keep consuming the input stream.
+ Log.e(TAG, "Unable to write to file " + outFile.getPath(), e);
+ out.close();
+ out = null;
+ outFile.delete();
+ }
+ }
+ size -= got;
+ }
+ if (out != null) out.close();
+ }
+
+ // Now twiddle the state to match the backup, assuming all went well
+ if (outFile != null) {
+ try {
+ Libcore.os.chmod(outFile.getPath(), (int)mode);
+ } catch (ErrnoException e) {
+ e.rethrowAsIOException();
+ }
+ outFile.setLastModified(mtime);
+ }
+ }
}
diff --git a/core/java/android/app/backup/FullBackupAgent.java b/core/java/android/app/backup/FullBackupAgent.java
index f0a1f2a..4dca593 100644
--- a/core/java/android/app/backup/FullBackupAgent.java
+++ b/core/java/android/app/backup/FullBackupAgent.java
@@ -28,6 +28,9 @@ import libcore.io.OsConstants;
import libcore.io.StructStat;
import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
import java.util.HashSet;
import java.util.LinkedList;
@@ -53,8 +56,12 @@ public class FullBackupAgent extends BackupAgent {
private String mCacheDir;
private String mLibDir;
+ private File NULL_FILE;
+
@Override
public void onCreate() {
+ NULL_FILE = new File("/dev/null");
+
mPm = getPackageManager();
try {
ApplicationInfo appInfo = mPm.getApplicationInfo(getPackageName(), 0);
@@ -177,7 +184,40 @@ public class FullBackupAgent extends BackupAgent {
}
}
+ /**
+ * Dummy -- We're never used for restore of an incremental dataset
+ */
+ @Override
+ public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState)
+ throws IOException {
+ }
+
+ /**
+ * Restore the described file from the given pipe.
+ */
@Override
- public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState) {
+ public void onRestoreFile(ParcelFileDescriptor data, long size,
+ int type, String domain, String relpath, long mode, long mtime)
+ throws IOException {
+ String basePath = null;
+ File outFile = null;
+
+ if (DEBUG) Log.d(TAG, "onRestoreFile() size=" + size + " type=" + type
+ + " domain=" + domain + " relpath=" + relpath + " mode=" + mode
+ + " mtime=" + mtime);
+
+ // Parse out the semantic domains into the correct physical location
+ if (domain.equals(FullBackup.DATA_TREE_TOKEN)) basePath = mFilesDir;
+ else if (domain.equals(FullBackup.DATABASE_TREE_TOKEN)) basePath = mDatabaseDir;
+ else if (domain.equals(FullBackup.ROOT_TREE_TOKEN)) basePath = mMainDir;
+ else if (domain.equals(FullBackup.SHAREDPREFS_TREE_TOKEN)) basePath = mSharedPrefsDir;
+
+ // Not a supported output location? We need to consume the data
+ // anyway, so send it to /dev/null
+ outFile = (basePath != null) ? new File(basePath, relpath) : null;
+ if (DEBUG) Log.i(TAG, "[" + domain + " : " + relpath + "] mapped to " + outFile.getPath());
+
+ // Now that we've figured out where the data goes, send it on its way
+ FullBackup.restoreToFile(data, size, type, mode, mtime, outFile);
}
}
diff --git a/core/java/android/app/backup/IBackupManager.aidl b/core/java/android/app/backup/IBackupManager.aidl
index 94e31a8..bac874e 100644
--- a/core/java/android/app/backup/IBackupManager.aidl
+++ b/core/java/android/app/backup/IBackupManager.aidl
@@ -147,6 +147,14 @@ interface IBackupManager {
boolean allApps, in String[] packageNames);
/**
+ * Restore device content from the data stream passed through the given socket. The
+ * data stream must be in the format emitted by fullBackup().
+ *
+ * <p>Callers must hold the android.permission.BACKUP permission to use this method.
+ */
+ void fullRestore(in ParcelFileDescriptor fd);
+
+ /**
* Confirm that the requested full backup/restore operation can proceed. The system will
* not actually perform the operation described to fullBackup() / fullRestore() unless the
* UI calls back into the Backup Manager to confirm, passing the correct token. At
diff --git a/core/java/android/content/res/CompatibilityInfo.java b/core/java/android/content/res/CompatibilityInfo.java
index 854d410..dca53a8 100644
--- a/core/java/android/content/res/CompatibilityInfo.java
+++ b/core/java/android/content/res/CompatibilityInfo.java
@@ -113,8 +113,13 @@ public class CompatibilityInfo implements Parcelable {
public CompatibilityInfo(ApplicationInfo appInfo, int screenLayout, boolean forceCompat) {
int compatFlags = 0;
+ // We can't rely on the application always setting
+ // FLAG_RESIZEABLE_FOR_SCREENS so will compute it based on various input.
+ boolean anyResizeable = false;
+
if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) {
compatFlags |= LARGE_SCREENS;
+ anyResizeable = true;
if (!forceCompat) {
// If we aren't forcing the app into compatibility mode, then
// assume if it supports large screens that we should allow it
@@ -123,9 +128,13 @@ public class CompatibilityInfo implements Parcelable {
}
}
if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS) != 0) {
- compatFlags |= XLARGE_SCREENS | EXPANDABLE;
+ anyResizeable = true;
+ if (!forceCompat) {
+ compatFlags |= XLARGE_SCREENS | EXPANDABLE;
+ }
}
if ((appInfo.flags & ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS) != 0) {
+ anyResizeable = true;
compatFlags |= EXPANDABLE;
}
@@ -160,7 +169,7 @@ public class CompatibilityInfo implements Parcelable {
if ((screenLayout&Configuration.SCREENLAYOUT_COMPAT_NEEDED) != 0) {
if ((compatFlags&EXPANDABLE) != 0) {
supportsScreen = true;
- } else if ((appInfo.flags & ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS) == 0) {
+ } else if (!anyResizeable) {
compatFlags |= ALWAYS_COMPAT;
}
}
diff --git a/core/java/android/database/sqlite/SQLiteQueryBuilder.java b/core/java/android/database/sqlite/SQLiteQueryBuilder.java
index b6aca2b..9c09e81 100644
--- a/core/java/android/database/sqlite/SQLiteQueryBuilder.java
+++ b/core/java/android/database/sqlite/SQLiteQueryBuilder.java
@@ -24,8 +24,8 @@ import android.util.Log;
import java.util.Iterator;
import java.util.Map;
-import java.util.Set;
import java.util.Map.Entry;
+import java.util.Set;
import java.util.regex.Pattern;
/**
@@ -43,7 +43,7 @@ public class SQLiteQueryBuilder
private StringBuilder mWhereClause = null; // lazily created
private boolean mDistinct;
private SQLiteDatabase.CursorFactory mFactory;
- private boolean mStrictProjectionMap;
+ private boolean mStrict;
public SQLiteQueryBuilder() {
mDistinct = false;
@@ -145,10 +145,37 @@ public class SQLiteQueryBuilder
}
/**
+ * Need to keep this to not break the build until ContactsProvider2 has been changed to
+ * use the new API
+ * TODO: Remove this
* @hide
*/
public void setStrictProjectionMap(boolean flag) {
- mStrictProjectionMap = flag;
+ }
+
+ /**
+ * When set, the selection is verified against malicious arguments.
+ * When using this class to create a statement using
+ * {@link #buildQueryString(boolean, String, String[], String, String, String, String, String)},
+ * non-numeric limits will raise an exception. If a projection map is specified, fields
+ * not in that map will be ignored.
+ * If this class is used to execute the statement directly using
+ * {@link #query(SQLiteDatabase, String[], String, String[], String, String, String)}
+ * or
+ * {@link #query(SQLiteDatabase, String[], String, String[], String, String, String, String)},
+ * additionally also parenthesis escaping selection are caught.
+ *
+ * To summarize: To get maximum protection against malicious third party apps (for example
+ * content provider consumers), make sure to do the following:
+ * <ul>
+ * <li>Set this value to true</li>
+ * <li>Use a projection map</li>
+ * <li>Use one of the query overloads instead of getting the statement as a sql string</li>
+ * </ul>
+ * By default, this value is false.
+ */
+ public void setStrict(boolean flag) {
+ mStrict = flag;
}
/**
@@ -217,13 +244,6 @@ public class SQLiteQueryBuilder
}
}
- private static void appendClauseEscapeClause(StringBuilder s, String name, String clause) {
- if (!TextUtils.isEmpty(clause)) {
- s.append(name);
- DatabaseUtils.appendEscapedSQLString(s, clause);
- }
- }
-
/**
* Add the names that are non-null in columns to s, separating
* them with commas.
@@ -320,6 +340,19 @@ public class SQLiteQueryBuilder
return null;
}
+ if (mStrict && selection != null && selection.length() > 0) {
+ // Validate the user-supplied selection to detect syntactic anomalies
+ // in the selection string that could indicate a SQL injection attempt.
+ // The idea is to ensure that the selection clause is a valid SQL expression
+ // by compiling it twice: once wrapped in parentheses and once as
+ // originally specified. An attacker cannot create an expression that
+ // would escape the SQL expression while maintaining balanced parentheses
+ // in both the wrapped and original forms.
+ String sqlForValidation = buildQuery(projectionIn, "(" + selection + ")", groupBy,
+ having, sortOrder, limit);
+ validateSql(db, sqlForValidation); // will throw if query is invalid
+ }
+
String sql = buildQuery(
projectionIn, selection, groupBy, having,
sortOrder, limit);
@@ -329,7 +362,20 @@ public class SQLiteQueryBuilder
}
return db.rawQueryWithFactory(
mFactory, sql, selectionArgs,
- SQLiteDatabase.findEditTable(mTables));
+ SQLiteDatabase.findEditTable(mTables)); // will throw if query is invalid
+ }
+
+ /**
+ * Verifies that a SQL statement is valid by compiling it.
+ * If the SQL statement is not valid, this method will throw a {@link SQLiteException}.
+ */
+ private void validateSql(SQLiteDatabase db, String sql) {
+ db.lock(sql);
+ try {
+ new SQLiteCompiledSql(db, sql).releaseSqlStatement();
+ } finally {
+ db.unlock();
+ }
}
/**
@@ -541,7 +587,7 @@ public class SQLiteQueryBuilder
continue;
}
- if (!mStrictProjectionMap &&
+ if (!mStrict &&
( userColumn.contains(" AS ") || userColumn.contains(" as "))) {
/* A column alias already exist */
projection[i] = userColumn;
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 419288b..c72c4b0 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -22,7 +22,6 @@ import android.os.Binder;
import android.os.RemoteException;
import java.net.InetAddress;
-import java.net.UnknownHostException;
/**
* Class that answers queries about the state of network connectivity. It also
@@ -40,8 +39,9 @@ import java.net.UnknownHostException;
* state of the available networks</li>
* </ol>
*/
-public class ConnectivityManager
-{
+public class ConnectivityManager {
+ private static final String TAG = "ConnectivityManager";
+
/**
* A change in network connectivity has occurred. A connection has either
* been established or lost. The NetworkInfo for the affected network is
@@ -109,7 +109,7 @@ public class ConnectivityManager
* The lookup key for an int that provides information about
* our connection to the internet at large. 0 indicates no connection,
* 100 indicates a great connection. Retrieve it with
- * {@link android.content.Intent@getIntExtra(String)}.
+ * {@link android.content.Intent#getIntExtra(String, int)}.
* {@hide}
*/
public static final String EXTRA_INET_CONDITION = "inetCondition";
@@ -120,13 +120,12 @@ public class ConnectivityManager
* <p>
* If an application uses the network in the background, it should listen
* for this broadcast and stop using the background data if the value is
- * false.
+ * {@code false}.
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_BACKGROUND_DATA_SETTING_CHANGED =
"android.net.conn.BACKGROUND_DATA_SETTING_CHANGED";
-
/**
* Broadcast Action: The network connection may not be good
* uses {@code ConnectivityManager.EXTRA_INET_CONDITION} and
@@ -255,7 +254,7 @@ public class ConnectivityManager
public static final int DEFAULT_NETWORK_PREFERENCE = TYPE_WIFI;
- private IConnectivityManager mService;
+ private final IConnectivityManager mService;
static public boolean isNetworkTypeValid(int networkType) {
return networkType >= 0 && networkType <= MAX_NETWORK_TYPE;
@@ -284,6 +283,15 @@ public class ConnectivityManager
}
}
+ /** {@hide} */
+ public NetworkInfo getActiveNetworkInfoForUid(int uid) {
+ try {
+ return mService.getActiveNetworkInfoForUid(uid);
+ } catch (RemoteException e) {
+ return null;
+ }
+ }
+
public NetworkInfo getNetworkInfo(int networkType) {
try {
return mService.getNetworkInfo(networkType);
@@ -300,7 +308,7 @@ public class ConnectivityManager
}
}
- /** @hide */
+ /** {@hide} */
public LinkProperties getActiveLinkProperties() {
try {
return mService.getActiveLinkProperties();
@@ -309,7 +317,7 @@ public class ConnectivityManager
}
}
- /** @hide */
+ /** {@hide} */
public LinkProperties getLinkProperties(int networkType) {
try {
return mService.getLinkProperties(networkType);
@@ -479,19 +487,11 @@ public class ConnectivityManager
}
/**
- * Don't allow use of default constructor.
- */
- @SuppressWarnings({"UnusedDeclaration"})
- private ConnectivityManager() {
- }
-
- /**
* {@hide}
*/
public ConnectivityManager(IConnectivityManager service) {
if (service == null) {
- throw new IllegalArgumentException(
- "ConnectivityManager() cannot be constructed with null service");
+ throw new IllegalArgumentException("missing IConnectivityManager");
}
mService = service;
}
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 8be492c..647a60a 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -33,13 +33,11 @@ interface IConnectivityManager
int getNetworkPreference();
NetworkInfo getActiveNetworkInfo();
-
+ NetworkInfo getActiveNetworkInfoForUid(int uid);
NetworkInfo getNetworkInfo(int networkType);
-
NetworkInfo[] getAllNetworkInfo();
LinkProperties getActiveLinkProperties();
-
LinkProperties getLinkProperties(int networkType);
boolean setRadios(boolean onOff);
diff --git a/core/java/android/net/INetworkPolicyListener.aidl b/core/java/android/net/INetworkPolicyListener.aidl
new file mode 100644
index 0000000..9230151
--- /dev/null
+++ b/core/java/android/net/INetworkPolicyListener.aidl
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+/** {@hide} */
+oneway interface INetworkPolicyListener {
+
+ void onRulesChanged(int uid, int uidRules);
+
+}
diff --git a/core/java/android/net/INetworkPolicyManager.aidl b/core/java/android/net/INetworkPolicyManager.aidl
index d9351ee..c1f3530 100644
--- a/core/java/android/net/INetworkPolicyManager.aidl
+++ b/core/java/android/net/INetworkPolicyManager.aidl
@@ -16,6 +16,8 @@
package android.net;
+import android.net.INetworkPolicyListener;
+
/**
* Interface that creates and modifies network policy rules.
*
@@ -26,6 +28,11 @@ interface INetworkPolicyManager {
void setUidPolicy(int uid, int policy);
int getUidPolicy(int uid);
+ boolean isUidForeground(int uid);
+
+ void registerListener(INetworkPolicyListener listener);
+ void unregisterListener(INetworkPolicyListener listener);
+
// TODO: build API to surface stats details for settings UI
}
diff --git a/core/java/android/net/NetworkInfo.java b/core/java/android/net/NetworkInfo.java
index 5f5e11c..537750a 100644
--- a/core/java/android/net/NetworkInfo.java
+++ b/core/java/android/net/NetworkInfo.java
@@ -74,7 +74,9 @@ public class NetworkInfo implements Parcelable {
/** IP traffic not available. */
DISCONNECTED,
/** Attempt to connect failed. */
- FAILED
+ FAILED,
+ /** Access to this network is blocked. */
+ BLOCKED
}
/**
@@ -96,6 +98,7 @@ public class NetworkInfo implements Parcelable {
stateMap.put(DetailedState.DISCONNECTING, State.DISCONNECTING);
stateMap.put(DetailedState.DISCONNECTED, State.DISCONNECTED);
stateMap.put(DetailedState.FAILED, State.DISCONNECTED);
+ stateMap.put(DetailedState.BLOCKED, State.DISCONNECTED);
}
private int mNetworkType;
@@ -138,6 +141,23 @@ public class NetworkInfo implements Parcelable {
mIsRoaming = false;
}
+ /** {@hide} */
+ public NetworkInfo(NetworkInfo source) {
+ if (source != null) {
+ mNetworkType = source.mNetworkType;
+ mSubtype = source.mSubtype;
+ mTypeName = source.mTypeName;
+ mSubtypeName = source.mSubtypeName;
+ mState = source.mState;
+ mDetailedState = source.mDetailedState;
+ mReason = source.mReason;
+ mExtraInfo = source.mExtraInfo;
+ mIsFailover = source.mIsFailover;
+ mIsRoaming = source.mIsRoaming;
+ mIsAvailable = source.mIsAvailable;
+ }
+ }
+
/**
* Reports the type of network (currently mobile or Wi-Fi) to which the
* info in this object pertains.
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index 1913aa7..dd7c1b0 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -19,6 +19,8 @@ package android.net;
import android.content.Context;
import android.os.RemoteException;
+import java.io.PrintWriter;
+
/**
* Manager for creating and modifying network policy rules.
*
@@ -28,12 +30,13 @@ public class NetworkPolicyManager {
/** No specific network policy, use system default. */
public static final int POLICY_NONE = 0x0;
- /** Reject network usage when application in background. */
- public static final int POLICY_REJECT_BACKGROUND = 0x1;
- /** Reject network usage on paid network connections. */
- public static final int POLICY_REJECT_PAID = 0x2;
- /** Application should conserve data. */
- public static final int POLICY_CONSERVE_DATA = 0x4;
+ /** Reject network usage on paid networks when application in background. */
+ public static final int POLICY_REJECT_PAID_BACKGROUND = 0x1;
+
+ /** All network traffic should be allowed. */
+ public static final int RULE_ALLOW_ALL = 0x0;
+ /** Reject traffic on paid networks. */
+ public static final int RULE_REJECT_PAID = 0x1;
private INetworkPolicyManager mService;
@@ -51,9 +54,8 @@ public class NetworkPolicyManager {
/**
* Set policy flags for specific UID.
*
- * @param policy {@link #POLICY_NONE} or combination of
- * {@link #POLICY_REJECT_BACKGROUND}, {@link #POLICY_REJECT_PAID},
- * or {@link #POLICY_CONSERVE_DATA}.
+ * @param policy {@link #POLICY_NONE} or combination of flags like
+ * {@link #POLICY_REJECT_PAID_BACKGROUND}.
*/
public void setUidPolicy(int uid, int policy) {
try {
@@ -69,5 +71,23 @@ public class NetworkPolicyManager {
return POLICY_NONE;
}
}
+
+ /** {@hide} */
+ public static void dumpPolicy(PrintWriter fout, int policy) {
+ fout.write("[");
+ if ((policy & POLICY_REJECT_PAID_BACKGROUND) != 0) {
+ fout.write("REJECT_PAID_BACKGROUND");
+ }
+ fout.write("]");
+ }
+
+ /** {@hide} */
+ public static void dumpRules(PrintWriter fout, int rules) {
+ fout.write("[");
+ if ((rules & RULE_REJECT_PAID) != 0) {
+ fout.write("REJECT_PAID");
+ }
+ fout.write("]");
+ }
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 017e5e3..c9db697 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -982,10 +982,21 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit
*/
static final int HORIZONTAL_DIRECTION_MASK = 0xC0000000;
+ /*
+ * Array of horizontal direction flags for mapping attribute "horizontalDirection" to correct
+ * flag value.
+ * {@hide}
+ */
private static final int[] HORIZONTAL_DIRECTION_FLAGS = { HORIZONTAL_DIRECTION_LTR,
HORIZONTAL_DIRECTION_RTL, HORIZONTAL_DIRECTION_INHERIT, HORIZONTAL_DIRECTION_LOCALE};
/**
+ * Default horizontalDirection.
+ * {@hide}
+ */
+ private static final int HORIZONTAL_DIRECTION_DEFAULT = HORIZONTAL_DIRECTION_INHERIT;
+
+ /**
* View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
* should add all focusable Views regardless if they are focusable in touch mode.
*/
@@ -2442,7 +2453,7 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit
public View(Context context) {
mContext = context;
mResources = context != null ? context.getResources() : null;
- mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED;
+ mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED | HORIZONTAL_DIRECTION_INHERIT;
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
}
@@ -2641,12 +2652,18 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit
}
break;
case com.android.internal.R.styleable.View_horizontalDirection:
- final int layoutDirection = a.getInt(attr, 0);
- if (layoutDirection != 0) {
- viewFlagValues |= HORIZONTAL_DIRECTION_FLAGS[layoutDirection];
- viewFlagMasks |= HORIZONTAL_DIRECTION_MASK;
- }
- break;
+ // Clear any HORIZONTAL_DIRECTION flag already set
+ viewFlagValues &= ~HORIZONTAL_DIRECTION_MASK;
+ // Set the HORIZONTAL_DIRECTION flags depending on the value of the attribute
+ final int horizontalDirection = a.getInt(attr, -1);
+ if (horizontalDirection != -1) {
+ viewFlagValues |= HORIZONTAL_DIRECTION_FLAGS[horizontalDirection];
+ } else {
+ // Set to default (HORIZONTAL_DIRECTION_INHERIT)
+ viewFlagValues |= HORIZONTAL_DIRECTION_DEFAULT;
+ }
+ viewFlagMasks |= HORIZONTAL_DIRECTION_MASK;
+ break;
case com.android.internal.R.styleable.View_drawingCacheQuality:
final int cacheQuality = a.getInt(attr, 0);
if (cacheQuality != 0) {
@@ -8513,10 +8530,14 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit
mPrivateFlags &= ~AWAKEN_SCROLL_BARS_ON_ATTACH;
}
jumpDrawablesToCurrentState();
+ resolveHorizontalDirection();
+ }
- // We are supposing here that the parent directionality will be resolved before its children
- // View horizontalDirection public attribute resolution to an internal var.
- // Resolving the layout direction. LTR is set initially.
+ /**
+ * Resolving the layout direction. LTR is set initially.
+ * We are supposing here that the parent directionality will be resolved before its children
+ */
+ private void resolveHorizontalDirection() {
mPrivateFlags2 &= ~RESOLVED_LAYOUT_RTL;
switch (getHorizontalDirection()) {
case HORIZONTAL_DIRECTION_INHERIT:
diff --git a/core/java/android/webkit/HTML5VideoFullScreen.java b/core/java/android/webkit/HTML5VideoFullScreen.java
index 1004b5f..57cda97 100644
--- a/core/java/android/webkit/HTML5VideoFullScreen.java
+++ b/core/java/android/webkit/HTML5VideoFullScreen.java
@@ -199,6 +199,9 @@ public class HTML5VideoFullScreen extends HTML5VideoView
mVideoSurfaceView.getHolder().setFixedSize(mVideoWidth, mVideoHeight);
}
+ public boolean fullScreenExited() {
+ return (mLayout == null);
+ }
private final WebChromeClient.CustomViewCallback mCallback =
new WebChromeClient.CustomViewCallback() {
diff --git a/core/java/android/webkit/HTML5VideoInline.java b/core/java/android/webkit/HTML5VideoInline.java
index 25921bc..ef1906c 100644
--- a/core/java/android/webkit/HTML5VideoInline.java
+++ b/core/java/android/webkit/HTML5VideoInline.java
@@ -12,10 +12,15 @@ import android.opengl.GLES20;
*/
public class HTML5VideoInline extends HTML5VideoView{
- // Due to the fact that SurfaceTexture consume a lot of memory, we make it
- // as static. m_textureNames is the texture bound with this SurfaceTexture.
+ // Due to the fact that the decoder consume a lot of memory, we make the
+ // surface texture as singleton. But the GL texture (m_textureNames)
+ // associated with the surface texture can be used for showing the screen
+ // shot when paused, so they are not singleton.
private static SurfaceTexture mSurfaceTexture = null;
- private static int[] mTextureNames;
+ private int[] mTextureNames;
+ // Every time when the VideoLayer Id change, we need to recreate the
+ // SurfaceTexture in order to delete the old video's decoder memory.
+ private static int mVideoLayerUsingSurfaceTexture = -1;
// Video control FUNCTIONS:
@Override
@@ -28,11 +33,12 @@ public class HTML5VideoInline extends HTML5VideoView{
HTML5VideoInline(int videoLayerId, int position,
boolean autoStart) {
init(videoLayerId, position, autoStart);
+ mTextureNames = null;
}
@Override
public void decideDisplayMode() {
- mPlayer.setTexture(getSurfaceTextureInstance());
+ mPlayer.setTexture(getSurfaceTexture(getVideoLayerId()));
}
// Normally called immediately after setVideoURI. But for full screen,
@@ -52,31 +58,38 @@ public class HTML5VideoInline extends HTML5VideoView{
// Inline Video specific FUNCTIONS:
@Override
- public SurfaceTexture getSurfaceTexture() {
+ public SurfaceTexture getSurfaceTexture(int videoLayerId) {
+ // Create the surface texture.
+ if (videoLayerId != mVideoLayerUsingSurfaceTexture
+ || mSurfaceTexture == null) {
+ if (mTextureNames == null) {
+ mTextureNames = new int[1];
+ GLES20.glGenTextures(1, mTextureNames, 0);
+ }
+ mSurfaceTexture = new SurfaceTexture(mTextureNames[0]);
+ }
+ mVideoLayerUsingSurfaceTexture = videoLayerId;
return mSurfaceTexture;
}
+ public boolean surfaceTextureDeleted() {
+ return (mSurfaceTexture == null);
+ }
+
@Override
public void deleteSurfaceTexture() {
mSurfaceTexture = null;
+ mVideoLayerUsingSurfaceTexture = -1;
return;
}
- // SurfaceTexture is a singleton here , too
- private SurfaceTexture getSurfaceTextureInstance() {
- // Create the surface texture.
- if (mSurfaceTexture == null)
- {
- mTextureNames = new int[1];
- GLES20.glGenTextures(1, mTextureNames, 0);
- mSurfaceTexture = new SurfaceTexture(mTextureNames[0]);
- }
- return mSurfaceTexture;
- }
-
@Override
public int getTextureName() {
- return mTextureNames[0];
+ if (mTextureNames != null) {
+ return mTextureNames[0];
+ } else {
+ return 0;
+ }
}
private void setFrameAvailableListener(SurfaceTexture.OnFrameAvailableListener l) {
diff --git a/core/java/android/webkit/HTML5VideoView.java b/core/java/android/webkit/HTML5VideoView.java
index c05498a..5983a44 100644
--- a/core/java/android/webkit/HTML5VideoView.java
+++ b/core/java/android/webkit/HTML5VideoView.java
@@ -287,7 +287,7 @@ public class HTML5VideoView implements MediaPlayer.OnPreparedListener {
return false;
}
- public SurfaceTexture getSurfaceTexture() {
+ public SurfaceTexture getSurfaceTexture(int videoLayerId) {
return null;
}
@@ -315,4 +315,14 @@ public class HTML5VideoView implements MediaPlayer.OnPreparedListener {
// Only used in HTML5VideoFullScreen
}
+ public boolean surfaceTextureDeleted() {
+ // Only meaningful for HTML5VideoInline
+ return false;
+ }
+
+ public boolean fullScreenExited() {
+ // Only meaningful for HTML5VideoFullScreen
+ return false;
+ }
+
}
diff --git a/core/java/android/webkit/HTML5VideoViewProxy.java b/core/java/android/webkit/HTML5VideoViewProxy.java
index 7d8669b..d0237b5 100644
--- a/core/java/android/webkit/HTML5VideoViewProxy.java
+++ b/core/java/android/webkit/HTML5VideoViewProxy.java
@@ -106,12 +106,14 @@ class HTML5VideoViewProxy extends Handler
public static void setBaseLayer(int layer) {
// Don't do this for full screen mode.
if (mHTML5VideoView != null
- && !mHTML5VideoView.isFullScreenMode()) {
+ && !mHTML5VideoView.isFullScreenMode()
+ && !mHTML5VideoView.surfaceTextureDeleted()) {
mBaseLayer = layer;
- SurfaceTexture surfTexture = mHTML5VideoView.getSurfaceTexture();
- int textureName = mHTML5VideoView.getTextureName();
int currentVideoLayerId = mHTML5VideoView.getVideoLayerId();
+ SurfaceTexture surfTexture = mHTML5VideoView.getSurfaceTexture(currentVideoLayerId);
+ int textureName = mHTML5VideoView.getTextureName();
+
if (layer != 0 && surfTexture != null && currentVideoLayerId != -1) {
int playerState = mHTML5VideoView.getCurrentState();
if (mHTML5VideoView.getPlayerBuffering())
@@ -171,14 +173,12 @@ class HTML5VideoViewProxy extends Handler
boolean backFromFullScreenMode = false;
if (mHTML5VideoView != null) {
currentVideoLayerId = mHTML5VideoView.getVideoLayerId();
- if (mHTML5VideoView instanceof HTML5VideoFullScreen) {
- backFromFullScreenMode = true;
- }
+ backFromFullScreenMode = mHTML5VideoView.fullScreenExited();
}
if (backFromFullScreenMode
- || currentVideoLayerId != videoLayerId
- || mHTML5VideoView.getSurfaceTexture() == null) {
+ || currentVideoLayerId != videoLayerId
+ || mHTML5VideoView.surfaceTextureDeleted()) {
// Here, we handle the case when switching to a new video,
// either inside a WebView or across WebViews
// For switching videos within a WebView or across the WebView,
diff --git a/core/java/android/webkit/ZoomManager.java b/core/java/android/webkit/ZoomManager.java
index e41dd1c..0573d88 100644
--- a/core/java/android/webkit/ZoomManager.java
+++ b/core/java/android/webkit/ZoomManager.java
@@ -906,7 +906,7 @@ class ZoomManager {
// scaleAll(), we need to post a Runnable to ensure requestLayout().
// Additionally, only update the text wrap scale if the width changed.
mWebView.post(new PostScale(w != ow &&
- !mWebView.getSettings().getUseFixedViewport(), mInZoomOverview));
+ !mWebView.getSettings().getUseFixedViewport(), mInZoomOverview, w < ow));
}
private class PostScale implements Runnable {
@@ -915,10 +915,14 @@ class ZoomManager {
// it could be changed between the time this callback is initiated and
// the time it's actually run.
final boolean mInZoomOverviewBeforeSizeChange;
+ final boolean mInPortraitMode;
- public PostScale(boolean updateTextWrap, boolean inZoomOverview) {
+ public PostScale(boolean updateTextWrap,
+ boolean inZoomOverview,
+ boolean inPortraitMode) {
mUpdateTextWrap = updateTextWrap;
mInZoomOverviewBeforeSizeChange = inZoomOverview;
+ mInPortraitMode = inPortraitMode;
}
public void run() {
@@ -927,10 +931,10 @@ class ZoomManager {
// still want to send the notification over to webkit.
// Keep overview mode unchanged when rotating.
float newScale = mActualScale;
- if (mWebView.getSettings().getUseWideViewPort()) {
- final float zoomOverviewScale = getZoomOverviewScale();
- newScale = (mInZoomOverviewBeforeSizeChange) ?
- zoomOverviewScale : Math.max(mActualScale, zoomOverviewScale);
+ if (mWebView.getSettings().getUseWideViewPort() &&
+ mInPortraitMode &&
+ mInZoomOverviewBeforeSizeChange) {
+ newScale = getZoomOverviewScale();
}
setZoomScale(newScale, mUpdateTextWrap, true);
// update the zoom buttons as the scale can be changed
diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java
index 9933d68..586ece8 100644
--- a/core/java/android/widget/SearchView.java
+++ b/core/java/android/widget/SearchView.java
@@ -93,6 +93,7 @@ public class SearchView extends LinearLayout {
private boolean mClearingFocus;
private int mMaxWidth;
private boolean mVoiceButtonEnabled;
+ private CharSequence mUserQuery;
private SearchableInfo mSearchable;
private Bundle mAppSearchData;
@@ -372,6 +373,7 @@ public class SearchView extends LinearLayout {
mQueryTextView.setText(query);
if (query != null) {
mQueryTextView.setSelection(query.length());
+ mUserQuery = query;
}
// If the query is not empty and submit is requested, submit the query
@@ -885,6 +887,7 @@ public class SearchView extends LinearLayout {
private void onTextChanged(CharSequence newText) {
CharSequence text = mQueryTextView.getText();
+ mUserQuery = text;
boolean hasText = !TextUtils.isEmpty(text);
if (isSubmitButtonEnabled()) {
updateSubmitButton(hasText);
@@ -1124,7 +1127,7 @@ public class SearchView extends LinearLayout {
if (data != null) {
intent.setData(data);
}
- intent.putExtra(SearchManager.USER_QUERY, query);
+ intent.putExtra(SearchManager.USER_QUERY, mUserQuery);
if (query != null) {
intent.putExtra(SearchManager.QUERY, query);
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 18c3b24..5886c64 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -8787,10 +8787,22 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
TypedArray styledAttributes = mContext.obtainStyledAttributes(R.styleable.Theme);
- mode.setTitle(mContext.getString(com.android.internal.R.string.textSelectionCABTitle));
+ boolean allowText = getContext().getResources().getBoolean(
+ com.android.internal.R.bool.allow_action_menu_item_text_with_icon);
+
+ mode.setTitle(allowText ?
+ mContext.getString(com.android.internal.R.string.textSelectionCABTitle) : null);
mode.setSubtitle(null);
+ int selectAllIconId = 0; // No icon by default
+ if (!allowText) {
+ // Provide an icon, text will not be displayed on smaller screens.
+ selectAllIconId = styledAttributes.getResourceId(
+ R.styleable.Theme_actionModeSelectAllDrawable, 0);
+ }
+
menu.add(0, ID_SELECT_ALL, 0, com.android.internal.R.string.selectAll).
+ setIcon(selectAllIconId).
setAlphabeticShortcut('a').
setShowAsAction(
MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT);