Merge "Updating APIs for CDMA conference call support." into lmp-dev
diff --git a/api/current.txt b/api/current.txt
index bb74d6f..a1f4bc2 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -8686,7 +8686,7 @@
method public java.util.List<android.content.pm.PackageInstaller.SessionInfo> getAllSessions();
method public java.util.List<android.content.pm.PackageInstaller.SessionInfo> getMySessions();
method public android.content.pm.PackageInstaller.SessionInfo getSessionInfo(int);
- method public android.content.pm.PackageInstaller.Session openSession(int);
+ method public android.content.pm.PackageInstaller.Session openSession(int) throws java.io.IOException;
method public void registerSessionCallback(android.content.pm.PackageInstaller.SessionCallback);
method public void registerSessionCallback(android.content.pm.PackageInstaller.SessionCallback, android.os.Handler);
method public void uninstall(java.lang.String, android.content.IntentSender);
@@ -8719,16 +8719,15 @@
method public java.lang.String[] getNames() throws java.io.IOException;
method public java.io.InputStream openRead(java.lang.String) throws java.io.IOException;
method public java.io.OutputStream openWrite(java.lang.String, long, long) throws java.io.IOException;
- method public void setProgress(float);
+ method public void setStagingProgress(float);
}
public static abstract class PackageInstaller.SessionCallback {
ctor public PackageInstaller.SessionCallback();
+ method public abstract void onActiveChanged(int, boolean);
method public abstract void onBadgingChanged(int);
- method public abstract void onClosed(int);
method public abstract void onCreated(int);
method public abstract void onFinished(int, boolean);
- method public abstract void onOpened(int);
method public abstract void onProgressChanged(int, float);
}
@@ -8741,7 +8740,7 @@
method public java.lang.String getInstallerPackageName();
method public float getProgress();
method public int getSessionId();
- method public boolean isOpen();
+ method public boolean isActive();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator CREATOR;
}
@@ -14051,6 +14050,7 @@
field public static final int CONTENT_TYPE_SONIFICATION = 4; // 0x4
field public static final int CONTENT_TYPE_SPEECH = 1; // 0x1
field public static final int CONTENT_TYPE_UNKNOWN = 0; // 0x0
+ field public static final android.os.Parcelable.Creator CREATOR;
field public static final int FLAG_AUDIBILITY_ENFORCED = 1; // 0x1
field public static final int USAGE_ALARM = 4; // 0x4
field public static final int USAGE_ASSISTANCE_ACCESSIBILITY = 11; // 0xb
@@ -14236,9 +14236,9 @@
field public static final int AUDIO_SESSION_ID_GENERATE = 0; // 0x0
field public static final int ERROR = -1; // 0xffffffff
field public static final int ERROR_DEAD_OBJECT = -6; // 0xfffffffa
- field public static final java.lang.String EXTRA_AUDIO_PLUG_STATE = "android.media.extra.audio_plug_state";
- field public static final java.lang.String EXTRA_ENCODINGS = "android.media.extra.encodings";
- field public static final java.lang.String EXTRA_MAX_CHANNEL_COUNT = "android.media.extra.max_channel_count";
+ field public static final java.lang.String EXTRA_AUDIO_PLUG_STATE = "android.media.extra.AUDIO_PLUG_STATE";
+ field public static final java.lang.String EXTRA_ENCODINGS = "android.media.extra.ENCODINGS";
+ field public static final java.lang.String EXTRA_MAX_CHANNEL_COUNT = "android.media.extra.MAX_CHANNEL_COUNT";
field public static final java.lang.String EXTRA_RINGER_MODE = "android.media.EXTRA_RINGER_MODE";
field public static final java.lang.String EXTRA_SCO_AUDIO_PREVIOUS_STATE = "android.media.extra.SCO_AUDIO_PREVIOUS_STATE";
field public static final java.lang.String EXTRA_SCO_AUDIO_STATE = "android.media.extra.SCO_AUDIO_STATE";
@@ -14710,7 +14710,7 @@
public static final class MediaCodecInfo.CodecCapabilities {
ctor public MediaCodecInfo.CodecCapabilities();
- method public static android.media.MediaCodecInfo.CodecCapabilities CreateFromProfileLevel(java.lang.String, int, int);
+ method public static android.media.MediaCodecInfo.CodecCapabilities createFromProfileLevel(java.lang.String, int, int);
method public android.media.MediaCodecInfo.AudioCapabilities getAudioCapabilities();
method public android.media.MediaFormat getDefaultFormat();
method public android.media.MediaCodecInfo.EncoderCapabilities getEncoderCapabilities();
diff --git a/core/java/android/content/pm/IPackageInstallerCallback.aidl b/core/java/android/content/pm/IPackageInstallerCallback.aidl
index fe98ee7..974eb1e 100644
--- a/core/java/android/content/pm/IPackageInstallerCallback.aidl
+++ b/core/java/android/content/pm/IPackageInstallerCallback.aidl
@@ -20,8 +20,7 @@
oneway interface IPackageInstallerCallback {
void onSessionCreated(int sessionId);
void onSessionBadgingChanged(int sessionId);
- void onSessionOpened(int sessionId);
+ void onSessionActiveChanged(int sessionId, boolean active);
void onSessionProgressChanged(int sessionId, float progress);
- void onSessionClosed(int sessionId);
void onSessionFinished(int sessionId, boolean success);
}
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 7c34a65..0a211cf 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -304,9 +304,12 @@
* Open an existing session to actively perform work. To succeed, the caller
* must be the owner of the install session.
*/
- public @NonNull Session openSession(int sessionId) {
+ public @NonNull Session openSession(int sessionId) throws IOException {
try {
return new Session(mInstaller.openSession(sessionId));
+ } catch (RuntimeException e) {
+ ExceptionUtils.maybeUnwrapIOException(e);
+ throw e;
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
}
@@ -363,7 +366,7 @@
public @NonNull List<SessionInfo> getAllSessions() {
final ApplicationInfo info = mContext.getApplicationInfo();
if ("com.google.android.googlequicksearchbox".equals(info.packageName)
- && info.versionCode <= 300400070) {
+ && info.versionCode <= 300400110) {
Log.d(TAG, "Ignoring callback request from old prebuilt");
return Collections.EMPTY_LIST;
}
@@ -436,27 +439,32 @@
public abstract void onBadgingChanged(int sessionId);
/**
- * Session has been opened. A session is usually opened when the
- * installer is actively writing data.
+ * Active state for session has been changed.
+ * <p>
+ * A session is considered active whenever there is ongoing forward
+ * progress being made, such as the installer holding an open
+ * {@link Session} instance while streaming data into place, or the
+ * system optimizing code as the result of
+ * {@link Session#commit(IntentSender)}.
+ * <p>
+ * If the installer closes the {@link Session} without committing, the
+ * session is considered inactive until the installer opens the session
+ * again.
*/
- public abstract void onOpened(int sessionId);
+ public abstract void onActiveChanged(int sessionId, boolean active);
/**
* Progress for given session has been updated.
* <p>
* Note that this progress may not directly correspond to the value
- * reported by {@link PackageInstaller.Session#setProgress(float)}, as
- * the system may carve out a portion of the overall progress to
- * represent its own internal installation work.
+ * reported by
+ * {@link PackageInstaller.Session#setStagingProgress(float)}, as the
+ * system may carve out a portion of the overall progress to represent
+ * its own internal installation work.
*/
public abstract void onProgressChanged(int sessionId, float progress);
/**
- * Session has been closed.
- */
- public abstract void onClosed(int sessionId);
-
- /**
* Session has completely finished, either with success or failure.
*/
public abstract void onFinished(int sessionId, boolean success);
@@ -467,10 +475,9 @@
Handler.Callback {
private static final int MSG_SESSION_CREATED = 1;
private static final int MSG_SESSION_BADGING_CHANGED = 2;
- private static final int MSG_SESSION_OPENED = 3;
+ private static final int MSG_SESSION_ACTIVE_CHANGED = 3;
private static final int MSG_SESSION_PROGRESS_CHANGED = 4;
- private static final int MSG_SESSION_CLOSED = 5;
- private static final int MSG_SESSION_FINISHED = 6;
+ private static final int MSG_SESSION_FINISHED = 5;
final SessionCallback mCallback;
final Handler mHandler;
@@ -482,24 +489,23 @@
@Override
public boolean handleMessage(Message msg) {
+ final int sessionId = msg.arg1;
switch (msg.what) {
case MSG_SESSION_CREATED:
- mCallback.onCreated(msg.arg1);
+ mCallback.onCreated(sessionId);
return true;
case MSG_SESSION_BADGING_CHANGED:
- mCallback.onBadgingChanged(msg.arg1);
+ mCallback.onBadgingChanged(sessionId);
return true;
- case MSG_SESSION_OPENED:
- mCallback.onOpened(msg.arg1);
+ case MSG_SESSION_ACTIVE_CHANGED:
+ final boolean active = msg.arg2 != 0;
+ mCallback.onActiveChanged(sessionId, active);
return true;
case MSG_SESSION_PROGRESS_CHANGED:
- mCallback.onProgressChanged(msg.arg1, (float) msg.obj);
- return true;
- case MSG_SESSION_CLOSED:
- mCallback.onClosed(msg.arg1);
+ mCallback.onProgressChanged(sessionId, (float) msg.obj);
return true;
case MSG_SESSION_FINISHED:
- mCallback.onFinished(msg.arg1, msg.arg2 != 0);
+ mCallback.onFinished(sessionId, msg.arg2 != 0);
return true;
}
return false;
@@ -516,8 +522,9 @@
}
@Override
- public void onSessionOpened(int sessionId) {
- mHandler.obtainMessage(MSG_SESSION_OPENED, sessionId, 0).sendToTarget();
+ public void onSessionActiveChanged(int sessionId, boolean active) {
+ mHandler.obtainMessage(MSG_SESSION_ACTIVE_CHANGED, sessionId, active ? 1 : 0)
+ .sendToTarget();
}
@Override
@@ -527,11 +534,6 @@
}
@Override
- public void onSessionClosed(int sessionId) {
- mHandler.obtainMessage(MSG_SESSION_CLOSED, sessionId, 0).sendToTarget();
- }
-
- @Override
public void onSessionFinished(int sessionId, boolean success) {
mHandler.obtainMessage(MSG_SESSION_FINISHED, sessionId, success ? 1 : 0)
.sendToTarget();
@@ -567,7 +569,7 @@
// TODO: remove this temporary guard once we have new prebuilts
final ApplicationInfo info = mContext.getApplicationInfo();
if ("com.google.android.googlequicksearchbox".equals(info.packageName)
- && info.versionCode <= 300400070) {
+ && info.versionCode <= 300400110) {
Log.d(TAG, "Ignoring callback request from old prebuilt");
return;
}
@@ -629,10 +631,22 @@
mSession = session;
}
- /**
- * Set current progress. Valid values are anywhere between 0 and 1.
- */
+ /** {@hide} */
+ @Deprecated
public void setProgress(float progress) {
+ setStagingProgress(progress);
+ }
+
+ /**
+ * Set current progress of staging this session. Valid values are
+ * anywhere between 0 and 1.
+ * <p>
+ * Note that this progress may not directly correspond to the value
+ * reported by {@link SessionCallback#onProgressChanged(int, float)}, as
+ * the system may carve out a portion of the overall progress to
+ * represent its own internal installation work.
+ */
+ public void setStagingProgress(float progress) {
try {
mSession.setClientProgress(progress);
} catch (RemoteException e) {
@@ -986,7 +1000,7 @@
/** {@hide} */
public boolean sealed;
/** {@hide} */
- public boolean open;
+ public boolean active;
/** {@hide} */
public int mode;
@@ -1010,7 +1024,7 @@
resolvedBaseCodePath = source.readString();
progress = source.readFloat();
sealed = source.readInt() != 0;
- open = source.readInt() != 0;
+ active = source.readInt() != 0;
mode = source.readInt();
sizeBytes = source.readLong();
@@ -1036,20 +1050,37 @@
/**
* Return current overall progress of this session, between 0 and 1.
* <p>
- * Note that this progress may not directly correspond to the value reported
- * by {@link PackageInstaller.Session#setProgress(float)}, as the system may
- * carve out a portion of the overall progress to represent its own internal
- * installation work.
+ * Note that this progress may not directly correspond to the value
+ * reported by
+ * {@link PackageInstaller.Session#setStagingProgress(float)}, as the
+ * system may carve out a portion of the overall progress to represent
+ * its own internal installation work.
*/
public float getProgress() {
return progress;
}
/**
- * Return if this session is currently open.
+ * Return if this session is currently active.
+ * <p>
+ * A session is considered active whenever there is ongoing forward
+ * progress being made, such as the installer holding an open
+ * {@link Session} instance while streaming data into place, or the
+ * system optimizing code as the result of
+ * {@link Session#commit(IntentSender)}.
+ * <p>
+ * If the installer closes the {@link Session} without committing, the
+ * session is considered inactive until the installer opens the session
+ * again.
*/
+ public boolean isActive() {
+ return active;
+ }
+
+ /** {@hide} */
+ @Deprecated
public boolean isOpen() {
- return open;
+ return isActive();
}
/**
@@ -1105,7 +1136,7 @@
dest.writeString(resolvedBaseCodePath);
dest.writeFloat(progress);
dest.writeInt(sealed ? 1 : 0);
- dest.writeInt(open ? 1 : 0);
+ dest.writeInt(active ? 1 : 0);
dest.writeInt(mode);
dest.writeLong(sizeBytes);
diff --git a/core/java/android/print/PrintManager.java b/core/java/android/print/PrintManager.java
index 9361286..bf8ac65 100644
--- a/core/java/android/print/PrintManager.java
+++ b/core/java/android/print/PrintManager.java
@@ -535,7 +535,7 @@
destroyed = isDestroyedLocked();
}
- if (destroyed) {
+ if (destroyed && observer != null) {
try {
observer.onDestroy();
} catch (RemoteException re) {
diff --git a/core/java/android/view/RenderNode.java b/core/java/android/view/RenderNode.java
index 9dc9766..47f72a8 100644
--- a/core/java/android/view/RenderNode.java
+++ b/core/java/android/view/RenderNode.java
@@ -367,6 +367,10 @@
throw new IllegalArgumentException("Unrecognized outline?");
}
+ public boolean hasShadow() {
+ return nHasShadow(mNativeRenderNode);
+ }
+
/**
* Enables or disables clipping to the outline.
*
@@ -861,6 +865,7 @@
float alpha);
private static native boolean nSetOutlineEmpty(long renderNode);
private static native boolean nSetOutlineNone(long renderNode);
+ private static native boolean nHasShadow(long renderNode);
private static native boolean nSetClipToOutline(long renderNode, boolean clipToOutline);
private static native boolean nSetRevealClip(long renderNode,
boolean shouldClip, float x, float y, float radius);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 92ad4e8..770e78c 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -10224,6 +10224,7 @@
*
* @return true if the content in this view might overlap, false otherwise.
*/
+ @ViewDebug.ExportedProperty(category = "drawing")
public boolean hasOverlappingRendering() {
return true;
}
@@ -10926,6 +10927,17 @@
invalidateViewProperty(false, false);
}
+ /**
+ * HierarchyViewer only
+ *
+ * @hide
+ */
+ @ViewDebug.ExportedProperty(category = "drawing")
+ public boolean hasShadow() {
+ return mRenderNode.hasShadow();
+ }
+
+
/** @hide */
public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
mRenderNode.setRevealClip(shouldClip, x, y, radius);
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 974fe4e..ac1b6a9 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -3301,6 +3301,7 @@
* @return True if the group's children will be clipped to their bounds,
* false otherwise.
*/
+ @ViewDebug.ExportedProperty(category = "drawing")
public boolean getClipChildren() {
return ((mGroupFlags & FLAG_CLIP_CHILDREN) != 0);
}
@@ -3349,6 +3350,7 @@
*
* @attr ref android.R.styleable#ViewGroup_clipToPadding
*/
+ @ViewDebug.ExportedProperty(category = "drawing")
public boolean getClipToPadding() {
return hasBooleanFlag(FLAG_CLIP_TO_PADDING);
}
diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp
index 949f4ff..050037e 100644
--- a/core/jni/android_view_RenderNode.cpp
+++ b/core/jni/android_view_RenderNode.cpp
@@ -173,6 +173,12 @@
return true;
}
+static jboolean android_view_RenderNode_hasShadow(JNIEnv* env,
+ jobject clazz, jlong renderNodePtr) {
+ RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+ return renderNode->stagingProperties().hasShadow();
+}
+
static jboolean android_view_RenderNode_setClipToOutline(JNIEnv* env,
jobject clazz, jlong renderNodePtr, jboolean clipToOutline) {
RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
@@ -491,6 +497,7 @@
{ "nSetOutlineConvexPath", "(JJF)Z", (void*) android_view_RenderNode_setOutlineConvexPath },
{ "nSetOutlineEmpty", "(J)Z", (void*) android_view_RenderNode_setOutlineEmpty },
{ "nSetOutlineNone", "(J)Z", (void*) android_view_RenderNode_setOutlineNone },
+ { "nHasShadow", "(J)Z", (void*) android_view_RenderNode_hasShadow },
{ "nSetClipToOutline", "(JZ)Z", (void*) android_view_RenderNode_setClipToOutline },
{ "nSetRevealClip", "(JZFFF)Z", (void*) android_view_RenderNode_setRevealClip },
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 7e6d335..a8edb77 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -158,9 +158,11 @@
// Marks the start of a frame, which will update the frame time and move all
// next frame animations into the current frame
- virtual void startFrame() {
- mRootNode->doAttachAnimatingNodes(this);
- AnimationContext::startFrame();
+ virtual void startFrame(TreeInfo::TraversalMode mode) {
+ if (mode == TreeInfo::MODE_FULL) {
+ mRootNode->doAttachAnimatingNodes(this);
+ }
+ AnimationContext::startFrame(mode);
}
// Runs any animations still left in mCurrentFrameAnimations
diff --git a/core/res/res/values/colors_material.xml b/core/res/res/values/colors_material.xml
index d8e14a0..939cbf1 100644
--- a/core/res/res/values/colors_material.xml
+++ b/core/res/res/values/colors_material.xml
@@ -19,8 +19,8 @@
<color name="background_material_dark">#ff212121</color>
<color name="background_material_light">#fffafafa</color>
- <color name="ripple_material_light">#20444444</color>
- <color name="ripple_material_dark">#20ffffff</color>
+ <color name="ripple_material_light">#40000000</color>
+ <color name="ripple_material_dark">#40ffffff</color>
<color name="button_material_dark">#ff5a595b</color>
<color name="button_material_light">#ffd6d7d7</color>
diff --git a/graphics/java/android/graphics/drawable/Ripple.java b/graphics/java/android/graphics/drawable/Ripple.java
index 43922b8..6f95f91 100644
--- a/graphics/java/android/graphics/drawable/Ripple.java
+++ b/graphics/java/android/graphics/drawable/Ripple.java
@@ -22,6 +22,7 @@
import android.animation.TimeInterpolator;
import android.graphics.Canvas;
import android.graphics.CanvasProperty;
+import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Rect;
@@ -58,7 +59,7 @@
private final Rect mBounds;
/** Full-opacity color for drawing this ripple. */
- private int mColor;
+ private int mColorOpaque;
/** Maximum ripple radius. */
private float mOuterRadius;
@@ -120,7 +121,7 @@
}
public void setup(int maxRadius, int color, float density) {
- mColor = color | 0xFF000000;
+ mColorOpaque = color | 0xFF000000;
if (maxRadius != RippleDrawable.RADIUS_AUTO) {
mHasMaxRadius = true;
@@ -236,6 +237,9 @@
if (N > 0) {
cancelHardwareAnimations(false);
+ // We canceled old animations, but we're about to run new ones.
+ mHardwareAnimating = true;
+
for (int i = 0; i < N; i++) {
pendingAnimations.get(i).setTarget(c);
pendingAnimations.get(i).start();
@@ -253,9 +257,8 @@
private boolean drawSoftware(Canvas c, Paint p) {
boolean hasContent = false;
- // Cache the paint alpha so we can restore it later.
- final int paintAlpha = p.getAlpha();
- final int alpha = (int) (paintAlpha * mOpacity + 0.5f);
+ p.setColor(mColorOpaque);
+ final int alpha = (int) (255 * mOpacity + 0.5f);
final float radius = MathUtils.lerp(0, mOuterRadius, mTweenRadius);
if (alpha > 0 && radius > 0) {
final float x = MathUtils.lerp(
@@ -268,8 +271,6 @@
hasContent = true;
}
- p.setAlpha(paintAlpha);
-
return hasContent;
}
@@ -369,7 +370,7 @@
final float startRadius = MathUtils.lerp(0, mOuterRadius, mTweenRadius);
final Paint paint = getTempPaint();
paint.setAntiAlias(true);
- paint.setColor(mColor);
+ paint.setColor(mColorOpaque);
paint.setAlpha((int) (255 * mOpacity + 0.5f));
paint.setStyle(Style.FILL);
mPropPaint = CanvasProperty.createPaint(paint);
@@ -402,6 +403,12 @@
mHardwareAnimating = true;
+ // Set up the software values to match the hardware end values.
+ mOpacity = 0;
+ mTweenX = 1;
+ mTweenY = 1;
+ mTweenRadius = 1;
+
invalidateSelf();
}
@@ -412,7 +419,7 @@
public void jump() {
mCanceled = true;
endSoftwareAnimations();
- endHardwareAnimations();
+ cancelHardwareAnimations(true);
mCanceled = false;
}
@@ -438,24 +445,6 @@
}
}
- private void endHardwareAnimations() {
- final ArrayList<RenderNodeAnimator> runningAnimations = mRunningAnimations;
- final int N = runningAnimations.size();
- for (int i = 0; i < N; i++) {
- runningAnimations.get(i).end();
- }
- runningAnimations.clear();
-
- // Abort any pending animations. Since we always have a completion
- // listener on a pending animation, we also need to remove ourselves.
- if (!mPendingAnimations.isEmpty()) {
- mPendingAnimations.clear();
- removeSelf();
- }
-
- mHardwareAnimating = false;
- }
-
private Paint getTempPaint() {
if (mTempPaint == null) {
mTempPaint = new Paint();
diff --git a/graphics/java/android/graphics/drawable/RippleBackground.java b/graphics/java/android/graphics/drawable/RippleBackground.java
index 80ecea3..bc6f5fb 100644
--- a/graphics/java/android/graphics/drawable/RippleBackground.java
+++ b/graphics/java/android/graphics/drawable/RippleBackground.java
@@ -22,6 +22,7 @@
import android.animation.TimeInterpolator;
import android.graphics.Canvas;
import android.graphics.CanvasProperty;
+import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Rect;
@@ -46,8 +47,6 @@
private static final float WAVE_OUTER_SIZE_INFLUENCE_MAX = 200f;
private static final float WAVE_OUTER_SIZE_INFLUENCE_MIN = 40f;
- private static final long RIPPLE_ENTER_DELAY = 80;
-
// Hardware animators.
private final ArrayList<RenderNodeAnimator> mRunningAnimations =
new ArrayList<RenderNodeAnimator>();
@@ -60,7 +59,10 @@
private final Rect mBounds;
/** Full-opacity color for drawing this ripple. */
- private int mColor;
+ private int mColorOpaque;
+
+ /** Maximum alpha value for drawing this ripple. */
+ private int mColorAlpha;
/** Maximum ripple radius. */
private float mOuterRadius;
@@ -103,7 +105,8 @@
}
public void setup(int maxRadius, int color, float density) {
- mColor = color | 0xFF000000;
+ mColorOpaque = color | 0xFF000000;
+ mColorAlpha = Color.alpha(color);
if (maxRadius != RippleDrawable.RADIUS_AUTO) {
mHasMaxRadius = true;
@@ -159,6 +162,11 @@
return hasContent;
}
+ public boolean shouldDraw() {
+ final int outerAlpha = (int) (mColorAlpha * mOuterOpacity + 0.5f);
+ return mCanUseHardware && mHardwareAnimating || outerAlpha > 0 && mOuterRadius > 0;
+ }
+
private boolean drawHardware(HardwareCanvas c) {
// If we have any pending hardware animations, cancel any running
// animations and start those now.
@@ -167,6 +175,9 @@
if (N > 0) {
cancelHardwareAnimations(false);
+ // We canceled old animations, but we're about to run new ones.
+ mHardwareAnimating = true;
+
for (int i = 0; i < N; i++) {
pendingAnimations.get(i).setTarget(c);
pendingAnimations.get(i).start();
@@ -184,10 +195,8 @@
private boolean drawSoftware(Canvas c, Paint p) {
boolean hasContent = false;
- // Cache the paint alpha so we can restore it later.
- final int paintAlpha = p.getAlpha();
-
- final int outerAlpha = (int) (paintAlpha * mOuterOpacity + 0.5f);
+ p.setColor(mColorOpaque);
+ final int outerAlpha = (int) (mColorAlpha * mOuterOpacity + 0.5f);
if (outerAlpha > 0 && mOuterRadius > 0) {
p.setAlpha(outerAlpha);
p.setStyle(Style.FILL);
@@ -195,8 +204,6 @@
hasContent = true;
}
- p.setAlpha(paintAlpha);
-
return hasContent;
}
@@ -248,25 +255,25 @@
// Determine at what time the inner and outer opacity intersect.
// inner(t) = mOpacity - t * WAVE_OPACITY_DECAY_VELOCITY / 1000
// outer(t) = mOuterOpacity + t * WAVE_OUTER_OPACITY_VELOCITY / 1000
- final int outerInflection = Math.max(0, (int) (1000 * (1 - mOuterOpacity)
+ final int inflectionDuration = Math.max(0, (int) (1000 * (1 - mOuterOpacity)
/ (WAVE_OPACITY_DECAY_VELOCITY + outerOpacityVelocity) + 0.5f));
- final int inflectionOpacity = (int) (255 * (mOuterOpacity + outerInflection
- * outerOpacityVelocity * outerSizeInfluence / 1000) + 0.5f);
+ final int inflectionOpacity = (int) (mColorAlpha * (mOuterOpacity
+ + inflectionDuration * outerOpacityVelocity * outerSizeInfluence / 1000) + 0.5f);
if (mCanUseHardware) {
- exitHardware(opacityDuration, outerInflection, inflectionOpacity);
+ exitHardware(opacityDuration, inflectionDuration, inflectionOpacity);
} else {
- exitSoftware(opacityDuration, outerInflection, inflectionOpacity);
+ exitSoftware(opacityDuration, inflectionDuration, inflectionOpacity);
}
}
- private void exitHardware(int opacityDuration, int outerInflection, int inflectionOpacity) {
+ private void exitHardware(int opacityDuration, int inflectionDuration, int inflectionOpacity) {
mPendingAnimations.clear();
final Paint outerPaint = getTempPaint();
outerPaint.setAntiAlias(true);
- outerPaint.setColor(mColor);
- outerPaint.setAlpha((int) (255 * mOuterOpacity + 0.5f));
+ outerPaint.setColor(mColorOpaque);
+ outerPaint.setAlpha((int) (mColorAlpha * mOuterOpacity + 0.5f));
outerPaint.setStyle(Style.FILL);
mPropOuterPaint = CanvasProperty.createPaint(outerPaint);
mPropOuterRadius = CanvasProperty.createFloat(mOuterRadius);
@@ -274,21 +281,21 @@
mPropOuterY = CanvasProperty.createFloat(mOuterY);
final RenderNodeAnimator outerOpacityAnim;
- if (outerInflection > 0) {
+ if (inflectionDuration > 0) {
// Outer opacity continues to increase for a bit.
- outerOpacityAnim = new RenderNodeAnimator(
- mPropOuterPaint, RenderNodeAnimator.PAINT_ALPHA, inflectionOpacity);
- outerOpacityAnim.setDuration(outerInflection);
+ outerOpacityAnim = new RenderNodeAnimator(mPropOuterPaint,
+ RenderNodeAnimator.PAINT_ALPHA, inflectionOpacity);
+ outerOpacityAnim.setDuration(inflectionDuration);
outerOpacityAnim.setInterpolator(LINEAR_INTERPOLATOR);
// Chain the outer opacity exit animation.
- final int outerDuration = opacityDuration - outerInflection;
+ final int outerDuration = opacityDuration - inflectionDuration;
if (outerDuration > 0) {
final RenderNodeAnimator outerFadeOutAnim = new RenderNodeAnimator(
mPropOuterPaint, RenderNodeAnimator.PAINT_ALPHA, 0);
outerFadeOutAnim.setDuration(outerDuration);
outerFadeOutAnim.setInterpolator(LINEAR_INTERPOLATOR);
- outerFadeOutAnim.setStartDelay(outerInflection);
+ outerFadeOutAnim.setStartDelay(inflectionDuration);
outerFadeOutAnim.setStartValue(inflectionOpacity);
outerFadeOutAnim.addListener(mAnimationListener);
@@ -320,7 +327,7 @@
*/
public void jump() {
endSoftwareAnimations();
- endHardwareAnimations();
+ cancelHardwareAnimations(true);
}
private void endSoftwareAnimations() {
@@ -330,23 +337,6 @@
}
}
- private void endHardwareAnimations() {
- final ArrayList<RenderNodeAnimator> runningAnimations = mRunningAnimations;
- final int N = runningAnimations.size();
- for (int i = 0; i < N; i++) {
- runningAnimations.get(i).end();
- }
- runningAnimations.clear();
-
- // Abort any pending animations. Since we always have a completion
- // listener on a pending animation, we also need to remove ourselves.
- if (!mPendingAnimations.isEmpty()) {
- mPendingAnimations.clear();
- }
-
- mHardwareAnimating = false;
- }
-
private Paint getTempPaint() {
if (mTempPaint == null) {
mTempPaint = new Paint();
@@ -354,18 +344,18 @@
return mTempPaint;
}
- private void exitSoftware(int opacityDuration, int outerInflection, int inflectionOpacity) {
+ private void exitSoftware(int opacityDuration, int inflectionDuration, int inflectionOpacity) {
final ObjectAnimator outerOpacityAnim;
- if (outerInflection > 0) {
+ if (inflectionDuration > 0) {
// Outer opacity continues to increase for a bit.
outerOpacityAnim = ObjectAnimator.ofFloat(this,
"outerOpacity", inflectionOpacity / 255.0f);
outerOpacityAnim.setAutoCancel(true);
- outerOpacityAnim.setDuration(outerInflection);
+ outerOpacityAnim.setDuration(inflectionDuration);
outerOpacityAnim.setInterpolator(LINEAR_INTERPOLATOR);
// Chain the outer opacity exit animation.
- final int outerDuration = opacityDuration - outerInflection;
+ final int outerDuration = opacityDuration - inflectionDuration;
if (outerDuration > 0) {
outerOpacityAnim.addListener(new AnimatorListenerAdapter() {
@Override
@@ -446,14 +436,4 @@
mHardwareAnimating = false;
}
};
-
- /**
- * Interpolator with a smooth log deceleration
- */
- private static final class LogInterpolator implements TimeInterpolator {
- @Override
- public float getInterpolation(float input) {
- return 1 - (float) Math.pow(400, -input * 1.4);
- }
- }
}
diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java
index fa762b7..b05fb61 100644
--- a/graphics/java/android/graphics/drawable/RippleDrawable.java
+++ b/graphics/java/android/graphics/drawable/RippleDrawable.java
@@ -242,7 +242,7 @@
@Override
protected boolean onStateChange(int[] stateSet) {
- super.onStateChange(stateSet);
+ final boolean changed = super.onStateChange(stateSet);
boolean enabled = false;
boolean pressed = false;
@@ -263,19 +263,7 @@
setRippleActive(enabled && pressed);
setBackgroundActive(focused || (enabled && pressed));
- // Update the paint color. Only applicable when animated in software.
- if (mRipplePaint != null && mState.mColor != null) {
- final ColorStateList stateList = mState.mColor;
- final int newColor = stateList.getColorForState(stateSet, 0);
- final int oldColor = mRipplePaint.getColor();
- if (oldColor != newColor) {
- mRipplePaint.setColor(newColor);
- invalidateSelf();
- return true;
- }
- }
-
- return false;
+ return changed;
}
private void setRippleActive(boolean active) {
@@ -587,6 +575,10 @@
ripples[i].onHotspotBoundsChanged();
}
+ if (mRipple != null) {
+ mRipple.onHotspotBoundsChanged();
+ }
+
if (mBackground != null) {
mBackground.onHotspotBoundsChanged();
}
@@ -617,17 +609,23 @@
final boolean drawNonMaskContent = mLayerState.mNum > (hasMask ? 1 : 0);
final boolean drawMask = hasMask && mMask.getOpacity() != PixelFormat.OPAQUE;
final Rect bounds = getDirtyBounds();
+ final int saveCount = canvas.save(Canvas.CLIP_SAVE_FLAG);
+ canvas.clipRect(bounds);
// If we have content, draw it into a layer first.
- final int contentLayer = drawNonMaskContent ?
- drawContentLayer(canvas, bounds, SRC_OVER) : -1;
+ final int contentLayer;
+ if (drawNonMaskContent) {
+ contentLayer = drawContentLayer(canvas, bounds, SRC_OVER);
+ } else {
+ contentLayer = -1;
+ }
// Next, try to draw the ripples (into a layer if necessary). If we need
// to mask against the underlying content, set the xfermode to SRC_ATOP.
final PorterDuffXfermode xfermode = (hasMask || !drawNonMaskContent) ? SRC_OVER : SRC_ATOP;
// If we have a background and a non-opaque mask, draw the masking layer.
- final int backgroundLayer = drawBackgroundLayer(canvas, bounds, xfermode);
+ final int backgroundLayer = drawBackgroundLayer(canvas, bounds, xfermode, drawMask);
if (backgroundLayer >= 0) {
if (drawMask) {
drawMaskingLayer(canvas, bounds, DST_IN);
@@ -644,10 +642,13 @@
canvas.restoreToCount(rippleLayer);
}
- // Composite the layers if needed.
- if (contentLayer >= 0) {
- canvas.restoreToCount(contentLayer);
+ // If we failed to draw anything, at least draw a color so that
+ // invalidation works correctly.
+ if (contentLayer < 0 && backgroundLayer < 0 && rippleLayer < 0) {
+ canvas.drawColor(Color.TRANSPARENT);
}
+
+ canvas.restoreToCount(saveCount);
}
/**
@@ -711,81 +712,29 @@
return restoreToCount;
}
- private int drawBackgroundLayer(Canvas canvas, Rect bounds, PorterDuffXfermode mode) {
- // Separate the ripple color and alpha channel. The alpha will be
- // applied when we merge the ripples down to the canvas.
- final int rippleARGB;
- if (mState.mColor != null) {
- rippleARGB = mState.mColor.getColorForState(getState(), Color.TRANSPARENT);
- } else {
- rippleARGB = Color.TRANSPARENT;
+ private int drawBackgroundLayer(
+ Canvas canvas, Rect bounds, PorterDuffXfermode mode, boolean drawMask) {
+ int saveCount = -1;
+
+ if (mBackground != null && mBackground.shouldDraw()) {
+ // TODO: We can avoid saveLayer here if we push the xfermode into
+ // the background's render thread animator at exit() time.
+ if (drawMask || mode != SRC_OVER) {
+ saveCount = canvas.saveLayer(bounds.left, bounds.top, bounds.right,
+ bounds.bottom, getMaskingPaint(mode));
+ }
+
+ final float x = mHotspotBounds.exactCenterX();
+ final float y = mHotspotBounds.exactCenterY();
+ canvas.translate(x, y);
+ mBackground.draw(canvas, getRipplePaint());
+ canvas.translate(-x, -y);
}
- if (mRipplePaint == null) {
- mRipplePaint = new Paint();
- mRipplePaint.setAntiAlias(true);
- }
-
- final int rippleAlpha = Color.alpha(rippleARGB);
- final Paint ripplePaint = mRipplePaint;
- ripplePaint.setColor(rippleARGB);
- ripplePaint.setAlpha(0xFF);
-
- boolean drewRipples = false;
- int restoreToCount = -1;
- int restoreTranslate = -1;
-
- // Draw background.
- final RippleBackground background = mBackground;
- if (background != null) {
- // If we're masking the ripple layer, make sure we have a layer
- // first. This will merge SRC_OVER (directly) onto the canvas.
- final Paint maskingPaint = getMaskingPaint(mode);
- maskingPaint.setAlpha(rippleAlpha);
- restoreToCount = canvas.saveLayer(bounds.left, bounds.top,
- bounds.right, bounds.bottom, maskingPaint);
-
- restoreTranslate = canvas.save();
- // Translate the canvas to the current hotspot bounds.
- canvas.translate(mHotspotBounds.exactCenterX(), mHotspotBounds.exactCenterY());
-
- drewRipples = background.draw(canvas, ripplePaint);
- }
-
- // Always restore the translation.
- if (restoreTranslate >= 0) {
- canvas.restoreToCount(restoreTranslate);
- }
-
- // If we created a layer with no content, merge it immediately.
- if (restoreToCount >= 0 && !drewRipples) {
- canvas.restoreToCount(restoreToCount);
- restoreToCount = -1;
- }
-
- return restoreToCount;
+ return saveCount;
}
private int drawRippleLayer(Canvas canvas, Rect bounds, PorterDuffXfermode mode) {
- // Separate the ripple color and alpha channel. The alpha will be
- // applied when we merge the ripples down to the canvas.
- final int rippleARGB;
- if (mState.mColor != null) {
- rippleARGB = mState.mColor.getColorForState(getState(), Color.TRANSPARENT);
- } else {
- rippleARGB = Color.TRANSPARENT;
- }
-
- if (mRipplePaint == null) {
- mRipplePaint = new Paint();
- mRipplePaint.setAntiAlias(true);
- }
-
- final int rippleAlpha = Color.alpha(rippleARGB);
- final Paint ripplePaint = mRipplePaint;
- ripplePaint.setColor(rippleARGB);
- ripplePaint.setAlpha(0xFF);
-
boolean drewRipples = false;
int restoreToCount = -1;
int restoreTranslate = -1;
@@ -807,16 +756,21 @@
// first. This will merge SRC_OVER (directly) onto the canvas.
if (restoreToCount < 0) {
final Paint maskingPaint = getMaskingPaint(mode);
- maskingPaint.setAlpha(rippleAlpha);
+ final int color = mState.mColor.getColorForState(getState(), Color.TRANSPARENT);
+ final int alpha = Color.alpha(color);
+ maskingPaint.setAlpha(alpha / 2);
+
+ // TODO: We can avoid saveLayer here if we're only drawing one
+ // ripple and we don't have content or a translucent mask.
restoreToCount = canvas.saveLayer(bounds.left, bounds.top,
bounds.right, bounds.bottom, maskingPaint);
- restoreTranslate = canvas.save();
// Translate the canvas to the current hotspot bounds.
+ restoreTranslate = canvas.save();
canvas.translate(mHotspotBounds.exactCenterX(), mHotspotBounds.exactCenterY());
}
- drewRipples |= ripple.draw(canvas, ripplePaint);
+ drewRipples |= ripple.draw(canvas, getRipplePaint());
}
// Always restore the translation.
@@ -845,6 +799,14 @@
return restoreToCount;
}
+ private Paint getRipplePaint() {
+ if (mRipplePaint == null) {
+ mRipplePaint = new Paint();
+ mRipplePaint.setAntiAlias(true);
+ }
+ return mRipplePaint;
+ }
+
private Paint getMaskingPaint(PorterDuffXfermode xfermode) {
if (mMaskingPaint == null) {
mMaskingPaint = new Paint();
diff --git a/libs/hwui/AnimationContext.cpp b/libs/hwui/AnimationContext.cpp
index 716dcf5..a20bdae 100644
--- a/libs/hwui/AnimationContext.cpp
+++ b/libs/hwui/AnimationContext.cpp
@@ -17,7 +17,6 @@
#include "Animator.h"
#include "RenderNode.h"
-#include "TreeInfo.h"
#include "renderthread/TimeLord.h"
namespace android {
@@ -34,7 +33,7 @@
}
void AnimationContext::destroy() {
- startFrame();
+ startFrame(TreeInfo::MODE_RT_ONLY);
while (mCurrentFrameAnimations.mNextHandle) {
AnimationHandle* current = mCurrentFrameAnimations.mNextHandle;
AnimatorManager& animators = current->mRenderNode->animators();
@@ -55,7 +54,7 @@
handle->insertAfter(&mNextFrameAnimations);
}
-void AnimationContext::startFrame() {
+void AnimationContext::startFrame(TreeInfo::TraversalMode mode) {
LOG_ALWAYS_FATAL_IF(mCurrentFrameAnimations.mNextHandle,
"Missed running animations last frame!");
AnimationHandle* head = mNextFrameAnimations.mNextHandle;
diff --git a/libs/hwui/AnimationContext.h b/libs/hwui/AnimationContext.h
index 9b3d5f4..909ed36 100644
--- a/libs/hwui/AnimationContext.h
+++ b/libs/hwui/AnimationContext.h
@@ -20,6 +20,7 @@
#include <utils/RefBase.h>
#include <utils/StrongPointer.h>
+#include "TreeInfo.h"
#include "renderthread/TimeLord.h"
#include "utils/Macros.h"
@@ -30,7 +31,6 @@
class AnimationListener;
class BaseRenderNodeAnimator;
class RenderNode;
-class TreeInfo;
/*
* AnimationHandle is several classes merged into one.
@@ -90,7 +90,7 @@
// Marks the start of a frame, which will update the frame time and move all
// next frame animations into the current frame
- ANDROID_API virtual void startFrame();
+ ANDROID_API virtual void startFrame(TreeInfo::TraversalMode mode);
// Runs any animations still left in mCurrentFrameAnimations that were not run
// as part of the standard RenderNode:prepareTree pass.
diff --git a/libs/hwui/RenderProperties.h b/libs/hwui/RenderProperties.h
index 0c8d07f..46eeb6a 100644
--- a/libs/hwui/RenderProperties.h
+++ b/libs/hwui/RenderProperties.h
@@ -569,6 +569,10 @@
return getClipToBounds() && (getZ() <= 0 || getOutline().isEmpty());
}
+ bool hasShadow() const {
+ return getZ() >= 0.0f && getOutline().getPath() != NULL;
+ }
+
private:
// Rendering properties
struct PrimitiveFields {
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 4129a89..5e6796c 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -150,7 +150,7 @@
if (mPrefetechedLayers.size() && info.mode == TreeInfo::MODE_FULL) {
info.canvasContext = this;
}
- mAnimationContext->startFrame();
+ mAnimationContext->startFrame(info.mode);
mRootRenderNode->prepareTree(info);
mAnimationContext->runRemainingAnimations(info);
diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index 308f783..9b644f4 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -530,7 +530,6 @@
}
}
- /** @hide */
public static final Parcelable.Creator<AudioAttributes> CREATOR
= new Parcelable.Creator<AudioAttributes>() {
/**
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 9ee7027..e3b8985 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -243,7 +243,7 @@
* or unplugged.
* An integer value of 1 indicates a plugged-in state, 0 is unplugged.
*/
- public static final String EXTRA_AUDIO_PLUG_STATE = "android.media.extra.audio_plug_state";
+ public static final String EXTRA_AUDIO_PLUG_STATE = "android.media.extra.AUDIO_PLUG_STATE";
/**
* Extra used in {@link #ACTION_HDMI_AUDIO_PLUG} to define the maximum number of channels
@@ -251,7 +251,7 @@
* The corresponding integer value is only available when the device is plugged in (as expressed
* by {@link #EXTRA_AUDIO_PLUG_STATE}).
*/
- public static final String EXTRA_MAX_CHANNEL_COUNT = "android.media.extra.max_channel_count";
+ public static final String EXTRA_MAX_CHANNEL_COUNT = "android.media.extra.MAX_CHANNEL_COUNT";
/**
* Extra used in {@link #ACTION_HDMI_AUDIO_PLUG} to define the audio encodings supported by
@@ -261,7 +261,7 @@
* {@link AudioFormat} (for instance see {@link AudioFormat#ENCODING_PCM_16BIT}). Use
* {@link android.content.Intent#getIntArrayExtra(String)} to retrieve the encoding values.
*/
- public static final String EXTRA_ENCODINGS = "android.media.extra.encodings";
+ public static final String EXTRA_ENCODINGS = "android.media.extra.ENCODINGS";
/**
* Broadcast Action: An analog audio speaker/headset plugged in or unplugged.
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 3e8ee93..675916b 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -1622,8 +1622,7 @@
* @throws IllegalStateException if in the Uninitialized state.
*/
public MediaCodecInfo getCodecInfo() {
- return MediaCodecList.getCodecInfoAt(
- MediaCodecList.findCodecByName(getName()));
+ return MediaCodecList.getInfoFor(getName());
}
private native final ByteBuffer[] getBuffers(boolean input);
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index 323a3e3..01f8193 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -321,6 +321,9 @@
// check feature support
for (Feature feat: getValidFeatures()) {
Integer yesNo = (Integer)map.get(MediaFormat.KEY_FEATURE_ + feat.mName);
+ if (yesNo == null) {
+ continue;
+ }
if ((yesNo == 1 && !isFeatureSupported(feat.mName)) ||
(yesNo == 0 && isFeatureRequired(feat.mName))) {
return false;
@@ -414,7 +417,7 @@
* profile} and {@code level}. If the type, or profile-level combination
* is not understood by the framework, it returns null.
*/
- public static CodecCapabilities CreateFromProfileLevel(
+ public static CodecCapabilities createFromProfileLevel(
String mime, int profile, int level) {
CodecProfileLevel pl = new CodecProfileLevel();
pl.profile = profile;
@@ -470,13 +473,12 @@
Integer yesNo = (Integer)map.get(key);
if (yesNo == null) {
continue;
- } else if (yesNo > 0) {
- mFlagsRequired |= feat.mValue;
- mDefaultFormat.setInteger(key, 1);
- } else {
- mFlagsSupported |= feat.mValue;
- mDefaultFormat.setInteger(key, 1);
}
+ if (yesNo > 0) {
+ mFlagsRequired |= feat.mValue;
+ }
+ mFlagsSupported |= feat.mValue;
+ mDefaultFormat.setInteger(key, 1);
// TODO restrict features by mFlagsVerified once all codecs reliably verify them
}
}
diff --git a/media/java/android/media/MediaCodecList.java b/media/java/android/media/MediaCodecList.java
index 5084c5c..85e9b16 100644
--- a/media/java/android/media/MediaCodecList.java
+++ b/media/java/android/media/MediaCodecList.java
@@ -116,6 +116,11 @@
/* package private */ static native final int findCodecByName(String codec);
+ /** @hide */
+ public static MediaCodecInfo getInfoFor(String codec) {
+ return sAllCodecInfos[findCodecByName(codec)];
+ }
+
private static native final void native_init();
/**
diff --git a/packages/PrintSpooler/res/layout/preview_page_loading.xml b/packages/PrintSpooler/res/layout/preview_page_loading.xml
new file mode 100644
index 0000000..1af3a17
--- /dev/null
+++ b/packages/PrintSpooler/res/layout/preview_page_loading.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_margin="36dip"
+ android:layout_gravity="center"
+ android:src="@drawable/ic_grayedout_printer"
+ android:contentDescription="@null"
+ android:scaleType="centerInside"
+ android:adjustViewBounds="true">
+ </ImageView>
+
+</FrameLayout>
diff --git a/packages/PrintSpooler/res/values-land/constants.xml b/packages/PrintSpooler/res/values-land/constants.xml
index 6cf9754b5..84fc050 100644
--- a/packages/PrintSpooler/res/values-land/constants.xml
+++ b/packages/PrintSpooler/res/values-land/constants.xml
@@ -16,7 +16,7 @@
<resources>
- <integer name="preview_page_per_row_count">2</integer>
+ <integer name="preview_page_per_row_count">4</integer>
<integer name="print_option_column_count">3</integer>
diff --git a/packages/PrintSpooler/res/values/strings.xml b/packages/PrintSpooler/res/values/strings.xml
index 5b7fda3..27e1d51 100644
--- a/packages/PrintSpooler/res/values/strings.xml
+++ b/packages/PrintSpooler/res/values/strings.xml
@@ -76,7 +76,6 @@
<!-- Title for the print dialog announced to the user for accessibility. Not shown in the UI. [CHAR LIMIT=none] -->
<string name="print_dialog">Print dialog</string>
-
<!-- Template for the message that shows the current page out of the total number of pages -->
<string name="current_page_template"><xliff:g id="current_page">%1$d</xliff:g>
/<xliff:g id="page_count">%2$d</xliff:g></string>
diff --git a/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java b/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java
index 09e8b39..1e7a011 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/model/RemotePrintDocument.java
@@ -317,6 +317,11 @@
return mState == STATE_FAILED;
}
+ public boolean hasLaidOutPages() {
+ return mDocumentInfo.info != null
+ && mDocumentInfo.info.getPageCount() > 0;
+ }
+
public void clearUpdateError() {
if (!hasUpdateError()) {
throw new IllegalStateException("No update error to clear");
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java
index d949673..ce0b9b6 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java
@@ -17,6 +17,9 @@
package com.android.printspooler.ui;
import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.drawable.BitmapDrawable;
import android.os.ParcelFileDescriptor;
import android.print.PageRange;
import android.print.PrintAttributes.MediaSize;
@@ -26,12 +29,12 @@
import android.support.v7.widget.RecyclerView.ViewHolder;
import android.util.Log;
import android.util.SparseArray;
-import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
+import android.view.View.MeasureSpec;
import android.widget.TextView;
import com.android.printspooler.R;
import com.android.printspooler.model.PageContentRepository;
@@ -48,7 +51,7 @@
* This class represents the adapter for the pages in the print preview list.
*/
public final class PageAdapter extends Adapter implements
- PageContentRepository.OnMalformedPdfFileListener{
+ PageContentRepository.OnMalformedPdfFileListener {
private static final String LOG_TAG = "PageAdapter";
private static final int MAX_PREVIEW_PAGES_BATCH = 50;
@@ -86,6 +89,8 @@
// Pages the user selected in the UI.
private PageRange[] mSelectedPages;
+ private BitmapDrawable mEmptyState;
+
private int mDocumentPageCount = PrintDocumentInfo.PAGE_COUNT_UNKNOWN;
private int mSelectedPageCount;
@@ -257,7 +262,7 @@
}
if (updatePreviewAreaAndPageSize) {
- updatePreviewAreaAndPageSize();
+ updatePreviewAreaPageSizeAndEmptyState();
}
if (documentChanged) {
@@ -318,12 +323,12 @@
}
// OK, there are bugs in recycler view which tries to bind views
- // without recycling them which would give us a chane to clean up.
+ // without recycling them which would give us a chance to clean up.
PageContentProvider boundProvider = mPageContentRepository
- .peekPageContentProvider(pageIndexInFile);
+ .peekPageContentProvider(pageIndexInFile);
if (boundProvider != null) {
PageContentView owner = (PageContentView) boundProvider.getOwner();
- owner.init(null, mMediaSize, mMinMargins);
+ owner.init(null, mEmptyState, mMediaSize, mMinMargins);
mPageContentRepository.releasePageContentProvider(boundProvider);
}
@@ -333,7 +338,7 @@
} else {
onSelectedPageNotInFile(pageInDocument);
}
- content.init(provider, mMediaSize, mMinMargins);
+ content.init(provider, mEmptyState, mMediaSize, mMinMargins);
View pageSelector = page.findViewById(R.id.page_selector);
pageSelector.setTag(myHolder);
@@ -384,7 +389,7 @@
mSelectedPages = selectedPages;
mSelectedPageCount = PageRangeUtils.getNormalizedPageCount(
mSelectedPages, mDocumentPageCount);
- updatePreviewAreaAndPageSize();
+ updatePreviewAreaPageSizeAndEmptyState();
notifyDataSetChanged();
}
return mSelectedPages;
@@ -392,12 +397,12 @@
public void onPreviewAreaSizeChanged() {
if (mMediaSize != null) {
- updatePreviewAreaAndPageSize();
+ updatePreviewAreaPageSizeAndEmptyState();
notifyDataSetChanged();
}
}
- private void updatePreviewAreaAndPageSize() {
+ private void updatePreviewAreaPageSizeAndEmptyState() {
final int availableWidth = mPreviewArea.getWidth();
final int availableHeight = mPreviewArea.getHeight();
@@ -419,7 +424,7 @@
final int pageContentDesiredHeight = (int) (((float) pageContentDesiredWidth
/ pageAspectRatio) + 0.5f);
- // If the page does not fit entirely in a vertial direction,
+ // If the page does not fit entirely in a vertical direction,
// we shirk it but not less than the minimal page width.
final int pageContentMinHeight = (int) (mPreviewPageMinWidth / pageAspectRatio + 0.5f);
final int pageContentMaxHeight = Math.max(pageContentMinHeight,
@@ -448,6 +453,23 @@
mPreviewArea.setPadding(horizontalPadding, verticalPadding,
horizontalPadding, verticalPadding);
+
+ // Now update the empty state drawable, as it depends on the page
+ // size and is reused for all views for better performance.
+ LayoutInflater inflater = LayoutInflater.from(mContext);
+ View content = inflater.inflate(R.layout.preview_page_loading, null, false);
+ content.measure(MeasureSpec.makeMeasureSpec(mPageContentWidth, MeasureSpec.EXACTLY),
+ MeasureSpec.makeMeasureSpec(mPageContentHeight, MeasureSpec.EXACTLY));
+ content.layout(0, 0, content.getMeasuredWidth(), content.getMeasuredHeight());
+
+ Bitmap bitmap = Bitmap.createBitmap(mPageContentWidth, mPageContentHeight,
+ Bitmap.Config.ARGB_8888);
+ Canvas canvas = new Canvas(bitmap);
+ content.draw(canvas);
+
+ // Do not recycle the old bitmap if such as it may be set as an empty
+ // state to any of the page views. Just let the GC take care of it.
+ mEmptyState = new BitmapDrawable(mContext.getResources(), bitmap);
}
private PageRange[] computeSelectedPages() {
@@ -718,7 +740,7 @@
private void recyclePageView(PageContentView page, int pageIndexInAdapter) {
PageContentProvider provider = page.getPageContentProvider();
if (provider != null) {
- page.init(null, null, null);
+ page.init(null, null, null, null);
mPageContentRepository.releasePageContentProvider(provider);
mBoundPagesInAdapter.remove(pageIndexInAdapter);
}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
index 022e0d0..535081f 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
@@ -114,14 +114,15 @@
private static final int DEST_ADAPTER_ITEM_ID_SAVE_AS_PDF = Integer.MAX_VALUE;
private static final int DEST_ADAPTER_ITEM_ID_ALL_PRINTERS = Integer.MAX_VALUE - 1;
- private static final int STATE_CONFIGURING = 0;
- private static final int STATE_PRINT_CONFIRMED = 1;
- private static final int STATE_PRINT_CANCELED = 2;
- private static final int STATE_UPDATE_FAILED = 3;
- private static final int STATE_CREATE_FILE_FAILED = 4;
- private static final int STATE_PRINTER_UNAVAILABLE = 5;
- private static final int STATE_UPDATE_SLOW = 6;
- private static final int STATE_PRINT_COMPLETED = 7;
+ private static final int STATE_INITIALIZING = 0;
+ private static final int STATE_CONFIGURING = 1;
+ private static final int STATE_PRINT_CONFIRMED = 2;
+ private static final int STATE_PRINT_CANCELED = 3;
+ private static final int STATE_UPDATE_FAILED = 4;
+ private static final int STATE_CREATE_FILE_FAILED = 5;
+ private static final int STATE_PRINTER_UNAVAILABLE = 6;
+ private static final int STATE_UPDATE_SLOW = 7;
+ private static final int STATE_PRINT_COMPLETED = 8;
private static final int UI_STATE_PREVIEW = 0;
private static final int UI_STATE_ERROR = 1;
@@ -196,7 +197,7 @@
private int mCurrentPageCount;
- private int mState;
+ private int mState = STATE_INITIALIZING;
private int mUiState = UI_STATE_PREVIEW;
@@ -290,10 +291,17 @@
mPrintedDocument.start();
ensurePreviewUiShown();
+
+ setState(STATE_CONFIGURING);
}
@Override
public void onPause() {
+ if (mState == STATE_INITIALIZING) {
+ super.onPause();
+ return;
+ }
+
if (isFinishing()) {
PrintSpoolerService spooler = mSpoolerProvider.getSpooler();
spooler.updatePrintJobUserConfigurableOptionsNoPersistence(mPrintJob);
@@ -341,9 +349,13 @@
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
+ if (mState == STATE_INITIALIZING) {
+ return super.onKeyUp(keyCode, event);
+ }
+
if (keyCode == KeyEvent.KEYCODE_BACK
&& event.isTracking() && !event.isCanceled()) {
- if (mPrintPreviewController != null&&mPrintPreviewController.isOptionsOpened()
+ if (mPrintPreviewController != null && mPrintPreviewController.isOptionsOpened()
&& !hasErrors()) {
mPrintPreviewController.closeOptions();
} else {
@@ -900,7 +912,7 @@
final boolean willUpdate = mPrintedDocument.update(mPrintJob.getAttributes(),
pages, preview);
- if (willUpdate) {
+ if (willUpdate && !mPrintedDocument.hasLaidOutPages()) {
// When the update is done we update the print preview.
mProgressMessageController.post();
return true;
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintPreviewController.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintPreviewController.java
index 2b5b41b..a25e05e 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintPreviewController.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintPreviewController.java
@@ -195,6 +195,7 @@
if (mPageAdapter.isOpened()) {
mPageAdapter.close(null);
}
+ mRecyclerView.setAdapter(null);
mPageAdapter.destroy();
}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/widget/PageContentView.java b/packages/PrintSpooler/src/com/android/printspooler/widget/PageContentView.java
index 23a01bd..e2ae758 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/widget/PageContentView.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/widget/PageContentView.java
@@ -17,17 +17,15 @@
package com.android.printspooler.widget;
import android.content.Context;
-import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
import android.print.PrintAttributes.MediaSize;
import android.print.PrintAttributes.Margins;
import android.util.AttributeSet;
-import android.util.TypedValue;
import android.view.View;
import com.android.printspooler.model.PageContentRepository;
-import com.android.printspooler.model.PageContentRepository.PageContentProvider;
import com.android.printspooler.model.PageContentRepository.RenderSpec;
+import com.android.printspooler.model.PageContentRepository.PageContentProvider;
/**
* This class represents a page in the print preview list. The width of the page
@@ -37,35 +35,20 @@
*/
public class PageContentView extends View
implements PageContentRepository.OnPageContentAvailableCallback {
-
- private final ColorDrawable mEmptyState;
-
private PageContentProvider mProvider;
private MediaSize mMediaSize;
private Margins mMinMargins;
+ private Drawable mEmptyState;
+
private boolean mContentRequested;
private boolean mNeedsLayout;
public PageContentView(Context context, AttributeSet attrs) {
super(context, attrs);
-
- TypedValue typedValue = new TypedValue();
- context.getTheme().resolveAttribute(com.android.internal.R.attr.textColorPrimary,
- typedValue, true);
-
- mEmptyState = new ColorDrawable(typedValue.data);
-
- setBackground(mEmptyState);
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
- requestPageContentIfNeeded();
}
@Override
@@ -85,15 +68,19 @@
return mProvider;
}
- public void init(PageContentProvider provider, MediaSize mediaSize, Margins minMargins) {
+ public void init(PageContentProvider provider, Drawable emptyState,
+ MediaSize mediaSize, Margins minMargins) {
final boolean providerChanged = (mProvider == null)
? provider != null : !mProvider.equals(provider);
+ final boolean loadingDrawableChanged = (mEmptyState == null)
+ ? mEmptyState != null : !mEmptyState.equals(emptyState);
final boolean mediaSizeChanged = (mMediaSize == null)
? mediaSize != null : !mMediaSize.equals(mediaSize);
final boolean marginsChanged = (mMinMargins == null)
? minMargins != null : !mMinMargins.equals(minMargins);
- if (!providerChanged && !mediaSizeChanged && !marginsChanged) {
+ if (!providerChanged && !mediaSizeChanged
+ && !marginsChanged && !loadingDrawableChanged) {
return;
}
@@ -101,6 +88,7 @@
mMediaSize = mediaSize;
mMinMargins = minMargins;
+ mEmptyState = emptyState;
mContentRequested = false;
mNeedsLayout = mNeedsLayout || mediaSizeChanged || marginsChanged;
diff --git a/services/core/java/com/android/server/NativeDaemonEvent.java b/services/core/java/com/android/server/NativeDaemonEvent.java
index 2095152..59d50bd 100644
--- a/services/core/java/com/android/server/NativeDaemonEvent.java
+++ b/services/core/java/com/android/server/NativeDaemonEvent.java
@@ -201,20 +201,16 @@
}
while (current < length) {
// find the end of the word
- if (quoted) {
- wordEnd = current;
- while ((wordEnd = rawEvent.indexOf('\"', wordEnd)) != -1) {
- if (rawEvent.charAt(wordEnd - 1) != '\\') {
- break;
- } else {
- wordEnd++; // skip this escaped quote and keep looking
- }
+ char terminator = quoted ? '\"' : ' ';
+ wordEnd = current;
+ while (wordEnd < length && rawEvent.charAt(wordEnd) != terminator) {
+ if (rawEvent.charAt(wordEnd) == '\\') {
+ // skip the escaped char
+ ++wordEnd;
}
- } else {
- wordEnd = rawEvent.indexOf(' ', current);
+ ++wordEnd;
}
- // if we didn't find the end-o-word token, take the rest of the string
- if (wordEnd == -1) wordEnd = length;
+ if (wordEnd > length) wordEnd = length;
String word = rawEvent.substring(current, wordEnd);
current += word.length();
if (!quoted) {
diff --git a/services/core/java/com/android/server/NsdService.java b/services/core/java/com/android/server/NsdService.java
index cf7e65c..cb1748d 100644
--- a/services/core/java/com/android/server/NsdService.java
+++ b/services/core/java/com/android/server/NsdService.java
@@ -397,8 +397,7 @@
break;
case NsdManager.NATIVE_DAEMON_EVENT:
NativeEvent event = (NativeEvent) msg.obj;
- if (!handleNativeEvent(event.code, event.raw,
- NativeDaemonEvent.unescapeArgs(event.raw))) {
+ if (!handleNativeEvent(event.code, event.raw, event.cooked)) {
result = NOT_HANDLED;
}
break;
@@ -474,8 +473,14 @@
case NativeResponseCode.SERVICE_RESOLVED:
/* NNN resolveId fullName hostName port txtlen txtdata */
if (DBG) Slog.d(TAG, "SERVICE_RESOLVED Raw: " + raw);
- int index = cooked[2].indexOf(".");
- if (index == -1) {
+ int index = 0;
+ while (index < cooked[2].length() && cooked[2].charAt(index) != '.') {
+ if (cooked[2].charAt(index) == '\\') {
+ ++index;
+ }
+ ++index;
+ }
+ if (index >= cooked[2].length()) {
Slog.e(TAG, "Invalid service found " + raw);
break;
}
@@ -483,6 +488,8 @@
String rest = cooked[2].substring(index);
String type = rest.replace(".local.", "");
+ name = unescape(name);
+
clientInfo.mResolvedService.setServiceName(name);
clientInfo.mResolvedService.setServiceType(type);
clientInfo.mResolvedService.setPort(Integer.parseInt(cooked[4]));
@@ -541,6 +548,30 @@
}
}
+ private String unescape(String s) {
+ StringBuilder sb = new StringBuilder(s.length());
+ for (int i = 0; i < s.length(); ++i) {
+ char c = s.charAt(i);
+ if (c == '\\') {
+ if (++i >= s.length()) {
+ Slog.e(TAG, "Unexpected end of escape sequence in: " + s);
+ break;
+ }
+ c = s.charAt(i);
+ if (c != '.' && c != '\\') {
+ if (i + 2 >= s.length()) {
+ Slog.e(TAG, "Unexpected end of escape sequence in: " + s);
+ break;
+ }
+ c = (char) ((c-'0') * 100 + (s.charAt(i+1)-'0') * 10 + (s.charAt(i+2)-'0'));
+ i += 2;
+ }
+ }
+ sb.append(c);
+ }
+ return sb.toString();
+ }
+
private NativeDaemonConnector mNativeConnector;
private final CountDownLatch mNativeDaemonConnected = new CountDownLatch(1);
@@ -625,10 +656,12 @@
private class NativeEvent {
final int code;
final String raw;
+ final String[] cooked;
- NativeEvent(int code, String raw) {
+ NativeEvent(int code, String raw, String[] cooked) {
this.code = code;
this.raw = raw;
+ this.cooked = cooked;
}
}
@@ -644,7 +677,7 @@
public boolean onEvent(int code, String raw, String[] cooked) {
// TODO: NDC translates a message to a callback, we could enhance NDC to
// directly interact with a state machine through messages
- NativeEvent event = new NativeEvent(code, raw);
+ NativeEvent event = new NativeEvent(code, raw, cooked);
mNsdStateMachine.sendMessage(NsdManager.NATIVE_DAEMON_EVENT, event);
return true;
}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 9a00923..89ea905 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -897,10 +897,9 @@
private static class Callbacks extends Handler {
private static final int MSG_SESSION_CREATED = 1;
private static final int MSG_SESSION_BADGING_CHANGED = 2;
- private static final int MSG_SESSION_OPENED = 3;
+ private static final int MSG_SESSION_ACTIVE_CHANGED = 3;
private static final int MSG_SESSION_PROGRESS_CHANGED = 4;
- private static final int MSG_SESSION_CLOSED = 5;
- private static final int MSG_SESSION_FINISHED = 6;
+ private static final int MSG_SESSION_FINISHED = 5;
private final RemoteCallbackList<IPackageInstallerCallback>
mCallbacks = new RemoteCallbackList<>();
@@ -945,15 +944,12 @@
case MSG_SESSION_BADGING_CHANGED:
callback.onSessionBadgingChanged(sessionId);
break;
- case MSG_SESSION_OPENED:
- callback.onSessionOpened(sessionId);
+ case MSG_SESSION_ACTIVE_CHANGED:
+ callback.onSessionActiveChanged(sessionId, (boolean) msg.obj);
break;
case MSG_SESSION_PROGRESS_CHANGED:
callback.onSessionProgressChanged(sessionId, (float) msg.obj);
break;
- case MSG_SESSION_CLOSED:
- callback.onSessionClosed(sessionId);
- break;
case MSG_SESSION_FINISHED:
callback.onSessionFinished(sessionId, (boolean) msg.obj);
break;
@@ -968,18 +964,14 @@
obtainMessage(MSG_SESSION_BADGING_CHANGED, sessionId, userId).sendToTarget();
}
- private void notifySessionOpened(int sessionId, int userId) {
- obtainMessage(MSG_SESSION_OPENED, sessionId, userId).sendToTarget();
+ private void notifySessionActiveChanged(int sessionId, int userId, boolean active) {
+ obtainMessage(MSG_SESSION_ACTIVE_CHANGED, sessionId, userId, active).sendToTarget();
}
private void notifySessionProgressChanged(int sessionId, int userId, float progress) {
obtainMessage(MSG_SESSION_PROGRESS_CHANGED, sessionId, userId, progress).sendToTarget();
}
- private void notifySessionClosed(int sessionId, int userId) {
- obtainMessage(MSG_SESSION_CLOSED, sessionId, userId).sendToTarget();
- }
-
public void notifySessionFinished(int sessionId, int userId, boolean success) {
obtainMessage(MSG_SESSION_FINISHED, sessionId, userId, success).sendToTarget();
}
@@ -1022,18 +1014,14 @@
writeSessionsAsync();
}
- public void onSessionOpened(PackageInstallerSession session) {
- mCallbacks.notifySessionOpened(session.sessionId, session.userId);
+ public void onSessionActiveChanged(PackageInstallerSession session, boolean active) {
+ mCallbacks.notifySessionActiveChanged(session.sessionId, session.userId, active);
}
public void onSessionProgressChanged(PackageInstallerSession session, float progress) {
mCallbacks.notifySessionProgressChanged(session.sessionId, session.userId, progress);
}
- public void onSessionClosed(PackageInstallerSession session) {
- mCallbacks.notifySessionClosed(session.sessionId, session.userId);
- }
-
public void onSessionFinished(PackageInstallerSession session, boolean success) {
mCallbacks.notifySessionFinished(session.sessionId, session.userId, success);
synchronized (mSessions) {
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 85ff54e..f8273c0 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -227,7 +227,7 @@
mResolvedBaseFile.getAbsolutePath() : null;
info.progress = mProgress;
info.sealed = mSealed;
- info.open = mOpenCount.get() > 0;
+ info.active = mOpenCount.get() > 0;
info.mode = params.mode;
info.sizeBytes = params.sizeBytes;
@@ -833,14 +833,14 @@
public void open() {
if (mOpenCount.getAndIncrement() == 0) {
- mCallback.onSessionOpened(this);
+ mCallback.onSessionActiveChanged(this, true);
}
}
@Override
public void close() {
if (mOpenCount.decrementAndGet() == 0) {
- mCallback.onSessionClosed(this);
+ mCallback.onSessionActiveChanged(this, false);
}
}
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index 8af5e98..1d9e6a9 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -38,8 +38,8 @@
import static com.android.internal.telephony.PhoneConstants.SUBSCRIPTION_KEY;
import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ISO_COUNTRY;
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_IDP_STRING;
import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY;
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_IDP_STRING;
import java.util.Locale;
import java.util.regex.Matcher;
@@ -2215,81 +2215,79 @@
cdmaCheckAndProcessPlusCodeByNumberFormat(String dialStr,int currFormat,int defaultFormat) {
String retStr = dialStr;
+ boolean useNanp = (currFormat == defaultFormat) && (currFormat == FORMAT_NANP);
+
// Checks if the plus sign character is in the passed-in dial string
if (dialStr != null &&
dialStr.lastIndexOf(PLUS_SIGN_STRING) != -1) {
- // Format the string based on the rules for the country the number is from,
- // and the current country the phone is camped on.
- if ((currFormat == defaultFormat) && (currFormat == FORMAT_NANP)) {
- // Handle case where default and current telephone numbering plans are NANP.
- String postDialStr = null;
- String tempDialStr = dialStr;
- // Sets the retStr to null since the conversion will be performed below.
- retStr = null;
- if (DBG) log("checkAndProcessPlusCode,dialStr=" + dialStr);
- // This routine is to process the plus sign in the dial string by loop through
- // the network portion, post dial portion 1, post dial portion 2... etc. if
- // applied
- do {
- String networkDialStr;
+ // Handle case where default and current telephone numbering plans are NANP.
+ String postDialStr = null;
+ String tempDialStr = dialStr;
+
+ // Sets the retStr to null since the conversion will be performed below.
+ retStr = null;
+ if (DBG) log("checkAndProcessPlusCode,dialStr=" + dialStr);
+ // This routine is to process the plus sign in the dial string by loop through
+ // the network portion, post dial portion 1, post dial portion 2... etc. if
+ // applied
+ do {
+ String networkDialStr;
+ // Format the string based on the rules for the country the number is from,
+ // and the current country the phone is camped
+ if (useNanp) {
networkDialStr = extractNetworkPortion(tempDialStr);
- // Handles the conversion within NANP
- networkDialStr = processPlusCodeWithinNanp(networkDialStr);
+ } else {
+ networkDialStr = extractNetworkPortionAlt(tempDialStr);
- // Concatenates the string that is converted from network portion
- if (!TextUtils.isEmpty(networkDialStr)) {
- if (retStr == null) {
- retStr = networkDialStr;
- } else {
- retStr = retStr.concat(networkDialStr);
- }
+ }
+
+ networkDialStr = processPlusCode(networkDialStr, useNanp);
+
+ // Concatenates the string that is converted from network portion
+ if (!TextUtils.isEmpty(networkDialStr)) {
+ if (retStr == null) {
+ retStr = networkDialStr;
} else {
- // This should never happen since we checked the if dialStr is null
- // and if it contains the plus sign in the beginning of this function.
- // The plus sign is part of the network portion.
- Rlog.e("checkAndProcessPlusCode: null newDialStr", networkDialStr);
- return dialStr;
+ retStr = retStr.concat(networkDialStr);
}
- postDialStr = extractPostDialPortion(tempDialStr);
- if (!TextUtils.isEmpty(postDialStr)) {
- int dialableIndex = findDialableIndexFromPostDialStr(postDialStr);
+ } else {
+ // This should never happen since we checked the if dialStr is null
+ // and if it contains the plus sign in the beginning of this function.
+ // The plus sign is part of the network portion.
+ Rlog.e("checkAndProcessPlusCode: null newDialStr", networkDialStr);
+ return dialStr;
+ }
+ postDialStr = extractPostDialPortion(tempDialStr);
+ if (!TextUtils.isEmpty(postDialStr)) {
+ int dialableIndex = findDialableIndexFromPostDialStr(postDialStr);
- // dialableIndex should always be greater than 0
- if (dialableIndex >= 1) {
- retStr = appendPwCharBackToOrigDialStr(dialableIndex,
- retStr,postDialStr);
- // Skips the P/W character, extracts the dialable portion
- tempDialStr = postDialStr.substring(dialableIndex);
- } else {
- // Non-dialable character such as P/W should not be at the end of
- // the dial string after P/W processing in CdmaConnection.java
- // Set the postDialStr to "" to break out of the loop
- if (dialableIndex < 0) {
- postDialStr = "";
- }
- Rlog.e("wrong postDialStr=", postDialStr);
+ // dialableIndex should always be greater than 0
+ if (dialableIndex >= 1) {
+ retStr = appendPwCharBackToOrigDialStr(dialableIndex,
+ retStr,postDialStr);
+ // Skips the P/W character, extracts the dialable portion
+ tempDialStr = postDialStr.substring(dialableIndex);
+ } else {
+ // Non-dialable character such as P/W should not be at the end of
+ // the dial string after P/W processing in CdmaConnection.java
+ // Set the postDialStr to "" to break out of the loop
+ if (dialableIndex < 0) {
+ postDialStr = "";
}
+ Rlog.e("wrong postDialStr=", postDialStr);
}
- if (DBG) log("checkAndProcessPlusCode,postDialStr=" + postDialStr);
- } while (!TextUtils.isEmpty(postDialStr) && !TextUtils.isEmpty(tempDialStr));
- } else {
- // TODO: Support NANP international conversion and other telephone numbering plans.
- // Currently the phone is never used in non-NANP system, so return the original
- // dial string.
- Rlog.e("checkAndProcessPlusCode:non-NANP not supported", dialStr);
- }
+ }
+ if (DBG) log("checkAndProcessPlusCode,postDialStr=" + postDialStr);
+ } while (!TextUtils.isEmpty(postDialStr) && !TextUtils.isEmpty(tempDialStr));
}
return retStr;
- }
+ }
- // This function gets the default international dialing prefix
- private static String getDefaultIdp( ) {
- String ps = null;
- SystemProperties.get(PROPERTY_IDP_STRING, ps);
- if (TextUtils.isEmpty(ps)) {
- ps = NANP_IDP_STRING;
- }
+ private static String getCurrentIdp(boolean useNanp) {
+ // in case, there is no IDD is found, we shouldn't convert it.
+ String ps = SystemProperties.get(
+ PROPERTY_OPERATOR_IDP_STRING, useNanp ? NANP_IDP_STRING : PLUS_SIGN_STRING);
return ps;
}
@@ -2399,31 +2397,32 @@
}
/**
- * This function handles the plus code conversion within NANP CDMA network
+ * This function handles the plus code conversion
* If the number format is
* 1)+1NANP,remove +,
* 2)other than +1NANP, any + numbers,replace + with the current IDP
*/
- private static String processPlusCodeWithinNanp(String networkDialStr) {
+ private static String processPlusCode(String networkDialStr, boolean useNanp) {
String retStr = networkDialStr;
- if (DBG) log("processPlusCodeWithinNanp,networkDialStr=" + networkDialStr);
+ if (DBG) log("processPlusCode, networkDialStr = " + networkDialStr
+ + "for NANP = " + useNanp);
// If there is a plus sign at the beginning of the dial string,
// Convert the plus sign to the default IDP since it's an international number
if (networkDialStr != null &&
networkDialStr.charAt(0) == PLUS_SIGN_CHAR &&
networkDialStr.length() > 1) {
String newStr = networkDialStr.substring(1);
- if (isOneNanp(newStr)) {
+ // TODO: for nonNanp, should the '+' be removed if following number is country code
+ if (useNanp && isOneNanp(newStr)) {
// Remove the leading plus sign
retStr = newStr;
- } else {
- String idpStr = getDefaultIdp();
- // Replaces the plus sign with the default IDP
- retStr = networkDialStr.replaceFirst("[+]", idpStr);
+ } else {
+ // Replaces the plus sign with the default IDP
+ retStr = networkDialStr.replaceFirst("[+]", getCurrentIdp(useNanp));
}
}
- if (DBG) log("processPlusCodeWithinNanp,retStr=" + retStr);
+ if (DBG) log("processPlusCode, retStr=" + retStr);
return retStr;
}
diff --git a/telephony/java/com/android/internal/telephony/TelephonyProperties.java b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
index 5ec4247..34992b8 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyProperties.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
@@ -123,8 +123,8 @@
/** Indicate the timer value for exiting emergency callback mode */
static final String PROPERTY_ECM_EXIT_TIMER = "ro.cdma.ecmexittimer";
- /** The international dialing prefix conversion string */
- static final String PROPERTY_IDP_STRING = "ro.cdma.idpstring";
+ /** the international dialing prefix of current operator network */
+ static final String PROPERTY_OPERATOR_IDP_STRING = "telephony.operator.idpstring";
/**
* Defines the schema for the carrier specified OTASP number