Merge "Fix blank Keyguard #4" into lmp-dev
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index 0ee8d86f..47ea732 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -1725,7 +1725,7 @@
for (int i = 0; i < numViolations; ++i) {
if (LOG_V) Log.d(TAG, "strict mode violation stacks read from binder call. i=" + i);
ViolationInfo info = new ViolationInfo(p, !currentlyGathering);
- if (info.crashInfo.stackTrace.length() > 10000) {
+ if (info.crashInfo.stackTrace != null && info.crashInfo.stackTrace.length() > 10000) {
// 10000 characters is way too large for this to be any sane kind of
// strict mode collection of stacks. We've had a problem where we leave
// strict mode violations associated with the thread, and it keeps tacking
diff --git a/core/java/android/util/LocalLog.java b/core/java/android/util/LocalLog.java
index eeb6d58..e49b8c3 100644
--- a/core/java/android/util/LocalLog.java
+++ b/core/java/android/util/LocalLog.java
@@ -20,6 +20,7 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.util.Calendar;
import java.util.Iterator;
import java.util.LinkedList;
@@ -30,18 +31,21 @@
private LinkedList<String> mLog;
private int mMaxLines;
- private Time mNow;
+ private long mNow;
public LocalLog(int maxLines) {
mLog = new LinkedList<String>();
mMaxLines = maxLines;
- mNow = new Time();
}
public synchronized void log(String msg) {
if (mMaxLines > 0) {
- mNow.setToNow();
- mLog.add(mNow.format("%H:%M:%S") + " - " + msg);
+ mNow = System.currentTimeMillis();
+ StringBuilder sb = new StringBuilder();
+ Calendar c = Calendar.getInstance();
+ c.setTimeInMillis(mNow);
+ sb.append(String.format("%tm-%td %tH:%tM:%tS.%tL", c, c, c, c, c, c));
+ mLog.add(sb.toString() + " - " + msg);
while (mLog.size() > mMaxLines) mLog.remove();
}
}
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 5d2822d..1e46517 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -493,7 +493,6 @@
private static native void nInvokeFunctor(long functor, boolean waitForCompletion);
- private static native long nCreateDisplayListLayer(long nativeProxy, int width, int height);
private static native long nCreateTextureLayer(long nativeProxy);
private static native void nBuildLayer(long nativeProxy, long node);
private static native boolean nCopyLayerInto(long nativeProxy, long layer, long bitmap);
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index a8edb77..6219956 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -320,13 +320,6 @@
RenderProxy::invokeFunctor(functor, waitForCompletion);
}
-static jlong android_view_ThreadedRenderer_createDisplayListLayer(JNIEnv* env, jobject clazz,
- jlong proxyPtr, jint width, jint height) {
- RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
- DeferredLayerUpdater* layer = proxy->createDisplayListLayer(width, height);
- return reinterpret_cast<jlong>(layer);
-}
-
static jlong android_view_ThreadedRenderer_createTextureLayer(JNIEnv* env, jobject clazz,
jlong proxyPtr) {
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
@@ -443,7 +436,6 @@
{ "nDestroy", "(J)V", (void*) android_view_ThreadedRenderer_destroy },
{ "nRegisterAnimatingRenderNode", "(JJ)V", (void*) android_view_ThreadedRenderer_registerAnimatingRenderNode },
{ "nInvokeFunctor", "(JZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor },
- { "nCreateDisplayListLayer", "(JII)J", (void*) android_view_ThreadedRenderer_createDisplayListLayer },
{ "nCreateTextureLayer", "(J)J", (void*) android_view_ThreadedRenderer_createTextureLayer },
{ "nBuildLayer", "(JJ)V", (void*) android_view_ThreadedRenderer_buildLayer },
{ "nCopyLayerInto", "(JJJ)Z", (void*) android_view_ThreadedRenderer_copyLayerInto },
diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp
index 836de45..a6d7e78 100644
--- a/libs/hwui/DeferredLayerUpdater.cpp
+++ b/libs/hwui/DeferredLayerUpdater.cpp
@@ -18,38 +18,52 @@
#include "OpenGLRenderer.h"
#include "LayerRenderer.h"
+#include "renderthread/EglManager.h"
+#include "renderthread/RenderTask.h"
namespace android {
namespace uirenderer {
-static void defaultLayerDestroyer(Layer* layer) {
- Caches::getInstance().resourceCache.decrementRefcount(layer);
-}
+class DeleteLayerTask : public renderthread::RenderTask {
+public:
+ DeleteLayerTask(renderthread::EglManager& eglManager, Layer* layer)
+ : mEglManager(eglManager)
+ , mLayer(layer)
+ {}
-DeferredLayerUpdater::DeferredLayerUpdater(Layer* layer, LayerDestroyer destroyer)
+ virtual void run() {
+ mEglManager.requireGlContext();
+ LayerRenderer::destroyLayer(mLayer);
+ mLayer = 0;
+ delete this;
+ }
+
+private:
+ renderthread::EglManager& mEglManager;
+ Layer* mLayer;
+};
+
+DeferredLayerUpdater::DeferredLayerUpdater(renderthread::RenderThread& thread, Layer* layer)
: mSurfaceTexture(0)
, mTransform(0)
, mNeedsGLContextAttach(false)
, mUpdateTexImage(false)
, mLayer(layer)
, mCaches(Caches::getInstance())
- , mDestroyer(destroyer) {
+ , mRenderThread(thread) {
mWidth = mLayer->layer.getWidth();
mHeight = mLayer->layer.getHeight();
mBlend = mLayer->isBlend();
mColorFilter = SkSafeRef(mLayer->getColorFilter());
mAlpha = mLayer->getAlpha();
mMode = mLayer->getMode();
-
- if (!mDestroyer) {
- mDestroyer = defaultLayerDestroyer;
- }
}
DeferredLayerUpdater::~DeferredLayerUpdater() {
SkSafeUnref(mColorFilter);
setTransform(0);
- mDestroyer(mLayer);
+ mRenderThread.queue(new DeleteLayerTask(mRenderThread.eglManager(), mLayer));
+ mLayer = 0;
}
void DeferredLayerUpdater::setPaint(const SkPaint* paint) {
@@ -121,7 +135,12 @@
void DeferredLayerUpdater::detachSurfaceTexture() {
if (mSurfaceTexture.get()) {
- mSurfaceTexture->detachFromContext();
+ mRenderThread.eglManager().requireGlContext();
+ status_t err = mSurfaceTexture->detachFromContext();
+ if (err != 0) {
+ // TODO: Elevate to fatal exception
+ ALOGE("Failed to detach SurfaceTexture from context %d", err);
+ }
mSurfaceTexture = 0;
mLayer->clearTexture();
}
diff --git a/libs/hwui/DeferredLayerUpdater.h b/libs/hwui/DeferredLayerUpdater.h
index c838c32..dda3e89 100644
--- a/libs/hwui/DeferredLayerUpdater.h
+++ b/libs/hwui/DeferredLayerUpdater.h
@@ -25,19 +25,18 @@
#include "Layer.h"
#include "Rect.h"
#include "RenderNode.h"
+#include "renderthread/RenderThread.h"
namespace android {
namespace uirenderer {
-typedef void (*LayerDestroyer)(Layer* layer);
-
// Container to hold the properties a layer should be set to at the start
// of a render pass
class DeferredLayerUpdater : public VirtualLightRefBase {
public:
// Note that DeferredLayerUpdater assumes it is taking ownership of the layer
// and will not call incrementRef on it as a result.
- ANDROID_API DeferredLayerUpdater(Layer* layer, LayerDestroyer = 0);
+ ANDROID_API DeferredLayerUpdater(renderthread::RenderThread& thread, Layer* layer);
ANDROID_API ~DeferredLayerUpdater();
ANDROID_API bool setSize(uint32_t width, uint32_t height) {
@@ -99,8 +98,7 @@
Layer* mLayer;
Caches& mCaches;
-
- LayerDestroyer mDestroyer;
+ renderthread::RenderThread& mRenderThread;
void doUpdateTexImage();
};
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 1c416a7..b50a433 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -344,11 +344,6 @@
task->run();
}
-Layer* CanvasContext::createRenderLayer(int width, int height) {
- requireSurface();
- return LayerRenderer::createRenderLayer(mRenderThread.renderState(), width, height);
-}
-
Layer* CanvasContext::createTextureLayer() {
requireSurface();
return LayerRenderer::createTextureLayer(mRenderThread.renderState());
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 2460f6b8..d4282fa 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -83,7 +83,6 @@
void runWithGlContext(RenderTask* task);
- Layer* createRenderLayer(int width, int height);
Layer* createTextureLayer();
ANDROID_API static void setTextureAtlas(RenderThread& thread,
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 9528874..047819d 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -257,31 +257,16 @@
RenderThread::getInstance().queue(task);
}
-CREATE_BRIDGE3(createDisplayListLayer, CanvasContext* context, int width, int height) {
- Layer* layer = args->context->createRenderLayer(args->width, args->height);
- if (!layer) return 0;
- return new DeferredLayerUpdater(layer, RenderProxy::enqueueDestroyLayer);
-}
-
-DeferredLayerUpdater* RenderProxy::createDisplayListLayer(int width, int height) {
- SETUP_TASK(createDisplayListLayer);
- args->width = width;
- args->height = height;
- args->context = mContext;
- void* retval = postAndWait(task);
- DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(retval);
- return layer;
-}
-
-CREATE_BRIDGE1(createTextureLayer, CanvasContext* context) {
+CREATE_BRIDGE2(createTextureLayer, RenderThread* thread, CanvasContext* context) {
Layer* layer = args->context->createTextureLayer();
if (!layer) return 0;
- return new DeferredLayerUpdater(layer, RenderProxy::enqueueDestroyLayer);
+ return new DeferredLayerUpdater(*args->thread, layer);
}
DeferredLayerUpdater* RenderProxy::createTextureLayer() {
SETUP_TASK(createTextureLayer);
args->context = mContext;
+ args->thread = &mRenderThread;
void* retval = postAndWait(task);
DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(retval);
return layer;
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 8b8d99c..678e7e2 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -80,7 +80,6 @@
ANDROID_API void runWithGlContext(RenderTask* task);
static void enqueueDestroyLayer(Layer* layer);
- ANDROID_API DeferredLayerUpdater* createDisplayListLayer(int width, int height);
ANDROID_API DeferredLayerUpdater* createTextureLayer();
ANDROID_API void buildLayer(RenderNode* node);
ANDROID_API bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap);
diff --git a/media/java/android/media/RemoteControlClient.java b/media/java/android/media/RemoteControlClient.java
index 3c2ad0e..0336f11 100644
--- a/media/java/android/media/RemoteControlClient.java
+++ b/media/java/android/media/RemoteControlClient.java
@@ -572,7 +572,8 @@
// USE_SESSIONS
if (mSession != null && mMetadataBuilder != null) {
- mSession.setMetadata(mMetadataBuilder.build());
+ mMediaMetadata = mMetadataBuilder.build();
+ mSession.setMetadata(mMediaMetadata);
}
mApplied = true;
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 3453a67..34e57bc 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -506,7 +506,14 @@
}
private void fullyPopulateCaches(final int userHandle) {
- DatabaseHelper dbHelper = mOpenHelpers.get(userHandle);
+ DatabaseHelper dbHelper;
+ synchronized (this) {
+ dbHelper = mOpenHelpers.get(userHandle);
+ }
+ if (dbHelper == null) {
+ // User is gone.
+ return;
+ }
// Only populate the globals cache once, for the owning user
if (userHandle == UserHandle.USER_OWNER) {
fullyPopulateCache(dbHelper, TABLE_GLOBAL, sGlobalCache);
@@ -611,10 +618,15 @@
long oldId = Binder.clearCallingIdentity();
try {
- DatabaseHelper dbHelper = mOpenHelpers.get(callingUser);
+ DatabaseHelper dbHelper;
+ synchronized (this) {
+ dbHelper = mOpenHelpers.get(callingUser);
+ }
if (null == dbHelper) {
establishDbTracking(callingUser);
- dbHelper = mOpenHelpers.get(callingUser);
+ synchronized (this) {
+ dbHelper = mOpenHelpers.get(callingUser);
+ }
}
return dbHelper;
} finally {
diff --git a/policy/src/com/android/internal/policy/impl/GlobalActions.java b/policy/src/com/android/internal/policy/impl/GlobalActions.java
index dfcdaa0..b0b2886 100644
--- a/policy/src/com/android/internal/policy/impl/GlobalActions.java
+++ b/policy/src/com/android/internal/policy/impl/GlobalActions.java
@@ -23,6 +23,7 @@
import com.android.internal.R;
import com.android.internal.widget.LockPatternUtils;
+import android.app.ActivityManager;
import android.app.ActivityManagerNative;
import android.app.AlertDialog;
import android.app.Dialog;
@@ -370,6 +371,11 @@
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
+ // don't actually trigger the bugreport if we are running stability
+ // tests via monkey
+ if (ActivityManager.isUserAMonkey()) {
+ return;
+ }
// Add a little delay before executing, to give the
// dialog a chance to go away before it takes a
// screenshot.
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 7d4156f..aff64e3 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -764,6 +764,35 @@
.getAccessibilityFocusClickPointInScreenNotLocked(outPoint);
}
+ /**
+ * Gets the bounds of the active window.
+ *
+ * @param outBounds The output to which to write the bounds.
+ */
+ boolean getActiveWindowBounds(Rect outBounds) {
+ // TODO: This should be refactored to work with accessibility
+ // focus in multiple windows.
+ IBinder token;
+ synchronized (mLock) {
+ final int windowId = mSecurityPolicy.mActiveWindowId;
+ token = mGlobalWindowTokens.get(windowId);
+ if (token == null) {
+ token = getCurrentUserStateLocked().mWindowTokens.get(windowId);
+ }
+ }
+ mWindowManagerService.getWindowFrame(token, outBounds);
+ if (!outBounds.isEmpty()) {
+ return true;
+ }
+ return false;
+ }
+
+ boolean accessibilityFocusOnlyInActiveWindow() {
+ synchronized (mLock) {
+ return mWindowsForAccessibilityCallback == null;
+ }
+ }
+
int getActiveWindowId() {
return mSecurityPolicy.getActiveWindowId();
}
@@ -1581,10 +1610,15 @@
if (userState.mUserId != UserHandle.USER_OWNER) {
return;
}
- if (hasRunningServicesLocked(userState) && LockPatternUtils.isDeviceEncrypted()) {
- // If there are running accessibility services we do not have encryption as
- // the user needs the accessibility layer to be running to authenticate.
- mLockPatternUtils.clearEncryptionPassword();
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ if (hasRunningServicesLocked(userState) && LockPatternUtils.isDeviceEncrypted()) {
+ // If there are running accessibility services we do not have encryption as
+ // the user needs the accessibility layer to be running to authenticate.
+ mLockPatternUtils.clearEncryptionPassword();
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
}
}
@@ -3207,6 +3241,13 @@
point.y = (int) (point.y * (1 / spec.scale));
}
+ // Make sure the point is within the window.
+ Rect windowBounds = mTempRect;
+ getActiveWindowBounds(windowBounds);
+ if (!windowBounds.contains(point.x, point.y)) {
+ return false;
+ }
+
// Make sure the point is within the screen.
Point screenSize = mTempPoint;
mDefaultDisplay.getRealSize(screenSize);
@@ -3566,6 +3607,9 @@
}
private void notifyWindowsChanged() {
+ if (mWindowsForAccessibilityCallback == null) {
+ return;
+ }
final long identity = Binder.clearCallingIdentity();
try {
// Let the client know the windows changed.
@@ -3650,6 +3694,10 @@
}
private boolean isRetrievalAllowingWindow(int windowId) {
+ // The system gets to interact with any window it wants.
+ if (Binder.getCallingUid() == Process.SYSTEM_UID) {
+ return true;
+ }
if (windowId == mActiveWindowId) {
return true;
}
diff --git a/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
index 94befad..b9ed89b 100644
--- a/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
+++ b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
@@ -205,6 +205,9 @@
// The long pressing pointer Y if coordinate remapping is needed.
private int mLongPressingPointerDeltaY;
+ // The id of the last touch explored window.
+ private int mLastTouchedWindowId;
+
// Whether touch exploration is in progress.
private boolean mTouchExplorationInProgress;
@@ -365,6 +368,11 @@
mInjectedPointerTracker.mLastInjectedHoverEventForClick.recycle();
mInjectedPointerTracker.mLastInjectedHoverEventForClick = null;
}
+ mLastTouchedWindowId = -1;
+ } break;
+ case AccessibilityEvent.TYPE_VIEW_HOVER_ENTER:
+ case AccessibilityEvent.TYPE_VIEW_HOVER_EXIT: {
+ mLastTouchedWindowId = event.getWindowId();
} break;
}
if (mNext != null) {
@@ -1208,6 +1216,24 @@
MAX_DRAGGING_ANGLE_COS);
}
+ private boolean computeClickLocation(Point outLocation) {
+ MotionEvent lastExploreEvent = mInjectedPointerTracker.getLastInjectedHoverEventForClick();
+ if (lastExploreEvent != null) {
+ final int lastExplorePointerIndex = lastExploreEvent.getActionIndex();
+ outLocation.x = (int) lastExploreEvent.getX(lastExplorePointerIndex);
+ outLocation.y = (int) lastExploreEvent.getY(lastExplorePointerIndex);
+ if (!mAms.accessibilityFocusOnlyInActiveWindow()
+ || mLastTouchedWindowId == mAms.getActiveWindowId()) {
+ mAms.getAccessibilityFocusClickPointInScreen(outLocation);
+ }
+ return true;
+ }
+ if (mAms.getAccessibilityFocusClickPointInScreen(outLocation)) {
+ return true;
+ }
+ return false;
+ }
+
/**
* Gets the symbolic name of a state.
*
@@ -1284,10 +1310,12 @@
return;
}
+ int clickLocationX;
+ int clickLocationY;
+
final int pointerId = mEvent.getPointerId(mEvent.getActionIndex());
final int pointerIndex = mEvent.findPointerIndex(pointerId);
-
Point clickLocation = mTempPoint;
if (!computeClickLocation(clickLocation)) {
return;
@@ -1311,27 +1339,6 @@
}
}
- private boolean computeClickLocation(Point outPoint) {
- // Try to click on the accessiblity focused view and if that
- // fails try the last touch explored location, if such.
- Point point = mTempPoint;
- if (mAms.getAccessibilityFocusClickPointInScreen(point)) {
- outPoint.x = point.x;
- outPoint.y = point.y;
- return true;
- } else {
- MotionEvent lastExploreEvent =
- mInjectedPointerTracker.getLastInjectedHoverEventForClick();
- if (lastExploreEvent != null) {
- final int lastExplorePointerIndex = lastExploreEvent.getActionIndex();
- outPoint.x = (int) lastExploreEvent.getX(lastExplorePointerIndex);
- outPoint.y = (int) lastExploreEvent.getY(lastExplorePointerIndex);
- return true;
- }
- }
- return false;
- }
-
/**
* Class for delayed sending of hover enter and move events.
*/
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 47396bd..8b524dd 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -58,6 +58,7 @@
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
+import java.util.HashMap;
import java.util.LinkedList;
import java.util.Locale;
import java.util.TimeZone;
@@ -141,6 +142,25 @@
private final SparseArray<AlarmManager.AlarmClockInfo> mHandlerSparseAlarmClockArray =
new SparseArray<>();
+ // Alarm delivery ordering bookkeeping
+ static final int PRIO_TICK = 0;
+ static final int PRIO_WAKEUP = 1;
+ static final int PRIO_NORMAL = 2;
+
+ class PriorityClass {
+ int seq;
+ int priority;
+
+ PriorityClass() {
+ seq = mCurrentSeq - 1;
+ priority = PRIO_NORMAL;
+ }
+ }
+
+ final HashMap<String, PriorityClass> mPriorities =
+ new HashMap<String, PriorityClass>();
+ int mCurrentSeq = 0;
+
class WakeupEvent {
public long when;
public int uid;
@@ -356,22 +376,62 @@
final Comparator<Alarm> mAlarmDispatchComparator = new Comparator<Alarm>() {
@Override
public int compare(Alarm lhs, Alarm rhs) {
- if ((!lhs.operation.getCreatorPackage().equals(rhs.operation.getCreatorPackage()))
- && lhs.wakeup != rhs.wakeup) {
- // We want to put wakeup alarms before non-wakeup alarms, since they are
- // the things that drive most activity in the alarm manager. However,
- // alarms from the same package should always be ordered strictly by time.
- return lhs.wakeup ? -1 : 1;
+ // priority class trumps everything. TICK < WAKEUP < NORMAL
+ if (lhs.priorityClass.priority < rhs.priorityClass.priority) {
+ return -1;
+ } else if (lhs.priorityClass.priority > rhs.priorityClass.priority) {
+ return 1;
}
+
+ // within each class, sort by nominal delivery time
if (lhs.whenElapsed < rhs.whenElapsed) {
return -1;
} else if (lhs.whenElapsed > rhs.whenElapsed) {
return 1;
}
+
+ // same priority class + same target delivery time
return 0;
}
};
+ void calculateDeliveryPriorities(ArrayList<Alarm> alarms) {
+ final int N = alarms.size();
+ for (int i = 0; i < N; i++) {
+ Alarm a = alarms.get(i);
+
+ final int alarmPrio;
+ if (Intent.ACTION_TIME_TICK.equals(a.operation.getIntent().getAction())) {
+ alarmPrio = PRIO_TICK;
+ } else if (a.wakeup) {
+ alarmPrio = PRIO_WAKEUP;
+ } else {
+ alarmPrio = PRIO_NORMAL;
+ }
+
+ PriorityClass packagePrio = a.priorityClass;
+ if (packagePrio == null) packagePrio = mPriorities.get(a.operation.getCreatorPackage());
+ if (packagePrio == null) {
+ packagePrio = a.priorityClass = new PriorityClass(); // lowest prio & stale sequence
+ mPriorities.put(a.operation.getCreatorPackage(), packagePrio);
+ }
+ a.priorityClass = packagePrio;
+
+ if (packagePrio.seq != mCurrentSeq) {
+ // first alarm we've seen in the current delivery generation from this package
+ packagePrio.priority = alarmPrio;
+ packagePrio.seq = mCurrentSeq;
+ } else {
+ // Multiple alarms from this package being delivered in this generation;
+ // bump the package's delivery class if it's warranted.
+ // TICK < WAKEUP < NORMAL
+ if (alarmPrio < packagePrio.priority) {
+ packagePrio.priority = alarmPrio;
+ }
+ }
+ }
+ }
+
// minimum recurrence period or alarm futurity for us to be able to fuzz it
static final long MIN_FUZZABLE_INTERVAL = 10000;
static final BatchTimeOrder sBatchOrder = new BatchTimeOrder();
@@ -1381,6 +1441,10 @@
}
}
+ // This is a new alarm delivery set; bump the sequence number to indicate that
+ // all apps' alarm delivery classes should be recalculated.
+ mCurrentSeq++;
+ calculateDeliveryPriorities(triggerList);
Collections.sort(triggerList, mAlarmDispatchComparator);
if (localLOGV) {
@@ -1423,6 +1487,7 @@
public long repeatInterval;
public final AlarmManager.AlarmClockInfo alarmClock;
public final int userId;
+ public PriorityClass priorityClass;
public Alarm(int _type, long _when, long _whenElapsed, long _windowLength, long _maxWhen,
long _interval, PendingIntent _op, WorkSource _ws,
@@ -1676,6 +1741,7 @@
rescheduleKernelAlarmsLocked();
updateNextAlarmClockLocked();
if (mPendingNonWakeupAlarms.size() > 0) {
+ calculateDeliveryPriorities(mPendingNonWakeupAlarms);
triggerList.addAll(mPendingNonWakeupAlarms);
Collections.sort(triggerList, mAlarmDispatchComparator);
final long thisDelayTime = nowELAPSED - mStartCurrentDelayTime;
@@ -1889,6 +1955,7 @@
if (pkgList != null && (pkgList.length > 0)) {
for (String pkg : pkgList) {
removeLocked(pkg);
+ mPriorities.remove(pkg);
for (int i=mBroadcastStats.size()-1; i>=0; i--) {
ArrayMap<String, BroadcastStats> uidStats = mBroadcastStats.valueAt(i);
if (uidStats.remove(pkg) != null) {
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 3dab17f..b29cdf4 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -4231,6 +4231,7 @@
NetworkInfo result = new NetworkInfo(
networkType, 0, ConnectivityManager.getNetworkTypeName(networkType), "");
result.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null, null);
+ result.setIsAvailable(true);
return result;
}
}
diff --git a/services/core/java/com/android/server/EventLogTags.logtags b/services/core/java/com/android/server/EventLogTags.logtags
index 5aaeb6a..99a1254 100644
--- a/services/core/java/com/android/server/EventLogTags.logtags
+++ b/services/core/java/com/android/server/EventLogTags.logtags
@@ -134,6 +134,8 @@
# + check activity_launch_time for Home app
# Value of "unknown sources" setting at app install time
3110 unknown_sources_enabled (value|1)
+# Package Manager critical info
+3120 pm_critical_info (msg|3)
# ---------------------------
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 50cb5fc..f912fd4 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -1379,7 +1379,7 @@
// Set flag to monitor and not change apk file paths when
// scanning install directories.
- int scanFlags = SCAN_NO_PATHS | SCAN_DEFER_DEX | SCAN_BOOTING;
+ final int scanFlags = SCAN_NO_PATHS | SCAN_DEFER_DEX | SCAN_BOOTING;
final HashSet<String> alreadyDexOpted = new HashSet<String>();
@@ -1523,13 +1523,13 @@
scanFlags | SCAN_NO_DEX, 0);
// Collected privileged system packages.
- File privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app");
+ final File privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app");
scanDirLI(privilegedAppDir, PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR
| PackageParser.PARSE_IS_PRIVILEGED, scanFlags, 0);
// Collect ordinary system packages.
- File systemAppDir = new File(Environment.getRootDirectory(), "app");
+ final File systemAppDir = new File(Environment.getRootDirectory(), "app");
scanDirLI(systemAppDir, PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
@@ -1544,7 +1544,7 @@
| PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
// Collect all OEM packages.
- File oemAppDir = new File(Environment.getOemDirectory(), "app");
+ final File oemAppDir = new File(Environment.getOemDirectory(), "app");
scanDirLI(oemAppDir, PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
@@ -1579,8 +1579,11 @@
* application can be scanned.
*/
if (mSettings.isDisabledSystemPackageLPr(ps.name)) {
- Slog.i(TAG, "Expecting better updatd system app for " + ps.name
- + "; removing system app");
+ logCriticalInfo(Log.WARN, "Expecting better updated system app for "
+ + ps.name + "; removing system app. Last known codePath="
+ + ps.codePathString + ", installStatus=" + ps.installStatus
+ + ", versionCode=" + ps.versionCode + "; scanned versionCode="
+ + scannedPkg.mVersionCode);
removePackageLI(ps, true);
}
@@ -1589,9 +1592,8 @@
if (!mSettings.isDisabledSystemPackageLPr(ps.name)) {
psit.remove();
- String msg = "System package " + ps.name
- + " no longer exists; wiping its data";
- reportSettingsProblem(Log.WARN, msg);
+ logCriticalInfo(Log.WARN, "System package " + ps.name
+ + " no longer exists; wiping its data");
removeDataDirsLI(ps.name);
} else {
final PackageSetting disabledPs = mSettings.getDisabledSystemPkgLPr(ps.name);
@@ -1648,7 +1650,7 @@
PackageSetting deletedPs = mSettings.mPackages.get(deletedAppName);
deletedPs.pkgFlags &= ~ApplicationInfo.FLAG_SYSTEM;
}
- reportSettingsProblem(Log.WARN, msg);
+ logCriticalInfo(Log.WARN, msg);
}
}
@@ -1792,7 +1794,8 @@
}
void cleanupInstallFailedPackage(PackageSetting ps) {
- Slog.i(TAG, "Cleaning up incompletely installed app: " + ps.name);
+ logCriticalInfo(Log.WARN, "Cleaning up incompletely installed app: " + ps.name);
+
removeDataDirsLI(ps.name);
if (ps.codePath != null) {
if (ps.codePath.isDirectory()) {
@@ -4029,7 +4032,7 @@
// Delete invalid userdata apps
if ((parseFlags & PackageParser.PARSE_IS_SYSTEM) == 0 &&
e.error == PackageManager.INSTALL_FAILED_INVALID_APK) {
- Slog.w(TAG, "Deleting invalid package at " + file);
+ logCriticalInfo(Log.WARN, "Deleting invalid package at " + file);
if (file.isDirectory()) {
FileUtils.deleteContents(file);
}
@@ -4045,8 +4048,14 @@
File fname = new File(systemDir, "uiderrors.txt");
return fname;
}
-
+
static void reportSettingsProblem(int priority, String msg) {
+ logCriticalInfo(priority, msg);
+ }
+
+ static void logCriticalInfo(int priority, String msg) {
+ Slog.println(priority, TAG, msg);
+ EventLogTags.writePmCriticalInfo(msg);
try {
File fname = getSettingsProblemFile();
FileOutputStream out = new FileOutputStream(fname, true);
@@ -4061,7 +4070,6 @@
-1, -1);
} catch (java.io.IOException e) {
}
- Slog.println(priority, TAG, msg);
}
private void collectCertificatesLI(PackageParser pp, PackageSetting ps,
@@ -4155,7 +4163,7 @@
if (pkg.mVersionCode < ps.versionCode) {
// The system package has been updated and the code path does not match
// Ignore entry. Skip it.
- Log.i(TAG, "Package " + ps.name + " at " + scanFile
+ logCriticalInfo(Log.INFO, "Package " + ps.name + " at " + scanFile
+ " ignored: updated version " + ps.versionCode
+ " better than this " + pkg.mVersionCode);
if (!updatedPkg.codePath.equals(scanFile)) {
@@ -4185,7 +4193,8 @@
// Just remove the loaded entries from package lists.
mPackages.remove(ps.name);
}
- Slog.w(TAG, "Package " + ps.name + " at " + scanFile
+
+ logCriticalInfo(Log.WARN, "Package " + ps.name + " at " + scanFile
+ "reverting from " + ps.codePathString
+ ": new version " + pkg.mVersionCode
+ " better than installed " + ps.versionCode);
@@ -4232,7 +4241,8 @@
*/
if (compareSignatures(ps.signatures.mSignatures, pkg.mSignatures)
!= PackageManager.SIGNATURE_MATCH) {
- if (DEBUG_INSTALL) Slog.d(TAG, "Signature mismatch!");
+ logCriticalInfo(Log.WARN, "Package " + ps.name + " appeared on system, but"
+ + " signatures don't match existing userdata copy; removing");
deletePackageLI(pkg.packageName, null, true, null, null, 0, null, false);
ps = null;
} else {
@@ -4243,6 +4253,9 @@
*/
if (pkg.mVersionCode < ps.versionCode) {
shouldHideSystemApp = true;
+ logCriticalInfo(Log.INFO, "Package " + ps.name + " appeared at " + scanFile
+ + " but new version " + pkg.mVersionCode + " better than installed "
+ + ps.versionCode + "; hiding system");
} else {
/*
* The newly found system app is a newer version that the
@@ -4250,9 +4263,9 @@
* already-installed application and replace it with our own
* while keeping the application data.
*/
- Slog.w(TAG, "Package " + ps.name + " at " + scanFile + "reverting from "
- + ps.codePathString + ": new version " + pkg.mVersionCode
- + " better than installed " + ps.versionCode);
+ logCriticalInfo(Log.WARN, "Package " + ps.name + " at " + scanFile
+ + " reverting from " + ps.codePathString + ": new version "
+ + pkg.mVersionCode + " better than installed " + ps.versionCode);
InstallArgs args = createInstallArgsForExisting(packageFlagsToInstallFlags(ps),
ps.codePathString, ps.resourcePathString, ps.legacyNativeLibraryPathString,
getAppDexInstructionSets(ps));
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index 77d3beb..c003fa6 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -4357,13 +4357,15 @@
continue;
}
- entriesToAdd[i].value->getPos()
- .printf("using v%d attributes; synthesizing resource %s:%s/%s for configuration %s.",
- SDK_L,
- String8(p->getName()).string(),
- String8(t->getName()).string(),
- String8(entriesToAdd[i].value->getName()).string(),
- entriesToAdd[i].key.toString().string());
+ if (bundle->getVerbose()) {
+ entriesToAdd[i].value->getPos()
+ .printf("using v%d attributes; synthesizing resource %s:%s/%s for configuration %s.",
+ SDK_L,
+ String8(p->getName()).string(),
+ String8(t->getName()).string(),
+ String8(entriesToAdd[i].value->getName()).string(),
+ entriesToAdd[i].key.toString().string());
+ }
sp<Entry> newEntry = t->getEntry(c->getName(),
entriesToAdd[i].value->getPos(),
@@ -4437,13 +4439,15 @@
resPath.convertToResPath();
// Add a resource table entry.
- SourcePos(target->getSourceFile(), -1).printf(
- "using v%d attributes; synthesizing resource %s:%s/%s for configuration %s.",
- SDK_L,
- mAssets->getPackage().string(),
- newFile->getResourceType().string(),
- String8(resourceName).string(),
- newConfig.toString().string());
+ if (bundle->getVerbose()) {
+ SourcePos(target->getSourceFile(), -1).printf(
+ "using v%d attributes; synthesizing resource %s:%s/%s for configuration %s.",
+ SDK_L,
+ mAssets->getPackage().string(),
+ newFile->getResourceType().string(),
+ String8(resourceName).string(),
+ newConfig.toString().string());
+ }
addEntry(SourcePos(),
String16(mAssets->getPackage()),
@@ -4466,12 +4470,14 @@
sp<XMLNode> node = attrsToRemove[i].key;
size_t attrIndex = attrsToRemove[i].value;
const XMLNode::attribute_entry& ae = node->getAttributes()[attrIndex];
- SourcePos(node->getFilename(), node->getStartLineNumber()).printf(
- "removing attribute %s%s%s from <%s>",
- String8(ae.ns).string(),
- (ae.ns.size() == 0 ? "" : ":"),
- String8(ae.name).string(),
- String8(node->getElementName()).string());
+ if (bundle->getVerbose()) {
+ SourcePos(node->getFilename(), node->getStartLineNumber()).printf(
+ "removing attribute %s%s%s from <%s>",
+ String8(ae.ns).string(),
+ (ae.ns.size() == 0 ? "" : ":"),
+ String8(ae.name).string(),
+ String8(node->getElementName()).string());
+ }
node->removeAttribute(attrIndex);
}
diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
index 4a6a434..28a109d 100644
--- a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
+++ b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
@@ -159,7 +159,7 @@
return null;
}
// As unfortunate as it is, it's possible to use enums with all attribute formats,
- // not just integers/enums. So, we need to search the enums always. In case,
+ // not just integers/enums. So, we need to search the enums always. In case
// enums are used, the returned value is an integer.
Integer v = resolveEnumAttribute(index);
return v == null ? mResourceData[index].getValue() : String.valueOf((int) v);
@@ -197,7 +197,7 @@
}
} catch (NumberFormatException e) {
Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
- String.format("\"%s\" in attribute \"%2$s\" is not a valid integer",
+ String.format("\"%1$s\" in attribute \"%2$s\" is not a valid integer",
s, mNames[index]),
null);
return defValue;
@@ -221,7 +221,7 @@
}
} catch (NumberFormatException e) {
Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
- String.format("\"%s\" in attribute \"%2$s\" cannot be converted to float.",
+ String.format("\"%1$s\" in attribute \"%2$s\" cannot be converted to float.",
s, mNames[index]),
null);
}
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 5514798..53756d2 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -1072,7 +1072,7 @@
sbuf.append(",ipfail=");
sbuf.append(result.numIpConfigFailures);
}
- sbuf.append(result.autoJoinStatus).append("} ");
+ sbuf.append(",").append(result.autoJoinStatus).append("} ");
}
sbuf.append('\n');
}