Merge "Update the comment in sendEnvelope." into lmp-dev
diff --git a/Android.mk b/Android.mk
index 03aa762..35d13d7 100644
--- a/Android.mk
+++ b/Android.mk
@@ -204,6 +204,7 @@
core/java/android/os/IUserManager.aidl \
core/java/android/os/IVibratorService.aidl \
core/java/android/service/notification/INotificationListener.aidl \
+ core/java/android/service/notification/IStatusBarNotificationHolder.aidl \
core/java/android/service/notification/IConditionListener.aidl \
core/java/android/service/notification/IConditionProvider.aidl \
core/java/android/print/ILayoutResultCallback.aidl \
diff --git a/api/current.txt b/api/current.txt
index eb1aedc..39772dd 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();
@@ -28231,17 +28231,19 @@
public abstract class Conference {
ctor public Conference(android.telecomm.PhoneAccountHandle);
- method public boolean addConnection(android.telecomm.Connection);
- method public void destroy();
+ method public final boolean addConnection(android.telecomm.Connection);
+ method public final void destroy();
method public final int getCapabilities();
method public final java.util.List<android.telecomm.Connection> getConnections();
method public final android.telecomm.PhoneAccountHandle getPhoneAccount();
method public final int getState();
method public void onDisconnect();
method public void onHold();
+ method public void onMerge();
method public void onSeparate(android.telecomm.Connection);
+ method public void onSwap();
method public void onUnhold();
- method public void removeConnection(android.telecomm.Connection);
+ method public final void removeConnection(android.telecomm.Connection);
method public final void setActive();
method public final void setCapabilities(int);
method public final void setDisconnected(int, java.lang.String);
@@ -28392,13 +28394,13 @@
method public static java.lang.String toString(int);
field public static final int ADD_CALL = 16; // 0x10
field public static final int ALL = 255; // 0xff
- field public static final int GENERIC_CONFERENCE = 128; // 0x80
field public static final int HOLD = 1; // 0x1
- field public static final int MERGE_CALLS = 4; // 0x4
+ field public static final int MANAGE_CONFERENCE = 128; // 0x80
+ field public static final int MERGE_CONFERENCE = 4; // 0x4
field public static final int MUTE = 64; // 0x40
field public static final int RESPOND_VIA_TEXT = 32; // 0x20
field public static final int SUPPORT_HOLD = 2; // 0x2
- field public static final int SWAP_CALLS = 8; // 0x8
+ field public static final int SWAP_CONFERENCE = 8; // 0x8
}
public class PropertyPresentation {
@@ -28410,7 +28412,7 @@
}
public final class RemoteConference {
- method public final void addListener(android.telecomm.RemoteConference.Listener);
+ method public final void addCallback(android.telecomm.RemoteConference.Callback);
method public void disconnect();
method public final int getCallCapabilities();
method public final java.util.List<android.telecomm.RemoteConnection> getConnections();
@@ -28418,13 +28420,13 @@
method public java.lang.String getDisconnectMessage();
method public final int getState();
method public void hold();
- method public final void removeListener(android.telecomm.RemoteConference.Listener);
+ method public final void removeCallback(android.telecomm.RemoteConference.Callback);
method public void separate(android.telecomm.RemoteConnection);
method public void unhold();
}
- public static abstract class RemoteConference.Listener {
- ctor public RemoteConference.Listener();
+ public static abstract class RemoteConference.Callback {
+ ctor public RemoteConference.Callback();
method public void onCapabilitiesChanged(android.telecomm.RemoteConference, int);
method public void onConnectionAdded(android.telecomm.RemoteConference, android.telecomm.RemoteConnection);
method public void onConnectionRemoved(android.telecomm.RemoteConference, android.telecomm.RemoteConnection);
@@ -28515,17 +28517,17 @@
method public void registerPhoneAccount(android.telecomm.PhoneAccount);
method public void showInCallScreen(boolean);
method public void unregisterPhoneAccount(android.telecomm.PhoneAccountHandle);
- field public static final java.lang.String ACTION_CHANGE_PHONE_ACCOUNTS = "android.telecomm.intent.action.CHANGE_PHONE_ACCOUNTS";
- field public static final java.lang.String ACTION_CONNECTION_SERVICE_CONFIGURE = "android.intent.action.CONNECTION_SERVICE_CONFIGURE";
- field public static final java.lang.String ACTION_SHOW_CALL_SETTINGS = "android.telecomm.intent.action.SHOW_CALL_SETTINGS";
+ field public static final java.lang.String ACTION_CHANGE_PHONE_ACCOUNTS = "android.telecomm.action.CHANGE_PHONE_ACCOUNTS";
+ field public static final java.lang.String ACTION_CONNECTION_SERVICE_CONFIGURE = "android.telecomm.action.CONNECTION_SERVICE_CONFIGURE";
+ field public static final java.lang.String ACTION_SHOW_CALL_SETTINGS = "android.telecomm.action.SHOW_CALL_SETTINGS";
field public static final char DTMF_CHARACTER_PAUSE = 44; // 0x002c ','
field public static final char DTMF_CHARACTER_WAIT = 59; // 0x003b ';'
field public static final java.lang.String EXTRA_CALL_BACK_NUMBER = "android.telecomm.extra.CALL_BACK_NUMBER";
field public static final java.lang.String EXTRA_CALL_DISCONNECT_CAUSE = "android.telecomm.extra.CALL_DISCONNECT_CAUSE";
field public static final java.lang.String EXTRA_CALL_DISCONNECT_MESSAGE = "android.telecomm.extra.CALL_DISCONNECT_MESSAGE";
field public static final java.lang.String EXTRA_CONNECTION_SERVICE = "android.telecomm.extra.CONNECTION_SERVICE";
- field public static final java.lang.String EXTRA_PHONE_ACCOUNT_HANDLE = "android.intent.extra.PHONE_ACCOUNT_HANDLE";
- field public static final java.lang.String EXTRA_START_CALL_WITH_SPEAKERPHONE = "android.intent.extra.START_CALL_WITH_SPEAKERPHONE";
+ field public static final java.lang.String EXTRA_PHONE_ACCOUNT_HANDLE = "android.telecomm.extra.PHONE_ACCOUNT_HANDLE";
+ field public static final java.lang.String EXTRA_START_CALL_WITH_SPEAKERPHONE = "android.telecomm.extra.START_CALL_WITH_SPEAKERPHONE";
}
}
@@ -29049,7 +29051,7 @@
method public boolean setCdmaSubscription(int);
method public void setLine1NumberForDisplay(java.lang.String, java.lang.String);
method public void setLine1NumberForDisplay(long, java.lang.String, java.lang.String);
- method public boolean setOperatorBrandOverride(java.lang.String, java.lang.String);
+ method public boolean setOperatorBrandOverride(java.lang.String);
method public boolean setPreferredNetworkType(int);
field public static final java.lang.String ACTION_PHONE_STATE_CHANGED = "android.intent.action.PHONE_STATE";
field public static final java.lang.String ACTION_RESPOND_VIA_MESSAGE = "android.intent.action.RESPOND_VIA_MESSAGE";
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/service/notification/INotificationListener.aidl b/core/java/android/service/notification/INotificationListener.aidl
index 8ca9b6c..e6bf6ba 100644
--- a/core/java/android/service/notification/INotificationListener.aidl
+++ b/core/java/android/service/notification/INotificationListener.aidl
@@ -16,6 +16,7 @@
package android.service.notification;
+import android.service.notification.IStatusBarNotificationHolder;
import android.service.notification.StatusBarNotification;
import android.service.notification.NotificationRankingUpdate;
@@ -23,9 +24,9 @@
oneway interface INotificationListener
{
void onListenerConnected(in NotificationRankingUpdate update);
- void onNotificationPosted(in StatusBarNotification notification,
+ void onNotificationPosted(in IStatusBarNotificationHolder notificationHolder,
in NotificationRankingUpdate update);
- void onNotificationRemoved(in StatusBarNotification notification,
+ void onNotificationRemoved(in IStatusBarNotificationHolder notificationHolder,
in NotificationRankingUpdate update);
void onNotificationRankingUpdate(in NotificationRankingUpdate update);
void onListenerHintsChanged(int hints);
diff --git a/core/java/android/service/notification/IStatusBarNotificationHolder.aidl b/core/java/android/service/notification/IStatusBarNotificationHolder.aidl
new file mode 100644
index 0000000..fd6b59e
--- /dev/null
+++ b/core/java/android/service/notification/IStatusBarNotificationHolder.aidl
@@ -0,0 +1,24 @@
+/**
+ * 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.
+ */
+
+package android.service.notification;
+
+import android.service.notification.StatusBarNotification;
+
+/** @hide */
+interface IStatusBarNotificationHolder {
+ StatusBarNotification get();
+}
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index 2ca8098..d744070 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -603,8 +603,15 @@
private class INotificationListenerWrapper extends INotificationListener.Stub {
@Override
- public void onNotificationPosted(StatusBarNotification sbn,
+ public void onNotificationPosted(IStatusBarNotificationHolder sbnHolder,
NotificationRankingUpdate update) {
+ StatusBarNotification sbn;
+ try {
+ sbn = sbnHolder.get();
+ } catch (RemoteException e) {
+ Log.w(TAG, "onNotificationPosted: Error receiving StatusBarNotification", e);
+ return;
+ }
Notification.Builder.rebuild(getContext(), sbn.getNotification());
// protect subclass from concurrent modifications of (@link mNotificationKeys}.
@@ -618,8 +625,15 @@
}
}
@Override
- public void onNotificationRemoved(StatusBarNotification sbn,
+ public void onNotificationRemoved(IStatusBarNotificationHolder sbnHolder,
NotificationRankingUpdate update) {
+ StatusBarNotification sbn;
+ try {
+ sbn = sbnHolder.get();
+ } catch (RemoteException e) {
+ Log.w(TAG, "onNotificationRemoved: Error receiving StatusBarNotification", e);
+ return;
+ }
// protect subclass from concurrent modifications of (@link mNotificationKeys}.
synchronized (mWrapper) {
applyUpdate(update);
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/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 7c5233c..72dd930 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -182,11 +182,11 @@
<protected-broadcast android:name="android.hardware.usb.action.USB_DEVICE_DETACHED" />
<protected-broadcast android:name="android.intent.action.HEADSET_PLUG" />
- <protected-broadcast android:name="android.intent.action.ANALOG_AUDIO_DOCK_PLUG" />
- <protected-broadcast android:name="android.intent.action.DIGITAL_AUDIO_DOCK_PLUG" />
- <protected-broadcast android:name="android.intent.action.HDMI_AUDIO_PLUG" />
- <protected-broadcast android:name="android.intent.action.USB_AUDIO_ACCESSORY_PLUG" />
- <protected-broadcast android:name="android.intent.action.USB_AUDIO_DEVICE_PLUG" />
+ <protected-broadcast android:name="android.media.action.ANALOG_AUDIO_DOCK_PLUG" />
+ <protected-broadcast android:name="android.media.action.DIGITAL_AUDIO_DOCK_PLUG" />
+ <protected-broadcast android:name="android.media.action.HDMI_AUDIO_PLUG" />
+ <protected-broadcast android:name="android.media.action.USB_AUDIO_ACCESSORY_PLUG" />
+ <protected-broadcast android:name="android.media.action.USB_AUDIO_DEVICE_PLUG" />
<protected-broadcast android:name="android.media.AUDIO_BECOMING_NOISY" />
<protected-broadcast android:name="android.media.RINGER_MODE_CHANGED" />
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/RenderState.cpp b/libs/hwui/RenderState.cpp
index a7c5e85..ec8307f 100644
--- a/libs/hwui/RenderState.cpp
+++ b/libs/hwui/RenderState.cpp
@@ -38,6 +38,7 @@
}
void RenderState::onGLContextDestroyed() {
+ AutoMutex _lock(mLayerLock);
if (CC_UNLIKELY(!mActiveLayers.empty())) {
mCaches->dumpMemoryUsage();
for (std::set<renderthread::CanvasContext*>::iterator cit = mRegisteredContexts.begin();
@@ -51,6 +52,13 @@
}
context->mRootRenderNode->debugDumpLayers(" ");
}
+
+ for (std::set<const Layer*>::iterator lit = mActiveLayers.begin();
+ lit != mActiveLayers.end(); lit++) {
+ const Layer* layer = *(lit);
+ ALOGD("Layer %p, fbo %d, buildlayered %d",
+ layer, layer->getFbo(), layer->wasBuildLayered);
+ }
LOG_ALWAYS_FATAL("layers have survived gl context destruction");
}
}
diff --git a/libs/hwui/RenderState.h b/libs/hwui/RenderState.h
index c7ab197..74bafca 100644
--- a/libs/hwui/RenderState.h
+++ b/libs/hwui/RenderState.h
@@ -19,6 +19,7 @@
#include <set>
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
+#include <utils/Mutex.h>
#include <private/hwui/DrawGlInfo.h>
@@ -52,9 +53,11 @@
void debugOverdraw(bool enable, bool clear);
void registerLayer(const Layer* layer) {
+ AutoMutex _lock(mLayerLock);
mActiveLayers.insert(layer);
}
void unregisterLayer(const Layer* layer) {
+ AutoMutex _lock(mLayerLock);
mActiveLayers.erase(layer);
}
@@ -83,6 +86,7 @@
GLsizei mViewportWidth;
GLsizei mViewportHeight;
GLuint mFramebuffer;
+ Mutex mLayerLock;
};
} /* namespace uirenderer */
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/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index bc538ed..54f043d 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -69,6 +69,7 @@
import android.service.notification.IConditionListener;
import android.service.notification.IConditionProvider;
import android.service.notification.INotificationListener;
+import android.service.notification.IStatusBarNotificationHolder;
import android.service.notification.NotificationListenerService;
import android.service.notification.NotificationRankingUpdate;
import android.service.notification.StatusBarNotification;
@@ -2848,8 +2849,9 @@
private void notifyPosted(final ManagedServiceInfo info,
final StatusBarNotification sbn, NotificationRankingUpdate rankingUpdate) {
final INotificationListener listener = (INotificationListener)info.service;
+ StatusBarNotificationHolder sbnHolder = new StatusBarNotificationHolder(sbn);
try {
- listener.onNotificationPosted(sbn, rankingUpdate);
+ listener.onNotificationPosted(sbnHolder, rankingUpdate);
} catch (RemoteException ex) {
Log.e(TAG, "unable to notify listener (posted): " + listener, ex);
}
@@ -2861,8 +2863,9 @@
return;
}
final INotificationListener listener = (INotificationListener) info.service;
+ StatusBarNotificationHolder sbnHolder = new StatusBarNotificationHolder(sbn);
try {
- listener.onNotificationRemoved(sbn, rankingUpdate);
+ listener.onNotificationRemoved(sbnHolder, rankingUpdate);
} catch (RemoteException ex) {
Log.e(TAG, "unable to notify listener (removed): " + listener, ex);
}
@@ -2950,4 +2953,22 @@
return zen ? "zen" : ('\'' + pkgFilter + '\'');
}
}
+
+ /**
+ * Wrapper for a StatusBarNotification object that allows transfer across a oneway
+ * binder without sending large amounts of data over a oneway transaction.
+ */
+ private static final class StatusBarNotificationHolder
+ extends IStatusBarNotificationHolder.Stub {
+ private final StatusBarNotification mValue;
+
+ public StatusBarNotificationHolder(StatusBarNotification value) {
+ mValue = value;
+ }
+
+ @Override
+ public StatusBarNotification get() {
+ return mValue;
+ }
+ }
}
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/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index d2a627e..7b4270b 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -3783,21 +3783,25 @@
} else {
pi = generatePackageInfoFromSettingsLPw(ps.name, flags, userId);
}
- if ((flags&PackageManager.GET_PERMISSIONS) == 0) {
- if (numMatch == permissions.length) {
- pi.requestedPermissions = permissions;
- } else {
- pi.requestedPermissions = new String[numMatch];
- numMatch = 0;
- for (int i=0; i<permissions.length; i++) {
- if (tmp[i]) {
- pi.requestedPermissions[numMatch] = permissions[i];
- numMatch++;
+ // The above might return null in cases of uninstalled apps or install-state
+ // skew across users/profiles.
+ if (pi != null) {
+ if ((flags&PackageManager.GET_PERMISSIONS) == 0) {
+ if (numMatch == permissions.length) {
+ pi.requestedPermissions = permissions;
+ } else {
+ pi.requestedPermissions = new String[numMatch];
+ numMatch = 0;
+ for (int i=0; i<permissions.length; i++) {
+ if (tmp[i]) {
+ pi.requestedPermissions[numMatch] = permissions[i];
+ numMatch++;
+ }
}
}
}
+ list.add(pi);
}
- list.add(pi);
}
@Override
@@ -10260,7 +10264,7 @@
|| !bp.packageSetting.keySetData.isUsingUpgradeKeySets()
|| ((PackageSetting) bp.packageSetting).sharedUser != null) {
sigsOk = compareSignatures(bp.packageSetting.signatures.mSignatures,
- pkg.mSignatures) != PackageManager.SIGNATURE_MATCH;
+ pkg.mSignatures) == PackageManager.SIGNATURE_MATCH;
} else {
sigsOk = checkUpgradeKeySetLP((PackageSetting) bp.packageSetting, pkg);
}
diff --git a/telecomm/java/android/telecomm/Call.java b/telecomm/java/android/telecomm/Call.java
index 5bf0855..c3aa2a0 100644
--- a/telecomm/java/android/telecomm/Call.java
+++ b/telecomm/java/android/telecomm/Call.java
@@ -517,6 +517,20 @@
}
/**
+ * Merges the calls within this conference. See {@link PhoneCapabilities#MERGE_CONFERENCE}.
+ */
+ public void mergeConference() {
+ mInCallAdapter.mergeConference(mTelecommCallId);
+ }
+
+ /**
+ * Swaps the calls within this conference. See {@link PhoneCapabilities#SWAP_CONFERENCE}.
+ */
+ public void swapConference() {
+ mInCallAdapter.swapConference(mTelecommCallId);
+ }
+
+ /**
* Obtains the parent of this {@code Call} in a conference, if any.
*
* @return The parent {@code Call}, or {@code null} if this {@code Call} is not a
diff --git a/telecomm/java/android/telecomm/Conference.java b/telecomm/java/android/telecomm/Conference.java
index 879ff66..c838b48 100644
--- a/telecomm/java/android/telecomm/Conference.java
+++ b/telecomm/java/android/telecomm/Conference.java
@@ -93,6 +93,18 @@
public void onUnhold() {}
/**
+ * Invoked when the child calls should be merged. Only invoked if the conference contains the
+ * capability {@link PhoneCapabilities#MERGE_CONFERENCE}.
+ */
+ public void onMerge() {}
+
+ /**
+ * Invoked when the child calls should be swapped. Only invoked if the conference contains the
+ * capability {@link PhoneCapabilities#SWAP_CONFERENCE}.
+ */
+ public void onSwap() {}
+
+ /**
* Sets state to be on hold.
*/
public final void setOnHold() {
@@ -141,7 +153,7 @@
* @param connection The connection to add.
* @return True if the connection was successfully added.
*/
- public boolean addConnection(Connection connection) {
+ public final boolean addConnection(Connection connection) {
if (connection != null && !mChildConnections.contains(connection)) {
if (connection.setConference(this)) {
mChildConnections.add(connection);
@@ -160,7 +172,7 @@
* @param connection The connection to remove.
* @return True if the connection was successfully removed.
*/
- public void removeConnection(Connection connection) {
+ public final void removeConnection(Connection connection) {
Log.d(this, "removing %s from %s", connection, mChildConnections);
if (connection != null && mChildConnections.remove(connection)) {
connection.resetConference();
@@ -173,7 +185,7 @@
/**
* Tears down the conference object and any of it's current connections.
*/
- public void destroy() {
+ public final void destroy() {
Log.d(this, "destroying conference : %s", this);
// Tear down the children.
for (Connection connection : mChildConnections) {
diff --git a/telecomm/java/android/telecomm/Connection.java b/telecomm/java/android/telecomm/Connection.java
index 4d6e267..6df117e 100644
--- a/telecomm/java/android/telecomm/Connection.java
+++ b/telecomm/java/android/telecomm/Connection.java
@@ -1068,10 +1068,10 @@
if (mState != state) {
Log.d(this, "setState: %s", stateToString(state));
mState = state;
+ onSetState(state);
for (Listener l : mListeners) {
l.onStateChanged(this, state);
}
- onSetState(state);
}
}
diff --git a/telecomm/java/android/telecomm/ConnectionService.java b/telecomm/java/android/telecomm/ConnectionService.java
index 2dc6910..833aa26 100644
--- a/telecomm/java/android/telecomm/ConnectionService.java
+++ b/telecomm/java/android/telecomm/ConnectionService.java
@@ -72,6 +72,8 @@
private static final int MSG_ON_PHONE_ACCOUNT_CLICKED = 15;
private static final int MSG_REMOVE_CONNECTION_SERVICE_ADAPTER = 16;
private static final int MSG_ANSWER_VIDEO = 17;
+ private static final int MSG_MERGE_CONFERENCE = 18;
+ private static final int MSG_SWAP_CONFERENCE = 19;
private static Connection sNullConnection;
@@ -182,6 +184,16 @@
}
@Override
+ public void mergeConference(String callId) {
+ mHandler.obtainMessage(MSG_MERGE_CONFERENCE, callId).sendToTarget();
+ }
+
+ @Override
+ public void swapConference(String callId) {
+ mHandler.obtainMessage(MSG_SWAP_CONFERENCE, callId).sendToTarget();
+ }
+
+ @Override
public void onPostDialContinue(String callId, boolean proceed) {
SomeArgs args = SomeArgs.obtain();
args.arg1 = callId;
@@ -298,6 +310,12 @@
case MSG_SPLIT_FROM_CONFERENCE:
splitFromConference((String) msg.obj);
break;
+ case MSG_MERGE_CONFERENCE:
+ mergeConference((String) msg.obj);
+ break;
+ case MSG_SWAP_CONFERENCE:
+ swapConference((String) msg.obj);
+ break;
case MSG_ON_POST_DIAL_CONTINUE: {
SomeArgs args = (SomeArgs) msg.obj;
try {
@@ -639,6 +657,22 @@
}
}
+ private void mergeConference(String callId) {
+ Log.d(this, "mergeConference(%s)", callId);
+ Conference conference = findConferenceForAction(callId, "mergeConference");
+ if (conference != null) {
+ conference.onMerge();
+ }
+ }
+
+ private void swapConference(String callId) {
+ Log.d(this, "swapConference(%s)", callId);
+ Conference conference = findConferenceForAction(callId, "swapConference");
+ if (conference != null) {
+ conference.onSwap();
+ }
+ }
+
private void onPostDialContinue(String callId, boolean proceed) {
Log.d(this, "onPostDialContinue(%s)", callId);
findConnectionForAction(callId, "stopDtmfTone").onPostDialContinue(proceed);
diff --git a/telecomm/java/android/telecomm/InCallAdapter.java b/telecomm/java/android/telecomm/InCallAdapter.java
index 80f7b57..96ea5a6 100644
--- a/telecomm/java/android/telecomm/InCallAdapter.java
+++ b/telecomm/java/android/telecomm/InCallAdapter.java
@@ -241,6 +241,26 @@
}
/**
+ * Instructs Telecomm to merge child calls of the specified conference call.
+ */
+ public void mergeConference(String callId) {
+ try {
+ mAdapter.mergeConference(callId);
+ } catch (RemoteException ignored) {
+ }
+ }
+
+ /**
+ * Instructs Telecomm to swap the child calls of the specified conference call.
+ */
+ public void swapConference(String callId) {
+ try {
+ mAdapter.swapConference(callId);
+ } catch (RemoteException ignored) {
+ }
+ }
+
+ /**
* Instructs Telecomm to turn the proximity sensor on.
*/
public void turnProximitySensorOn() {
diff --git a/telecomm/java/android/telecomm/PhoneCapabilities.java b/telecomm/java/android/telecomm/PhoneCapabilities.java
index 3d76608..7a338b4 100644
--- a/telecomm/java/android/telecomm/PhoneCapabilities.java
+++ b/telecomm/java/android/telecomm/PhoneCapabilities.java
@@ -27,11 +27,17 @@
/** Call supports the hold feature. */
public static final int SUPPORT_HOLD = 0x00000002;
- /** Call can currently be merged. */
- public static final int MERGE_CALLS = 0x00000004;
+ /**
+ * Calls within a conference can be merged. Some connection services create a conference call
+ * only after two calls have been merged. However, a conference call can also be added the
+ * moment there are more than one call. CDMA calls are implemented in this way because the call
+ * actions are more limited when more than one call exists. This flag allows merge to be exposed
+ * as a capability on the conference call instead of individual calls.
+ */
+ public static final int MERGE_CONFERENCE = 0x00000004;
- /** Call can currently be swapped with another call. */
- public static final int SWAP_CALLS = 0x00000008;
+ /** Calls withing a conference can be swapped between foreground and background. */
+ public static final int SWAP_CONFERENCE = 0x00000008;
/** Call currently supports adding another call to this one. */
public static final int ADD_CALL = 0x00000010;
@@ -42,8 +48,11 @@
/** Call can be muted. */
public static final int MUTE = 0x00000040;
- /** Call supports generic conference mode. */
- public static final int GENERIC_CONFERENCE = 0x00000080;
+ /**
+ * Call supports conference call management. This capability only applies to conference calls
+ * which can have other calls as children.
+ */
+ public static final int MANAGE_CONFERENCE = 0x00000080;
/**
* Local device supports video telephony.
@@ -69,8 +78,8 @@
*/
public static final int VoWIFI = 0x00000800;
- public static final int ALL = HOLD | SUPPORT_HOLD | MERGE_CALLS | SWAP_CALLS | ADD_CALL
- | RESPOND_VIA_TEXT | MUTE | GENERIC_CONFERENCE;
+ public static final int ALL = HOLD | SUPPORT_HOLD | MERGE_CONFERENCE | SWAP_CONFERENCE | ADD_CALL
+ | RESPOND_VIA_TEXT | MUTE | MANAGE_CONFERENCE;
public static String toString(int capabilities) {
StringBuilder builder = new StringBuilder();
@@ -81,11 +90,11 @@
if ((capabilities & SUPPORT_HOLD) != 0) {
builder.append(" SUPPORT_HOLD");
}
- if ((capabilities & MERGE_CALLS) != 0) {
- builder.append(" MERGE_CALLS");
+ if ((capabilities & MERGE_CONFERENCE) != 0) {
+ builder.append(" MERGE_CONFERENCE");
}
- if ((capabilities & SWAP_CALLS) != 0) {
- builder.append(" SWAP_CALLS");
+ if ((capabilities & SWAP_CONFERENCE) != 0) {
+ builder.append(" SWAP_CONFERENCE");
}
if ((capabilities & ADD_CALL) != 0) {
builder.append(" ADD_CALL");
@@ -96,8 +105,8 @@
if ((capabilities & MUTE) != 0) {
builder.append(" MUTE");
}
- if ((capabilities & GENERIC_CONFERENCE) != 0) {
- builder.append(" GENERIC_CONFERENCE");
+ if ((capabilities & MANAGE_CONFERENCE) != 0) {
+ builder.append(" MANAGE_CONFERENCE");
}
if ((capabilities & SUPPORTS_VT_LOCAL) != 0) {
builder.append(" SUPPORTS_VT_LOCAL");
diff --git a/telecomm/java/android/telecomm/RemoteConference.java b/telecomm/java/android/telecomm/RemoteConference.java
index 02f6de6..b073827 100644
--- a/telecomm/java/android/telecomm/RemoteConference.java
+++ b/telecomm/java/android/telecomm/RemoteConference.java
@@ -32,7 +32,7 @@
*/
public final class RemoteConference {
- public abstract static class Listener {
+ public abstract static class Callback {
public void onStateChanged(RemoteConference conference, int oldState, int newState) {}
public void onDisconnected(RemoteConference conference, int cause, String message) {}
public void onConnectionAdded(RemoteConference conference, RemoteConnection connection) {}
@@ -44,7 +44,7 @@
private final String mId;
private final IConnectionService mConnectionService;
- private final Set<Listener> mListeners = new CopyOnWriteArraySet<>();
+ private final Set<Callback> mCallbacks = new CopyOnWriteArraySet<>();
private final List<RemoteConnection> mChildConnections = new CopyOnWriteArrayList<>();
private final List<RemoteConnection> mUnmodifiableChildConnections =
Collections.unmodifiableList(mChildConnections);
@@ -70,8 +70,8 @@
for (RemoteConnection connection : mChildConnections) {
connection.setConference(null);
}
- for (Listener l : mListeners) {
- l.onDestroyed(this);
+ for (Callback c : mCallbacks) {
+ c.onDestroyed(this);
}
}
@@ -88,8 +88,8 @@
if (mState != newState) {
int oldState = mState;
mState = newState;
- for (Listener l : mListeners) {
- l.onStateChanged(this, oldState, newState);
+ for (Callback c : mCallbacks) {
+ c.onStateChanged(this, oldState, newState);
}
}
}
@@ -99,8 +99,8 @@
if (!mChildConnections.contains(connection)) {
mChildConnections.add(connection);
connection.setConference(this);
- for (Listener l : mListeners) {
- l.onConnectionAdded(this, connection);
+ for (Callback c : mCallbacks) {
+ c.onConnectionAdded(this, connection);
}
}
}
@@ -110,8 +110,8 @@
if (mChildConnections.contains(connection)) {
mChildConnections.remove(connection);
connection.setConference(null);
- for (Listener l : mListeners) {
- l.onConnectionRemoved(this, connection);
+ for (Callback c : mCallbacks) {
+ c.onConnectionRemoved(this, connection);
}
}
}
@@ -120,8 +120,8 @@
void setCallCapabilities(int capabilities) {
if (mCallCapabilities != capabilities) {
mCallCapabilities = capabilities;
- for (Listener l : mListeners) {
- l.onCapabilitiesChanged(this, mCallCapabilities);
+ for (Callback c : mCallbacks) {
+ c.onCapabilitiesChanged(this, mCallCapabilities);
}
}
}
@@ -132,8 +132,8 @@
mDisconnectCause = cause;
mDisconnectMessage = message;
setState(Connection.STATE_DISCONNECTED);
- for (Listener l : mListeners) {
- l.onDisconnected(this, cause, message);
+ for (Callback c : mCallbacks) {
+ c.onDisconnected(this, cause, message);
}
}
}
@@ -188,11 +188,11 @@
return mDisconnectMessage;
}
- public final void addListener(Listener listener) {
- mListeners.add(listener);
+ public final void addCallback(Callback callback) {
+ mCallbacks.add(callback);
}
- public final void removeListener(Listener listener) {
- mListeners.remove(listener);
+ public final void removeCallback(Callback callback) {
+ mCallbacks.remove(callback);
}
}
diff --git a/telecomm/java/android/telecomm/RemoteConnectionService.java b/telecomm/java/android/telecomm/RemoteConnectionService.java
index 0b6badb..79193c2 100644
--- a/telecomm/java/android/telecomm/RemoteConnectionService.java
+++ b/telecomm/java/android/telecomm/RemoteConnectionService.java
@@ -191,7 +191,7 @@
conference.setState(parcel.getState());
conference.setCallCapabilities(parcel.getCapabilities());
mConferenceById.put(callId, conference);
- conference.addListener(new RemoteConference.Listener() {
+ conference.addCallback(new RemoteConference.Callback() {
@Override
public void onDestroyed(RemoteConference c) {
mConferenceById.remove(callId);
diff --git a/telecomm/java/android/telecomm/TelecommManager.java b/telecomm/java/android/telecomm/TelecommManager.java
index b8f6964..5e9e6d0 100644
--- a/telecomm/java/android/telecomm/TelecommManager.java
+++ b/telecomm/java/android/telecomm/TelecommManager.java
@@ -46,34 +46,34 @@
*
* @hide
*/
- public static final String ACTION_INCOMING_CALL = "android.intent.action.INCOMING_CALL";
+ public static final String ACTION_INCOMING_CALL = "android.telecomm.action.INCOMING_CALL";
/**
* The {@link android.content.Intent} action used to configure a
* {@link android.telecomm.ConnectionService}.
*/
public static final String ACTION_CONNECTION_SERVICE_CONFIGURE =
- "android.intent.action.CONNECTION_SERVICE_CONFIGURE";
+ "android.telecomm.action.CONNECTION_SERVICE_CONFIGURE";
/**
* The {@link android.content.Intent} action used to show the call settings page.
*/
public static final String ACTION_SHOW_CALL_SETTINGS =
- "android.telecomm.intent.action.SHOW_CALL_SETTINGS";
+ "android.telecomm.action.SHOW_CALL_SETTINGS";
/**
* The {@link android.content.Intent} action used to show the settings page used to configure
* {@link PhoneAccount} preferences.
*/
public static final String ACTION_CHANGE_PHONE_ACCOUNTS =
- "android.telecomm.intent.action.CHANGE_PHONE_ACCOUNTS";
+ "android.telecomm.action.CHANGE_PHONE_ACCOUNTS";
/**
* Optional extra for {@link android.content.Intent#ACTION_CALL} containing a boolean that
* determines whether the speakerphone should be automatically turned on for an outgoing call.
*/
public static final String EXTRA_START_CALL_WITH_SPEAKERPHONE =
- "android.intent.extra.START_CALL_WITH_SPEAKERPHONE";
+ "android.telecomm.extra.START_CALL_WITH_SPEAKERPHONE";
/**
* Optional extra for {@link android.content.Intent#ACTION_CALL} containing an integer that
@@ -86,7 +86,7 @@
* @hide
*/
public static final String EXTRA_START_CALL_WITH_VIDEO_STATE =
- "android.intent.extra.START_CALL_WITH_VIDEO_STATE";
+ "android.telecomm.extra.START_CALL_WITH_VIDEO_STATE";
/**
* The extra used with an {@link android.content.Intent#ACTION_CALL} and
@@ -96,7 +96,7 @@
* Retrieve with {@link android.content.Intent#getParcelableExtra(String)}.
*/
public static final String EXTRA_PHONE_ACCOUNT_HANDLE =
- "android.intent.extra.PHONE_ACCOUNT_HANDLE";
+ "android.telecomm.extra.PHONE_ACCOUNT_HANDLE";
/**
* Optional extra for {@link #ACTION_INCOMING_CALL} containing a {@link Bundle} which contains
@@ -106,7 +106,7 @@
* @hide
*/
public static final String EXTRA_INCOMING_CALL_EXTRAS =
- "android.intent.extra.INCOMING_CALL_EXTRAS";
+ "android.telecomm.extra.INCOMING_CALL_EXTRAS";
/**
* Optional extra for {@link android.content.Intent#ACTION_CALL} and
@@ -117,7 +117,7 @@
* @hide
*/
public static final String EXTRA_OUTGOING_CALL_EXTRAS =
- "android.intent.extra.OUTGOING_CALL_EXTRAS";
+ "android.telecomm.extra.OUTGOING_CALL_EXTRAS";
/**
* Optional extra for {@link android.telephony.TelephonyManager#ACTION_PHONE_STATE_CHANGED}
@@ -203,7 +203,7 @@
* @hide
*/
public static final String ACTION_CURRENT_TTY_MODE_CHANGED =
- "android.telecomm.intent.action.CURRENT_TTY_MODE_CHANGED";
+ "android.telecomm.action.CURRENT_TTY_MODE_CHANGED";
/**
* The lookup key for an int that indicates the current TTY mode.
@@ -226,7 +226,7 @@
* @hide
*/
public static final String ACTION_TTY_PREFERRED_MODE_CHANGED =
- "android.telecomm.intent.action.TTY_PREFERRED_MODE_CHANGED";
+ "android.telecomm.action.TTY_PREFERRED_MODE_CHANGED";
/**
* The lookup key for an int that indicates preferred TTY mode. Valid modes are: -
diff --git a/telecomm/java/com/android/internal/telecomm/IConnectionService.aidl b/telecomm/java/com/android/internal/telecomm/IConnectionService.aidl
index 32b877d..a673733 100644
--- a/telecomm/java/com/android/internal/telecomm/IConnectionService.aidl
+++ b/telecomm/java/com/android/internal/telecomm/IConnectionService.aidl
@@ -65,6 +65,10 @@
void splitFromConference(String callId);
+ void mergeConference(String conferenceCallId);
+
+ void swapConference(String conferenceCallId);
+
void onPostDialContinue(String callId, boolean proceed);
void onPhoneAccountClicked(String callId);
diff --git a/telecomm/java/com/android/internal/telecomm/IInCallAdapter.aidl b/telecomm/java/com/android/internal/telecomm/IInCallAdapter.aidl
index 2ce5c6b..626bb91 100644
--- a/telecomm/java/com/android/internal/telecomm/IInCallAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecomm/IInCallAdapter.aidl
@@ -54,6 +54,10 @@
void splitFromConference(String callId);
+ void mergeConference(String callId);
+
+ void swapConference(String callId);
+
void turnOnProximitySensor();
void turnOffProximitySensor(boolean screenOnImmediately);
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/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index ab63e1d..6c35058 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -3023,9 +3023,9 @@
}
/**
- * Override the branding for the input ICCID.
+ * Override the branding for the current ICCID.
*
- * Once set, whenever the ICCID is inserted into the device, the service
+ * Once set, whenever the SIM is present in the device, the service
* provider name (SPN) and the operator name will both be replaced by the
* brand value input. To unset the value, the same function should be
* called with a null brand value.
@@ -3034,14 +3034,12 @@
* {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
* or has to be carrier app - see #hasCarrierPrivileges.
*
- * @param iccId The ICCID of that the branding applies to.
* @param brand The brand name to display/set.
* @return true if the operation was executed correctly.
*/
- public boolean setOperatorBrandOverride(String iccId, String brand) {
- // TODO: Validate ICCID format.
+ public boolean setOperatorBrandOverride(String brand) {
try {
- return getITelephony().setOperatorBrandOverride(iccId, brand);
+ return getITelephony().setOperatorBrandOverride(brand);
} catch (RemoteException ex) {
Rlog.e(TAG, "setOperatorBrandOverride RemoteException", ex);
} catch (NullPointerException ex) {
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 5c3dcdb..f587d72 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -766,9 +766,9 @@
String getLine1AlphaTagForDisplay(long subId);
/**
- * Override the operator branding for the input ICCID.
+ * Override the operator branding for the current ICCID.
*
- * Once set, whenever the ICCID is inserted into the device, the service
+ * Once set, whenever the SIM is present in the device, the service
* provider name (SPN) and the operator name will both be replaced by the
* brand value input. To unset the value, the same function should be
* called with a null brand value.
@@ -777,11 +777,10 @@
* {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
* or has to be carrier app - see #hasCarrierPrivileges.
*
- * @param iccid The ICCID of that the branding applies to.
* @param brand The brand name to display/set.
* @return true if the operation was executed correctly.
*/
- boolean setOperatorBrandOverride(String iccId, String brand);
+ boolean setOperatorBrandOverride(String brand);
/**
* Returns the result and response from RIL for oem request
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