summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CleanSpec.mk1
-rw-r--r--core/java/android/app/ActivityThread.java25
-rw-r--r--core/java/android/app/ApplicationThreadNative.java12
-rw-r--r--core/java/android/app/IApplicationThread.java8
-rw-r--r--core/java/android/content/ContentProvider.java23
-rw-r--r--core/java/android/content/ContentProviderNative.java178
-rw-r--r--core/java/android/content/IContentProvider.java10
-rw-r--r--core/java/android/content/pm/IPackageManager.aidl2
-rw-r--r--core/java/android/database/AbstractCursor.java10
-rw-r--r--core/java/android/database/AbstractWindowedCursor.java26
-rw-r--r--core/java/android/database/BulkCursorNative.java8
-rw-r--r--core/java/android/database/BulkCursorToCursorAdaptor.java112
-rw-r--r--core/java/android/database/CrossProcessCursor.java2
-rw-r--r--core/java/android/database/CursorToBulkCursorAdaptor.java213
-rw-r--r--core/java/android/database/CursorWindow.java16
-rw-r--r--core/java/android/database/sqlite/SQLiteCursor.java17
-rw-r--r--core/java/android/net/NetworkPolicy.java13
-rw-r--r--core/java/android/view/TextureView.java14
-rw-r--r--core/java/android/view/View.java11
-rw-r--r--core/java/android/view/accessibility/AccessibilityEvent.java9
-rw-r--r--core/java/android/webkit/WebView.java7
-rw-r--r--core/java/android/webkit/WebViewCore.java7
-rw-r--r--core/java/android/widget/SpellChecker.java87
-rw-r--r--core/java/com/android/internal/app/ShutdownThread.java1
-rw-r--r--core/java/com/android/internal/widget/LockPatternView.java87
-rw-r--r--core/res/res/drawable-hdpi/stat_notify_disabled.pngbin0 -> 1059 bytes
-rw-r--r--core/res/res/drawable-mdpi/stat_notify_disabled.pngbin0 -> 738 bytes
-rw-r--r--core/res/res/drawable-xhdpi/stat_notify_disabled.pngbin0 -> 1409 bytes
-rwxr-xr-xcore/res/res/values/strings.xml9
-rwxr-xr-xdata/sounds/AudioPackage7.mk14
-rw-r--r--data/sounds/effects/ogg/Lock.oggbin16459 -> 4661 bytes
-rw-r--r--data/sounds/effects/ogg/Unlock.oggbin11739 -> 4666 bytes
-rw-r--r--data/sounds/effects/wav/Lock.wavbin106496 -> 11352 bytes
-rw-r--r--data/sounds/effects/wav/Unlock.wavbin109436 -> 11352 bytes
-rw-r--r--data/sounds/notifications/ogg/Acrux.oggbin0 -> 10908 bytes
-rw-r--r--data/sounds/notifications/ogg/Bellatrix.oggbin0 -> 15714 bytes
-rw-r--r--data/sounds/notifications/ogg/Pollux.oggbin0 -> 23463 bytes
-rw-r--r--data/sounds/notifications/ogg/Tejat.oggbin0 -> 15866 bytes
-rw-r--r--data/sounds/ringtones/ogg/Girtab.oggbin0 -> 44376 bytes
-rw-r--r--data/sounds/ringtones/ogg/Zeta.oggbin0 -> 77919 bytes
-rw-r--r--graphics/java/android/graphics/drawable/GradientDrawable.java2
-rwxr-xr-xmedia/java/android/media/videoeditor/AudioTrack.java6
-rw-r--r--media/java/android/media/videoeditor/MediaArtistNativeHelper.java3
-rwxr-xr-xmedia/java/android/media/videoeditor/MediaProperties.java2
-rw-r--r--media/libstagefright/AwesomePlayer.cpp10
-rw-r--r--media/libstagefright/NuCachedSource2.cpp58
-rw-r--r--media/libstagefright/include/NuCachedSource2.h12
-rw-r--r--policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java3
-rw-r--r--policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java39
-rw-r--r--services/java/com/android/server/BackupManagerService.java9
-rw-r--r--services/java/com/android/server/SystemServer.java8
-rw-r--r--services/java/com/android/server/am/ActivityStack.java20
-rw-r--r--services/java/com/android/server/net/NetworkPolicyManagerService.java19
-rw-r--r--services/java/com/android/server/pm/PackageManagerService.java18
-rw-r--r--services/java/com/android/server/pm/Settings.java5
-rw-r--r--services/java/com/android/server/wm/WindowManagerService.java18
-rw-r--r--services/surfaceflinger/Android.mk3
-rwxr-xr-xtelephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java1
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java1
-rw-r--r--test-runner/src/android/test/mock/MockContentProvider.java39
-rw-r--r--test-runner/src/android/test/mock/MockIContentProvider.java9
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentProvider.java23
62 files changed, 776 insertions, 454 deletions
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 9381437f5dd0..fb334fce090e 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -116,6 +116,7 @@ $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/media/audio/)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/fonts/DroidSans*)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/media/audio/)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/fonts/DroidSans*)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/media/audio/)
# ************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
# ************************************************
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index d2facdcc172c..8afe9bf0468e 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -490,6 +490,15 @@ public final class ActivityThread {
// Formatting for checkin service - update version if row format changes
private static final int ACTIVITY_THREAD_CHECKIN_VERSION = 1;
+ private void updatePendingConfiguration(Configuration config) {
+ synchronized (mPackages) {
+ if (mPendingConfiguration == null ||
+ mPendingConfiguration.isOtherSeqNewer(config)) {
+ mPendingConfiguration = config;
+ }
+ }
+ }
+
public final void schedulePauseActivity(IBinder token, boolean finished,
boolean userLeaving, int configChanges) {
queueOrSendMessage(
@@ -530,8 +539,8 @@ public final class ActivityThread {
// we use token to identify this activity without having to send the
// activity itself back to the activity manager. (matters more with ipc)
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
- ActivityInfo info, CompatibilityInfo compatInfo, Bundle state,
- List<ResultInfo> pendingResults,
+ ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
+ Bundle state, List<ResultInfo> pendingResults,
List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,
String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {
ActivityClientRecord r = new ActivityClientRecord();
@@ -553,6 +562,8 @@ public final class ActivityThread {
r.profileFd = profileFd;
r.autoStopProfiler = autoStopProfiler;
+ updatePendingConfiguration(curConfig);
+
queueOrSendMessage(H.LAUNCH_ACTIVITY, r);
}
@@ -697,12 +708,7 @@ public final class ActivityThread {
}
public void scheduleConfigurationChanged(Configuration config) {
- synchronized (mPackages) {
- if (mPendingConfiguration == null ||
- mPendingConfiguration.isOtherSeqNewer(config)) {
- mPendingConfiguration = config;
- }
- }
+ updatePendingConfiguration(config);
queueOrSendMessage(H.CONFIGURATION_CHANGED, config);
}
@@ -1966,6 +1972,9 @@ public final class ActivityThread {
mProfiler.autoStopProfiler = r.autoStopProfiler;
}
+ // Make sure we are running with the most recent config.
+ handleConfigurationChanged(null, null);
+
if (localLOGV) Slog.v(
TAG, "Handling launch of " + r);
Activity a = performLaunchActivity(r, customIntent);
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index cde06cd891de..c4a4feaff611 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -132,6 +132,7 @@ public abstract class ApplicationThreadNative extends Binder
IBinder b = data.readStrongBinder();
int ident = data.readInt();
ActivityInfo info = ActivityInfo.CREATOR.createFromParcel(data);
+ Configuration curConfig = Configuration.CREATOR.createFromParcel(data);
CompatibilityInfo compatInfo = CompatibilityInfo.CREATOR.createFromParcel(data);
Bundle state = data.readBundle();
List<ResultInfo> ri = data.createTypedArrayList(ResultInfo.CREATOR);
@@ -142,7 +143,7 @@ public abstract class ApplicationThreadNative extends Binder
ParcelFileDescriptor profileFd = data.readInt() != 0
? data.readFileDescriptor() : null;
boolean autoStopProfiler = data.readInt() != 0;
- scheduleLaunchActivity(intent, b, ident, info, compatInfo, state, ri, pi,
+ scheduleLaunchActivity(intent, b, ident, info, curConfig, compatInfo, state, ri, pi,
notResumed, isForward, profileName, profileFd, autoStopProfiler);
return true;
}
@@ -630,10 +631,10 @@ class ApplicationThreadProxy implements IApplicationThread {
}
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
- ActivityInfo info, CompatibilityInfo compatInfo, Bundle state,
- List<ResultInfo> pendingResults,
- List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,
- String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler)
+ ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
+ Bundle state, List<ResultInfo> pendingResults,
+ List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,
+ String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler)
throws RemoteException {
Parcel data = Parcel.obtain();
data.writeInterfaceToken(IApplicationThread.descriptor);
@@ -641,6 +642,7 @@ class ApplicationThreadProxy implements IApplicationThread {
data.writeStrongBinder(token);
data.writeInt(ident);
info.writeToParcel(data, 0);
+ curConfig.writeToParcel(data, 0);
compatInfo.writeToParcel(data, 0);
data.writeBundle(state);
data.writeTypedList(pendingResults);
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index 5d200b46a4e0..1253fe7896c4 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -53,10 +53,10 @@ public interface IApplicationThread extends IInterface {
void scheduleResumeActivity(IBinder token, boolean isForward) throws RemoteException;
void scheduleSendResult(IBinder token, List<ResultInfo> results) throws RemoteException;
void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
- ActivityInfo info, CompatibilityInfo compatInfo, Bundle state,
- List<ResultInfo> pendingResults,
- List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,
- String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler)
+ ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
+ Bundle state, List<ResultInfo> pendingResults,
+ List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,
+ String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler)
throws RemoteException;
void scheduleRelaunchActivity(IBinder token, List<ResultInfo> pendingResults,
List<Intent> pendingNewIntents, int configChanges,
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index 8057d4bd260f..e452f1fa3162 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -22,10 +22,6 @@ import android.content.pm.ProviderInfo;
import android.content.res.AssetFileDescriptor;
import android.content.res.Configuration;
import android.database.Cursor;
-import android.database.CursorToBulkCursorAdaptor;
-import android.database.CursorWindow;
-import android.database.IBulkCursor;
-import android.database.IContentObserver;
import android.database.SQLException;
import android.net.Uri;
import android.os.AsyncTask;
@@ -168,22 +164,9 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
return ContentProvider.this;
}
- /**
- * Remote version of a query, which returns an IBulkCursor. The bulk
- * cursor should be wrapped with BulkCursorToCursorAdaptor before use.
- */
- public IBulkCursor bulkQuery(Uri uri, String[] projection,
- String selection, String[] selectionArgs, String sortOrder,
- IContentObserver observer, CursorWindow window) {
- enforceReadPermission(uri);
- Cursor cursor = ContentProvider.this.query(uri, projection,
- selection, selectionArgs, sortOrder);
- if (cursor == null) {
- return null;
- }
- return new CursorToBulkCursorAdaptor(cursor, observer,
- ContentProvider.this.getClass().getName(),
- hasWritePermission(uri), window);
+ @Override
+ public String getProviderName() {
+ return getContentProvider().getClass().getName();
}
public Cursor query(Uri uri, String[] projection,
diff --git a/core/java/android/content/ContentProviderNative.java b/core/java/android/content/ContentProviderNative.java
index 9a20951b8a99..064755e95fbd 100644
--- a/core/java/android/content/ContentProviderNative.java
+++ b/core/java/android/content/ContentProviderNative.java
@@ -20,6 +20,7 @@ import android.content.res.AssetFileDescriptor;
import android.database.BulkCursorNative;
import android.database.BulkCursorToCursorAdaptor;
import android.database.Cursor;
+import android.database.CursorToBulkCursorAdaptor;
import android.database.CursorWindow;
import android.database.DatabaseUtils;
import android.database.IBulkCursor;
@@ -65,6 +66,13 @@ abstract public class ContentProviderNative extends Binder implements IContentPr
return new ContentProviderProxy(obj);
}
+ /**
+ * Gets the name of the content provider.
+ * Should probably be part of the {@link IContentProvider} interface.
+ * @return The content provider name.
+ */
+ public abstract String getProviderName();
+
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
@@ -98,33 +106,23 @@ abstract public class ContentProviderNative extends Binder implements IContentPr
}
String sortOrder = data.readString();
- IContentObserver observer = IContentObserver.Stub.
- asInterface(data.readStrongBinder());
+ IContentObserver observer = IContentObserver.Stub.asInterface(
+ data.readStrongBinder());
CursorWindow window = CursorWindow.CREATOR.createFromParcel(data);
- // Flag for whether caller wants the number of
- // rows in the cursor and the position of the
- // "_id" column index (or -1 if non-existent)
- // Only to be returned if binder != null.
- boolean wantsCursorMetadata = data.readInt() != 0;
-
- IBulkCursor bulkCursor = bulkQuery(url, projection, selection,
- selectionArgs, sortOrder, observer, window);
- if (bulkCursor != null) {
- final IBinder binder = bulkCursor.asBinder();
- if (wantsCursorMetadata) {
- final int count = bulkCursor.count();
- final int index = BulkCursorToCursorAdaptor.findRowIdColumnIndex(
- bulkCursor.getColumnNames());
-
- reply.writeNoException();
- reply.writeStrongBinder(binder);
- reply.writeInt(count);
- reply.writeInt(index);
- } else {
- reply.writeNoException();
- reply.writeStrongBinder(binder);
- }
+ Cursor cursor = query(url, projection, selection, selectionArgs, sortOrder);
+ if (cursor != null) {
+ CursorToBulkCursorAdaptor adaptor = new CursorToBulkCursorAdaptor(
+ cursor, observer, getProviderName(), window);
+ final IBinder binder = adaptor.asBinder();
+ final int count = adaptor.count();
+ final int index = BulkCursorToCursorAdaptor.findRowIdColumnIndex(
+ adaptor.getColumnNames());
+
+ reply.writeNoException();
+ reply.writeStrongBinder(binder);
+ reply.writeInt(count);
+ reply.writeInt(index);
} else {
reply.writeNoException();
reply.writeStrongBinder(null);
@@ -324,92 +322,70 @@ final class ContentProviderProxy implements IContentProvider
return mRemote;
}
- // Like bulkQuery() but sets up provided 'adaptor' if not null.
- private IBulkCursor bulkQueryInternal(
- Uri url, String[] projection,
- String selection, String[] selectionArgs, String sortOrder,
- IContentObserver observer, CursorWindow window,
- BulkCursorToCursorAdaptor adaptor) throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
+ public Cursor query(Uri url, String[] projection, String selection,
+ String[] selectionArgs, String sortOrder) throws RemoteException {
+ CursorWindow window = new CursorWindow(false /* window will be used remotely */);
try {
- data.writeInterfaceToken(IContentProvider.descriptor);
-
- url.writeToParcel(data, 0);
- int length = 0;
- if (projection != null) {
- length = projection.length;
- }
- data.writeInt(length);
- for (int i = 0; i < length; i++) {
- data.writeString(projection[i]);
- }
- data.writeString(selection);
- if (selectionArgs != null) {
- length = selectionArgs.length;
- } else {
- length = 0;
- }
- data.writeInt(length);
- for (int i = 0; i < length; i++) {
- data.writeString(selectionArgs[i]);
- }
- data.writeString(sortOrder);
- data.writeStrongBinder(observer.asBinder());
- window.writeToParcel(data, 0);
-
- // Flag for whether or not we want the number of rows in the
- // cursor and the position of the "_id" column index (or -1 if
- // non-existent). Only to be returned if binder != null.
- final boolean wantsCursorMetadata = (adaptor != null);
- data.writeInt(wantsCursorMetadata ? 1 : 0);
-
- mRemote.transact(IContentProvider.QUERY_TRANSACTION, data, reply, 0);
+ BulkCursorToCursorAdaptor adaptor = new BulkCursorToCursorAdaptor();
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ try {
+ data.writeInterfaceToken(IContentProvider.descriptor);
+
+ url.writeToParcel(data, 0);
+ int length = 0;
+ if (projection != null) {
+ length = projection.length;
+ }
+ data.writeInt(length);
+ for (int i = 0; i < length; i++) {
+ data.writeString(projection[i]);
+ }
+ data.writeString(selection);
+ if (selectionArgs != null) {
+ length = selectionArgs.length;
+ } else {
+ length = 0;
+ }
+ data.writeInt(length);
+ for (int i = 0; i < length; i++) {
+ data.writeString(selectionArgs[i]);
+ }
+ data.writeString(sortOrder);
+ data.writeStrongBinder(adaptor.getObserver().asBinder());
+ window.writeToParcel(data, 0);
- DatabaseUtils.readExceptionFromParcel(reply);
+ mRemote.transact(IContentProvider.QUERY_TRANSACTION, data, reply, 0);
- IBulkCursor bulkCursor = null;
- IBinder bulkCursorBinder = reply.readStrongBinder();
- if (bulkCursorBinder != null) {
- bulkCursor = BulkCursorNative.asInterface(bulkCursorBinder);
+ DatabaseUtils.readExceptionFromParcel(reply);
- if (wantsCursorMetadata) {
+ IBulkCursor bulkCursor = BulkCursorNative.asInterface(reply.readStrongBinder());
+ if (bulkCursor != null) {
int rowCount = reply.readInt();
int idColumnPosition = reply.readInt();
- if (bulkCursor != null) {
- adaptor.set(bulkCursor, rowCount, idColumnPosition);
- }
+ adaptor.initialize(bulkCursor, rowCount, idColumnPosition);
+ } else {
+ adaptor.close();
+ adaptor = null;
}
+ return adaptor;
+ } catch (RemoteException ex) {
+ adaptor.close();
+ throw ex;
+ } catch (RuntimeException ex) {
+ adaptor.close();
+ throw ex;
+ } finally {
+ data.recycle();
+ reply.recycle();
}
- return bulkCursor;
} finally {
- data.recycle();
- reply.recycle();
- }
- }
-
- public IBulkCursor bulkQuery(Uri url, String[] projection,
- String selection, String[] selectionArgs, String sortOrder, IContentObserver observer,
- CursorWindow window) throws RemoteException {
- return bulkQueryInternal(
- url, projection, selection, selectionArgs, sortOrder,
- observer, window,
- null /* BulkCursorToCursorAdaptor */);
- }
-
- public Cursor query(Uri url, String[] projection, String selection,
- String[] selectionArgs, String sortOrder) throws RemoteException {
- //TODO make a pool of windows so we can reuse memory dealers
- CursorWindow window = new CursorWindow(false /* window will be used remotely */);
- BulkCursorToCursorAdaptor adaptor = new BulkCursorToCursorAdaptor();
- IBulkCursor bulkCursor = bulkQueryInternal(
- url, projection, selection, selectionArgs, sortOrder,
- adaptor.getObserver(), window,
- adaptor);
- if (bulkCursor == null) {
- return null;
+ // We close the window now because the cursor adaptor does not
+ // take ownership of the window until the first call to onMove.
+ // The adaptor will obtain a fresh reference to the window when
+ // it is filled.
+ window.close();
}
- return adaptor;
}
public String getType(Uri url) throws RemoteException
diff --git a/core/java/android/content/IContentProvider.java b/core/java/android/content/IContentProvider.java
index 72bc9c2f69f9..2a67ff8dac54 100644
--- a/core/java/android/content/IContentProvider.java
+++ b/core/java/android/content/IContentProvider.java
@@ -18,9 +18,6 @@ package android.content;
import android.content.res.AssetFileDescriptor;
import android.database.Cursor;
-import android.database.CursorWindow;
-import android.database.IBulkCursor;
-import android.database.IContentObserver;
import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
@@ -36,13 +33,6 @@ import java.util.ArrayList;
* @hide
*/
public interface IContentProvider extends IInterface {
- /**
- * @hide - hide this because return type IBulkCursor and parameter
- * IContentObserver are system private classes.
- */
- public IBulkCursor bulkQuery(Uri url, String[] projection,
- String selection, String[] selectionArgs, String sortOrder, IContentObserver observer,
- CursorWindow window) throws RemoteException;
public Cursor query(Uri url, String[] projection, String selection,
String[] selectionArgs, String sortOrder) throws RemoteException;
public String getType(Uri url) throws RemoteException;
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index a3bcc287e021..decb974bded8 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -362,4 +362,6 @@ interface IPackageManager {
void verifyPendingInstall(int id, int verificationCode);
VerifierDeviceIdentity getVerifierDeviceIdentity();
+
+ boolean isFirstBoot();
}
diff --git a/core/java/android/database/AbstractCursor.java b/core/java/android/database/AbstractCursor.java
index 3f23b8900c5f..ee6aec6f0d2d 100644
--- a/core/java/android/database/AbstractCursor.java
+++ b/core/java/android/database/AbstractCursor.java
@@ -78,13 +78,11 @@ public abstract class AbstractCursor implements CrossProcessCursor {
}
public void deactivate() {
- deactivateInternal();
+ onDeactivateOrClose();
}
- /**
- * @hide
- */
- public void deactivateInternal() {
+ /** @hide */
+ protected void onDeactivateOrClose() {
if (mSelfObserver != null) {
mContentResolver.unregisterContentObserver(mSelfObserver);
mSelfObserverRegistered = false;
@@ -108,7 +106,7 @@ public abstract class AbstractCursor implements CrossProcessCursor {
public void close() {
mClosed = true;
mContentObservable.unregisterAll();
- deactivateInternal();
+ onDeactivateOrClose();
}
/**
diff --git a/core/java/android/database/AbstractWindowedCursor.java b/core/java/android/database/AbstractWindowedCursor.java
index bfc8123e07fd..5836265c4945 100644
--- a/core/java/android/database/AbstractWindowedCursor.java
+++ b/core/java/android/database/AbstractWindowedCursor.java
@@ -19,6 +19,11 @@ package android.database;
/**
* A base class for Cursors that store their data in {@link CursorWindow}s.
* <p>
+ * The cursor owns the cursor window it uses. When the cursor is closed,
+ * its window is also closed. Likewise, when the window used by the cursor is
+ * changed, its old window is closed. This policy of strict ownership ensures
+ * that cursor windows are not leaked.
+ * </p><p>
* Subclasses are responsible for filling the cursor window with data during
* {@link #onMove(int, int)}, allocating a new cursor window if necessary.
* During {@link #requery()}, the existing cursor window should be cleared and
@@ -180,4 +185,25 @@ public abstract class AbstractWindowedCursor extends AbstractCursor {
mWindow = null;
}
}
+
+ /**
+ * If there is a window, clear it.
+ * Otherwise, creates a local window.
+ * @hide
+ */
+ protected void clearOrCreateLocalWindow() {
+ if (mWindow == null) {
+ // If there isn't a window set already it will only be accessed locally
+ mWindow = new CursorWindow(true /* the window is local only */);
+ } else {
+ mWindow.clear();
+ }
+ }
+
+ /** @hide */
+ @Override
+ protected void onDeactivateOrClose() {
+ super.onDeactivateOrClose();
+ closeWindow();
+ }
}
diff --git a/core/java/android/database/BulkCursorNative.java b/core/java/android/database/BulkCursorNative.java
index 9925a9ab7c0d..4fada8c2fd29 100644
--- a/core/java/android/database/BulkCursorNative.java
+++ b/core/java/android/database/BulkCursorNative.java
@@ -62,13 +62,13 @@ public abstract class BulkCursorNative extends Binder implements IBulkCursor
data.enforceInterface(IBulkCursor.descriptor);
int startPos = data.readInt();
CursorWindow window = getWindow(startPos);
+ reply.writeNoException();
if (window == null) {
reply.writeInt(0);
- return true;
+ } else {
+ reply.writeInt(1);
+ window.writeToParcel(reply, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
}
- reply.writeNoException();
- reply.writeInt(1);
- window.writeToParcel(reply, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
return true;
}
diff --git a/core/java/android/database/BulkCursorToCursorAdaptor.java b/core/java/android/database/BulkCursorToCursorAdaptor.java
index 9c1b26d0a648..cbdd07fb29d3 100644
--- a/core/java/android/database/BulkCursorToCursorAdaptor.java
+++ b/core/java/android/database/BulkCursorToCursorAdaptor.java
@@ -21,40 +21,24 @@ import android.os.RemoteException;
import android.util.Log;
/**
- * Adapts an {@link IBulkCursor} to a {@link Cursor} for use in the local
- * process.
+ * Adapts an {@link IBulkCursor} to a {@link Cursor} for use in the local process.
*
* {@hide}
*/
public final class BulkCursorToCursorAdaptor extends AbstractWindowedCursor {
private static final String TAG = "BulkCursor";
- private SelfContentObserver mObserverBridge;
+ private SelfContentObserver mObserverBridge = new SelfContentObserver(this);
private IBulkCursor mBulkCursor;
private int mCount;
private String[] mColumns;
private boolean mWantsAllOnMoveCalls;
- public void set(IBulkCursor bulkCursor) {
- mBulkCursor = bulkCursor;
-
- try {
- mCount = mBulkCursor.count();
- mWantsAllOnMoveCalls = mBulkCursor.getWantsAllOnMoveCalls();
-
- // Search for the rowID column index and set it for our parent
- mColumns = mBulkCursor.getColumnNames();
- mRowIdColumnIndex = findRowIdColumnIndex(mColumns);
- } catch (RemoteException ex) {
- Log.e(TAG, "Setup failed because the remote process is dead");
- }
- }
-
/**
- * Version of set() that does fewer Binder calls if the caller
- * already knows BulkCursorToCursorAdaptor's properties.
+ * Initializes the adaptor.
+ * Must be called before first use.
*/
- public void set(IBulkCursor bulkCursor, int count, int idIndex) {
+ public void initialize(IBulkCursor bulkCursor, int count, int idIndex) {
mBulkCursor = bulkCursor;
mColumns = null; // lazily retrieved
mCount = count;
@@ -80,31 +64,37 @@ public final class BulkCursorToCursorAdaptor extends AbstractWindowedCursor {
*
* @return A SelfContentObserver hooked up to this Cursor
*/
- public synchronized IContentObserver getObserver() {
- if (mObserverBridge == null) {
- mObserverBridge = new SelfContentObserver(this);
- }
+ public IContentObserver getObserver() {
return mObserverBridge.getContentObserver();
}
+ private void throwIfCursorIsClosed() {
+ if (mBulkCursor == null) {
+ throw new StaleDataException("Attempted to access a cursor after it has been closed.");
+ }
+ }
+
@Override
public int getCount() {
+ throwIfCursorIsClosed();
return mCount;
}
@Override
public boolean onMove(int oldPosition, int newPosition) {
+ throwIfCursorIsClosed();
+
try {
// Make sure we have the proper window
if (mWindow != null) {
if (newPosition < mWindow.getStartPosition() ||
newPosition >= (mWindow.getStartPosition() + mWindow.getNumRows())) {
- mWindow = mBulkCursor.getWindow(newPosition);
+ setWindow(mBulkCursor.getWindow(newPosition));
} else if (mWantsAllOnMoveCalls) {
mBulkCursor.onMove(newPosition);
}
} else {
- mWindow = mBulkCursor.getWindow(newPosition);
+ setWindow(mBulkCursor.getWindow(newPosition));
}
} catch (RemoteException ex) {
// We tried to get a window and failed
@@ -126,44 +116,54 @@ public final class BulkCursorToCursorAdaptor extends AbstractWindowedCursor {
// which is what actually makes the data set invalid.
super.deactivate();
- try {
- mBulkCursor.deactivate();
- } catch (RemoteException ex) {
- Log.w(TAG, "Remote process exception when deactivating");
+ if (mBulkCursor != null) {
+ try {
+ mBulkCursor.deactivate();
+ } catch (RemoteException ex) {
+ Log.w(TAG, "Remote process exception when deactivating");
+ }
}
- mWindow = null;
}
@Override
public void close() {
super.close();
- try {
- mBulkCursor.close();
- } catch (RemoteException ex) {
- Log.w(TAG, "Remote process exception when closing");
+
+ if (mBulkCursor != null) {
+ try {
+ mBulkCursor.close();
+ } catch (RemoteException ex) {
+ Log.w(TAG, "Remote process exception when closing");
+ } finally {
+ mBulkCursor = null;
+ }
}
- mWindow = null;
}
@Override
public boolean requery() {
+ throwIfCursorIsClosed();
+
try {
- int oldCount = mCount;
- //TODO get the window from a pool somewhere to avoid creating the memory dealer
- mCount = mBulkCursor.requery(getObserver(), new CursorWindow(
- false /* the window will be accessed across processes */));
- if (mCount != -1) {
- mPos = -1;
- closeWindow();
-
- // super.requery() will call onChanged. Do it here instead of relying on the
- // observer from the far side so that observers can see a correct value for mCount
- // when responding to onChanged.
- super.requery();
- return true;
- } else {
- deactivate();
- return false;
+ CursorWindow newWindow = new CursorWindow(false /* create a remote window */);
+ try {
+ mCount = mBulkCursor.requery(getObserver(), newWindow);
+ if (mCount != -1) {
+ mPos = -1;
+ closeWindow();
+
+ // super.requery() will call onChanged. Do it here instead of relying on the
+ // observer from the far side so that observers can see a correct value for mCount
+ // when responding to onChanged.
+ super.requery();
+ return true;
+ } else {
+ deactivate();
+ return false;
+ }
+ } finally {
+ // Don't take ownership of the window until the next call to onMove.
+ newWindow.close();
}
} catch (Exception ex) {
Log.e(TAG, "Unable to requery because the remote process exception " + ex.getMessage());
@@ -174,6 +174,8 @@ public final class BulkCursorToCursorAdaptor extends AbstractWindowedCursor {
@Override
public String[] getColumnNames() {
+ throwIfCursorIsClosed();
+
if (mColumns == null) {
try {
mColumns = mBulkCursor.getColumnNames();
@@ -187,6 +189,8 @@ public final class BulkCursorToCursorAdaptor extends AbstractWindowedCursor {
@Override
public Bundle getExtras() {
+ throwIfCursorIsClosed();
+
try {
return mBulkCursor.getExtras();
} catch (RemoteException e) {
@@ -198,6 +202,8 @@ public final class BulkCursorToCursorAdaptor extends AbstractWindowedCursor {
@Override
public Bundle respond(Bundle extras) {
+ throwIfCursorIsClosed();
+
try {
return mBulkCursor.respond(extras);
} catch (RemoteException e) {
diff --git a/core/java/android/database/CrossProcessCursor.java b/core/java/android/database/CrossProcessCursor.java
index 77ba3a54463a..8e6a5aa01598 100644
--- a/core/java/android/database/CrossProcessCursor.java
+++ b/core/java/android/database/CrossProcessCursor.java
@@ -16,7 +16,7 @@
package android.database;
-public interface CrossProcessCursor extends Cursor{
+public interface CrossProcessCursor extends Cursor {
/**
* returns a pre-filled window, return NULL if no such window
*/
diff --git a/core/java/android/database/CursorToBulkCursorAdaptor.java b/core/java/android/database/CursorToBulkCursorAdaptor.java
index 8fa4d3b5414d..a65b3b304558 100644
--- a/core/java/android/database/CursorToBulkCursorAdaptor.java
+++ b/core/java/android/database/CursorToBulkCursorAdaptor.java
@@ -24,19 +24,37 @@ import android.util.Log;
/**
* Wraps a BulkCursor around an existing Cursor making it remotable.
+ * <p>
+ * If the wrapped cursor is a {@link AbstractWindowedCursor} then it owns
+ * the cursor window. Otherwise, the adaptor takes ownership of the
+ * cursor itself and ensures it gets closed as needed during deactivation
+ * and requeries.
+ * </p>
*
* {@hide}
*/
public final class CursorToBulkCursorAdaptor extends BulkCursorNative
implements IBinder.DeathRecipient {
private static final String TAG = "Cursor";
- private final CrossProcessCursor mCursor;
- private CursorWindow mWindow;
+
+ private final Object mLock = new Object();
private final String mProviderName;
private ContentObserverProxy mObserver;
- private static final class ContentObserverProxy extends ContentObserver
- {
+ /**
+ * The cursor that is being adapted.
+ * This field is set to null when the cursor is closed.
+ */
+ private CrossProcessCursor mCursor;
+
+ /**
+ * The cursor window used by the cross process cursor.
+ * This field is always null for abstract windowed cursors since they are responsible
+ * for managing the lifetime of their window.
+ */
+ private CursorWindow mWindowForNonWindowedCursor;
+
+ private static final class ContentObserverProxy extends ContentObserver {
protected IContentObserver mRemote;
public ContentObserverProxy(IContentObserver remoteObserver, DeathRecipient recipient) {
@@ -70,7 +88,7 @@ public final class CursorToBulkCursorAdaptor extends BulkCursorNative
}
public CursorToBulkCursorAdaptor(Cursor cursor, IContentObserver observer, String providerName,
- boolean allowWrite, CursorWindow window) {
+ CursorWindow window) {
try {
mCursor = (CrossProcessCursor) cursor;
if (mCursor instanceof AbstractWindowedCursor) {
@@ -81,90 +99,167 @@ public final class CursorToBulkCursorAdaptor extends BulkCursorNative
+ providerName, new RuntimeException());
}
}
- windowedCursor.setWindow(window);
+ windowedCursor.setWindow(window); // cursor takes ownership of window
} else {
- mWindow = window;
+ mWindowForNonWindowedCursor = window; // we own the window
mCursor.fillWindow(0, window);
}
} catch (ClassCastException e) {
// TODO Implement this case.
+ window.close();
throw new UnsupportedOperationException(
"Only CrossProcessCursor cursors are supported across process for now", e);
}
mProviderName = providerName;
- createAndRegisterObserverProxy(observer);
+ synchronized (mLock) {
+ createAndRegisterObserverProxyLocked(observer);
+ }
}
-
+
+ private void closeCursorAndWindowLocked() {
+ if (mCursor != null) {
+ unregisterObserverProxyLocked();
+ mCursor.close();
+ mCursor = null;
+ }
+
+ if (mWindowForNonWindowedCursor != null) {
+ mWindowForNonWindowedCursor.close();
+ mWindowForNonWindowedCursor = null;
+ }
+ }
+
+ private void throwIfCursorIsClosed() {
+ if (mCursor == null) {
+ throw new StaleDataException("Attempted to access a cursor after it has been closed.");
+ }
+ }
+
+ @Override
public void binderDied() {
- mCursor.close();
- if (mWindow != null) {
- mWindow.close();
+ synchronized (mLock) {
+ closeCursorAndWindowLocked();
}
}
-
+
+ @Override
public CursorWindow getWindow(int startPos) {
- mCursor.moveToPosition(startPos);
-
- if (mWindow != null) {
- if (startPos < mWindow.getStartPosition() ||
- startPos >= (mWindow.getStartPosition() + mWindow.getNumRows())) {
- mCursor.fillWindow(startPos, mWindow);
- }
- return mWindow;
- } else {
- return ((AbstractWindowedCursor)mCursor).getWindow();
+ synchronized (mLock) {
+ throwIfCursorIsClosed();
+
+ mCursor.moveToPosition(startPos);
+
+ final CursorWindow window;
+ if (mCursor instanceof AbstractWindowedCursor) {
+ window = ((AbstractWindowedCursor)mCursor).getWindow();
+ } else {
+ window = mWindowForNonWindowedCursor;
+ if (window != null
+ && (startPos < window.getStartPosition() ||
+ startPos >= (window.getStartPosition() + window.getNumRows()))) {
+ mCursor.fillWindow(startPos, window);
+ }
+ }
+
+ // Acquire a reference before returning from this RPC.
+ // The Binder proxy will decrement the reference count again as part of writing
+ // the CursorWindow to the reply parcel as a return value.
+ if (window != null) {
+ window.acquireReference();
+ }
+ return window;
}
}
+ @Override
public void onMove(int position) {
- mCursor.onMove(mCursor.getPosition(), position);
+ synchronized (mLock) {
+ throwIfCursorIsClosed();
+
+ mCursor.onMove(mCursor.getPosition(), position);
+ }
}
+ @Override
public int count() {
- return mCursor.getCount();
+ synchronized (mLock) {
+ throwIfCursorIsClosed();
+
+ return mCursor.getCount();
+ }
}
+ @Override
public String[] getColumnNames() {
- return mCursor.getColumnNames();
+ synchronized (mLock) {
+ throwIfCursorIsClosed();
+
+ return mCursor.getColumnNames();
+ }
}
+ @Override
public void deactivate() {
- maybeUnregisterObserverProxy();
- mCursor.deactivate();
+ synchronized (mLock) {
+ if (mCursor != null) {
+ unregisterObserverProxyLocked();
+ mCursor.deactivate();
+ }
+ }
}
+ @Override
public void close() {
- maybeUnregisterObserverProxy();
- mCursor.close();
+ synchronized (mLock) {
+ closeCursorAndWindowLocked();
+ }
}
+ @Override
public int requery(IContentObserver observer, CursorWindow window) {
- if (mWindow == null) {
- ((AbstractWindowedCursor)mCursor).setWindow(window);
- }
- try {
- if (!mCursor.requery()) {
- return -1;
+ synchronized (mLock) {
+ throwIfCursorIsClosed();
+
+ if (mCursor instanceof AbstractWindowedCursor) {
+ ((AbstractWindowedCursor) mCursor).setWindow(window);
+ } else {
+ if (mWindowForNonWindowedCursor != null) {
+ mWindowForNonWindowedCursor.close();
+ }
+ mWindowForNonWindowedCursor = window;
}
- } catch (IllegalStateException e) {
- IllegalStateException leakProgram = new IllegalStateException(
- mProviderName + " Requery misuse db, mCursor isClosed:" +
- mCursor.isClosed(), e);
- throw leakProgram;
- }
-
- if (mWindow != null) {
- mCursor.fillWindow(0, window);
- mWindow = window;
+
+ try {
+ if (!mCursor.requery()) {
+ return -1;
+ }
+ } catch (IllegalStateException e) {
+ IllegalStateException leakProgram = new IllegalStateException(
+ mProviderName + " Requery misuse db, mCursor isClosed:" +
+ mCursor.isClosed(), e);
+ throw leakProgram;
+ }
+
+ if (!(mCursor instanceof AbstractWindowedCursor)) {
+ if (window != null) {
+ mCursor.fillWindow(0, window);
+ }
+ }
+
+ unregisterObserverProxyLocked();
+ createAndRegisterObserverProxyLocked(observer);
+ return mCursor.getCount();
}
- maybeUnregisterObserverProxy();
- createAndRegisterObserverProxy(observer);
- return mCursor.getCount();
}
+ @Override
public boolean getWantsAllOnMoveCalls() {
- return mCursor.getWantsAllOnMoveCalls();
+ synchronized (mLock) {
+ throwIfCursorIsClosed();
+
+ return mCursor.getWantsAllOnMoveCalls();
+ }
}
/**
@@ -173,7 +268,7 @@ public final class CursorToBulkCursorAdaptor extends BulkCursorNative
* @param observer the IContentObserver that wants to monitor the cursor
* @throws IllegalStateException if an observer is already registered
*/
- private void createAndRegisterObserverProxy(IContentObserver observer) {
+ private void createAndRegisterObserverProxyLocked(IContentObserver observer) {
if (mObserver != null) {
throw new IllegalStateException("an observer is already registered");
}
@@ -182,7 +277,7 @@ public final class CursorToBulkCursorAdaptor extends BulkCursorNative
}
/** Unregister the observer if it is already registered. */
- private void maybeUnregisterObserverProxy() {
+ private void unregisterObserverProxyLocked() {
if (mObserver != null) {
mCursor.unregisterContentObserver(mObserver);
mObserver.unlinkToDeath(this);
@@ -190,11 +285,21 @@ public final class CursorToBulkCursorAdaptor extends BulkCursorNative
}
}
+ @Override
public Bundle getExtras() {
- return mCursor.getExtras();
+ synchronized (mLock) {
+ throwIfCursorIsClosed();
+
+ return mCursor.getExtras();
+ }
}
+ @Override
public Bundle respond(Bundle extras) {
- return mCursor.respond(extras);
+ synchronized (mLock) {
+ throwIfCursorIsClosed();
+
+ return mCursor.respond(extras);
+ }
}
}
diff --git a/core/java/android/database/CursorWindow.java b/core/java/android/database/CursorWindow.java
index 2e3ef286fe80..5a91b80034e4 100644
--- a/core/java/android/database/CursorWindow.java
+++ b/core/java/android/database/CursorWindow.java
@@ -16,6 +16,8 @@
package android.database;
+import dalvik.system.CloseGuard;
+
import android.content.res.Resources;
import android.database.sqlite.SQLiteClosable;
import android.database.sqlite.SQLiteException;
@@ -48,6 +50,8 @@ public class CursorWindow extends SQLiteClosable implements Parcelable {
private int mStartPos;
+ private final CloseGuard mCloseGuard = CloseGuard.get();
+
private static native int nativeInitializeEmpty(int cursorWindowSize, boolean localOnly);
private static native int nativeInitializeFromBinder(IBinder nativeBinder);
private static native void nativeDispose(int windowPtr);
@@ -91,6 +95,7 @@ public class CursorWindow extends SQLiteClosable implements Parcelable {
throw new CursorWindowAllocationException("Cursor window allocation of " +
(sCursorWindowSize / 1024) + " kb failed. " + printStats());
}
+ mCloseGuard.open("close");
recordNewWindow(Binder.getCallingPid(), mWindowPtr);
}
@@ -102,11 +107,15 @@ public class CursorWindow extends SQLiteClosable implements Parcelable {
throw new CursorWindowAllocationException("Cursor window could not be "
+ "created from binder.");
}
+ mCloseGuard.open("close");
}
@Override
protected void finalize() throws Throwable {
try {
+ if (mCloseGuard != null) {
+ mCloseGuard.warnIfOpen();
+ }
dispose();
} finally {
super.finalize();
@@ -114,6 +123,9 @@ public class CursorWindow extends SQLiteClosable implements Parcelable {
}
private void dispose() {
+ if (mCloseGuard != null) {
+ mCloseGuard.close();
+ }
if (mWindowPtr != 0) {
recordClosingOfWindow(mWindowPtr);
nativeDispose(mWindowPtr);
@@ -677,6 +689,10 @@ public class CursorWindow extends SQLiteClosable implements Parcelable {
public void writeToParcel(Parcel dest, int flags) {
dest.writeStrongBinder(nativeGetBinder(mWindowPtr));
dest.writeInt(mStartPos);
+
+ if ((flags & Parcelable.PARCELABLE_WRITE_RETURN_VALUE) != 0) {
+ releaseReference();
+ }
}
@Override
diff --git a/core/java/android/database/sqlite/SQLiteCursor.java b/core/java/android/database/sqlite/SQLiteCursor.java
index 81fe8241106a..9d7e15201be5 100644
--- a/core/java/android/database/sqlite/SQLiteCursor.java
+++ b/core/java/android/database/sqlite/SQLiteCursor.java
@@ -89,8 +89,6 @@ public class SQLiteCursor extends AbstractWindowedCursor {
* @param query the {@link SQLiteQuery} object associated with this cursor object.
*/
public SQLiteCursor(SQLiteCursorDriver driver, String editTable, SQLiteQuery query) {
- // The AbstractCursor constructor needs to do some setup.
- super();
if (query == null) {
throw new IllegalArgumentException("query object cannot be null");
}
@@ -157,12 +155,7 @@ public class SQLiteCursor extends AbstractWindowedCursor {
}
private void fillWindow(int startPos) {
- if (mWindow == null) {
- // If there isn't a window set already it will only be accessed locally
- mWindow = new CursorWindow(true /* the window is local only */);
- } else {
- mWindow.clear();
- }
+ clearOrCreateLocalWindow();
mWindow.setStartPosition(startPos);
int count = getQuery().fillWindow(mWindow);
if (startPos == 0) { // fillWindow returns count(*) only for startPos = 0
@@ -214,16 +207,9 @@ public class SQLiteCursor extends AbstractWindowedCursor {
return mColumns;
}
- private void deactivateCommon() {
- if (false) Log.v(TAG, "<<< Releasing cursor " + this);
- closeWindow();
- if (false) Log.v("DatabaseWindow", "closing window in release()");
- }
-
@Override
public void deactivate() {
super.deactivate();
- deactivateCommon();
mDriver.cursorDeactivated();
}
@@ -231,7 +217,6 @@ public class SQLiteCursor extends AbstractWindowedCursor {
public void close() {
super.close();
synchronized (this) {
- deactivateCommon();
mQuery.close();
mDriver.cursorClosed();
}
diff --git a/core/java/android/net/NetworkPolicy.java b/core/java/android/net/NetworkPolicy.java
index aaad8a1c7a98..1b24f0c7b35f 100644
--- a/core/java/android/net/NetworkPolicy.java
+++ b/core/java/android/net/NetworkPolicy.java
@@ -40,6 +40,8 @@ public class NetworkPolicy implements Parcelable, Comparable<NetworkPolicy> {
public long limitBytes;
public long lastSnooze;
+ private static final long DEFAULT_MTU = 1500;
+
public NetworkPolicy(NetworkTemplate template, int cycleDay, long warningBytes, long limitBytes,
long lastSnooze) {
this.template = checkNotNull(template, "missing NetworkTemplate");
@@ -71,6 +73,17 @@ public class NetworkPolicy implements Parcelable, Comparable<NetworkPolicy> {
return 0;
}
+ /**
+ * Test if given measurement is near enough to {@link #limitBytes} to be
+ * considered over-limit.
+ */
+ public boolean isOverLimit(long totalBytes) {
+ // over-estimate, since kernel will trigger limit once first packet
+ // trips over limit.
+ totalBytes += 2 * DEFAULT_MTU;
+ return limitBytes != LIMIT_DISABLED && totalBytes >= limitBytes;
+ }
+
/** {@inheritDoc} */
public int compareTo(NetworkPolicy another) {
if (another == null || another.limitBytes == LIMIT_DISABLED) {
diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java
index d57132aef84d..169738257b3b 100644
--- a/core/java/android/view/TextureView.java
+++ b/core/java/android/view/TextureView.java
@@ -502,9 +502,23 @@ public class TextureView extends View {
* @see #isAvailable()
* @see #getBitmap(int, int)
* @see #getBitmap()
+ *
+ * @throws IllegalStateException if the hardware rendering context cannot be
+ * acquired to capture the bitmap
*/
public Bitmap getBitmap(Bitmap bitmap) {
if (bitmap != null && isAvailable()) {
+ AttachInfo info = mAttachInfo;
+ if (info != null && info.mHardwareRenderer != null &&
+ info.mHardwareRenderer.isEnabled()) {
+ if (!info.mHardwareRenderer.validate()) {
+ throw new IllegalStateException("Could not acquire hardware rendering context");
+ }
+ }
+
+ applyUpdate();
+ applyTransformMatrix();
+
mLayer.copyInto(bitmap);
}
return bitmap;
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 15544ccc4887..86be28a534da 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -1486,7 +1486,8 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
| AccessibilityEvent.TYPE_VIEW_FOCUSED
| AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
| AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
- | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT;
+ | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
+ | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED;
/**
* Temporary Rect currently for use in setBackground(). This will probably
@@ -10125,6 +10126,14 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
return mHardwareLayer;
}
+ /**
+ * Destroys this View's hardware layer if possible.
+ *
+ * @return True if the layer was destroyed, false otherwise.
+ *
+ * @see #setLayerType(int, android.graphics.Paint)
+ * @see #LAYER_TYPE_HARDWARE
+ */
boolean destroyLayer() {
if (mHardwareLayer != null) {
mHardwareLayer.destroy();
diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java
index 25bc559e94e3..86dd9df0cb0a 100644
--- a/core/java/android/view/accessibility/AccessibilityEvent.java
+++ b/core/java/android/view/accessibility/AccessibilityEvent.java
@@ -200,15 +200,6 @@ import java.util.List;
* <li>{@link #getBeforeText()} - The text of the source before the change.</li>
* <li>{@link #getContentDescription()} - The content description of the source.</li>
* </ul>
- * <em>Note:</em> This event type is not dispatched to descendants though
- * {@link android.view.View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
- * View.dispatchPopulateAccessibilityEvent(AccessibilityEvent)}, hence the event
- * source {@link android.view.View} and the sub-tree rooted at it will not receive
- * calls to {@link android.view.View#onPopulateAccessibilityEvent(AccessibilityEvent)
- * View.onPopulateAccessibilityEvent(AccessibilityEvent)}. The preferred way to add
- * text content to such events is by setting the
- * {@link android.R.styleable#View_contentDescription contentDescription} of the source
- * view.</br>
* </p>
* <p>
* <b>View text selection changed</b> - represents the event of changing the text
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index f46af5137661..6d19c23fd2cb 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -2074,7 +2074,8 @@ public class WebView extends AbsoluteLayout
* If the value of the encoding parameter is 'base64', then the data must
* be encoded as base64. Otherwise, the data must use ASCII encoding for
* octets inside the range of safe URL characters and use the standard %xx
- * hex encoding of URLs for octets outside that range.
+ * hex encoding of URLs for octets outside that range. For example,
+ * '#', '%', '\', '?' should be replaced by %23, %25, %27, %3f respectively.
* <p>
* The 'data' scheme URL formed by this method uses the default US-ASCII
* charset. If you need need to set a different charset, you should form a
@@ -7415,6 +7416,10 @@ public class WebView extends AbsoluteLayout
}
}
+ void sendPluginDrawMsg() {
+ mWebViewCore.sendMessage(EventHub.PLUGIN_SURFACE_READY);
+ }
+
/**
* Returns plugin bounds if x/y in content coordinates corresponds to a
* plugin. Otherwise a NULL rectangle is returned.
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 44688b8bd2be..1294a28df190 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -1032,6 +1032,8 @@ public final class WebViewCore {
static final int EXECUTE_JS = 194;
+ static final int PLUGIN_SURFACE_READY = 195;
+
// private message ids
private static final int DESTROY = 200;
@@ -1587,6 +1589,10 @@ public final class WebViewCore {
nativeFullScreenPluginHidden(msg.arg1);
break;
+ case PLUGIN_SURFACE_READY:
+ nativePluginSurfaceReady();
+ break;
+
case ADD_PACKAGE_NAMES:
if (BrowserFrame.sJavaBridge == null) {
throw new IllegalStateException("No WebView " +
@@ -2826,6 +2832,7 @@ public final class WebViewCore {
private native void nativeResume();
private native void nativeFreeMemory();
private native void nativeFullScreenPluginHidden(int npp);
+ private native void nativePluginSurfaceReady();
private native boolean nativeValidNodeAndBounds(int frame, int node,
Rect bounds);
diff --git a/core/java/android/widget/SpellChecker.java b/core/java/android/widget/SpellChecker.java
index 62b078fb5df5..510e2d4cb488 100644
--- a/core/java/android/widget/SpellChecker.java
+++ b/core/java/android/widget/SpellChecker.java
@@ -44,7 +44,6 @@ public class SpellChecker implements SpellCheckerSessionListener {
private final static int MAX_SPELL_BATCH_SIZE = 50;
private final TextView mTextView;
- private final Editable mText;
final SpellCheckerSession mSpellCheckerSession;
final int mCookie;
@@ -64,7 +63,6 @@ public class SpellChecker implements SpellCheckerSessionListener {
public SpellChecker(TextView textView) {
mTextView = textView;
- mText = (Editable) textView.getText();
final TextServicesManager textServicesManager = (TextServicesManager) textView.getContext().
getSystemService(Context.TEXT_SERVICES_MANAGER_SERVICE);
@@ -121,9 +119,9 @@ public class SpellChecker implements SpellCheckerSessionListener {
return mLength - 1;
}
- private void addSpellCheckSpan(int start, int end) {
+ private void addSpellCheckSpan(Editable editable, int start, int end) {
final int index = nextSpellCheckSpanIndex();
- mText.setSpan(mSpellCheckSpans[index], start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ editable.setSpan(mSpellCheckSpans[index], start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
mIds[index] = mSpanSequenceCounter++;
}
@@ -168,8 +166,9 @@ public class SpellChecker implements SpellCheckerSessionListener {
private void spellCheck() {
if (mSpellCheckerSession == null) return;
- final int selectionStart = Selection.getSelectionStart(mText);
- final int selectionEnd = Selection.getSelectionEnd(mText);
+ Editable editable = (Editable) mTextView.getText();
+ final int selectionStart = Selection.getSelectionStart(editable);
+ final int selectionEnd = Selection.getSelectionEnd(editable);
TextInfo[] textInfos = new TextInfo[mLength];
int textInfosCount = 0;
@@ -178,12 +177,12 @@ public class SpellChecker implements SpellCheckerSessionListener {
final SpellCheckSpan spellCheckSpan = mSpellCheckSpans[i];
if (spellCheckSpan.isSpellCheckInProgress()) continue;
- final int start = mText.getSpanStart(spellCheckSpan);
- final int end = mText.getSpanEnd(spellCheckSpan);
+ final int start = editable.getSpanStart(spellCheckSpan);
+ final int end = editable.getSpanEnd(spellCheckSpan);
// Do not check this word if the user is currently editing it
if (start >= 0 && end > start && (selectionEnd < start || selectionStart > end)) {
- final String word = mText.subSequence(start, end).toString();
+ final String word = editable.subSequence(start, end).toString();
spellCheckSpan.setSpellCheckInProgress(true);
textInfos[textInfosCount++] = new TextInfo(word, mCookie, mIds[i]);
}
@@ -202,6 +201,8 @@ public class SpellChecker implements SpellCheckerSessionListener {
@Override
public void onGetSuggestions(SuggestionsInfo[] results) {
+ Editable editable = (Editable) mTextView.getText();
+
for (int i = 0; i < results.length; i++) {
SuggestionsInfo suggestionsInfo = results[i];
if (suggestionsInfo.getCookie() != mCookie) continue;
@@ -217,9 +218,9 @@ public class SpellChecker implements SpellCheckerSessionListener {
SpellCheckSpan spellCheckSpan = mSpellCheckSpans[j];
if (!isInDictionary && looksLikeTypo) {
- createMisspelledSuggestionSpan(suggestionsInfo, spellCheckSpan);
+ createMisspelledSuggestionSpan(editable, suggestionsInfo, spellCheckSpan);
}
- mText.removeSpan(spellCheckSpan);
+ editable.removeSpan(spellCheckSpan);
break;
}
}
@@ -234,18 +235,18 @@ public class SpellChecker implements SpellCheckerSessionListener {
}
}
- private void createMisspelledSuggestionSpan(SuggestionsInfo suggestionsInfo,
- SpellCheckSpan spellCheckSpan) {
- final int start = mText.getSpanStart(spellCheckSpan);
- final int end = mText.getSpanEnd(spellCheckSpan);
+ private void createMisspelledSuggestionSpan(Editable editable,
+ SuggestionsInfo suggestionsInfo, SpellCheckSpan spellCheckSpan) {
+ final int start = editable.getSpanStart(spellCheckSpan);
+ final int end = editable.getSpanEnd(spellCheckSpan);
// Other suggestion spans may exist on that region, with identical suggestions, filter
// them out to avoid duplicates. First, filter suggestion spans on that exact region.
- SuggestionSpan[] suggestionSpans = mText.getSpans(start, end, SuggestionSpan.class);
+ SuggestionSpan[] suggestionSpans = editable.getSpans(start, end, SuggestionSpan.class);
final int length = suggestionSpans.length;
for (int i = 0; i < length; i++) {
- final int spanStart = mText.getSpanStart(suggestionSpans[i]);
- final int spanEnd = mText.getSpanEnd(suggestionSpans[i]);
+ final int spanStart = editable.getSpanStart(suggestionSpans[i]);
+ final int spanEnd = editable.getSpanEnd(suggestionSpans[i]);
if (spanStart != start || spanEnd != end) {
suggestionSpans[i] = null;
break;
@@ -293,7 +294,7 @@ public class SpellChecker implements SpellCheckerSessionListener {
SuggestionSpan suggestionSpan = new SuggestionSpan(mTextView.getContext(), suggestions,
SuggestionSpan.FLAG_EASY_CORRECT | SuggestionSpan.FLAG_MISSPELLED);
- mText.setSpan(suggestionSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ editable.setSpan(suggestionSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
// TODO limit to the word rectangle region
mTextView.invalidate();
@@ -304,22 +305,24 @@ public class SpellChecker implements SpellCheckerSessionListener {
private Object mRange = new Object();
public void init(int start, int end) {
- mText.setSpan(mRange, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ ((Editable) mTextView.getText()).setSpan(mRange, start, end,
+ Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
public void close() {
- mText.removeSpan(mRange);
+ ((Editable) mTextView.getText()).removeSpan(mRange);
}
public boolean isDone() {
- return mText.getSpanStart(mRange) < 0;
+ return ((Editable) mTextView.getText()).getSpanStart(mRange) < 0;
}
public void parse() {
+ Editable editable = (Editable) mTextView.getText();
// Iterate over the newly added text and schedule new SpellCheckSpans
- final int start = mText.getSpanStart(mRange);
- final int end = mText.getSpanEnd(mRange);
- mWordIterator.setCharSequence(mText, start, end);
+ final int start = editable.getSpanStart(mRange);
+ final int end = editable.getSpanEnd(mRange);
+ mWordIterator.setCharSequence(editable, start, end);
// Move back to the beginning of the current word, if any
int wordStart = mWordIterator.preceding(start);
@@ -333,14 +336,16 @@ public class SpellChecker implements SpellCheckerSessionListener {
wordEnd = mWordIterator.getEnd(wordStart);
}
if (wordEnd == BreakIterator.DONE) {
- mText.removeSpan(mRange);
+ editable.removeSpan(mRange);
return;
}
// We need to expand by one character because we want to include the spans that
// end/start at position start/end respectively.
- SpellCheckSpan[] spellCheckSpans = mText.getSpans(start-1, end+1, SpellCheckSpan.class);
- SuggestionSpan[] suggestionSpans = mText.getSpans(start-1, end+1, SuggestionSpan.class);
+ SpellCheckSpan[] spellCheckSpans = editable.getSpans(start - 1, end + 1,
+ SpellCheckSpan.class);
+ SuggestionSpan[] suggestionSpans = editable.getSpans(start - 1, end + 1,
+ SuggestionSpan.class);
int nbWordsChecked = 0;
boolean scheduleOtherSpellCheck = false;
@@ -350,20 +355,20 @@ public class SpellChecker implements SpellCheckerSessionListener {
// A new word has been created across the interval boundaries with this edit.
// Previous spans (ended on start / started on end) removed, not valid anymore
if (wordStart < start && wordEnd > start) {
- removeSpansAt(start, spellCheckSpans);
- removeSpansAt(start, suggestionSpans);
+ removeSpansAt(editable, start, spellCheckSpans);
+ removeSpansAt(editable, start, suggestionSpans);
}
if (wordStart < end && wordEnd > end) {
- removeSpansAt(end, spellCheckSpans);
- removeSpansAt(end, suggestionSpans);
+ removeSpansAt(editable, end, spellCheckSpans);
+ removeSpansAt(editable, end, suggestionSpans);
}
// Do not create new boundary spans if they already exist
boolean createSpellCheckSpan = true;
if (wordEnd == start) {
for (int i = 0; i < spellCheckSpans.length; i++) {
- final int spanEnd = mText.getSpanEnd(spellCheckSpans[i]);
+ final int spanEnd = editable.getSpanEnd(spellCheckSpans[i]);
if (spanEnd == start) {
createSpellCheckSpan = false;
break;
@@ -373,7 +378,7 @@ public class SpellChecker implements SpellCheckerSessionListener {
if (wordStart == end) {
for (int i = 0; i < spellCheckSpans.length; i++) {
- final int spanStart = mText.getSpanStart(spellCheckSpans[i]);
+ final int spanStart = editable.getSpanStart(spellCheckSpans[i]);
if (spanStart == end) {
createSpellCheckSpan = false;
break;
@@ -386,7 +391,7 @@ public class SpellChecker implements SpellCheckerSessionListener {
scheduleOtherSpellCheck = true;
break;
}
- addSpellCheckSpan(wordStart, wordEnd);
+ addSpellCheckSpan(editable, wordStart, wordEnd);
nbWordsChecked++;
}
}
@@ -401,23 +406,23 @@ public class SpellChecker implements SpellCheckerSessionListener {
}
if (scheduleOtherSpellCheck) {
- mText.setSpan(mRange, wordStart, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ editable.setSpan(mRange, wordStart, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
} else {
- mText.removeSpan(mRange);
+ editable.removeSpan(mRange);
}
spellCheck();
}
- private <T> void removeSpansAt(int offset, T[] spans) {
+ private <T> void removeSpansAt(Editable editable, int offset, T[] spans) {
final int length = spans.length;
for (int i = 0; i < length; i++) {
final T span = spans[i];
- final int start = mText.getSpanStart(span);
+ final int start = editable.getSpanStart(span);
if (start > offset) continue;
- final int end = mText.getSpanEnd(span);
+ final int end = editable.getSpanEnd(span);
if (end < offset) continue;
- mText.removeSpan(span);
+ editable.removeSpan(span);
}
}
}
diff --git a/core/java/com/android/internal/app/ShutdownThread.java b/core/java/com/android/internal/app/ShutdownThread.java
index daabf425a461..77d0c97bbf62 100644
--- a/core/java/com/android/internal/app/ShutdownThread.java
+++ b/core/java/com/android/internal/app/ShutdownThread.java
@@ -109,7 +109,6 @@ public final class ShutdownThread extends Thread {
if (confirm) {
final CloseDialogReceiver closer = new CloseDialogReceiver(context);
final AlertDialog dialog = new AlertDialog.Builder(context)
- .setIconAttribute(android.R.attr.alertDialogIcon)
.setTitle(com.android.internal.R.string.power_off)
.setMessage(resourceId)
.setPositiveButton(com.android.internal.R.string.yes, new DialogInterface.OnClickListener() {
diff --git a/core/java/com/android/internal/widget/LockPatternView.java b/core/java/com/android/internal/widget/LockPatternView.java
index 97bbe5218b70..5b49bffd8f02 100644
--- a/core/java/com/android/internal/widget/LockPatternView.java
+++ b/core/java/com/android/internal/widget/LockPatternView.java
@@ -17,8 +17,6 @@
package com.android.internal.widget;
-import com.android.internal.R;
-
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
@@ -39,6 +37,10 @@ import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
+
+import com.android.internal.R;
import java.util.ArrayList;
import java.util.List;
@@ -401,6 +403,34 @@ public class LockPatternView extends View {
invalidate();
}
+ private void notifyCellAdded() {
+ if (mOnPatternListener != null) {
+ mOnPatternListener.onPatternCellAdded(mPattern);
+ }
+ sendAccessEvent(R.string.lockscreen_access_pattern_cell_added);
+ }
+
+ private void notifyPatternStarted() {
+ if (mOnPatternListener != null) {
+ mOnPatternListener.onPatternStart();
+ }
+ sendAccessEvent(R.string.lockscreen_access_pattern_start);
+ }
+
+ private void notifyPatternDetected() {
+ if (mOnPatternListener != null) {
+ mOnPatternListener.onPatternDetected(mPattern);
+ }
+ sendAccessEvent(R.string.lockscreen_access_pattern_detected);
+ }
+
+ private void notifyPatternCleared() {
+ if (mOnPatternListener != null) {
+ mOnPatternListener.onPatternCleared();
+ }
+ sendAccessEvent(R.string.lockscreen_access_pattern_cleared);
+ }
+
/**
* Clear the pattern.
*/
@@ -554,9 +584,7 @@ public class LockPatternView extends View {
private void addCellToPattern(Cell newCell) {
mPatternDrawLookup[newCell.getRow()][newCell.getColumn()] = true;
mPattern.add(newCell);
- if (mOnPatternListener != null) {
- mOnPatternListener.onPatternCellAdded(mPattern);
- }
+ notifyCellAdded();
}
// helper method to find which cell a point maps to
@@ -619,6 +647,27 @@ public class LockPatternView extends View {
}
@Override
+ public boolean onHoverEvent(MotionEvent event) {
+ if (AccessibilityManager.getInstance(mContext).isTouchExplorationEnabled()) {
+ final int action = event.getAction();
+ switch (action) {
+ case MotionEvent.ACTION_HOVER_ENTER:
+ event.setAction(MotionEvent.ACTION_DOWN);
+ break;
+ case MotionEvent.ACTION_HOVER_MOVE:
+ event.setAction(MotionEvent.ACTION_MOVE);
+ break;
+ case MotionEvent.ACTION_HOVER_EXIT:
+ event.setAction(MotionEvent.ACTION_UP);
+ break;
+ }
+ onTouchEvent(event);
+ event.setAction(action);
+ }
+ return super.onHoverEvent(event);
+ }
+
+ @Override
public boolean onTouchEvent(MotionEvent event) {
if (!mInputEnabled || !isEnabled()) {
return false;
@@ -636,10 +685,8 @@ public class LockPatternView extends View {
return true;
case MotionEvent.ACTION_CANCEL:
resetPattern();
- if (mOnPatternListener != null) {
- mPatternInProgress = false;
- mOnPatternListener.onPatternCleared();
- }
+ mPatternInProgress = false;
+ notifyPatternCleared();
if (PROFILE_DRAWING) {
if (mDrawingProfilingStarted) {
Debug.stopMethodTracing();
@@ -661,9 +708,9 @@ public class LockPatternView extends View {
final int patternSizePreHitDetect = mPattern.size();
Cell hitCell = detectAndAddHit(x, y);
final int patternSize = mPattern.size();
- if (hitCell != null && (mOnPatternListener != null) && (patternSize == 1)) {
+ if (hitCell != null && patternSize == 1) {
mPatternInProgress = true;
- mOnPatternListener.onPatternStart();
+ notifyPatternStarted();
}
// note current x and y for rubber banding of in progress patterns
final float dx = Math.abs(x - mInProgressX);
@@ -778,11 +825,17 @@ public class LockPatternView extends View {
}
}
+ private void sendAccessEvent(int resId) {
+ setContentDescription(mContext.getString(resId));
+ sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
+ setContentDescription(null);
+ }
+
private void handleActionUp(MotionEvent event) {
// report pattern detected
- if (!mPattern.isEmpty() && mOnPatternListener != null) {
+ if (!mPattern.isEmpty()) {
mPatternInProgress = false;
- mOnPatternListener.onPatternDetected(mPattern);
+ notifyPatternDetected();
invalidate();
}
if (PROFILE_DRAWING) {
@@ -798,13 +851,13 @@ public class LockPatternView extends View {
final float x = event.getX();
final float y = event.getY();
final Cell hitCell = detectAndAddHit(x, y);
- if (hitCell != null && mOnPatternListener != null) {
+ if (hitCell != null) {
mPatternInProgress = true;
mPatternDisplayMode = DisplayMode.Correct;
- mOnPatternListener.onPatternStart();
- } else if (mOnPatternListener != null) {
+ notifyPatternStarted();
+ } else {
mPatternInProgress = false;
- mOnPatternListener.onPatternCleared();
+ notifyPatternCleared();
}
if (hitCell != null) {
final float startX = getCenterXForColumn(hitCell.column);
diff --git a/core/res/res/drawable-hdpi/stat_notify_disabled.png b/core/res/res/drawable-hdpi/stat_notify_disabled.png
new file mode 100644
index 000000000000..5b5a7dcc6969
--- /dev/null
+++ b/core/res/res/drawable-hdpi/stat_notify_disabled.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_notify_disabled.png b/core/res/res/drawable-mdpi/stat_notify_disabled.png
new file mode 100644
index 000000000000..9661d3149dc3
--- /dev/null
+++ b/core/res/res/drawable-mdpi/stat_notify_disabled.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_notify_disabled.png b/core/res/res/drawable-xhdpi/stat_notify_disabled.png
new file mode 100644
index 000000000000..0a003af6fc9d
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/stat_notify_disabled.png
Binary files differ
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index b1dc252d16dc..3f0f2f34ba4d 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1958,6 +1958,15 @@
<!-- Displayed on lock screen's right tab - turn sound off -->
<string name="lockscreen_sound_off_label">Sound off</string>
+ <!-- Accessibility description sent when user starts drawing a lock pattern. [CHAR LIMIT=NONE] -->
+ <string name="lockscreen_access_pattern_start">Pattern started</string>
+ <!-- Accessibility description sent when the pattern times out and is cleared. [CHAR LIMIT=NONE] -->
+ <string name="lockscreen_access_pattern_cleared">Pattern cleared</string>
+ <!-- Accessibility description sent when user adds a cell to the pattern. [CHAR LIMIT=NONE] -->
+ <string name="lockscreen_access_pattern_cell_added">Cell added</string>
+ <!-- Accessibility description sent when user completes drawing a pattern. [CHAR LIMIT=NONE] -->
+ <string name="lockscreen_access_pattern_detected">Pattern completed</string>
+
<!-- Password keyboard strings. Used by LockScreen and Settings --><skip />
<!-- Label for "switch to symbols" key. Must be short to fit on key! -->
<string name="password_keyboard_label_symbol_key">\?123</string>
diff --git a/data/sounds/AudioPackage7.mk b/data/sounds/AudioPackage7.mk
index 629ceb356d7c..66edb7a745d5 100755
--- a/data/sounds/AudioPackage7.mk
+++ b/data/sounds/AudioPackage7.mk
@@ -27,35 +27,33 @@ PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/effects/ogg/Lock.ogg:system/media/audio/ui/Lock.ogg \
$(LOCAL_PATH)/effects/ogg/Unlock.ogg:system/media/audio/ui/Unlock.ogg \
$(LOCAL_PATH)/notifications/ogg/Adara.ogg:system/media/audio/notifications/Adara.ogg \
- $(LOCAL_PATH)/notifications/ogg/Altair.ogg:system/media/audio/notifications/Altair.ogg \
$(LOCAL_PATH)/notifications/ogg/Arcturus.ogg:system/media/audio/notifications/Arcturus.ogg \
- $(LOCAL_PATH)/notifications/ogg/Betelgeuse.ogg:system/media/audio/notifications/Betelgeuse.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Bellatrix.ogg:system/media/audio/notifications/Bellatrix.ogg \
$(LOCAL_PATH)/notifications/ogg/Capella.ogg:system/media/audio/notifications/Capella.ogg \
$(LOCAL_PATH)/notifications/ogg/CetiAlpha.ogg:system/media/audio/notifications/CetiAlpha.ogg \
- $(LOCAL_PATH)/notifications/ogg/Deneb.ogg:system/media/audio/notifications/Deneb.ogg \
$(LOCAL_PATH)/notifications/ogg/Hojus.ogg:system/media/audio/notifications/Hojus.ogg \
$(LOCAL_PATH)/notifications/ogg/Lalande.ogg:system/media/audio/notifications/Lalande.ogg \
$(LOCAL_PATH)/notifications/ogg/Mira.ogg:system/media/audio/notifications/Mira.ogg \
$(LOCAL_PATH)/notifications/ogg/Polaris.ogg:system/media/audio/notifications/Polaris.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Pollux.ogg:system/media/audio/notifications/Pollux.ogg \
$(LOCAL_PATH)/notifications/ogg/Procyon.ogg:system/media/audio/notifications/Procyon.ogg \
$(LOCAL_PATH)/notifications/ogg/Proxima.ogg:system/media/audio/notifications/Proxima.ogg \
- $(LOCAL_PATH)/notifications/ogg/Upsilon.ogg:system/media/audio/notifications/Upsilon.ogg \
$(LOCAL_PATH)/notifications/ogg/Shaula.ogg:system/media/audio/notifications/Shaula.ogg \
$(LOCAL_PATH)/notifications/ogg/Spica.ogg:system/media/audio/notifications/Spica.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Tejat.ogg:system/media/audio/notifications/Tejat.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Upsilon.ogg:system/media/audio/notifications/Upsilon.ogg \
$(LOCAL_PATH)/notifications/ogg/Vega.ogg:system/media/audio/notifications/Vega.ogg \
- $(LOCAL_PATH)/ringtones/ogg/Acheron.ogg:system/media/audio/ringtones/Acheron.ogg \
$(LOCAL_PATH)/ringtones/ogg/Andromeda.ogg:system/media/audio/ringtones/Andromeda.ogg \
$(LOCAL_PATH)/ringtones/ogg/Aquila.ogg:system/media/audio/ringtones/Aquila.ogg \
$(LOCAL_PATH)/ringtones/ogg/ArgoNavis.ogg:system/media/audio/ringtones/ArgoNavis.ogg \
$(LOCAL_PATH)/ringtones/ogg/CanisMajor.ogg:system/media/audio/ringtones/CanisMajor.ogg \
$(LOCAL_PATH)/ringtones/ogg/Carina.ogg:system/media/audio/ringtones/Carina.ogg \
- $(LOCAL_PATH)/ringtones/ogg/Cassiopeia.ogg:system/media/audio/ringtones/Cassiopeia.ogg \
$(LOCAL_PATH)/ringtones/ogg/Centaurus.ogg:system/media/audio/ringtones/Centaurus.ogg \
$(LOCAL_PATH)/ringtones/ogg/Cygnus.ogg:system/media/audio/ringtones/Cygnus.ogg \
$(LOCAL_PATH)/ringtones/ogg/Draco.ogg:system/media/audio/ringtones/Draco.ogg \
+ $(LOCAL_PATH)/ringtones/ogg/Girtab.ogg:system/media/audio/ringtones/Girtab.ogg \
$(LOCAL_PATH)/ringtones/ogg/Hydra.ogg:system/media/audio/ringtones/Hydra.ogg \
$(LOCAL_PATH)/ringtones/ogg/Machina.ogg:system/media/audio/ringtones/Machina.ogg \
- $(LOCAL_PATH)/ringtones/ogg/Nasqueron.ogg:system/media/audio/ringtones/Nasqueron.ogg \
$(LOCAL_PATH)/ringtones/ogg/Orion.ogg:system/media/audio/ringtones/Orion.ogg \
$(LOCAL_PATH)/ringtones/ogg/Pegasus.ogg:system/media/audio/ringtones/Pegasus.ogg \
$(LOCAL_PATH)/ringtones/ogg/Perseus.ogg:system/media/audio/ringtones/Perseus.ogg \
@@ -66,4 +64,4 @@ PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/ringtones/ogg/Solarium.ogg:system/media/audio/ringtones/Solarium.ogg \
$(LOCAL_PATH)/ringtones/ogg/Testudo.ogg:system/media/audio/ringtones/Testudo.ogg \
$(LOCAL_PATH)/ringtones/ogg/UrsaMinor.ogg:system/media/audio/ringtones/UrsaMinor.ogg \
- $(LOCAL_PATH)/ringtones/ogg/Vespa.ogg:system/media/audio/ringtones/Vespa.ogg
+ $(LOCAL_PATH)/ringtones/ogg/Zeta.ogg:system/media/audio/ringtones/Zeta.ogg
diff --git a/data/sounds/effects/ogg/Lock.ogg b/data/sounds/effects/ogg/Lock.ogg
index ed845bee50e3..e7928e493f40 100644
--- a/data/sounds/effects/ogg/Lock.ogg
+++ b/data/sounds/effects/ogg/Lock.ogg
Binary files differ
diff --git a/data/sounds/effects/ogg/Unlock.ogg b/data/sounds/effects/ogg/Unlock.ogg
index 0a47b5c23095..cca95940d950 100644
--- a/data/sounds/effects/ogg/Unlock.ogg
+++ b/data/sounds/effects/ogg/Unlock.ogg
Binary files differ
diff --git a/data/sounds/effects/wav/Lock.wav b/data/sounds/effects/wav/Lock.wav
index 1655a8902f5f..b8076369a3e9 100644
--- a/data/sounds/effects/wav/Lock.wav
+++ b/data/sounds/effects/wav/Lock.wav
Binary files differ
diff --git a/data/sounds/effects/wav/Unlock.wav b/data/sounds/effects/wav/Unlock.wav
index 2229d03b5fed..e1d475ed84dd 100644
--- a/data/sounds/effects/wav/Unlock.wav
+++ b/data/sounds/effects/wav/Unlock.wav
Binary files differ
diff --git a/data/sounds/notifications/ogg/Acrux.ogg b/data/sounds/notifications/ogg/Acrux.ogg
new file mode 100644
index 000000000000..74ad149a7191
--- /dev/null
+++ b/data/sounds/notifications/ogg/Acrux.ogg
Binary files differ
diff --git a/data/sounds/notifications/ogg/Bellatrix.ogg b/data/sounds/notifications/ogg/Bellatrix.ogg
new file mode 100644
index 000000000000..37a1bdcaabdf
--- /dev/null
+++ b/data/sounds/notifications/ogg/Bellatrix.ogg
Binary files differ
diff --git a/data/sounds/notifications/ogg/Pollux.ogg b/data/sounds/notifications/ogg/Pollux.ogg
new file mode 100644
index 000000000000..2f907fdb1909
--- /dev/null
+++ b/data/sounds/notifications/ogg/Pollux.ogg
Binary files differ
diff --git a/data/sounds/notifications/ogg/Tejat.ogg b/data/sounds/notifications/ogg/Tejat.ogg
new file mode 100644
index 000000000000..04ba06cef9b0
--- /dev/null
+++ b/data/sounds/notifications/ogg/Tejat.ogg
Binary files differ
diff --git a/data/sounds/ringtones/ogg/Girtab.ogg b/data/sounds/ringtones/ogg/Girtab.ogg
new file mode 100644
index 000000000000..f6b3a35a3859
--- /dev/null
+++ b/data/sounds/ringtones/ogg/Girtab.ogg
Binary files differ
diff --git a/data/sounds/ringtones/ogg/Zeta.ogg b/data/sounds/ringtones/ogg/Zeta.ogg
new file mode 100644
index 000000000000..ef64d2feda7e
--- /dev/null
+++ b/data/sounds/ringtones/ogg/Zeta.ogg
Binary files differ
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index de0fabc7bd8f..50964d5e5546 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -285,7 +285,7 @@ public class GradientDrawable extends Drawable {
of the fill (if any) without worrying about blending artifacts.
*/
final boolean useLayer = haveStroke && haveFill && st.mShape != LINE &&
- currStrokeAlpha < 255;
+ currStrokeAlpha < 255 && (mAlpha < 255 || mColorFilter != null);
/* Drawing with a layer is slower than direct drawing, but it
allows us to apply paint effects like alpha and colorfilter to
diff --git a/media/java/android/media/videoeditor/AudioTrack.java b/media/java/android/media/videoeditor/AudioTrack.java
index 2de82f25ecb6..c5cc2cad05de 100755
--- a/media/java/android/media/videoeditor/AudioTrack.java
+++ b/media/java/android/media/videoeditor/AudioTrack.java
@@ -147,14 +147,16 @@ public class AudioTrack {
} catch (Exception e) {
throw new IllegalArgumentException(e.getMessage() + " : " + filename);
}
- switch (mMANativeHelper.getFileType(properties.fileType)) {
+ int fileType = mMANativeHelper.getFileType(properties.fileType);
+ switch (fileType) {
case MediaProperties.FILE_3GP:
case MediaProperties.FILE_MP4:
case MediaProperties.FILE_MP3:
+ case MediaProperties.FILE_AMR:
break;
default: {
- throw new IllegalArgumentException("Unsupported input file type");
+ throw new IllegalArgumentException("Unsupported input file type: " + fileType);
}
}
switch (mMANativeHelper.getAudioCodecType(properties.audioFormat)) {
diff --git a/media/java/android/media/videoeditor/MediaArtistNativeHelper.java b/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
index d7b8eaa844ec..03ae62ac1e53 100644
--- a/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
+++ b/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
@@ -3239,6 +3239,9 @@ class MediaArtistNativeHelper {
case FileType.M4V:
retValue = MediaProperties.FILE_M4V;
break;
+ case FileType.AMR:
+ retValue = MediaProperties.FILE_AMR;
+ break;
default:
retValue = -1;
diff --git a/media/java/android/media/videoeditor/MediaProperties.java b/media/java/android/media/videoeditor/MediaProperties.java
index fd034abb03ae..cf518a5f3d7a 100755
--- a/media/java/android/media/videoeditor/MediaProperties.java
+++ b/media/java/android/media/videoeditor/MediaProperties.java
@@ -286,7 +286,7 @@ public class MediaProperties {
*/
public static final int FILE_3GP = 0;
public static final int FILE_MP4 = 1;
- // 2 is for AMRNB
+ public static final int FILE_AMR = 2;
public static final int FILE_MP3 = 3;
// 4 is for PCM
public static final int FILE_JPEG = 5;
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index fa9417a50ebe..1165af5183a6 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -2005,6 +2005,11 @@ status_t AwesomePlayer::finishSetDataSource_l() {
mConnectingDataSource->setUID(mUID);
}
+ String8 cacheConfig;
+ bool disconnectAtHighwatermark;
+ NuCachedSource2::RemoveCacheSpecificHeaders(
+ &mUriHeaders, &cacheConfig, &disconnectAtHighwatermark);
+
mLock.unlock();
status_t err = mConnectingDataSource->connect(mUri, &mUriHeaders);
mLock.lock();
@@ -2024,7 +2029,10 @@ status_t AwesomePlayer::finishSetDataSource_l() {
new ThrottledSource(
mConnectingDataSource, 50 * 1024 /* bytes/sec */));
#else
- mCachedSource = new NuCachedSource2(mConnectingDataSource);
+ mCachedSource = new NuCachedSource2(
+ mConnectingDataSource,
+ cacheConfig.isEmpty() ? NULL : cacheConfig.string(),
+ disconnectAtHighwatermark);
#endif
dataSource = mCachedSource;
diff --git a/media/libstagefright/NuCachedSource2.cpp b/media/libstagefright/NuCachedSource2.cpp
index 9adb841d5989..4f183f57bb64 100644
--- a/media/libstagefright/NuCachedSource2.cpp
+++ b/media/libstagefright/NuCachedSource2.cpp
@@ -177,7 +177,10 @@ void PageCache::copy(size_t from, void *data, size_t size) {
////////////////////////////////////////////////////////////////////////////////
-NuCachedSource2::NuCachedSource2(const sp<DataSource> &source)
+NuCachedSource2::NuCachedSource2(
+ const sp<DataSource> &source,
+ const char *cacheConfig,
+ bool disconnectAtHighwatermark)
: mSource(source),
mReflector(new AHandlerReflector<NuCachedSource2>(this)),
mLooper(new ALooper),
@@ -190,9 +193,24 @@ NuCachedSource2::NuCachedSource2(const sp<DataSource> &source)
mNumRetriesLeft(kMaxNumRetries),
mHighwaterThresholdBytes(kDefaultHighWaterThreshold),
mLowwaterThresholdBytes(kDefaultLowWaterThreshold),
- mKeepAliveIntervalUs(kDefaultKeepAliveIntervalUs) {
+ mKeepAliveIntervalUs(kDefaultKeepAliveIntervalUs),
+ mDisconnectAtHighwatermark(disconnectAtHighwatermark) {
+ // We are NOT going to support disconnect-at-highwatermark indefinitely
+ // and we are not guaranteeing support for client-specified cache
+ // parameters. Both of these are temporary measures to solve a specific
+ // problem that will be solved in a better way going forward.
+
updateCacheParamsFromSystemProperty();
+ if (cacheConfig != NULL) {
+ updateCacheParamsFromString(cacheConfig);
+ }
+
+ if (mDisconnectAtHighwatermark) {
+ // Makes no sense to disconnect and do keep-alives...
+ mKeepAliveIntervalUs = 0;
+ }
+
mLooper->setName("NuCachedSource2");
mLooper->registerHandler(mReflector);
mLooper->start();
@@ -339,6 +357,12 @@ void NuCachedSource2::onFetch() {
if (mFetching && mCache->totalSize() >= mHighwaterThresholdBytes) {
LOGI("Cache full, done prefetching for now");
mFetching = false;
+
+ if (mDisconnectAtHighwatermark
+ && (mSource->flags() & DataSource::kIsHTTPBasedSource)) {
+ LOGV("Disconnecting at high watermark");
+ static_cast<HTTPBase *>(mSource.get())->disconnect();
+ }
}
} else {
Mutex::Autolock autoLock(mLock);
@@ -637,4 +661,34 @@ void NuCachedSource2::updateCacheParamsFromString(const char *s) {
mKeepAliveIntervalUs);
}
+// static
+void NuCachedSource2::RemoveCacheSpecificHeaders(
+ KeyedVector<String8, String8> *headers,
+ String8 *cacheConfig,
+ bool *disconnectAtHighwatermark) {
+ *cacheConfig = String8();
+ *disconnectAtHighwatermark = false;
+
+ if (headers == NULL) {
+ return;
+ }
+
+ ssize_t index;
+ if ((index = headers->indexOfKey(String8("x-cache-config"))) >= 0) {
+ *cacheConfig = headers->valueAt(index);
+
+ headers->removeItemsAt(index);
+
+ LOGV("Using special cache config '%s'", cacheConfig->string());
+ }
+
+ if ((index = headers->indexOfKey(
+ String8("x-disconnect-at-highwatermark"))) >= 0) {
+ *disconnectAtHighwatermark = true;
+ headers->removeItemsAt(index);
+
+ LOGV("Client requested disconnection at highwater mark");
+ }
+}
+
} // namespace android
diff --git a/media/libstagefright/include/NuCachedSource2.h b/media/libstagefright/include/NuCachedSource2.h
index f04c56664713..7a03e7e4f976 100644
--- a/media/libstagefright/include/NuCachedSource2.h
+++ b/media/libstagefright/include/NuCachedSource2.h
@@ -28,7 +28,10 @@ struct ALooper;
struct PageCache;
struct NuCachedSource2 : public DataSource {
- NuCachedSource2(const sp<DataSource> &source);
+ NuCachedSource2(
+ const sp<DataSource> &source,
+ const char *cacheConfig = NULL,
+ bool disconnectAtHighwatermark = false);
virtual status_t initCheck() const;
@@ -56,6 +59,11 @@ struct NuCachedSource2 : public DataSource {
status_t getEstimatedBandwidthKbps(int32_t *kbps);
status_t setCacheStatCollectFreq(int32_t freqMs);
+ static void RemoveCacheSpecificHeaders(
+ KeyedVector<String8, String8> *headers,
+ String8 *cacheConfig,
+ bool *disconnectAtHighwatermark);
+
protected:
virtual ~NuCachedSource2();
@@ -105,6 +113,8 @@ private:
// If the keep-alive interval is 0, keep-alives are disabled.
int64_t mKeepAliveIntervalUs;
+ bool mDisconnectAtHighwatermark;
+
void onMessageReceived(const sp<AMessage> &msg);
void onFetch();
void onRead(const sp<AMessage> &msg);
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java b/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java
index 24dce1a0dd79..8343bbdf738e 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java
@@ -186,6 +186,9 @@ class KeyguardStatusViewManager implements OnClickListener {
mTransientTextManager = new TransientTextManager(mCarrierView);
+ mUpdateMonitor.registerInfoCallback(mInfoCallback);
+ mUpdateMonitor.registerSimStateCallback(mSimStateCallback);
+
resetStatusInfo();
refreshDate();
updateOwnerInfo();
diff --git a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
index 071044ed2b9c..265024be98b5 100644
--- a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
+++ b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
@@ -98,7 +98,8 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler
private View mLockScreen;
private View mUnlockScreen;
- private boolean mScreenOn = false;
+ private volatile boolean mScreenOn = false;
+ private volatile boolean mWindowFocused = false;
private boolean mEnableFallback = false; // assume no fallback UI until we know better
private boolean mShowLockBeforeUnlock = false;
@@ -110,6 +111,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler
private boolean mFaceLockServiceRunning = false;
private final Object mFaceLockServiceRunningLock = new Object();
+ private final Object mFaceLockStartupLock = new Object();
private Handler mHandler;
private final int MSG_SHOW_FACELOCK_AREA_VIEW = 0;
@@ -514,13 +516,10 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler
stopAndUnbindFromFaceLock();
}
- @Override
- public void onScreenTurnedOn() {
- mScreenOn = true;
- show();
-
- // When screen is turned on, need to bind to FaceLock service if we are using FaceLock
- // But only if not dealing with a call
+ /** When screen is turned on and focused, need to bind to FaceLock service if we are using
+ * FaceLock, but only if we're not dealing with a call
+ */
+ private void activateFaceLockIfAble() {
final boolean transportInvisible = mTransportControlView == null ? true :
mTransportControlView.getVisibility() != View.VISIBLE;
if (mUpdateMonitor.getPhoneState() == TelephonyManager.CALL_STATE_IDLE
@@ -534,12 +533,34 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler
}
}
- /** Unbind from facelock if something covers this window (such as an alarm) */
+ @Override
+ public void onScreenTurnedOn() {
+ boolean runFaceLock = false;
+ //Make sure to start facelock iff the screen is both on and focused
+ synchronized(mFaceLockStartupLock) {
+ mScreenOn = true;
+ runFaceLock = mWindowFocused;
+ }
+ show();
+ if(runFaceLock) activateFaceLockIfAble();
+ }
+
+ /** Unbind from facelock if something covers this window (such as an alarm)
+ * bind to facelock if the lockscreen window just came into focus, and the screen is on
+ */
@Override
public void onWindowFocusChanged (boolean hasWindowFocus) {
+ boolean runFaceLock = false;
+ //Make sure to start facelock iff the screen is both on and focused
+ synchronized(mFaceLockStartupLock) {
+ if(mScreenOn && !mWindowFocused) runFaceLock = hasWindowFocus;
+ mWindowFocused = hasWindowFocus;
+ }
if(!hasWindowFocus) {
stopAndUnbindFromFaceLock();
mHandler.sendEmptyMessage(MSG_HIDE_FACELOCK_AREA_VIEW);
+ } else if (runFaceLock) {
+ activateFaceLockIfAble();
}
}
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index 5758954794ff..f9f5458122ff 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -1966,6 +1966,9 @@ class BackupManagerService extends IBackupManager.Stub {
synchronized (mQueueLock) {
mBackupRunning = false;
if (mStatus == BackupConstants.TRANSPORT_NOT_INITIALIZED) {
+ // Make sure we back up everything and perform the one-time init
+ clearMetadata();
+ if (DEBUG) Slog.d(TAG, "Server requires init; rerunning");
backupNow();
}
}
@@ -1975,6 +1978,12 @@ class BackupManagerService extends IBackupManager.Stub {
mWakelock.release();
}
+ // Remove the PM metadata state. This will generate an init on the next pass.
+ void clearMetadata() {
+ final File pmState = new File(mStateDir, PACKAGE_MANAGER_SENTINEL);
+ if (pmState.exists()) pmState.delete();
+ }
+
// Invoke an agent's doBackup() and start a timeout message spinning on the main
// handler in case it doesn't get back to us.
int invokeAgentForBackup(String packageName, IBackupAgent agent,
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 5006de757cd3..3ae62add369f 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -163,6 +163,11 @@ class ServerThread extends Thread {
pm = PackageManagerService.main(context,
factoryTest != SystemServer.FACTORY_TEST_OFF,
onlyCore);
+ boolean firstBoot = false;
+ try {
+ firstBoot = pm.isFirstBoot();
+ } catch (RemoteException e) {
+ }
ActivityManagerService.setSystemProcess();
@@ -208,7 +213,8 @@ class ServerThread extends Thread {
Slog.i(TAG, "Window Manager");
wm = WindowManagerService.main(context, power,
- factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL);
+ factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL,
+ !firstBoot);
ServiceManager.addService(Context.WINDOW_SERVICE, wm);
ActivityManagerService.self().setWindowManager(wm);
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index 7bc19ab43882..b9d3d76bbd11 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -589,8 +589,8 @@ final class ActivityStack {
}
}
app.thread.scheduleLaunchActivity(new Intent(r.intent), r,
- System.identityHashCode(r),
- r.info, r.compat, r.icicle, results, newIntents, !andResume,
+ System.identityHashCode(r), r.info, mService.mConfiguration,
+ r.compat, r.icicle, results, newIntents, !andResume,
mService.isNextTransitionForward(), profileFile, profileFd,
profileAutoStop);
@@ -4035,7 +4035,18 @@ final class ActivityStack {
// But then we need to figure out how it needs to deal with that.
Configuration oldConfig = r.configuration;
r.configuration = newConfig;
-
+
+ // Determine what has changed. May be nothing, if this is a config
+ // that has come back from the app after going idle. In that case
+ // we just want to leave the official config object now in the
+ // activity and do nothing else.
+ final int changes = oldConfig.diff(newConfig);
+ if (changes == 0 && !r.forceNewConfig) {
+ if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
+ "Configuration no differences in " + r);
+ return true;
+ }
+
// If the activity isn't currently running, just leave the new
// configuration and it will pick that up next time it starts.
if (r.app == null || r.app.thread == null) {
@@ -4046,8 +4057,7 @@ final class ActivityStack {
return true;
}
- // Figure out what has changed between the two configurations.
- int changes = oldConfig.diff(newConfig);
+ // Figure out how to handle the changes between the configurations.
if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
Slog.v(TAG, "Checking to restart " + r.info.name + ": changed=0x"
+ Integer.toHexString(changes) + ", handles=0x"
diff --git a/services/java/com/android/server/net/NetworkPolicyManagerService.java b/services/java/com/android/server/net/NetworkPolicyManagerService.java
index 0da5cc631e41..e6107826aa8c 100644
--- a/services/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -85,7 +85,6 @@ import android.net.NetworkIdentity;
import android.net.NetworkPolicy;
import android.net.NetworkQuotaInfo;
import android.net.NetworkState;
-import android.net.NetworkStats;
import android.net.NetworkTemplate;
import android.os.Binder;
import android.os.Environment;
@@ -489,7 +488,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
final long end = currentTime;
final long totalBytes = getTotalBytes(policy.template, start, end);
- if (policy.limitBytes != LIMIT_DISABLED && totalBytes >= policy.limitBytes) {
+ if (policy.isOverLimit(totalBytes)) {
if (policy.lastSnooze >= start) {
enqueueNotification(policy, TYPE_LIMIT_SNOOZED, totalBytes);
} else {
@@ -574,7 +573,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
final CharSequence title = res.getText(R.string.data_usage_warning_title);
final CharSequence body = res.getString(R.string.data_usage_warning_body);
- builder.setSmallIcon(R.drawable.ic_menu_info_details);
+ builder.setSmallIcon(R.drawable.stat_notify_error);
builder.setTicker(title);
builder.setContentTitle(title);
builder.setContentText(body);
@@ -606,7 +605,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
break;
}
- builder.setSmallIcon(com.android.internal.R.drawable.ic_menu_block);
+ builder.setSmallIcon(R.drawable.stat_notify_disabled);
builder.setTicker(title);
builder.setContentTitle(title);
builder.setContentText(body);
@@ -640,7 +639,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
break;
}
- builder.setSmallIcon(R.drawable.ic_menu_info_details);
+ builder.setSmallIcon(R.drawable.stat_notify_error);
builder.setTicker(title);
builder.setContentTitle(title);
builder.setContentText(body);
@@ -677,7 +676,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
builder.setOnlyAlertOnce(true);
builder.setOngoing(true);
- builder.setSmallIcon(R.drawable.ic_menu_info_details);
+ builder.setSmallIcon(R.drawable.stat_notify_error);
builder.setTicker(title);
builder.setContentTitle(title);
builder.setContentText(body);
@@ -750,8 +749,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
final long totalBytes = getTotalBytes(policy.template, start, end);
// disable data connection when over limit and not snoozed
- final boolean overLimit = policy.limitBytes != LIMIT_DISABLED
- && totalBytes > policy.limitBytes && policy.lastSnooze < start;
+ final boolean overLimit = policy.isOverLimit(totalBytes) && policy.lastSnooze < start;
final boolean enabled = !overLimit;
setNetworkTemplateEnabled(policy.template, enabled);
@@ -1535,10 +1533,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
private long getTotalBytes(NetworkTemplate template, long start, long end) {
try {
- final NetworkStats stats = mNetworkStats.getSummaryForNetwork(
- template, start, end);
- final NetworkStats.Entry entry = stats.getValues(0, null);
- return entry.rxBytes + entry.txBytes;
+ return mNetworkStats.getSummaryForNetwork(template, start, end).getTotalBytes();
} catch (RemoteException e) {
// ignored; service lives in system_server
return 0;
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index 19dd606fe188..0e9f64c34480 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -1157,6 +1157,10 @@ public class PackageManagerService extends IPackageManager.Stub {
} // synchronized (mInstallLock)
}
+ public boolean isFirstBoot() {
+ return !mRestoredSettings;
+ }
+
private String getRequiredVerifierLPr() {
final Intent verification = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
final List<ResolveInfo> receivers = queryIntentReceivers(verification, PACKAGE_MIME_TYPE,
@@ -2983,12 +2987,14 @@ public class PackageManagerService extends IPackageManager.Stub {
}
if (pkgs != null) {
for (int i=0; i<pkgs.size(); i++) {
- try {
- ActivityManagerNative.getDefault().showBootMessage(
- mContext.getResources().getString(
- com.android.internal.R.string.android_upgrading_apk,
- i+1, pkgs.size()), true);
- } catch (RemoteException e) {
+ if (!isFirstBoot()) {
+ try {
+ ActivityManagerNative.getDefault().showBootMessage(
+ mContext.getResources().getString(
+ com.android.internal.R.string.android_upgrading_apk,
+ i+1, pkgs.size()), true);
+ } catch (RemoteException e) {
+ }
}
PackageParser.Package p = pkgs.get(i);
synchronized (mInstallLock) {
diff --git a/services/java/com/android/server/pm/Settings.java b/services/java/com/android/server/pm/Settings.java
index 7cdb5b15ba31..bfe6613cf630 100644
--- a/services/java/com/android/server/pm/Settings.java
+++ b/services/java/com/android/server/pm/Settings.java
@@ -1238,9 +1238,8 @@ final class Settings {
mReadMessages.append("No start tag found in settings file\n");
PackageManagerService.reportSettingsProblem(Log.WARN,
"No start tag found in package manager settings");
- Log
- .wtf(PackageManagerService.TAG,
- "No start tag found in package manager settings");
+ Log.wtf(PackageManagerService.TAG,
+ "No start tag found in package manager settings");
return false;
}
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 73a96013358a..06a6e9892dfc 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -297,6 +297,8 @@ public class WindowManagerService extends IWindowManager.Stub
final boolean mHaveInputMethods;
+ final boolean mAllowBootMessages;
+
final boolean mLimitedAlphaCompositing;
final WindowManagerPolicy mPolicy = PolicyManager.makeNewWindowManager();
@@ -633,8 +635,8 @@ public class WindowManagerService extends IWindowManager.Stub
float mCompatibleScreenScale;
public static WindowManagerService main(Context context,
- PowerManagerService pm, boolean haveInputMethods) {
- WMThread thr = new WMThread(context, pm, haveInputMethods);
+ PowerManagerService pm, boolean haveInputMethods, boolean allowBootMsgs) {
+ WMThread thr = new WMThread(context, pm, haveInputMethods, allowBootMsgs);
thr.start();
synchronized (thr) {
@@ -654,19 +656,21 @@ public class WindowManagerService extends IWindowManager.Stub
private final Context mContext;
private final PowerManagerService mPM;
private final boolean mHaveInputMethods;
+ private final boolean mAllowBootMessages;
public WMThread(Context context, PowerManagerService pm,
- boolean haveInputMethods) {
+ boolean haveInputMethods, boolean allowBootMsgs) {
super("WindowManager");
mContext = context;
mPM = pm;
mHaveInputMethods = haveInputMethods;
+ mAllowBootMessages = allowBootMsgs;
}
public void run() {
Looper.prepare();
WindowManagerService s = new WindowManagerService(mContext, mPM,
- mHaveInputMethods);
+ mHaveInputMethods, mAllowBootMessages);
android.os.Process.setThreadPriority(
android.os.Process.THREAD_PRIORITY_DISPLAY);
android.os.Process.setCanSelfBackground(false);
@@ -728,9 +732,10 @@ public class WindowManagerService extends IWindowManager.Stub
}
private WindowManagerService(Context context, PowerManagerService pm,
- boolean haveInputMethods) {
+ boolean haveInputMethods, boolean showBootMsgs) {
mContext = context;
mHaveInputMethods = haveInputMethods;
+ mAllowBootMessages = showBootMsgs;
mLimitedAlphaCompositing = context.getResources().getBoolean(
com.android.internal.R.bool.config_sf_limitedAlpha);
@@ -4846,6 +4851,9 @@ public class WindowManagerService extends IWindowManager.Stub
public void showBootMessage(final CharSequence msg, final boolean always) {
boolean first = false;
synchronized(mWindowMap) {
+ if (!mAllowBootMessages) {
+ return;
+ }
if (!mShowingBootMessages) {
if (!always) {
return;
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 51eb0a376d06..dab070567a29 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -22,6 +22,9 @@ LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
ifeq ($(TARGET_BOARD_PLATFORM), omap3)
LOCAL_CFLAGS += -DNO_RGBX_8888
endif
+ifeq ($(TARGET_BOARD_PLATFORM), omap4)
+ LOCAL_CFLAGS += -DHAS_CONTEXT_PRIORITY
+endif
ifeq ($(TARGET_BOARD_PLATFORM), s5pc110)
LOCAL_CFLAGS += -DHAS_CONTEXT_PRIORITY -DNEVER_DEFAULT_TO_ASYNC_MODE
endif
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java b/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
index dded39e1a6a3..fe41e7e61b0c 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
@@ -88,6 +88,7 @@ final class CdmaSMSDispatcher extends SMSDispatcher {
PendingIntent intent = tracker.mDeliveryIntent;
Intent fillIn = new Intent();
fillIn.putExtra("pdu", sms.getPdu());
+ fillIn.putExtra("format", android.telephony.SmsMessage.FORMAT_3GPP2);
try {
intent.send(mContext, Activity.RESULT_OK, fillIn);
} catch (CanceledException ex) {}
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java b/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java
index 4e1cc9afd13f..c1553d831c9b 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java
@@ -122,6 +122,7 @@ public final class GsmSMSDispatcher extends SMSDispatcher {
PendingIntent intent = tracker.mDeliveryIntent;
Intent fillIn = new Intent();
fillIn.putExtra("pdu", IccUtils.hexStringToBytes(pduString));
+ fillIn.putExtra("format", android.telephony.SmsMessage.FORMAT_3GPP);
try {
intent.send(mContext, Activity.RESULT_OK, fillIn);
} catch (CanceledException ex) {}
diff --git a/test-runner/src/android/test/mock/MockContentProvider.java b/test-runner/src/android/test/mock/MockContentProvider.java
index b63ff3dca8df..e0ce3228c75b 100644
--- a/test-runner/src/android/test/mock/MockContentProvider.java
+++ b/test-runner/src/android/test/mock/MockContentProvider.java
@@ -21,16 +21,12 @@ import android.content.ContentProviderOperation;
import android.content.ContentProviderResult;
import android.content.ContentValues;
import android.content.Context;
-import android.content.EntityIterator;
import android.content.IContentProvider;
import android.content.OperationApplicationException;
import android.content.pm.PathPermission;
import android.content.pm.ProviderInfo;
import android.content.res.AssetFileDescriptor;
import android.database.Cursor;
-import android.database.CursorWindow;
-import android.database.IBulkCursor;
-import android.database.IContentObserver;
import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
@@ -55,84 +51,75 @@ public class MockContentProvider extends ContentProvider {
* IContentProvider that directs all calls to this MockContentProvider.
*/
private class InversionIContentProvider implements IContentProvider {
- @SuppressWarnings("unused")
+ @Override
public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations)
throws RemoteException, OperationApplicationException {
return MockContentProvider.this.applyBatch(operations);
}
- @SuppressWarnings("unused")
+ @Override
public int bulkInsert(Uri url, ContentValues[] initialValues) throws RemoteException {
return MockContentProvider.this.bulkInsert(url, initialValues);
}
- @SuppressWarnings("unused")
- public IBulkCursor bulkQuery(Uri url, String[] projection, String selection,
- String[] selectionArgs, String sortOrder, IContentObserver observer,
- CursorWindow window) throws RemoteException {
- throw new UnsupportedOperationException("Must not come here");
- }
-
- @SuppressWarnings("unused")
+ @Override
public int delete(Uri url, String selection, String[] selectionArgs)
throws RemoteException {
return MockContentProvider.this.delete(url, selection, selectionArgs);
}
- @SuppressWarnings("unused")
+ @Override
public String getType(Uri url) throws RemoteException {
return MockContentProvider.this.getType(url);
}
- @SuppressWarnings("unused")
+ @Override
public Uri insert(Uri url, ContentValues initialValues) throws RemoteException {
return MockContentProvider.this.insert(url, initialValues);
}
- @SuppressWarnings("unused")
+ @Override
public AssetFileDescriptor openAssetFile(Uri url, String mode) throws RemoteException,
FileNotFoundException {
return MockContentProvider.this.openAssetFile(url, mode);
}
- @SuppressWarnings("unused")
+ @Override
public ParcelFileDescriptor openFile(Uri url, String mode) throws RemoteException,
FileNotFoundException {
return MockContentProvider.this.openFile(url, mode);
}
- @SuppressWarnings("unused")
+ @Override
public Cursor query(Uri url, String[] projection, String selection, String[] selectionArgs,
String sortOrder) throws RemoteException {
return MockContentProvider.this.query(url, projection, selection,
selectionArgs, sortOrder);
}
- @SuppressWarnings("unused")
+ @Override
public int update(Uri url, ContentValues values, String selection, String[] selectionArgs)
throws RemoteException {
return MockContentProvider.this.update(url, values, selection, selectionArgs);
}
- /**
- * @hide
- */
- @SuppressWarnings("unused")
+ @Override
public Bundle call(String method, String request, Bundle args)
throws RemoteException {
return MockContentProvider.this.call(method, request, args);
}
+ @Override
public IBinder asBinder() {
throw new UnsupportedOperationException();
}
- @SuppressWarnings("unused")
+ @Override
public String[] getStreamTypes(Uri url, String mimeTypeFilter) throws RemoteException {
return MockContentProvider.this.getStreamTypes(url, mimeTypeFilter);
}
- @SuppressWarnings("unused")
+ @Override
public AssetFileDescriptor openTypedAssetFile(Uri url, String mimeType, Bundle opts)
throws RemoteException, FileNotFoundException {
return MockContentProvider.this.openTypedAssetFile(url, mimeType, opts);
diff --git a/test-runner/src/android/test/mock/MockIContentProvider.java b/test-runner/src/android/test/mock/MockIContentProvider.java
index 183be415880c..b7733a4d55eb 100644
--- a/test-runner/src/android/test/mock/MockIContentProvider.java
+++ b/test-runner/src/android/test/mock/MockIContentProvider.java
@@ -23,9 +23,6 @@ import android.content.EntityIterator;
import android.content.IContentProvider;
import android.content.res.AssetFileDescriptor;
import android.database.Cursor;
-import android.database.CursorWindow;
-import android.database.IBulkCursor;
-import android.database.IContentObserver;
import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
@@ -47,12 +44,6 @@ public class MockIContentProvider implements IContentProvider {
throw new UnsupportedOperationException("unimplemented mock method");
}
- public IBulkCursor bulkQuery(Uri url, String[] projection, String selection,
- String[] selectionArgs, String sortOrder, IContentObserver observer,
- CursorWindow window) {
- throw new UnsupportedOperationException("unimplemented mock method");
- }
-
@SuppressWarnings("unused")
public int delete(Uri url, String selection, String[] selectionArgs)
throws RemoteException {
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentProvider.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentProvider.java
index 3835378b5da0..c91a3bf91c51 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentProvider.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentProvider.java
@@ -23,9 +23,6 @@ import android.content.IContentProvider;
import android.content.OperationApplicationException;
import android.content.res.AssetFileDescriptor;
import android.database.Cursor;
-import android.database.CursorWindow;
-import android.database.IBulkCursor;
-import android.database.IContentObserver;
import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
@@ -41,78 +38,84 @@ import java.util.ArrayList;
* TODO: never return null when the method is not supposed to. Return fake data instead.
*/
public final class BridgeContentProvider implements IContentProvider {
-
+ @Override
public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> arg0)
throws RemoteException, OperationApplicationException {
// TODO Auto-generated method stub
return null;
}
+ @Override
public int bulkInsert(Uri arg0, ContentValues[] arg1) throws RemoteException {
// TODO Auto-generated method stub
return 0;
}
- public IBulkCursor bulkQuery(Uri arg0, String[] arg1, String arg2, String[] arg3,
- String arg4, IContentObserver arg5, CursorWindow arg6) throws RemoteException {
- // TODO Auto-generated method stub
- return null;
- }
-
+ @Override
public Bundle call(String arg0, String arg1, Bundle arg2) throws RemoteException {
// TODO Auto-generated method stub
return null;
}
+ @Override
public int delete(Uri arg0, String arg1, String[] arg2) throws RemoteException {
// TODO Auto-generated method stub
return 0;
}
+ @Override
public String getType(Uri arg0) throws RemoteException {
// TODO Auto-generated method stub
return null;
}
+ @Override
public Uri insert(Uri arg0, ContentValues arg1) throws RemoteException {
// TODO Auto-generated method stub
return null;
}
+ @Override
public AssetFileDescriptor openAssetFile(Uri arg0, String arg1) throws RemoteException,
FileNotFoundException {
// TODO Auto-generated method stub
return null;
}
+ @Override
public ParcelFileDescriptor openFile(Uri arg0, String arg1) throws RemoteException,
FileNotFoundException {
// TODO Auto-generated method stub
return null;
}
+ @Override
public Cursor query(Uri arg0, String[] arg1, String arg2, String[] arg3, String arg4)
throws RemoteException {
// TODO Auto-generated method stub
return null;
}
+ @Override
public int update(Uri arg0, ContentValues arg1, String arg2, String[] arg3)
throws RemoteException {
// TODO Auto-generated method stub
return 0;
}
+ @Override
public IBinder asBinder() {
// TODO Auto-generated method stub
return null;
}
+ @Override
public String[] getStreamTypes(Uri arg0, String arg1) throws RemoteException {
// TODO Auto-generated method stub
return null;
}
+ @Override
public AssetFileDescriptor openTypedAssetFile(Uri arg0, String arg1, Bundle arg2)
throws RemoteException, FileNotFoundException {
// TODO Auto-generated method stub