Merge "Make Layoutlib compile on Java 6."
diff --git a/api/current.txt b/api/current.txt
index b9453cc..59bbb12 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -10926,11 +10926,12 @@
}
public final class MediaRecorder.OutputFormat {
+ field public static final int AAC_ADTS = 6; // 0x6
field public static final int AMR_NB = 3; // 0x3
field public static final int AMR_WB = 4; // 0x4
field public static final int DEFAULT = 0; // 0x0
field public static final int MPEG_4 = 2; // 0x2
- field public static final int RAW_AMR = 3; // 0x3
+ field public static final deprecated int RAW_AMR = 3; // 0x3
field public static final int THREE_GPP = 1; // 0x1
}
diff --git a/core/java/android/net/INetworkPolicyManager.aidl b/core/java/android/net/INetworkPolicyManager.aidl
index 633c38e0..442535a 100644
--- a/core/java/android/net/INetworkPolicyManager.aidl
+++ b/core/java/android/net/INetworkPolicyManager.aidl
@@ -43,7 +43,7 @@
NetworkPolicy[] getNetworkPolicies();
/** Snooze limit on policy matching given template. */
- void snoozePolicy(in NetworkTemplate template);
+ void snoozeLimit(in NetworkTemplate template);
/** Control if background data is restricted system-wide. */
void setRestrictBackground(boolean restrictBackground);
diff --git a/core/java/android/net/NetworkPolicy.java b/core/java/android/net/NetworkPolicy.java
index d9ea700..04cf1a3 100644
--- a/core/java/android/net/NetworkPolicy.java
+++ b/core/java/android/net/NetworkPolicy.java
@@ -38,18 +38,25 @@
public int cycleDay;
public long warningBytes;
public long limitBytes;
- public long lastSnooze;
+ public long lastWarningSnooze;
+ public long lastLimitSnooze;
public boolean metered;
private static final long DEFAULT_MTU = 1500;
- public NetworkPolicy(NetworkTemplate template, int cycleDay, long warningBytes, long limitBytes,
- long lastSnooze, boolean metered) {
+ public NetworkPolicy(NetworkTemplate template, int cycleDay, long warningBytes,
+ long limitBytes, boolean metered) {
+ this(template, cycleDay, warningBytes, limitBytes, SNOOZE_NEVER, SNOOZE_NEVER, metered);
+ }
+
+ public NetworkPolicy(NetworkTemplate template, int cycleDay, long warningBytes,
+ long limitBytes, long lastWarningSnooze, long lastLimitSnooze, boolean metered) {
this.template = checkNotNull(template, "missing NetworkTemplate");
this.cycleDay = cycleDay;
this.warningBytes = warningBytes;
this.limitBytes = limitBytes;
- this.lastSnooze = lastSnooze;
+ this.lastWarningSnooze = lastWarningSnooze;
+ this.lastLimitSnooze = lastLimitSnooze;
this.metered = metered;
}
@@ -58,7 +65,8 @@
cycleDay = in.readInt();
warningBytes = in.readLong();
limitBytes = in.readLong();
- lastSnooze = in.readLong();
+ lastWarningSnooze = in.readLong();
+ lastLimitSnooze = in.readLong();
metered = in.readInt() != 0;
}
@@ -68,7 +76,8 @@
dest.writeInt(cycleDay);
dest.writeLong(warningBytes);
dest.writeLong(limitBytes);
- dest.writeLong(lastSnooze);
+ dest.writeLong(lastWarningSnooze);
+ dest.writeLong(lastLimitSnooze);
dest.writeInt(metered ? 1 : 0);
}
@@ -78,6 +87,13 @@
}
/**
+ * Test if given measurement is over {@link #warningBytes}.
+ */
+ public boolean isOverWarning(long totalBytes) {
+ return warningBytes != WARNING_DISABLED && totalBytes >= warningBytes;
+ }
+
+ /**
* Test if given measurement is near enough to {@link #limitBytes} to be
* considered over-limit.
*/
@@ -88,6 +104,14 @@
return limitBytes != LIMIT_DISABLED && totalBytes >= limitBytes;
}
+ /**
+ * Clear any existing snooze values, setting to {@link #SNOOZE_NEVER}.
+ */
+ public void clearSnooze() {
+ lastWarningSnooze = SNOOZE_NEVER;
+ lastLimitSnooze = SNOOZE_NEVER;
+ }
+
/** {@inheritDoc} */
public int compareTo(NetworkPolicy another) {
if (another == null || another.limitBytes == LIMIT_DISABLED) {
@@ -103,7 +127,8 @@
@Override
public int hashCode() {
- return Objects.hashCode(template, cycleDay, warningBytes, limitBytes, lastSnooze, metered);
+ return Objects.hashCode(template, cycleDay, warningBytes, limitBytes, lastWarningSnooze,
+ lastLimitSnooze, metered);
}
@Override
@@ -111,8 +136,10 @@
if (obj instanceof NetworkPolicy) {
final NetworkPolicy other = (NetworkPolicy) obj;
return cycleDay == other.cycleDay && warningBytes == other.warningBytes
- && limitBytes == other.limitBytes && lastSnooze == other.lastSnooze
- && metered == other.metered && Objects.equal(template, other.template);
+ && limitBytes == other.limitBytes
+ && lastWarningSnooze == other.lastWarningSnooze
+ && lastLimitSnooze == other.lastLimitSnooze && metered == other.metered
+ && Objects.equal(template, other.template);
}
return false;
}
@@ -120,8 +147,9 @@
@Override
public String toString() {
return "NetworkPolicy[" + template + "]: cycleDay=" + cycleDay + ", warningBytes="
- + warningBytes + ", limitBytes=" + limitBytes + ", lastSnooze=" + lastSnooze
- + ", metered=" + metered;
+ + warningBytes + ", limitBytes=" + limitBytes + ", lastWarningSnooze="
+ + lastWarningSnooze + ", lastLimitSnooze=" + lastLimitSnooze + ", metered="
+ + metered;
}
public static final Creator<NetworkPolicy> CREATOR = new Creator<NetworkPolicy>() {
diff --git a/include/gui/DisplayEventReceiver.h b/include/gui/DisplayEventReceiver.h
index a281377..7bca8d6 100644
--- a/include/gui/DisplayEventReceiver.h
+++ b/include/gui/DisplayEventReceiver.h
@@ -95,6 +95,8 @@
* should be destroyed and getEvents() shouldn't be called again.
*/
ssize_t getEvents(Event* events, size_t count);
+ static ssize_t getEvents(const sp<BitTube>& dataChannel,
+ Event* events, size_t count);
/*
* setVsyncRate() sets the Event::VSync delivery rate. A value of
diff --git a/libs/gui/DisplayEventReceiver.cpp b/libs/gui/DisplayEventReceiver.cpp
index 3b3ccaa..6a4763d 100644
--- a/libs/gui/DisplayEventReceiver.cpp
+++ b/libs/gui/DisplayEventReceiver.cpp
@@ -80,7 +80,13 @@
ssize_t DisplayEventReceiver::getEvents(DisplayEventReceiver::Event* events,
size_t count) {
- ssize_t size = mDataChannel->read(events, sizeof(events[0])*count);
+ return DisplayEventReceiver::getEvents(mDataChannel, events, count);
+}
+
+ssize_t DisplayEventReceiver::getEvents(const sp<BitTube>& dataChannel,
+ Event* events, size_t count)
+{
+ ssize_t size = dataChannel->read(events, sizeof(events[0])*count);
ALOGE_IF(size<0,
"DisplayEventReceiver::getEvents error (%s)",
strerror(-size));
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index 95e0a18..5ec3983 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -26,6 +26,7 @@
ShapeCache.cpp \
SkiaColorFilter.cpp \
SkiaShader.cpp \
+ Snapshot.cpp \
TextureCache.cpp \
TextDropShadowCache.cpp
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index 71fb8da..7854729 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -38,8 +38,8 @@
#define LAYER_SIZE 64
// Defines the size in bits of the stencil buffer
-// Note: We only want 1 bit, but in practice we'll get 8 bits on all GPUs
-// for the foreseeable future
+// Note: Only 1 bit is required for clipping but more bits are required
+// to properly implement the winding fill rule when rasterizing paths
#define STENCIL_BUFFER_SIZE 0
/**
diff --git a/libs/hwui/Snapshot.cpp b/libs/hwui/Snapshot.cpp
new file mode 100644
index 0000000..a85362d
--- /dev/null
+++ b/libs/hwui/Snapshot.cpp
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Snapshot.h"
+
+#include <SkCanvas.h>
+
+namespace android {
+namespace uirenderer {
+
+///////////////////////////////////////////////////////////////////////////////
+// Constructors
+///////////////////////////////////////////////////////////////////////////////
+
+Snapshot::Snapshot(): flags(0), previous(NULL), layer(NULL), fbo(0),
+ invisible(false), empty(false) {
+
+ transform = &mTransformRoot;
+ clipRect = &mClipRectRoot;
+ region = NULL;
+}
+
+/**
+ * Copies the specified snapshot/ The specified snapshot is stored as
+ * the previous snapshot.
+ */
+Snapshot::Snapshot(const sp<Snapshot>& s, int saveFlags):
+ flags(0), previous(s), layer(NULL), fbo(s->fbo),
+ invisible(s->invisible), empty(false),
+ viewport(s->viewport), height(s->height) {
+
+ if (saveFlags & SkCanvas::kMatrix_SaveFlag) {
+ mTransformRoot.load(*s->transform);
+ transform = &mTransformRoot;
+ } else {
+ transform = s->transform;
+ }
+
+ if (saveFlags & SkCanvas::kClip_SaveFlag) {
+ mClipRectRoot.set(*s->clipRect);
+ clipRect = &mClipRectRoot;
+ } else {
+ clipRect = s->clipRect;
+ }
+
+ if (s->flags & Snapshot::kFlagFboTarget) {
+ flags |= Snapshot::kFlagFboTarget;
+ region = s->region;
+ } else {
+ region = NULL;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Clipping
+///////////////////////////////////////////////////////////////////////////////
+
+bool Snapshot::clip(float left, float top, float right, float bottom, SkRegion::Op op) {
+ Rect r(left, top, right, bottom);
+ transform->mapRect(r);
+ return clipTransformed(r, op);
+}
+
+bool Snapshot::clipTransformed(const Rect& r, SkRegion::Op op) {
+ bool clipped = false;
+
+ // NOTE: The unimplemented operations require support for regions
+ // Supporting regions would require using a stencil buffer instead
+ // of the scissor. The stencil buffer itself is not too expensive
+ // (memory cost excluded) but on fillrate limited devices, managing
+ // the stencil might have a negative impact on the framerate.
+ switch (op) {
+ case SkRegion::kDifference_Op:
+ break;
+ case SkRegion::kIntersect_Op:
+ clipped = clipRect->intersect(r);
+ if (!clipped) {
+ clipRect->setEmpty();
+ clipped = true;
+ }
+ break;
+ case SkRegion::kUnion_Op:
+ clipped = clipRect->unionWith(r);
+ break;
+ case SkRegion::kXOR_Op:
+ break;
+ case SkRegion::kReverseDifference_Op:
+ break;
+ case SkRegion::kReplace_Op:
+ clipRect->set(r);
+ clipped = true;
+ break;
+ }
+
+ if (clipped) {
+ flags |= Snapshot::kFlagClipSet;
+ }
+
+ return clipped;
+}
+
+void Snapshot::setClip(float left, float top, float right, float bottom) {
+ clipRect->set(left, top, right, bottom);
+ flags |= Snapshot::kFlagClipSet;
+}
+
+const Rect& Snapshot::getLocalClip() {
+ mat4 inverse;
+ inverse.loadInverse(*transform);
+
+ mLocalClip.set(*clipRect);
+ inverse.mapRect(mLocalClip);
+
+ return mLocalClip;
+}
+
+void Snapshot::resetClip(float left, float top, float right, float bottom) {
+ clipRect = &mClipRectRoot;
+ clipRect->set(left, top, right, bottom);
+ flags |= Snapshot::kFlagClipSet;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Transforms
+///////////////////////////////////////////////////////////////////////////////
+
+void Snapshot::resetTransform(float x, float y, float z) {
+ transform = &mTransformRoot;
+ transform->loadTranslate(x, y, z);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Queries
+///////////////////////////////////////////////////////////////////////////////
+
+bool Snapshot::isIgnored() const {
+ return invisible || empty;
+}
+
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/Snapshot.h b/libs/hwui/Snapshot.h
index aff7b93..c94af7e 100644
--- a/libs/hwui/Snapshot.h
+++ b/libs/hwui/Snapshot.h
@@ -23,7 +23,7 @@
#include <utils/RefBase.h>
#include <ui/Region.h>
-#include <SkCanvas.h>
+#include <SkRegion.h>
#include "Layer.h"
#include "Matrix.h"
@@ -43,43 +43,12 @@
*/
class Snapshot: public LightRefBase<Snapshot> {
public:
- Snapshot(): flags(0), previous(NULL), layer(NULL), fbo(0), invisible(false), empty(false) {
- transform = &mTransformRoot;
- clipRect = &mClipRectRoot;
- region = NULL;
- }
+
+ Snapshot();
+ Snapshot(const sp<Snapshot>& s, int saveFlags);
/**
- * Copies the specified snapshot/ The specified snapshot is stored as
- * the previous snapshot.
- */
- Snapshot(const sp<Snapshot>& s, int saveFlags):
- flags(0), previous(s), layer(NULL), fbo(s->fbo),
- invisible(s->invisible), empty(false), viewport(s->viewport), height(s->height) {
- if (saveFlags & SkCanvas::kMatrix_SaveFlag) {
- mTransformRoot.load(*s->transform);
- transform = &mTransformRoot;
- } else {
- transform = s->transform;
- }
-
- if (saveFlags & SkCanvas::kClip_SaveFlag) {
- mClipRectRoot.set(*s->clipRect);
- clipRect = &mClipRectRoot;
- } else {
- clipRect = s->clipRect;
- }
-
- if (s->flags & Snapshot::kFlagFboTarget) {
- flags |= Snapshot::kFlagFboTarget;
- region = s->region;
- } else {
- region = NULL;
- }
- }
-
- /**
- * Various flags set on #flags.
+ * Various flags set on ::flags.
*/
enum Flags {
/**
@@ -115,87 +84,41 @@
* by this snapshot's trasnformation.
*/
bool clip(float left, float top, float right, float bottom,
- SkRegion::Op op = SkRegion::kIntersect_Op) {
- Rect r(left, top, right, bottom);
- transform->mapRect(r);
- return clipTransformed(r, op);
- }
+ SkRegion::Op op = SkRegion::kIntersect_Op);
/**
* Modifies the current clip with the new clip rectangle and
* the specified operation. The specified rectangle is considered
* already transformed.
*/
- bool clipTransformed(const Rect& r, SkRegion::Op op = SkRegion::kIntersect_Op) {
- bool clipped = false;
-
- // NOTE: The unimplemented operations require support for regions
- // Supporting regions would require using a stencil buffer instead
- // of the scissor. The stencil buffer itself is not too expensive
- // (memory cost excluded) but on fillrate limited devices, managing
- // the stencil might have a negative impact on the framerate.
- switch (op) {
- case SkRegion::kDifference_Op:
- break;
- case SkRegion::kIntersect_Op:
- clipped = clipRect->intersect(r);
- if (!clipped) {
- clipRect->setEmpty();
- clipped = true;
- }
- break;
- case SkRegion::kUnion_Op:
- clipped = clipRect->unionWith(r);
- break;
- case SkRegion::kXOR_Op:
- break;
- case SkRegion::kReverseDifference_Op:
- break;
- case SkRegion::kReplace_Op:
- clipRect->set(r);
- clipped = true;
- break;
- }
-
- if (clipped) {
- flags |= Snapshot::kFlagClipSet;
- }
-
- return clipped;
- }
+ bool clipTransformed(const Rect& r, SkRegion::Op op = SkRegion::kIntersect_Op);
/**
* Sets the current clip.
*/
- void setClip(float left, float top, float right, float bottom) {
- clipRect->set(left, top, right, bottom);
- flags |= Snapshot::kFlagClipSet;
- }
+ void setClip(float left, float top, float right, float bottom);
- const Rect& getLocalClip() {
- mat4 inverse;
- inverse.loadInverse(*transform);
+ /**
+ * Returns the current clip in local coordinates. The clip rect is
+ * transformed by the inverse transform matrix.
+ */
+ const Rect& getLocalClip();
- mLocalClip.set(*clipRect);
- inverse.mapRect(mLocalClip);
+ /**
+ * Resets the clip to the specified rect.
+ */
+ void resetClip(float left, float top, float right, float bottom);
- return mLocalClip;
- }
+ /**
+ * Resets the current transform to a pure 3D translation.
+ */
+ void resetTransform(float x, float y, float z);
- void resetTransform(float x, float y, float z) {
- transform = &mTransformRoot;
- transform->loadTranslate(x, y, z);
- }
-
- void resetClip(float left, float top, float right, float bottom) {
- clipRect = &mClipRectRoot;
- clipRect->set(left, top, right, bottom);
- flags |= Snapshot::kFlagClipSet;
- }
-
- bool isIgnored() const {
- return invisible || empty;
- }
+ /**
+ * Indicates whether this snapshot should be ignored. A snapshot
+ * is typicalled ignored if its layer is invisible or empty.
+ */
+ bool isIgnored() const;
/**
* Dirty flags.
@@ -209,6 +132,8 @@
/**
* Only set when the flag kFlagIsLayer is set.
+ *
+ * This snapshot does not own the layer, this pointer must not be freed.
*/
Layer* layer;
@@ -249,17 +174,26 @@
/**
* Local transformation. Holds the current translation, scale and
* rotation values.
+ *
+ * This is a reference to a matrix owned by this snapshot or another
+ * snapshot. This pointer must not be freed. See ::mTransformRoot.
*/
mat4* transform;
/**
* Current clip region. The clip is stored in canvas-space coordinates,
* (screen-space coordinates in the regular case.)
+ *
+ * This is a reference to a rect owned by this snapshot or another
+ * snapshot. This pointer must not be freed. See ::mClipRectRoot.
*/
Rect* clipRect;
/**
* The ancestor layer's dirty region.
+ *
+ * This is a reference to a region owned by a layer. This pointer must
+ * not be freed.
*/
Region* region;
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index a720c0a..85d99c1 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -204,18 +204,24 @@
/** MPEG4 media file format*/
public static final int MPEG_4 = 2;
- /** The following formats are audio only .aac or .amr formats **/
- /** @deprecated Deprecated in favor of AMR_NB */
- /** Deprecated in favor of MediaRecorder.OutputFormat.AMR_NB */
- /** AMR NB file format */
+ /** The following formats are audio only .aac or .amr formats */
+
+ /**
+ * AMR NB file format
+ * @deprecated Deprecated in favor of MediaRecorder.OutputFormat.AMR_NB
+ */
public static final int RAW_AMR = 3;
+
/** AMR NB file format */
public static final int AMR_NB = 3;
+
/** AMR WB file format */
public static final int AMR_WB = 4;
+
/** @hide AAC ADIF file format */
public static final int AAC_ADIF = 5;
- /** @hide AAC ADTS file format */
+
+ /** AAC ADTS file format */
public static final int AAC_ADTS = 6;
/** @hide Stream over a socket, limited to a single stream */
diff --git a/packages/SystemUI/src/com/android/systemui/net/NetworkOverLimitActivity.java b/packages/SystemUI/src/com/android/systemui/net/NetworkOverLimitActivity.java
index 723e338..888b76e 100644
--- a/packages/SystemUI/src/com/android/systemui/net/NetworkOverLimitActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/net/NetworkOverLimitActivity.java
@@ -77,7 +77,7 @@
final INetworkPolicyManager policyService = INetworkPolicyManager.Stub.asInterface(
ServiceManager.getService(Context.NETWORK_POLICY_SERVICE));
try {
- policyService.snoozePolicy(template);
+ policyService.snoozeLimit(template);
} catch (RemoteException e) {
Slog.w(TAG, "problem snoozing network policy", e);
}
diff --git a/services/java/com/android/server/net/NetworkPolicyManagerService.java b/services/java/com/android/server/net/NetworkPolicyManagerService.java
index a71ccb5..5c9396f 100644
--- a/services/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -154,6 +154,7 @@
private static final int VERSION_ADDED_SNOOZE = 2;
private static final int VERSION_ADDED_RESTRICT_BACKGROUND = 3;
private static final int VERSION_ADDED_METERED = 4;
+ private static final int VERSION_SPLIT_SNOOZE = 5;
private static final long KB_IN_BYTES = 1024;
private static final long MB_IN_BYTES = KB_IN_BYTES * 1024;
@@ -176,6 +177,8 @@
private static final String ATTR_WARNING_BYTES = "warningBytes";
private static final String ATTR_LIMIT_BYTES = "limitBytes";
private static final String ATTR_LAST_SNOOZE = "lastSnooze";
+ private static final String ATTR_LAST_WARNING_SNOOZE = "lastWarningSnooze";
+ private static final String ATTR_LAST_LIMIT_SNOOZE = "lastLimitSnooze";
private static final String ATTR_METERED = "metered";
private static final String ATTR_UID = "uid";
private static final String ATTR_POLICY = "policy";
@@ -184,7 +187,9 @@
// @VisibleForTesting
public static final String ACTION_ALLOW_BACKGROUND =
- "com.android.server.action.ACTION_ALLOW_BACKGROUND";
+ "com.android.server.net.action.ALLOW_BACKGROUND";
+ public static final String ACTION_SNOOZE_WARNING =
+ "com.android.server.net.action.SNOOZE_WARNING";
private static final long TIME_CACHE_MAX_AGE = DAY_IN_MILLIS;
@@ -333,6 +338,11 @@
final IntentFilter allowFilter = new IntentFilter(ACTION_ALLOW_BACKGROUND);
mContext.registerReceiver(mAllowReceiver, allowFilter, MANAGE_NETWORK_POLICY, mHandler);
+ // listen for snooze warning from notifications
+ final IntentFilter snoozeWarningFilter = new IntentFilter(ACTION_SNOOZE_WARNING);
+ mContext.registerReceiver(mSnoozeWarningReceiver, snoozeWarningFilter,
+ MANAGE_NETWORK_POLICY, mHandler);
+
}
private IProcessObserver mProcessObserver = new IProcessObserver.Stub() {
@@ -418,6 +428,21 @@
};
/**
+ * Receiver that watches for {@link Notification} control of
+ * {@link NetworkPolicy#lastWarningSnooze}.
+ */
+ private BroadcastReceiver mSnoozeWarningReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ // on background handler thread, and verified MANAGE_NETWORK_POLICY
+ // permission above.
+
+ final NetworkTemplate template = intent.getParcelableExtra(EXTRA_NETWORK_TEMPLATE);
+ performSnooze(template, TYPE_WARNING);
+ }
+ };
+
+ /**
* Observer that watches for {@link INetworkManagementService} alerts.
*/
private INetworkManagementEventObserver mAlertObserver = new NetworkAlertObserver() {
@@ -458,7 +483,7 @@
final long totalBytes = getTotalBytes(policy.template, start, end);
if (policy.isOverLimit(totalBytes)) {
- if (policy.lastSnooze >= start) {
+ if (policy.lastLimitSnooze >= start) {
enqueueNotification(policy, TYPE_LIMIT_SNOOZED, totalBytes);
} else {
enqueueNotification(policy, TYPE_LIMIT, totalBytes);
@@ -468,7 +493,7 @@
} else {
notifyUnderLimitLocked(policy.template);
- if (policy.warningBytes != WARNING_DISABLED && totalBytes >= policy.warningBytes) {
+ if (policy.isOverWarning(totalBytes) && policy.lastWarningSnooze < start) {
enqueueNotification(policy, TYPE_WARNING, totalBytes);
}
}
@@ -534,7 +559,7 @@
final String tag = buildNotificationTag(policy, type);
final Notification.Builder builder = new Notification.Builder(mContext);
builder.setOnlyAlertOnce(true);
- builder.setOngoing(true);
+ builder.setWhen(0L);
final Resources res = mContext.getResources();
switch (type) {
@@ -547,9 +572,14 @@
builder.setContentTitle(title);
builder.setContentText(body);
- final Intent intent = buildViewDataUsageIntent(policy.template);
+ final Intent snoozeIntent = buildSnoozeWarningIntent(policy.template);
+ builder.setDeleteIntent(PendingIntent.getBroadcast(
+ mContext, 0, snoozeIntent, PendingIntent.FLAG_UPDATE_CURRENT));
+
+ final Intent viewIntent = buildViewDataUsageIntent(policy.template);
builder.setContentIntent(PendingIntent.getActivity(
- mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
+ mContext, 0, viewIntent, PendingIntent.FLAG_UPDATE_CURRENT));
+
break;
}
case TYPE_LIMIT: {
@@ -574,6 +604,7 @@
break;
}
+ builder.setOngoing(true);
builder.setSmallIcon(R.drawable.stat_notify_disabled);
builder.setTicker(title);
builder.setContentTitle(title);
@@ -608,6 +639,7 @@
break;
}
+ builder.setOngoing(true);
builder.setSmallIcon(R.drawable.stat_notify_error);
builder.setTicker(title);
builder.setContentTitle(title);
@@ -720,10 +752,11 @@
final long totalBytes = getTotalBytes(policy.template, start, end);
// disable data connection when over limit and not snoozed
- final boolean overLimit = policy.isOverLimit(totalBytes) && policy.lastSnooze < start;
- final boolean enabled = !overLimit;
+ final boolean overLimitWithoutSnooze = policy.isOverLimit(totalBytes)
+ && policy.lastLimitSnooze < start;
+ final boolean networkEnabled = !overLimitWithoutSnooze;
- setNetworkTemplateEnabled(policy.template, enabled);
+ setNetworkTemplateEnabled(policy.template, networkEnabled);
}
}
@@ -827,7 +860,7 @@
// metered network, but no policy limit; we still need to
// restrict apps, so push really high quota.
quotaBytes = Long.MAX_VALUE;
- } else if (policy.lastSnooze >= start) {
+ } else if (policy.lastLimitSnooze >= start) {
// snoozing past quota, but we still need to restrict apps,
// so push really high quota.
quotaBytes = Long.MAX_VALUE;
@@ -896,8 +929,8 @@
final int cycleDay = time.monthDay;
final NetworkTemplate template = buildTemplateMobileAll(subscriberId);
- mNetworkPolicy.put(template, new NetworkPolicy(
- template, cycleDay, warningBytes, LIMIT_DISABLED, SNOOZE_NEVER, true));
+ mNetworkPolicy.put(template, new NetworkPolicy(template, cycleDay, warningBytes,
+ LIMIT_DISABLED, SNOOZE_NEVER, SNOOZE_NEVER, true));
writePolicyLocked();
}
}
@@ -935,11 +968,13 @@
final int cycleDay = readIntAttribute(in, ATTR_CYCLE_DAY);
final long warningBytes = readLongAttribute(in, ATTR_WARNING_BYTES);
final long limitBytes = readLongAttribute(in, ATTR_LIMIT_BYTES);
- final long lastSnooze;
- if (version >= VERSION_ADDED_SNOOZE) {
- lastSnooze = readLongAttribute(in, ATTR_LAST_SNOOZE);
+ final long lastLimitSnooze;
+ if (version >= VERSION_SPLIT_SNOOZE) {
+ lastLimitSnooze = readLongAttribute(in, ATTR_LAST_LIMIT_SNOOZE);
+ } else if (version >= VERSION_ADDED_SNOOZE) {
+ lastLimitSnooze = readLongAttribute(in, ATTR_LAST_SNOOZE);
} else {
- lastSnooze = SNOOZE_NEVER;
+ lastLimitSnooze = SNOOZE_NEVER;
}
final boolean metered;
if (version >= VERSION_ADDED_METERED) {
@@ -955,11 +990,18 @@
metered = false;
}
}
+ final long lastWarningSnooze;
+ if (version >= VERSION_SPLIT_SNOOZE) {
+ lastWarningSnooze = readLongAttribute(in, ATTR_LAST_WARNING_SNOOZE);
+ } else {
+ lastWarningSnooze = SNOOZE_NEVER;
+ }
final NetworkTemplate template = new NetworkTemplate(
networkTemplate, subscriberId);
- mNetworkPolicy.put(template, new NetworkPolicy(
- template, cycleDay, warningBytes, limitBytes, lastSnooze, metered));
+ mNetworkPolicy.put(template, new NetworkPolicy(template, cycleDay,
+ warningBytes, limitBytes, lastWarningSnooze, lastLimitSnooze,
+ metered));
} else if (TAG_UID_POLICY.equals(tag)) {
final int uid = readIntAttribute(in, ATTR_UID);
@@ -1014,7 +1056,7 @@
out.startDocument(null, true);
out.startTag(null, TAG_POLICY_LIST);
- writeIntAttribute(out, ATTR_VERSION, VERSION_ADDED_METERED);
+ writeIntAttribute(out, ATTR_VERSION, VERSION_SPLIT_SNOOZE);
writeBooleanAttribute(out, ATTR_RESTRICT_BACKGROUND, mRestrictBackground);
// write all known network policies
@@ -1030,7 +1072,8 @@
writeIntAttribute(out, ATTR_CYCLE_DAY, policy.cycleDay);
writeLongAttribute(out, ATTR_WARNING_BYTES, policy.warningBytes);
writeLongAttribute(out, ATTR_LIMIT_BYTES, policy.limitBytes);
- writeLongAttribute(out, ATTR_LAST_SNOOZE, policy.lastSnooze);
+ writeLongAttribute(out, ATTR_LAST_WARNING_SNOOZE, policy.lastWarningSnooze);
+ writeLongAttribute(out, ATTR_LAST_LIMIT_SNOOZE, policy.lastLimitSnooze);
writeBooleanAttribute(out, ATTR_METERED, policy.metered);
out.endTag(null, TAG_NETWORK_POLICY);
}
@@ -1141,9 +1184,12 @@
}
@Override
- public void snoozePolicy(NetworkTemplate template) {
+ public void snoozeLimit(NetworkTemplate template) {
mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
+ performSnooze(template, TYPE_LIMIT);
+ }
+ private void performSnooze(NetworkTemplate template, int type) {
maybeRefreshTrustedTime();
final long currentTime = currentTimeMillis();
synchronized (mRulesLock) {
@@ -1153,7 +1199,16 @@
throw new IllegalArgumentException("unable to find policy for " + template);
}
- policy.lastSnooze = currentTime;
+ switch (type) {
+ case TYPE_WARNING:
+ policy.lastWarningSnooze = currentTime;
+ break;
+ case TYPE_LIMIT:
+ policy.lastLimitSnooze = currentTime;
+ break;
+ default:
+ throw new IllegalArgumentException("unexpected type");
+ }
updateNetworkEnabledLocked();
updateNetworkRulesLocked();
@@ -1246,12 +1301,17 @@
}
synchronized (mRulesLock) {
- if (argSet.contains("unsnooze")) {
+ if (argSet.contains("--unsnooze")) {
for (NetworkPolicy policy : mNetworkPolicy.values()) {
- policy.lastSnooze = SNOOZE_NEVER;
+ policy.clearSnooze();
}
+
+ updateNetworkEnabledLocked();
+ updateNetworkRulesLocked();
+ updateNotificationsLocked();
writePolicyLocked();
- fout.println("Wiped snooze timestamps");
+
+ fout.println("Cleared snooze timestamps");
return;
}
@@ -1599,6 +1659,12 @@
return new Intent(ACTION_ALLOW_BACKGROUND);
}
+ private static Intent buildSnoozeWarningIntent(NetworkTemplate template) {
+ final Intent intent = new Intent(ACTION_SNOOZE_WARNING);
+ intent.putExtra(EXTRA_NETWORK_TEMPLATE, template);
+ return intent;
+ }
+
private static Intent buildNetworkOverLimitIntent(NetworkTemplate template) {
final Intent intent = new Intent();
intent.setComponent(new ComponentName(
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index fc211e5..8b4c074 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -32,7 +32,6 @@
endif
ifeq ($(TARGET_BOARD_PLATFORM), omap4)
LOCAL_CFLAGS += -DHAS_CONTEXT_PRIORITY
- LOCAL_CFLAGS += -DUSE_TRIPLE_BUFFERING=1
endif
ifeq ($(TARGET_BOARD_PLATFORM), s5pc110)
LOCAL_CFLAGS += -DHAS_CONTEXT_PRIORITY -DNEVER_DEFAULT_TO_ASYNC_MODE
diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp b/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp
index f4afeea..09f1906 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp
+++ b/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007 The Android Open Source Project
+ * Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,7 +14,6 @@
* limitations under the License.
*/
-#include <assert.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
@@ -22,15 +21,6 @@
#include <unistd.h>
#include <fcntl.h>
-#include <signal.h>
-#include <termios.h>
-#include <sys/ioctl.h>
-#include <sys/mman.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/resource.h>
-
-#include <linux/unistd.h>
#include <utils/Log.h>
@@ -45,39 +35,30 @@
// ----------------------------------------------------------------------------
-DisplayHardwareBase::DisplayEventThreadBase::DisplayEventThreadBase(
+DisplayHardwareBase::DisplayEventThread::DisplayEventThread(
const sp<SurfaceFlinger>& flinger)
: Thread(false), mFlinger(flinger) {
}
-DisplayHardwareBase::DisplayEventThreadBase::~DisplayEventThreadBase() {
+DisplayHardwareBase::DisplayEventThread::~DisplayEventThread() {
}
-// ----------------------------------------------------------------------------
-
-DisplayHardwareBase::DisplayEventThread::DisplayEventThread(
- const sp<SurfaceFlinger>& flinger)
- : DisplayEventThreadBase(flinger)
-{
+void DisplayHardwareBase::DisplayEventThread::onFirstRef() {
+ if (initCheck() == NO_ERROR) {
+ run("DisplayEventThread", PRIORITY_URGENT_DISPLAY);
+ } else {
+ ALOGW("/sys/power/wait_for_fb_{wake|sleep} don't exist");
+ }
}
-DisplayHardwareBase::DisplayEventThread::~DisplayEventThread()
-{
+status_t DisplayHardwareBase::DisplayEventThread::initCheck() const {
+ return ((access(kSleepFileName, R_OK) == 0 &&
+ access(kWakeFileName, R_OK) == 0)) ? NO_ERROR : NO_INIT;
}
-bool DisplayHardwareBase::DisplayEventThread::threadLoop()
-{
- int err = 0;
- char buf;
- int fd;
+bool DisplayHardwareBase::DisplayEventThread::threadLoop() {
- fd = open(kSleepFileName, O_RDONLY, 0);
- do {
- err = read(fd, &buf, 1);
- } while (err < 0 && errno == EINTR);
- close(fd);
- ALOGW_IF(err<0, "ANDROID_WAIT_FOR_FB_SLEEP failed (%s)", strerror(errno));
- if (err >= 0) {
+ if (waitForFbSleep() == NO_ERROR) {
sp<SurfaceFlinger> flinger = mFlinger.promote();
ALOGD("About to give-up screen, flinger = %p", flinger.get());
if (flinger != 0) {
@@ -85,39 +66,51 @@
flinger->screenReleased(0);
mBarrier.wait();
}
+ if (waitForFbWake() == NO_ERROR) {
+ sp<SurfaceFlinger> flinger = mFlinger.promote();
+ ALOGD("Screen about to return, flinger = %p", flinger.get());
+ if (flinger != 0) {
+ flinger->screenAcquired(0);
+ }
+ return true;
+ }
}
- fd = open(kWakeFileName, O_RDONLY, 0);
+
+ // error, exit the thread
+ return false;
+}
+
+status_t DisplayHardwareBase::DisplayEventThread::waitForFbSleep() {
+ int err = 0;
+ char buf;
+ int fd = open(kSleepFileName, O_RDONLY, 0);
+ // if the file doesn't exist, the error will be caught in read() below
do {
- err = read(fd, &buf, 1);
+ err = read(fd, &buf, 1);
} while (err < 0 && errno == EINTR);
close(fd);
- ALOGW_IF(err<0, "ANDROID_WAIT_FOR_FB_WAKE failed (%s)", strerror(errno));
- if (err >= 0) {
- sp<SurfaceFlinger> flinger = mFlinger.promote();
- ALOGD("Screen about to return, flinger = %p", flinger.get());
- if (flinger != 0)
- flinger->screenAcquired(0);
- }
- return true;
+ ALOGE_IF(err<0, "*** ANDROID_WAIT_FOR_FB_SLEEP failed (%s)", strerror(errno));
+ return err < 0 ? -errno : int(NO_ERROR);
}
-status_t DisplayHardwareBase::DisplayEventThread::releaseScreen() const
-{
+status_t DisplayHardwareBase::DisplayEventThread::waitForFbWake() {
+ int err = 0;
+ char buf;
+ int fd = open(kWakeFileName, O_RDONLY, 0);
+ // if the file doesn't exist, the error will be caught in read() below
+ do {
+ err = read(fd, &buf, 1);
+ } while (err < 0 && errno == EINTR);
+ close(fd);
+ ALOGE_IF(err<0, "*** ANDROID_WAIT_FOR_FB_WAKE failed (%s)", strerror(errno));
+ return err < 0 ? -errno : int(NO_ERROR);
+}
+
+status_t DisplayHardwareBase::DisplayEventThread::releaseScreen() const {
mBarrier.open();
return NO_ERROR;
}
-status_t DisplayHardwareBase::DisplayEventThread::readyToRun()
-{
- return NO_ERROR;
-}
-
-status_t DisplayHardwareBase::DisplayEventThread::initCheck() const
-{
- return ((access(kSleepFileName, R_OK) == 0 &&
- access(kWakeFileName, R_OK) == 0)) ? NO_ERROR : NO_INIT;
-}
-
// ----------------------------------------------------------------------------
DisplayHardwareBase::DisplayHardwareBase(const sp<SurfaceFlinger>& flinger,
@@ -127,35 +120,27 @@
mDisplayEventThread = new DisplayEventThread(flinger);
}
-DisplayHardwareBase::~DisplayHardwareBase()
-{
+DisplayHardwareBase::~DisplayHardwareBase() {
// request exit
mDisplayEventThread->requestExitAndWait();
}
-bool DisplayHardwareBase::canDraw() const
-{
+bool DisplayHardwareBase::canDraw() const {
return mScreenAcquired;
}
-void DisplayHardwareBase::releaseScreen() const
-{
+void DisplayHardwareBase::releaseScreen() const {
status_t err = mDisplayEventThread->releaseScreen();
if (err >= 0) {
mScreenAcquired = false;
}
}
-void DisplayHardwareBase::acquireScreen() const
-{
- status_t err = mDisplayEventThread->acquireScreen();
- if (err >= 0) {
- mScreenAcquired = true;
- }
+void DisplayHardwareBase::acquireScreen() const {
+ mScreenAcquired = true;
}
-bool DisplayHardwareBase::isScreenAcquired() const
-{
+bool DisplayHardwareBase::isScreenAcquired() const {
return mScreenAcquired;
}
diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.h b/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.h
index ef2df43..91ea602 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.h
+++ b/services/surfaceflinger/DisplayHardware/DisplayHardwareBase.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007 The Android Open Source Project
+ * Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,8 +20,6 @@
#include <stdint.h>
#include <utils/RefBase.h>
#include <utils/threads.h>
-#include <linux/kd.h>
-#include <linux/vt.h>
#include "Barrier.h"
namespace android {
@@ -31,11 +29,11 @@
class DisplayHardwareBase
{
public:
- DisplayHardwareBase(
- const sp<SurfaceFlinger>& flinger,
- uint32_t displayIndex);
+ DisplayHardwareBase(
+ const sp<SurfaceFlinger>& flinger,
+ uint32_t displayIndex);
- ~DisplayHardwareBase();
+ ~DisplayHardwareBase();
// console management
void releaseScreen() const;
@@ -46,34 +44,22 @@
private:
- class DisplayEventThreadBase : public Thread {
- protected:
+ class DisplayEventThread : public Thread {
wp<SurfaceFlinger> mFlinger;
- public:
- DisplayEventThreadBase(const sp<SurfaceFlinger>& flinger);
- virtual ~DisplayEventThreadBase();
- virtual void onFirstRef() {
- run("DisplayEventThread", PRIORITY_URGENT_DISPLAY);
- }
- virtual status_t acquireScreen() const { return NO_ERROR; };
- virtual status_t releaseScreen() const { return NO_ERROR; };
- virtual status_t initCheck() const = 0;
- };
-
- class DisplayEventThread : public DisplayEventThreadBase
- {
mutable Barrier mBarrier;
+ status_t waitForFbSleep();
+ status_t waitForFbWake();
public:
- DisplayEventThread(const sp<SurfaceFlinger>& flinger);
+ DisplayEventThread(const sp<SurfaceFlinger>& flinger);
virtual ~DisplayEventThread();
+ virtual void onFirstRef();
virtual bool threadLoop();
- virtual status_t readyToRun();
- virtual status_t releaseScreen() const;
- virtual status_t initCheck() const;
+ status_t releaseScreen() const;
+ status_t initCheck() const;
};
- sp<DisplayEventThreadBase> mDisplayEventThread;
- mutable int mScreenAcquired;
+ sp<DisplayEventThread> mDisplayEventThread;
+ mutable int mScreenAcquired;
};
}; // namespace android
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 9c04d59..64f72d5 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -55,6 +55,7 @@
mCurrentTransform(0),
mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
mCurrentOpacity(true),
+ mRefreshPending(0),
mFrameLatencyNeeded(false),
mFrameLatencyOffset(0),
mFormat(PIXEL_FORMAT_NONE),
@@ -97,12 +98,7 @@
mSurfaceTexture = new SurfaceTextureLayer(mTextureName, this);
mSurfaceTexture->setFrameAvailableListener(new FrameQueuedListener(this));
mSurfaceTexture->setSynchronousMode(true);
-#ifdef USE_TRIPLE_BUFFERING
-#warning "using triple buffering"
- mSurfaceTexture->setBufferCountServer(3);
-#else
mSurfaceTexture->setBufferCountServer(2);
-#endif
}
Layer::~Layer()
@@ -113,7 +109,7 @@
void Layer::onFrameQueued() {
android_atomic_inc(&mQueuedFrames);
- mFlinger->signalEvent();
+ mFlinger->signalLayerUpdate();
}
// called with SurfaceFlinger::mStateLock as soon as the layer is entered
@@ -407,16 +403,37 @@
// pageflip handling...
// ----------------------------------------------------------------------------
+bool Layer::onPreComposition()
+{
+ // if there was more than one pending update, request a refresh
+ if (mRefreshPending >= 2) {
+ mRefreshPending = 0;
+ return true;
+ }
+ mRefreshPending = 0;
+ return false;
+}
+
void Layer::lockPageFlip(bool& recomputeVisibleRegions)
{
if (mQueuedFrames > 0) {
+
+ // if we've already called updateTexImage() without going through
+ // a composition step, we have to skip this layer at this point
+ // because we cannot call updateTeximage() without a corresponding
+ // compositionComplete() call.
+ // we'll trigger an update in onPreComposition().
+ if (mRefreshPending++) {
+ return;
+ }
+
// Capture the old state of the layer for comparisons later
const bool oldOpacity = isOpaque();
sp<GraphicBuffer> oldActiveBuffer = mActiveBuffer;
// signal another event if we have more frames pending
if (android_atomic_dec(&mQueuedFrames) > 1) {
- mFlinger->signalEvent();
+ mFlinger->signalLayerUpdate();
}
if (mSurfaceTexture->updateTexImage() < NO_ERROR) {
@@ -519,6 +536,10 @@
void Layer::unlockPageFlip(
const Transform& planeTransform, Region& outDirtyRegion)
{
+ if (mRefreshPending >= 2) {
+ return;
+ }
+
Region dirtyRegion(mPostedDirtyRegion);
if (!dirtyRegion.isEmpty()) {
mPostedDirtyRegion.clear();
@@ -552,9 +573,9 @@
snprintf(buffer, SIZE,
" "
"format=%2d, activeBuffer=[%4ux%4u:%4u,%3X],"
- " transform-hint=0x%02x, queued-frames=%d\n",
+ " transform-hint=0x%02x, queued-frames=%d, mRefreshPending=%d\n",
mFormat, w0, h0, s0,f0,
- getTransformHint(), mQueuedFrames);
+ getTransformHint(), mQueuedFrames, mRefreshPending);
result.append(buffer);
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 2dd4da1..bf30608 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -80,6 +80,7 @@
virtual wp<IBinder> getSurfaceTextureBinder() const;
virtual void onLayerDisplayed();
+ virtual bool onPreComposition();
// only for debugging
inline const sp<GraphicBuffer>& getActiveBuffer() const { return mActiveBuffer; }
@@ -115,14 +116,17 @@
uint32_t mCurrentTransform;
uint32_t mCurrentScalingMode;
bool mCurrentOpacity;
+ size_t mRefreshPending;
bool mFrameLatencyNeeded;
int mFrameLatencyOffset;
+
struct Statistics {
Statistics() : timestamp(0), set(0), vsync(0) { }
nsecs_t timestamp; // buffer timestamp
nsecs_t set; // buffer displayed timestamp
nsecs_t vsync; // vsync immediately before set
};
+
// protected by mLock
Statistics mFrameStats[128];
diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp
index d32fcdd..44aafdf 100644
--- a/services/surfaceflinger/LayerBase.cpp
+++ b/services/surfaceflinger/LayerBase.cpp
@@ -47,8 +47,7 @@
mOrientation(0),
mPlaneOrientation(0),
mTransactionFlags(0),
- mPremultipliedAlpha(true), mName("unnamed"), mDebug(false),
- mInvalidate(0)
+ mPremultipliedAlpha(true), mName("unnamed"), mDebug(false)
{
const DisplayHardware& hw(flinger->graphicPlane(0).displayHardware());
mFlags = hw.getFlags();
@@ -262,23 +261,11 @@
mTransformedBounds = tr.makeBounds(w, h);
}
-void LayerBase::lockPageFlip(bool& recomputeVisibleRegions)
-{
+void LayerBase::lockPageFlip(bool& recomputeVisibleRegions) {
}
void LayerBase::unlockPageFlip(
- const Transform& planeTransform, Region& outDirtyRegion)
-{
- if ((android_atomic_and(~1, &mInvalidate)&1) == 1) {
- outDirtyRegion.orSelf(visibleRegionScreen);
- }
-}
-
-void LayerBase::invalidate()
-{
- if ((android_atomic_or(1, &mInvalidate)&1) == 0) {
- mFlinger->signalEvent();
- }
+ const Transform& planeTransform, Region& outDirtyRegion) {
}
void LayerBase::drawRegion(const Region& reg) const
diff --git a/services/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h
index 6b62c9d..b8f7680 100644
--- a/services/surfaceflinger/LayerBase.h
+++ b/services/surfaceflinger/LayerBase.h
@@ -103,8 +103,6 @@
Rect visibleBounds() const;
void drawRegion(const Region& reg) const;
- void invalidate();
-
virtual sp<LayerBaseClient> getLayerBaseClient() const { return 0; }
virtual sp<Layer> getLayer() const { return 0; }
@@ -204,9 +202,16 @@
/** called with the state lock when the surface is removed from the
* current list */
- virtual void onRemoved() { };
+ virtual void onRemoved() { }
- virtual void onLayerDisplayed() { };
+ /** called after page-flip
+ */
+ virtual void onLayerDisplayed() { }
+
+ /** called before composition.
+ * returns true if the layer has pending updates.
+ */
+ virtual bool onPreComposition() { return false; }
/** always call base class first */
virtual void dump(String8& result, char* scratch, size_t size) const;
@@ -275,10 +280,6 @@
mutable bool mDebug;
- // atomic
- volatile int32_t mInvalidate;
-
-
public:
// called from class SurfaceFlinger
virtual ~LayerBase();
diff --git a/services/surfaceflinger/MessageQueue.cpp b/services/surfaceflinger/MessageQueue.cpp
index 70711e7..1ff3567 100644
--- a/services/surfaceflinger/MessageQueue.cpp
+++ b/services/surfaceflinger/MessageQueue.cpp
@@ -29,6 +29,7 @@
#include "MessageQueue.h"
#include "EventThread.h"
+#include "SurfaceFlinger.h"
namespace android {
@@ -48,14 +49,47 @@
// ---------------------------------------------------------------------------
+void MessageQueue::Handler::signalRefresh() {
+ if ((android_atomic_or(eventMaskRefresh, &mEventMask) & eventMaskRefresh) == 0) {
+ mQueue.mLooper->sendMessage(this, Message(MessageQueue::REFRESH));
+ }
+}
+
+void MessageQueue::Handler::signalInvalidate() {
+ if ((android_atomic_or(eventMaskInvalidate, &mEventMask) & eventMaskInvalidate) == 0) {
+ mQueue.mLooper->sendMessage(this, Message(MessageQueue::INVALIDATE));
+ }
+}
+
+void MessageQueue::Handler::handleMessage(const Message& message) {
+ switch (message.what) {
+ case INVALIDATE:
+ android_atomic_and(~eventMaskInvalidate, &mEventMask);
+ mQueue.mFlinger->onMessageReceived(message.what);
+ break;
+ case REFRESH:
+ android_atomic_and(~eventMaskRefresh, &mEventMask);
+ mQueue.mFlinger->onMessageReceived(message.what);
+ break;
+ }
+}
+
+// ---------------------------------------------------------------------------
+
MessageQueue::MessageQueue()
- : mLooper(new Looper(true)), mWorkPending(0)
{
}
MessageQueue::~MessageQueue() {
}
+void MessageQueue::init(const sp<SurfaceFlinger>& flinger)
+{
+ mFlinger = flinger;
+ mLooper = new Looper(true);
+ mHandler = new Handler(*this);
+}
+
void MessageQueue::setEventThread(const sp<EventThread>& eventThread)
{
mEventThread = eventThread;
@@ -68,25 +102,16 @@
void MessageQueue::waitMessage() {
do {
IPCThreadState::self()->flushCommands();
-
int32_t ret = mLooper->pollOnce(-1);
switch (ret) {
case ALOOPER_POLL_WAKE:
case ALOOPER_POLL_CALLBACK:
- // callback and/or wake
- if (android_atomic_and(0, &mWorkPending)) {
- return;
- }
continue;
-
+ case ALOOPER_POLL_ERROR:
+ ALOGE("ALOOPER_POLL_ERROR");
case ALOOPER_POLL_TIMEOUT:
// timeout (should not happen)
continue;
-
- case ALOOPER_POLL_ERROR:
- ALOGE("ALOOPER_POLL_ERROR");
- continue;
-
default:
// should not happen
ALOGE("Looper::pollOnce() returned unknown status %d", ret);
@@ -107,15 +132,12 @@
return NO_ERROR;
}
-void MessageQueue::scheduleWorkASAP() {
- if (android_atomic_or(1, &mWorkPending) == 0) {
- mLooper->wake();
- }
+void MessageQueue::invalidate() {
+ mHandler->signalInvalidate();
}
-status_t MessageQueue::invalidate() {
+void MessageQueue::refresh() {
mEvents->requestNextVsync();
- return NO_ERROR;
}
int MessageQueue::cb_eventReceiver(int fd, int events, void* data) {
@@ -126,10 +148,10 @@
int MessageQueue::eventReceiver(int fd, int events) {
ssize_t n;
DisplayEventReceiver::Event buffer[8];
- while ((n = getEvents(buffer, 8)) > 0) {
+ while ((n = DisplayEventReceiver::getEvents(mEventTube, buffer, 8)) > 0) {
for (int i=0 ; i<n ; i++) {
if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
- scheduleWorkASAP();
+ mHandler->signalRefresh();
break;
}
}
@@ -137,24 +159,6 @@
return 1;
}
-ssize_t MessageQueue::getEvents(
- DisplayEventReceiver::Event* events, size_t count)
-{
- ssize_t size = mEventTube->read(events, sizeof(events[0])*count);
- ALOGE_IF(size<0, "MessageQueue::getEvents error (%s)", strerror(-size));
- if (size >= 0) {
- // Note: if (size % sizeof(events[0])) != 0, we've got a
- // partial read. This can happen if the queue filed up (ie: if we
- // didn't pull from it fast enough).
- // We discard the partial event and rely on the sender to
- // re-send the event if appropriate (some events, like VSYNC
- // can be lost forever).
- // returns number of events read
- size /= sizeof(events[0]);
- }
- return size;
-}
-
// ---------------------------------------------------------------------------
}; // namespace android
diff --git a/services/surfaceflinger/MessageQueue.h b/services/surfaceflinger/MessageQueue.h
index 5ea197d..ea29e7e 100644
--- a/services/surfaceflinger/MessageQueue.h
+++ b/services/surfaceflinger/MessageQueue.h
@@ -33,6 +33,7 @@
class IDisplayEventConnection;
class EventThread;
+class SurfaceFlinger;
// ---------------------------------------------------------------------------
@@ -59,25 +60,48 @@
// ---------------------------------------------------------------------------
class MessageQueue {
+ class Handler : public MessageHandler {
+ enum {
+ eventMaskInvalidate = 0x1,
+ eventMaskRefresh = 0x2
+ };
+ MessageQueue& mQueue;
+ int32_t mEventMask;
+ public:
+ Handler(MessageQueue& queue) : mQueue(queue), mEventMask(0) { }
+ virtual void handleMessage(const Message& message);
+ void signalRefresh();
+ void signalInvalidate();
+ };
+
+ friend class Handler;
+
+ sp<SurfaceFlinger> mFlinger;
sp<Looper> mLooper;
sp<EventThread> mEventThread;
sp<IDisplayEventConnection> mEvents;
sp<BitTube> mEventTube;
- int32_t mWorkPending;
+ sp<Handler> mHandler;
+
static int cb_eventReceiver(int fd, int events, void* data);
int eventReceiver(int fd, int events);
- ssize_t getEvents(DisplayEventReceiver::Event* events, size_t count);
- void scheduleWorkASAP();
public:
+ enum {
+ INVALIDATE = 0,
+ REFRESH = 1,
+ };
+
MessageQueue();
~MessageQueue();
+ void init(const sp<SurfaceFlinger>& flinger);
void setEventThread(const sp<EventThread>& events);
void waitMessage();
status_t postMessage(const sp<MessageBase>& message, nsecs_t reltime=0);
- status_t invalidate();
+ void invalidate();
+ void refresh();
};
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index ff70ec3..870235b 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -125,11 +125,34 @@
ALOGI_IF(mDebugDDMS, "DDMS debugging enabled");
}
+void SurfaceFlinger::onFirstRef()
+{
+ mEventQueue.init(this);
+
+ run("SurfaceFlinger", PRIORITY_URGENT_DISPLAY);
+
+ // Wait for the main thread to be done with its initialization
+ mReadyToRunBarrier.wait();
+}
+
+
SurfaceFlinger::~SurfaceFlinger()
{
glDeleteTextures(1, &mWormholeTexName);
}
+void SurfaceFlinger::binderDied(const wp<IBinder>& who)
+{
+ // the window manager died on us. prepare its eulogy.
+
+ // reset screen orientation
+ Vector<ComposerState> state;
+ setTransactionState(state, eOrientationDefault, 0);
+
+ // restart the boot-animation
+ property_set("ctl.start", "bootanim");
+}
+
sp<IMemoryHeap> SurfaceFlinger::getCblk() const
{
return mServerHeap;
@@ -183,26 +206,6 @@
property_set("ctl.stop", "bootanim");
}
-void SurfaceFlinger::binderDied(const wp<IBinder>& who)
-{
- // the window manager died on us. prepare its eulogy.
-
- // reset screen orientation
- Vector<ComposerState> state;
- setTransactionState(state, eOrientationDefault, 0);
-
- // restart the boot-animation
- property_set("ctl.start", "bootanim");
-}
-
-void SurfaceFlinger::onFirstRef()
-{
- run("SurfaceFlinger", PRIORITY_URGENT_DISPLAY);
-
- // Wait for the main thread to be done with its initialization
- mReadyToRunBarrier.wait();
-}
-
static inline uint16_t pack565(int r, int g, int b) {
return (r<<11)|(g<<5)|b;
}
@@ -311,34 +314,6 @@
}
// ----------------------------------------------------------------------------
-#if 0
-#pragma mark -
-#pragma mark Events Handler
-#endif
-
-void SurfaceFlinger::waitForEvent() {
- mEventQueue.waitMessage();
-}
-
-void SurfaceFlinger::signalEvent() {
- mEventQueue.invalidate();
-}
-
-status_t SurfaceFlinger::postMessageAsync(const sp<MessageBase>& msg,
- nsecs_t reltime, uint32_t flags) {
- return mEventQueue.postMessage(msg, reltime);
-}
-
-status_t SurfaceFlinger::postMessageSync(const sp<MessageBase>& msg,
- nsecs_t reltime, uint32_t flags) {
- status_t res = mEventQueue.postMessage(msg, reltime);
- if (res == NO_ERROR) {
- msg->wait();
- }
- return res;
-}
-
-// ----------------------------------------------------------------------------
bool SurfaceFlinger::authenticateSurfaceTexture(
const sp<ISurfaceTexture>& surfaceTexture) const {
@@ -388,54 +363,93 @@
}
// ----------------------------------------------------------------------------
-#if 0
-#pragma mark -
-#pragma mark Main loop
-#endif
+
+void SurfaceFlinger::waitForEvent() {
+ mEventQueue.waitMessage();
+}
+
+void SurfaceFlinger::signalTransaction() {
+ mEventQueue.invalidate();
+}
+
+void SurfaceFlinger::signalLayerUpdate() {
+ mEventQueue.invalidate();
+}
+
+void SurfaceFlinger::signalRefresh() {
+ mEventQueue.refresh();
+}
+
+status_t SurfaceFlinger::postMessageAsync(const sp<MessageBase>& msg,
+ nsecs_t reltime, uint32_t flags) {
+ return mEventQueue.postMessage(msg, reltime);
+}
+
+status_t SurfaceFlinger::postMessageSync(const sp<MessageBase>& msg,
+ nsecs_t reltime, uint32_t flags) {
+ status_t res = mEventQueue.postMessage(msg, reltime);
+ if (res == NO_ERROR) {
+ msg->wait();
+ }
+ return res;
+}
bool SurfaceFlinger::threadLoop()
{
waitForEvent();
-
- // check for transactions
- if (CC_UNLIKELY(mConsoleSignals)) {
- handleConsoleEvents();
- }
-
- // if we're in a global transaction, don't do anything.
- const uint32_t mask = eTransactionNeeded | eTraversalNeeded;
- uint32_t transactionFlags = peekTransactionFlags(mask);
- if (CC_UNLIKELY(transactionFlags)) {
- handleTransaction(transactionFlags);
- }
-
- // post surfaces (if needed)
- handlePageFlip();
-
- if (mDirtyRegion.isEmpty()) {
- // nothing new to do.
- return true;
- }
-
- if (CC_UNLIKELY(mHwWorkListDirty)) {
- // build the h/w work list
- handleWorkList();
- }
-
- const DisplayHardware& hw(graphicPlane(0).displayHardware());
- if (CC_LIKELY(hw.canDraw())) {
- // repaint the framebuffer (if needed)
- handleRepaint();
- // inform the h/w that we're done compositing
- hw.compositionComplete();
- postFramebuffer();
- } else {
- // pretend we did the post
- hw.compositionComplete();
- }
return true;
}
+void SurfaceFlinger::onMessageReceived(int32_t what)
+{
+ switch (what) {
+ case MessageQueue::INVALIDATE: {
+ // check for transactions
+ if (CC_UNLIKELY(mConsoleSignals)) {
+ handleConsoleEvents();
+ }
+
+ // if we're in a global transaction, don't do anything.
+ const uint32_t mask = eTransactionNeeded | eTraversalNeeded;
+ uint32_t transactionFlags = peekTransactionFlags(mask);
+ if (CC_UNLIKELY(transactionFlags)) {
+ handleTransaction(transactionFlags);
+ }
+
+ // post surfaces (if needed)
+ handlePageFlip();
+
+ if (!mDirtyRegion.isEmpty()) {
+ signalRefresh();
+ }
+ } break;
+
+ case MessageQueue::REFRESH: {
+ if (!mDirtyRegion.isEmpty()) {
+ // NOTE: it is mandatory to call hw.compositionComplete()
+ // after handleRefresh()
+ handleRefresh();
+
+ const DisplayHardware& hw(graphicPlane(0).displayHardware());
+ if (CC_UNLIKELY(mHwWorkListDirty)) {
+ // build the h/w work list
+ handleWorkList();
+ }
+ if (CC_LIKELY(hw.canDraw())) {
+ // repaint the framebuffer (if needed)
+ handleRepaint();
+ // inform the h/w that we're done compositing
+ hw.compositionComplete();
+ postFramebuffer();
+ } else {
+ // pretend we did the post
+ hw.compositionComplete();
+ }
+ }
+ } break;
+ }
+}
+
void SurfaceFlinger::postFramebuffer()
{
// this should never happen. we do the flip anyways so we don't
@@ -717,13 +731,13 @@
void SurfaceFlinger::handlePageFlip()
{
- bool visibleRegions = mVisibleRegionsDirty;
- const LayerVector& currentLayers(mDrawingState.layersSortedByZ);
- visibleRegions |= lockPageFlip(currentLayers);
+ const DisplayHardware& hw = graphicPlane(0).displayHardware();
+ const Region screenRegion(hw.bounds());
- const DisplayHardware& hw = graphicPlane(0).displayHardware();
- const Region screenRegion(hw.bounds());
- if (visibleRegions) {
+ const LayerVector& currentLayers(mDrawingState.layersSortedByZ);
+ const bool visibleRegions = lockPageFlip(currentLayers);
+
+ if (visibleRegions || mVisibleRegionsDirty) {
Region opaqueRegion;
computeVisibleRegions(currentLayers, mDirtyRegion, opaqueRegion);
@@ -770,7 +784,7 @@
{
const GraphicPlane& plane(graphicPlane(0));
const Transform& planeTransform(plane.transform());
- size_t count = currentLayers.size();
+ const size_t count = currentLayers.size();
sp<LayerBase> const* layers = currentLayers.array();
for (size_t i=0 ; i<count ; i++) {
const sp<LayerBase>& layer(layers[i]);
@@ -778,6 +792,23 @@
}
}
+void SurfaceFlinger::handleRefresh()
+{
+ bool needInvalidate = false;
+ const LayerVector& currentLayers(mDrawingState.layersSortedByZ);
+ const size_t count = currentLayers.size();
+ for (size_t i=0 ; i<count ; i++) {
+ const sp<LayerBase>& layer(currentLayers[i]);
+ if (layer->onPreComposition()) {
+ needInvalidate = true;
+ }
+ }
+ if (needInvalidate) {
+ signalLayerUpdate();
+ }
+}
+
+
void SurfaceFlinger::handleWorkList()
{
mHwWorkListDirty = false;
@@ -1175,7 +1206,7 @@
{
uint32_t old = android_atomic_or(flags, &mTransactionFlags);
if ((old & flags)==0) { // wake the server up
- signalEvent();
+ signalTransaction();
}
return old;
}
@@ -1426,14 +1457,14 @@
{
// this may be called by a signal handler, we can't do too much in here
android_atomic_or(eConsoleReleased, &mConsoleSignals);
- signalEvent();
+ signalTransaction();
}
void SurfaceFlinger::screenAcquired(int dpy)
{
// this may be called by a signal handler, we can't do too much in here
android_atomic_or(eConsoleAcquired, &mConsoleSignals);
- signalEvent();
+ signalTransaction();
}
status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args)
@@ -1769,7 +1800,7 @@
const DisplayHardware& hw(graphicPlane(0).displayHardware());
const Rect bounds(hw.getBounds());
setInvalidateRegion(Region(bounds));
- signalEvent();
+ signalTransaction();
}
void SurfaceFlinger::setInvalidateRegion(const Region& reg) {
@@ -2245,7 +2276,7 @@
// make sure to redraw the whole screen when the animation is done
mDirtyRegion.set(hw.bounds());
- signalEvent();
+ signalTransaction();
return NO_ERROR;
}
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index c24a9de..fcd9361 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -190,6 +190,8 @@
status_t renderScreenToTextureLocked(DisplayID dpy,
GLuint* textureName, GLfloat* uOut, GLfloat* vOut);
+ void onMessageReceived(int32_t what);
+
status_t postMessageAsync(const sp<MessageBase>& msg,
nsecs_t reltime=0, uint32_t flags = 0);
@@ -283,7 +285,10 @@
public: // hack to work around gcc 4.0.3 bug
const GraphicPlane& graphicPlane(int dpy) const;
GraphicPlane& graphicPlane(int dpy);
- void signalEvent();
+
+ void signalTransaction();
+ void signalLayerUpdate();
+ void signalRefresh();
void repaintEverything();
private:
@@ -300,6 +305,7 @@
void handlePageFlip();
bool lockPageFlip(const LayerVector& currentLayers);
void unlockPageFlip(const LayerVector& currentLayers);
+ void handleRefresh();
void handleWorkList();
void handleRepaint();
void postFramebuffer();
diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
index 36a2567..2bf8b1c 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
@@ -21,7 +21,6 @@
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE;
import static android.net.ConnectivityManager.TYPE_WIFI;
import static android.net.NetworkPolicy.LIMIT_DISABLED;
-import static android.net.NetworkPolicy.SNOOZE_NEVER;
import static android.net.NetworkPolicy.WARNING_DISABLED;
import static android.net.NetworkPolicyManager.POLICY_NONE;
import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
@@ -256,41 +255,49 @@
}
public void testPidForegroundCombined() throws Exception {
+ IdleFuture idle;
+
// push all uid into background
+ idle = expectIdle();
mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, false);
mProcessObserver.onForegroundActivitiesChanged(PID_3, UID_B, false);
- waitUntilIdle();
+ idle.get();
assertFalse(mService.isUidForeground(UID_A));
assertFalse(mService.isUidForeground(UID_B));
// push one of the shared pids into foreground
+ idle = expectIdle();
mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, true);
- waitUntilIdle();
+ idle.get();
assertTrue(mService.isUidForeground(UID_A));
assertFalse(mService.isUidForeground(UID_B));
// and swap another uid into foreground
+ idle = expectIdle();
mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, false);
mProcessObserver.onForegroundActivitiesChanged(PID_3, UID_B, true);
- waitUntilIdle();
+ idle.get();
assertFalse(mService.isUidForeground(UID_A));
assertTrue(mService.isUidForeground(UID_B));
// push both pid into foreground
+ idle = expectIdle();
mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, true);
- waitUntilIdle();
+ idle.get();
assertTrue(mService.isUidForeground(UID_A));
// pull one out, should still be foreground
+ idle = expectIdle();
mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
- waitUntilIdle();
+ idle.get();
assertTrue(mService.isUidForeground(UID_A));
// pull final pid out, should now be background
+ idle = expectIdle();
mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, false);
- waitUntilIdle();
+ idle.get();
assertFalse(mService.isUidForeground(UID_A));
}
@@ -434,7 +441,7 @@
final long expectedCycle = parseTime("2007-11-05T00:00:00.000Z");
final NetworkPolicy policy = new NetworkPolicy(
- sTemplateWifi, 5, 1024L, 1024L, SNOOZE_NEVER, false);
+ sTemplateWifi, 5, 1024L, 1024L, false);
final long actualCycle = computeLastCycleBoundary(currentTime, policy);
assertTimeEquals(expectedCycle, actualCycle);
}
@@ -445,7 +452,7 @@
final long expectedCycle = parseTime("2007-10-20T00:00:00.000Z");
final NetworkPolicy policy = new NetworkPolicy(
- sTemplateWifi, 20, 1024L, 1024L, SNOOZE_NEVER, false);
+ sTemplateWifi, 20, 1024L, 1024L, false);
final long actualCycle = computeLastCycleBoundary(currentTime, policy);
assertTimeEquals(expectedCycle, actualCycle);
}
@@ -456,7 +463,7 @@
final long expectedCycle = parseTime("2007-01-30T00:00:00.000Z");
final NetworkPolicy policy = new NetworkPolicy(
- sTemplateWifi, 30, 1024L, 1024L, SNOOZE_NEVER, false);
+ sTemplateWifi, 30, 1024L, 1024L, false);
final long actualCycle = computeLastCycleBoundary(currentTime, policy);
assertTimeEquals(expectedCycle, actualCycle);
}
@@ -467,14 +474,14 @@
final long expectedCycle = parseTime("2007-02-28T23:59:59.000Z");
final NetworkPolicy policy = new NetworkPolicy(
- sTemplateWifi, 30, 1024L, 1024L, SNOOZE_NEVER, false);
+ sTemplateWifi, 30, 1024L, 1024L, false);
final long actualCycle = computeLastCycleBoundary(currentTime, policy);
assertTimeEquals(expectedCycle, actualCycle);
}
public void testNextCycleSane() throws Exception {
final NetworkPolicy policy = new NetworkPolicy(
- sTemplateWifi, 31, WARNING_DISABLED, LIMIT_DISABLED, SNOOZE_NEVER, false);
+ sTemplateWifi, 31, WARNING_DISABLED, LIMIT_DISABLED, false);
final LinkedHashSet<Long> seen = new LinkedHashSet<Long>();
// walk forwards, ensuring that cycle boundaries don't get stuck
@@ -489,7 +496,7 @@
public void testLastCycleSane() throws Exception {
final NetworkPolicy policy = new NetworkPolicy(
- sTemplateWifi, 31, WARNING_DISABLED, LIMIT_DISABLED, SNOOZE_NEVER, false);
+ sTemplateWifi, 31, WARNING_DISABLED, LIMIT_DISABLED, false);
final LinkedHashSet<Long> seen = new LinkedHashSet<Long>();
// walk backwards, ensuring that cycle boundaries look sane
@@ -547,7 +554,7 @@
replay();
setNetworkPolicies(new NetworkPolicy(
- sTemplateWifi, CYCLE_DAY, 1 * MB_IN_BYTES, 2 * MB_IN_BYTES, SNOOZE_NEVER, false));
+ sTemplateWifi, CYCLE_DAY, 1 * MB_IN_BYTES, 2 * MB_IN_BYTES, false));
future.get();
verifyAndReset();
}
@@ -604,9 +611,8 @@
future = expectMeteredIfacesChanged();
replay();
- setNetworkPolicies(
- new NetworkPolicy(sTemplateWifi, CYCLE_DAY, 1 * MB_IN_BYTES, 2 * MB_IN_BYTES,
- SNOOZE_NEVER, false));
+ setNetworkPolicies(new NetworkPolicy(sTemplateWifi, CYCLE_DAY, 1 * MB_IN_BYTES,
+ 2 * MB_IN_BYTES, false));
future.get();
verifyAndReset();
}
@@ -698,7 +704,7 @@
tagFuture = expectEnqueueNotification();
replay();
- mService.snoozePolicy(sTemplateWifi);
+ mService.snoozeLimit(sTemplateWifi);
assertNotificationType(TYPE_LIMIT_SNOOZED, tagFuture.get());
future.get();
verifyAndReset();
@@ -736,9 +742,8 @@
future = expectMeteredIfacesChanged(TEST_IFACE);
replay();
- setNetworkPolicies(
- new NetworkPolicy(sTemplateWifi, CYCLE_DAY, WARNING_DISABLED, LIMIT_DISABLED,
- SNOOZE_NEVER, true));
+ setNetworkPolicies(new NetworkPolicy(sTemplateWifi, CYCLE_DAY, WARNING_DISABLED,
+ LIMIT_DISABLED, true));
future.get();
verifyAndReset();
}
@@ -890,10 +895,10 @@
/**
* Wait until {@link #mService} internal {@link Handler} is idle.
*/
- private void waitUntilIdle() throws Exception {
+ private IdleFuture expectIdle() {
final IdleFuture future = new IdleFuture();
mService.addIdleHandler(future);
- future.get();
+ return future;
}
private static void assertTimeEquals(long expected, long actual) {
diff --git a/telephony/java/com/android/internal/telephony/CommandsInterface.java b/telephony/java/com/android/internal/telephony/CommandsInterface.java
index 7900a9d..a0efab2 100644
--- a/telephony/java/com/android/internal/telephony/CommandsInterface.java
+++ b/telephony/java/com/android/internal/telephony/CommandsInterface.java
@@ -759,6 +759,15 @@
* retMsg.obj = AsyncResult ar
* ar.exception carries exception on failure
* ar.userObject contains the orignal value of result.obj
+ * ar.result is String containing IMSI on success
+ */
+ void getIMSIForApp(String aid, Message result);
+
+ /**
+ * returned message
+ * retMsg.obj = AsyncResult ar
+ * ar.exception carries exception on failure
+ * ar.userObject contains the orignal value of result.obj
* ar.result is String containing IMEI on success
*/
void getIMEI(Message result);
@@ -1050,6 +1059,14 @@
String data, String pin2, Message response);
/**
+ * parameters equivalent to 27.007 AT+CRSM command
+ * response.obj will be an AsyncResult
+ * response.obj.userObj will be a IccIoResult on success
+ */
+ void iccIOForApp (int command, int fileid, String path, int p1, int p2, int p3,
+ String data, String pin2, String aid, Message response);
+
+ /**
* (AsyncResult)response.obj).result is an int[] with element [0] set to
* 1 for "CLIP is provisioned", and 0 for "CLIP is not provisioned".
*
diff --git a/telephony/java/com/android/internal/telephony/IccCardStatus.java b/telephony/java/com/android/internal/telephony/IccCardStatus.java
index c751a21..a3bdd76 100644
--- a/telephony/java/com/android/internal/telephony/IccCardStatus.java
+++ b/telephony/java/com/android/internal/telephony/IccCardStatus.java
@@ -24,7 +24,7 @@
* {@hide}
*/
public class IccCardStatus {
- static final int CARD_MAX_APPS = 8;
+ public static final int CARD_MAX_APPS = 8;
public enum CardState {
CARDSTATE_ABSENT,
diff --git a/telephony/java/com/android/internal/telephony/IccFileHandler.java b/telephony/java/com/android/internal/telephony/IccFileHandler.java
index 93b9b79..380bfd1 100644
--- a/telephony/java/com/android/internal/telephony/IccFileHandler.java
+++ b/telephony/java/com/android/internal/telephony/IccFileHandler.java
@@ -145,8 +145,9 @@
= obtainMessage(EVENT_GET_RECORD_SIZE_DONE,
new LoadLinearFixedContext(fileid, recordNum, onLoaded));
- phone.mCM.iccIO(COMMAND_GET_RESPONSE, fileid, getEFPath(fileid),
- 0, 0, GET_RESPONSE_EF_SIZE_BYTES, null, null, response);
+ phone.mCM.iccIOForApp(COMMAND_GET_RESPONSE, fileid, getEFPath(fileid),
+ 0, 0, GET_RESPONSE_EF_SIZE_BYTES, null, null,
+ phone.getIccCard().getAid(), response);
}
/**
@@ -164,9 +165,10 @@
onLoaded));
// TODO(): Verify when path changes are done.
- phone.mCM.iccIO(COMMAND_GET_RESPONSE, IccConstants.EF_IMG, "img",
+ phone.mCM.iccIOForApp(COMMAND_GET_RESPONSE, IccConstants.EF_IMG, "img",
recordNum, READ_RECORD_MODE_ABSOLUTE,
- GET_RESPONSE_EF_IMG_SIZE_BYTES, null, null, response);
+ GET_RESPONSE_EF_IMG_SIZE_BYTES, null, null,
+ phone.getIccCard().getAid(), response);
}
/**
@@ -182,8 +184,9 @@
Message response
= obtainMessage(EVENT_GET_EF_LINEAR_RECORD_SIZE_DONE,
new LoadLinearFixedContext(fileid, onLoaded));
- phone.mCM.iccIO(COMMAND_GET_RESPONSE, fileid, getEFPath(fileid),
- 0, 0, GET_RESPONSE_EF_SIZE_BYTES, null, null, response);
+ phone.mCM.iccIOForApp(COMMAND_GET_RESPONSE, fileid, getEFPath(fileid),
+ 0, 0, GET_RESPONSE_EF_SIZE_BYTES, null, null, phone.getIccCard().getAid(),
+ response);
}
/**
@@ -199,8 +202,9 @@
Message response = obtainMessage(EVENT_GET_RECORD_SIZE_DONE,
new LoadLinearFixedContext(fileid,onLoaded));
- phone.mCM.iccIO(COMMAND_GET_RESPONSE, fileid, getEFPath(fileid),
- 0, 0, GET_RESPONSE_EF_SIZE_BYTES, null, null, response);
+ phone.mCM.iccIOForApp(COMMAND_GET_RESPONSE, fileid, getEFPath(fileid),
+ 0, 0, GET_RESPONSE_EF_SIZE_BYTES, null, null,
+ phone.getIccCard().getAid(), response);
}
/**
@@ -217,8 +221,9 @@
Message response = obtainMessage(EVENT_GET_BINARY_SIZE_DONE,
fileid, 0, onLoaded);
- phone.mCM.iccIO(COMMAND_GET_RESPONSE, fileid, getEFPath(fileid),
- 0, 0, GET_RESPONSE_EF_SIZE_BYTES, null, null, response);
+ phone.mCM.iccIOForApp(COMMAND_GET_RESPONSE, fileid, getEFPath(fileid),
+ 0, 0, GET_RESPONSE_EF_SIZE_BYTES, null, null,
+ phone.getIccCard().getAid(), response);
}
/**
@@ -236,8 +241,8 @@
Message response = obtainMessage(EVENT_READ_ICON_DONE, fileid, 0,
onLoaded);
- phone.mCM.iccIO(COMMAND_READ_BINARY, fileid, "img", highOffset, lowOffset,
- length, null, null, response);
+ phone.mCM.iccIOForApp(COMMAND_READ_BINARY, fileid, "img", highOffset, lowOffset,
+ length, null, null, phone.getIccCard().getAid(), response);
}
/**
@@ -251,9 +256,10 @@
*/
public void updateEFLinearFixed(int fileid, int recordNum, byte[] data,
String pin2, Message onComplete) {
- phone.mCM.iccIO(COMMAND_UPDATE_RECORD, fileid, getEFPath(fileid),
+ phone.mCM.iccIOForApp(COMMAND_UPDATE_RECORD, fileid, getEFPath(fileid),
recordNum, READ_RECORD_MODE_ABSOLUTE, data.length,
- IccUtils.bytesToHexString(data), pin2, onComplete);
+ IccUtils.bytesToHexString(data), pin2,
+ phone.getIccCard().getAid(), onComplete);
}
/**
@@ -262,9 +268,10 @@
* @param data must be exactly as long as the EF
*/
public void updateEFTransparent(int fileid, byte[] data, Message onComplete) {
- phone.mCM.iccIO(COMMAND_UPDATE_BINARY, fileid, getEFPath(fileid),
+ phone.mCM.iccIOForApp(COMMAND_UPDATE_BINARY, fileid, getEFPath(fileid),
0, 0, data.length,
- IccUtils.bytesToHexString(data), null, onComplete);
+ IccUtils.bytesToHexString(data), null,
+ phone.getIccCard().getAid(), onComplete);
}
@@ -395,10 +402,11 @@
lc.results = new ArrayList<byte[]>(lc.countRecords);
}
- phone.mCM.iccIO(COMMAND_READ_RECORD, lc.efid, getEFPath(lc.efid),
+ phone.mCM.iccIOForApp(COMMAND_READ_RECORD, lc.efid, getEFPath(lc.efid),
lc.recordNum,
READ_RECORD_MODE_ABSOLUTE,
lc.recordSize, null, null,
+ phone.getIccCard().getAid(),
obtainMessage(EVENT_READ_RECORD_DONE, lc));
break;
case EVENT_GET_BINARY_SIZE_DONE:
@@ -433,8 +441,9 @@
size = ((data[RESPONSE_DATA_FILE_SIZE_1] & 0xff) << 8)
+ (data[RESPONSE_DATA_FILE_SIZE_2] & 0xff);
- phone.mCM.iccIO(COMMAND_READ_BINARY, fileid, getEFPath(fileid),
+ phone.mCM.iccIOForApp(COMMAND_READ_BINARY, fileid, getEFPath(fileid),
0, 0, size, null, null,
+ phone.getIccCard().getAid(),
obtainMessage(EVENT_READ_BINARY_DONE,
fileid, 0, response));
break;
@@ -468,10 +477,11 @@
if (lc.recordNum > lc.countRecords) {
sendResult(response, lc.results, null);
} else {
- phone.mCM.iccIO(COMMAND_READ_RECORD, lc.efid, getEFPath(lc.efid),
+ phone.mCM.iccIOForApp(COMMAND_READ_RECORD, lc.efid, getEFPath(lc.efid),
lc.recordNum,
READ_RECORD_MODE_ABSOLUTE,
lc.recordSize, null, null,
+ phone.getIccCard().getAid(),
obtainMessage(EVENT_READ_RECORD_DONE, lc));
}
}
diff --git a/telephony/java/com/android/internal/telephony/RIL.java b/telephony/java/com/android/internal/telephony/RIL.java
index 156eb32..f587fe1 100644
--- a/telephony/java/com/android/internal/telephony/RIL.java
+++ b/telephony/java/com/android/internal/telephony/RIL.java
@@ -880,9 +880,19 @@
public void
getIMSI(Message result) {
+ getIMSIForApp(null, result);
+ }
+
+ public void
+ getIMSIForApp(String aid, Message result) {
RILRequest rr = RILRequest.obtain(RIL_REQUEST_GET_IMSI, result);
- if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+ rr.mp.writeInt(1);
+ rr.mp.writeString(aid);
+
+ if (RILJ_LOGD) riljLog(rr.serialString() +
+ "> getIMSI: " + requestToString(rr.mRequest)
+ + " aid: " + aid);
send(rr);
}
@@ -1435,6 +1445,11 @@
public void
iccIO (int command, int fileid, String path, int p1, int p2, int p3,
String data, String pin2, Message result) {
+ iccIOForApp(command, fileid, path, p1, p2, p3, data, pin2, null, result);
+ }
+ public void
+ iccIOForApp (int command, int fileid, String path, int p1, int p2, int p3,
+ String data, String pin2, String aid, Message result) {
//Note: This RIL request has not been renamed to ICC,
// but this request is also valid for SIM and RUIM
RILRequest rr
@@ -1448,12 +1463,15 @@
rr.mp.writeInt(p3);
rr.mp.writeString(data);
rr.mp.writeString(pin2);
+ rr.mp.writeString(aid);
- if (RILJ_LOGD) riljLog(rr.serialString() + "> iccIO: " + requestToString(rr.mRequest)
+ if (RILJ_LOGD) riljLog(rr.serialString() + "> iccIO: "
+ + requestToString(rr.mRequest)
+ " 0x" + Integer.toHexString(command)
+ " 0x" + Integer.toHexString(fileid) + " "
+ " path: " + path + ","
- + p1 + "," + p2 + "," + p3);
+ + p1 + "," + p2 + "," + p3
+ + " aid: " + aid);
send(rr);
}
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccFileHandler.java b/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccFileHandler.java
index b57af0e..8375fd0 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccFileHandler.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccFileHandler.java
@@ -55,8 +55,8 @@
if (fileid == EF_CSIM_EPRL) {
// Entire PRL could be huge. We are only interested in
// the first 4 bytes of the record.
- phone.mCM.iccIO(COMMAND_READ_BINARY, fileid, getEFPath(fileid),
- 0, 0, 4, null, null,
+ phone.mCM.iccIOForApp(COMMAND_READ_BINARY, fileid, getEFPath(fileid),
+ 0, 0, 4, null, null, phone.getIccCard().getAid(),
obtainMessage(EVENT_READ_BINARY_DONE,
fileid, 0, onLoaded));
} else {
diff --git a/telephony/java/com/android/internal/telephony/cdma/RuimFileHandler.java b/telephony/java/com/android/internal/telephony/cdma/RuimFileHandler.java
index 3e2a29b..375cc07 100644
--- a/telephony/java/com/android/internal/telephony/cdma/RuimFileHandler.java
+++ b/telephony/java/com/android/internal/telephony/cdma/RuimFileHandler.java
@@ -57,8 +57,9 @@
Message response = obtainMessage(EVENT_READ_ICON_DONE, fileid, 0,
onLoaded);
- phone.mCM.iccIO(COMMAND_GET_RESPONSE, fileid, "img", 0, 0,
- GET_RESPONSE_EF_IMG_SIZE_BYTES, null, null, response);
+ phone.mCM.iccIOForApp(COMMAND_GET_RESPONSE, fileid, "img", 0, 0,
+ GET_RESPONSE_EF_IMG_SIZE_BYTES, null, null,
+ phone.getIccCard().getAid(), response);
}
@Override
diff --git a/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java b/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java
index b2fa051..de8401e 100755
--- a/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java
@@ -1309,7 +1309,7 @@
logv("fetchSimRecords " + recordsToLoad);
- phone.mCM.getIMSI(obtainMessage(EVENT_GET_IMSI_DONE));
+ phone.mCM.getIMSIForApp(phone.getIccCard().getAid(), obtainMessage(EVENT_GET_IMSI_DONE));
recordsToLoad++;
iccFh.loadEFTransparent(EF_ICCID, obtainMessage(EVENT_GET_ICCID_DONE));
diff --git a/telephony/java/com/android/internal/telephony/sip/SipCommandInterface.java b/telephony/java/com/android/internal/telephony/sip/SipCommandInterface.java
index 9201984..99f4e0f 100644
--- a/telephony/java/com/android/internal/telephony/sip/SipCommandInterface.java
+++ b/telephony/java/com/android/internal/telephony/sip/SipCommandInterface.java
@@ -84,6 +84,9 @@
public void getIMSI(Message result) {
}
+ public void getIMSIForApp(String aid, Message result) {
+ }
+
public void getIMEI(Message result) {
}
@@ -213,6 +216,9 @@
public void iccIO (int command, int fileid, String path, int p1, int p2,
int p3, String data, String pin2, Message result) {
}
+ public void iccIOForApp (int command, int fileid, String path, int p1, int p2,
+ int p3, String data, String pin2, String aid, Message result) {
+ }
public void getCLIR(Message result) {
}
diff --git a/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java b/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java
index 60d9d24..4f61509 100644
--- a/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java
+++ b/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java
@@ -504,6 +504,9 @@
resultSuccess(result, null);
}
+ public void getIMSI(Message result) {
+ getIMSIForApp(null, result);
+ }
/**
* returned message
* retMsg.obj = AsyncResult ar
@@ -511,7 +514,7 @@
* ar.userObject contains the original value of result.obj
* ar.result is String containing IMSI on success
*/
- public void getIMSI(Message result) {
+ public void getIMSIForApp(String aid, Message result) {
resultSuccess(result, "012345678901234");
}
@@ -1042,13 +1045,18 @@
unimplemented(result);
}
+ public void iccIO(int command, int fileid, String path, int p1, int p2, int p3, String data,
+ String pin2, Message response) {
+ iccIOForApp(command, fileid, path, p1, p2, p3, data,pin2, null, response);
+ }
+
/**
* parameters equivalent to 27.007 AT+CRSM command
* response.obj will be an AsyncResult
* response.obj.userObj will be a SimIoResult on success
*/
- public void iccIO (int command, int fileid, String path, int p1, int p2,
- int p3, String data, String pin2, Message result) {
+ public void iccIOForApp (int command, int fileid, String path, int p1, int p2,
+ int p3, String data, String pin2, String aid, Message result) {
unimplemented(result);
}
diff --git a/telephony/tests/telephonytests/src/com/android/internal/telephony/gsm/UsimDataDownloadCommands.java b/telephony/tests/telephonytests/src/com/android/internal/telephony/gsm/UsimDataDownloadCommands.java
index b385cee..ea6836d 100644
--- a/telephony/tests/telephonytests/src/com/android/internal/telephony/gsm/UsimDataDownloadCommands.java
+++ b/telephony/tests/telephonytests/src/com/android/internal/telephony/gsm/UsimDataDownloadCommands.java
@@ -612,4 +612,13 @@
@Override
public void getVoiceRadioTechnology(Message response) {
}
+
+ @Override
+ public void getIMSIForApp(String aid, Message result) {
+ }
+
+ @Override
+ public void iccIOForApp(int command, int fileid, String path, int p1, int p2, int p3,
+ String data, String pin2, String aid, Message response) {
+ }
}