Merge "Have R classes generate their own reference rewrite logic" into lmp-dev
diff --git a/api/current.txt b/api/current.txt
index 82a2d8b8..ffdd9f7 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -785,8 +785,8 @@
field public static final int largeScreens = 16843398; // 0x1010286
field public static final int largestWidthLimitDp = 16843622; // 0x1010366
field public static final int launchMode = 16842781; // 0x101001d
- field public static final int launchTaskBehindBackgroundAnimation = 16843921; // 0x1010491
field public static final int launchTaskBehindSourceAnimation = 16843922; // 0x1010492
+ field public static final int launchTaskBehindTargetAnimation = 16843921; // 0x1010491
field public static final int layerType = 16843604; // 0x1010354
field public static final int layout = 16842994; // 0x10100f2
field public static final int layoutAnimation = 16842988; // 0x10100ec
@@ -1349,6 +1349,7 @@
field public static final int transitionGroup = 16843803; // 0x101041b
field public static final int transitionName = 16843802; // 0x101041a
field public static final int transitionOrdering = 16843744; // 0x10103e0
+ field public static final int transitionVisibilityMode = 16843900; // 0x101047c
field public static final int translateX = 16843866; // 0x101045a
field public static final int translateY = 16843867; // 0x101045b
field public static final int translationX = 16843554; // 0x1010322
@@ -1385,7 +1386,6 @@
field public static final int viewportHeight = 16843805; // 0x101041d
field public static final int viewportWidth = 16843804; // 0x101041c
field public static final int visibility = 16842972; // 0x10100dc
- field public static final int visibilityMode = 16843900; // 0x101047c
field public static final int visible = 16843156; // 0x1010194
field public static final int vmSafeMode = 16843448; // 0x10102b8
field public static final int voiceIcon = 16843908; // 0x1010484
@@ -3773,10 +3773,11 @@
public class ActivityOptions {
method public static android.app.ActivityOptions makeCustomAnimation(android.content.Context, int, int);
- method public static android.app.ActivityOptions makeLaunchTaskBehindAnimation();
+ method public static deprecated android.app.ActivityOptions makeLaunchTaskBehindAnimation();
method public static android.app.ActivityOptions makeScaleUpAnimation(android.view.View, int, int, int, int);
method public static android.app.ActivityOptions makeSceneTransitionAnimation(android.app.Activity, android.view.View, java.lang.String);
method public static android.app.ActivityOptions makeSceneTransitionAnimation(android.app.Activity, android.util.Pair<android.view.View, java.lang.String>...);
+ method public static android.app.ActivityOptions makeTaskLaunchBehind();
method public static android.app.ActivityOptions makeThumbnailScaleUpAnimation(android.view.View, android.graphics.Bitmap, int, int);
method public android.os.Bundle toBundle();
method public void update(android.app.ActivityOptions);
@@ -5510,8 +5511,8 @@
field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM = "android.app.extra.DEVICE_ADMIN_PACKAGE_CHECKSUM";
field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER = "android.app.extra.DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER";
field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION = "android.app.extra.DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION";
- field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME = "android.app.extra.DEVICE_ADMIN_PACKAGE_NAME";
- field public static final java.lang.String EXTRA_PROVISIONING_EMAIL_ADDRESS = "android.app.extra.MANAGED_PROFILE_EMAIL_ADDRESS";
+ field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME = "android.app.extra.deviceAdminPackageName";
+ field public static final java.lang.String EXTRA_PROVISIONING_EMAIL_ADDRESS = "android.app.extra.ManagedProfileEmailAddress";
field public static final java.lang.String EXTRA_PROVISIONING_LOCALE = "android.app.extra.LOCALE";
field public static final java.lang.String EXTRA_PROVISIONING_LOCAL_TIME = "android.app.extra.LOCAL_TIME";
field public static final java.lang.String EXTRA_PROVISIONING_TIME_ZONE = "android.app.extra.TIME_ZONE";
@@ -7353,7 +7354,6 @@
field public static final java.lang.String NFC_SERVICE = "nfc";
field public static final java.lang.String NOTIFICATION_SERVICE = "notification";
field public static final java.lang.String NSD_SERVICE = "servicediscovery";
- field public static final java.lang.String PHONE_SERVICE = "phone_service";
field public static final java.lang.String POWER_SERVICE = "power";
field public static final java.lang.String PRINT_SERVICE = "print";
field public static final java.lang.String RESTRICTIONS_SERVICE = "restrictions";
@@ -8902,6 +8902,7 @@
field public static final java.lang.String FEATURE_SENSOR_COMPASS = "android.hardware.sensor.compass";
field public static final java.lang.String FEATURE_SENSOR_GYROSCOPE = "android.hardware.sensor.gyroscope";
field public static final java.lang.String FEATURE_SENSOR_HEART_RATE = "android.hardware.sensor.heartrate";
+ field public static final java.lang.String FEATURE_SENSOR_HEART_RATE_ECG = "android.hardware.sensor.heartrate.ecg";
field public static final java.lang.String FEATURE_SENSOR_LIGHT = "android.hardware.sensor.light";
field public static final java.lang.String FEATURE_SENSOR_PROXIMITY = "android.hardware.sensor.proximity";
field public static final java.lang.String FEATURE_SENSOR_RELATIVE_HUMIDITY = "android.hardware.sensor.relative_humidity";
@@ -22768,17 +22769,6 @@
}
-package android.phone {
-
- public final class PhoneManager {
- method public void cancelMissedCallsNotification();
- method public boolean handlePinMmi(java.lang.String);
- method public boolean isInAPhoneCall();
- method public void showCallScreen(boolean);
- }
-
-}
-
package android.preference {
public class CheckBoxPreference extends android.preference.TwoStatePreference {
@@ -27330,6 +27320,7 @@
method public final void cancelNotification(java.lang.String);
method public final void cancelNotifications(java.lang.String[]);
method public android.service.notification.StatusBarNotification[] getActiveNotifications();
+ method public android.service.notification.StatusBarNotification[] getActiveNotifications(java.lang.String[]);
method public final int getCurrentListenerHints();
method public android.service.notification.NotificationListenerService.RankingMap getCurrentRanking();
method public android.os.IBinder onBind(android.content.Intent);
@@ -28606,6 +28597,7 @@
public abstract class ConnectionService extends android.app.Service {
ctor public ConnectionService();
method public final void addConference(android.telecomm.Conference);
+ method public final void conferenceRemoteConnections(android.telecomm.RemoteConnection, android.telecomm.RemoteConnection);
method public final android.telecomm.RemoteConnection createRemoteIncomingConnection(android.telecomm.PhoneAccountHandle, android.telecomm.ConnectionRequest);
method public final android.telecomm.RemoteConnection createRemoteOutgoingConnection(android.telecomm.PhoneAccountHandle, android.telecomm.ConnectionRequest);
method public final java.util.Collection<android.telecomm.Connection> getAllConnections();
@@ -28615,6 +28607,7 @@
method public void onConnectionRemoved(android.telecomm.Connection);
method public android.telecomm.Connection onCreateIncomingConnection(android.telecomm.PhoneAccountHandle, android.telecomm.ConnectionRequest);
method public android.telecomm.Connection onCreateOutgoingConnection(android.telecomm.PhoneAccountHandle, android.telecomm.ConnectionRequest);
+ method public void onRemoteConferenceAdded(android.telecomm.RemoteConference);
field public static final java.lang.String SERVICE_INTERFACE = "android.telecomm.ConnectionService";
}
@@ -28691,6 +28684,30 @@
field public static final int UNKNOWN = 3; // 0x3
}
+ public final class RemoteConference {
+ method public final void addListener(android.telecomm.RemoteConference.Listener);
+ method public void disconnect();
+ method public final int getCallCapabilities();
+ method public final java.util.List<android.telecomm.RemoteConnection> getConnections();
+ method public int getDisconnectCause();
+ 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 void separate(android.telecomm.RemoteConnection);
+ method public void unhold();
+ }
+
+ public static abstract class RemoteConference.Listener {
+ ctor public RemoteConference.Listener();
+ 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);
+ method public void onDestroyed(android.telecomm.RemoteConference);
+ method public void onDisconnected(android.telecomm.RemoteConference, int, java.lang.String);
+ method public void onStateChanged(android.telecomm.RemoteConference, int, int);
+ }
+
public final class RemoteConnection {
method public void abort();
method public void addListener(android.telecomm.RemoteConnection.Listener);
@@ -28701,6 +28718,8 @@
method public java.lang.String getCallerDisplayName();
method public int getCallerDisplayNamePresentation();
method public java.util.List<android.telecomm.RemoteConnection> getChildren();
+ method public android.telecomm.RemoteConference getConference();
+ method public java.util.List<android.telecomm.RemoteConnection> getConferenceableConnections();
method public int getDisconnectCauseCode();
method public java.lang.String getDisconnectCauseMessage();
method public int getFailureCode();
@@ -28727,6 +28746,7 @@
method public void onCallCapabilitiesChanged(android.telecomm.RemoteConnection, int);
method public void onCallerDisplayNameChanged(android.telecomm.RemoteConnection, java.lang.String, int);
method public void onChildrenChanged(android.telecomm.RemoteConnection, java.util.List<android.telecomm.RemoteConnection>);
+ method public void onConferenceChanged(android.telecomm.RemoteConnection, android.telecomm.RemoteConference);
method public void onConferenceableConnectionsChanged(android.telecomm.RemoteConnection, java.util.List<android.telecomm.RemoteConnection>);
method public void onDestroyed(android.telecomm.RemoteConnection);
method public void onDisconnected(android.telecomm.RemoteConnection, int, java.lang.String);
@@ -28758,12 +28778,16 @@
public class TelecommManager {
method public void addNewIncomingCall(android.telecomm.PhoneAccountHandle, android.os.Bundle);
+ method public void cancelMissedCallsNotification();
method public void clearAccounts(java.lang.String);
method public android.telecomm.PhoneAccountHandle getDefaultOutgoingPhoneAccount();
method public java.util.List<android.telecomm.PhoneAccountHandle> getEnabledPhoneAccounts();
method public android.telecomm.PhoneAccount getPhoneAccount(android.telecomm.PhoneAccountHandle);
+ method public boolean handleMmi(java.lang.String);
method public boolean hasMultipleEnabledAccounts();
+ method public boolean isInCall();
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_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";
@@ -28986,10 +29010,10 @@
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator CREATOR;
field public static int INVALID_CHANNEL;
- field public static int MISSING_RESOURCE;
- field public static int NO_ERROR;
- field public static int NO_SUCH_ELEMENT;
- field public static int UNKNOWN_ERROR;
+ field public static int STATUS_MISSING_RESOURCE;
+ field public static int STATUS_NO_ERROR;
+ field public static int STATUS_NO_SUCH_ELEMENT;
+ field public static int STATUS_UNKNOWN_ERROR;
}
public class MessagingConfigurationManager {
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index b86621f..2173647 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -796,6 +796,12 @@
public static final int RECENT_INCLUDE_PROFILES = 0x0004;
/**
+ * Ignores all tasks that are on the home stack.
+ * @hide
+ */
+ public static final int RECENT_IGNORE_HOME_STACK_TASKS = 0x0008;
+
+ /**
* <p></p>Return a list of the tasks that the user has recently launched, with
* the most recent being first and older ones after in order.
*
@@ -985,7 +991,7 @@
ArrayList<AppTask> tasks = new ArrayList<AppTask>();
List<IAppTask> appTasks;
try {
- appTasks = ActivityManagerNative.getDefault().getAppTasks();
+ appTasks = ActivityManagerNative.getDefault().getAppTasks(mContext.getPackageName());
} catch (RemoteException e) {
// System dead, we will be dead too soon!
return null;
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 5b81cc3..82af99b 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -554,7 +554,8 @@
case GET_APP_TASKS_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
- List<IAppTask> list = getAppTasks();
+ String callingPackage = data.readString();
+ List<IAppTask> list = getAppTasks(callingPackage);
reply.writeNoException();
int N = list != null ? list.size() : -1;
reply.writeInt(N);
@@ -2880,10 +2881,11 @@
reply.recycle();
return res;
}
- public List<IAppTask> getAppTasks() throws RemoteException {
+ public List<IAppTask> getAppTasks(String callingPackage) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
+ data.writeString(callingPackage);
mRemote.transact(GET_APP_TASKS_TRANSACTION, data, reply, 0);
reply.readException();
ArrayList<IAppTask> list = null;
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 4c02314..9dd4605 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -128,6 +128,10 @@
public static final int ANIM_DEFAULT = 6;
/** @hide */
public static final int ANIM_LAUNCH_TASK_BEHIND = 7;
+ /** @hide */
+ public static final int ANIM_THUMBNAIL_ASPECT_SCALE_UP = 8;
+ /** @hide */
+ public static final int ANIM_THUMBNAIL_ASPECT_SCALE_DOWN = 9;
private String mPackageName;
private int mAnimationType = ANIM_NONE;
@@ -338,6 +342,67 @@
}
/**
+ * Create an ActivityOptions specifying an animation where the new activity
+ * window and a thumbnail is aspect-scaled to a new location.
+ *
+ * @param source The View that this thumbnail is animating from. This
+ * defines the coordinate space for <var>startX</var> and <var>startY</var>.
+ * @param thumbnail The bitmap that will be shown as the initial thumbnail
+ * of the animation.
+ * @param startX The x starting location of the bitmap, relative to <var>source</var>.
+ * @param startY The y starting location of the bitmap, relative to <var>source</var>.
+ * @param listener Optional OnAnimationStartedListener to find out when the
+ * requested animation has started running. If for some reason the animation
+ * is not executed, the callback will happen immediately.
+ * @return Returns a new ActivityOptions object that you can use to
+ * supply these options as the options Bundle when starting an activity.
+ * @hide
+ */
+ public static ActivityOptions makeThumbnailAspectScaleUpAnimation(View source,
+ Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener) {
+ return makeAspectScaledThumbnailAnimation(source, thumbnail, startX, startY, listener,
+ true);
+ }
+
+ /**
+ * Create an ActivityOptions specifying an animation where the new activity
+ * window and a thumbnail is aspect-scaled to a new location.
+ *
+ * @param source The View that this thumbnail is animating to. This
+ * defines the coordinate space for <var>startX</var> and <var>startY</var>.
+ * @param thumbnail The bitmap that will be shown as the final thumbnail
+ * of the animation.
+ * @param startX The x end location of the bitmap, relative to <var>source</var>.
+ * @param startY The y end location of the bitmap, relative to <var>source</var>.
+ * @param listener Optional OnAnimationStartedListener to find out when the
+ * requested animation has started running. If for some reason the animation
+ * is not executed, the callback will happen immediately.
+ * @return Returns a new ActivityOptions object that you can use to
+ * supply these options as the options Bundle when starting an activity.
+ * @hide
+ */
+ public static ActivityOptions makeThumbnailAspectScaleDownAnimation(View source,
+ Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener) {
+ return makeAspectScaledThumbnailAnimation(source, thumbnail, startX, startY, listener,
+ false);
+ }
+
+ private static ActivityOptions makeAspectScaledThumbnailAnimation(View source, Bitmap thumbnail,
+ int startX, int startY, OnAnimationStartedListener listener, boolean scaleUp) {
+ ActivityOptions opts = new ActivityOptions();
+ opts.mPackageName = source.getContext().getPackageName();
+ opts.mAnimationType = scaleUp ? ANIM_THUMBNAIL_ASPECT_SCALE_UP :
+ ANIM_THUMBNAIL_ASPECT_SCALE_DOWN;
+ opts.mThumbnail = thumbnail;
+ int[] pts = new int[2];
+ source.getLocationOnScreen(pts);
+ opts.mStartX = pts[0] + startX;
+ opts.mStartY = pts[1] + startY;
+ opts.setOnAnimationStartedListener(source.getHandler(), listener);
+ return opts;
+ }
+
+ /**
* Create an ActivityOptions to transition between Activities using cross-Activity scene
* animations. This method carries the position of one shared element to the started Activity.
* The position of <code>sharedElement</code> will be used as the epicenter for the
@@ -444,12 +509,17 @@
* android.R.styleable#AndroidManifestActivity_launchMode launchMode} values of
* <code>singleInstance</code> or <code>singleTask</code>.
*/
- public static ActivityOptions makeLaunchTaskBehindAnimation() {
+ public static ActivityOptions makeTaskLaunchBehind() {
final ActivityOptions opts = new ActivityOptions();
opts.mAnimationType = ANIM_LAUNCH_TASK_BEHIND;
return opts;
}
+ @Deprecated
+ public static ActivityOptions makeLaunchTaskBehindAnimation() {
+ return makeTaskLaunchBehind();
+ }
+
/** @hide */
public boolean getLaunchTaskBehind() {
return mAnimationType == ANIM_LAUNCH_TASK_BEHIND;
@@ -479,7 +549,9 @@
case ANIM_THUMBNAIL_SCALE_UP:
case ANIM_THUMBNAIL_SCALE_DOWN:
- mThumbnail = (Bitmap)opts.getParcelable(KEY_ANIM_THUMBNAIL);
+ case ANIM_THUMBNAIL_ASPECT_SCALE_UP:
+ case ANIM_THUMBNAIL_ASPECT_SCALE_DOWN:
+ mThumbnail = (Bitmap) opts.getParcelable(KEY_ANIM_THUMBNAIL);
mStartX = opts.getInt(KEY_ANIM_START_X, 0);
mStartY = opts.getInt(KEY_ANIM_START_Y, 0);
mAnimationStartedListener = IRemoteCallback.Stub.asInterface(
@@ -630,6 +702,8 @@
break;
case ANIM_THUMBNAIL_SCALE_UP:
case ANIM_THUMBNAIL_SCALE_DOWN:
+ case ANIM_THUMBNAIL_ASPECT_SCALE_UP:
+ case ANIM_THUMBNAIL_ASPECT_SCALE_DOWN:
mThumbnail = otherOptions.mThumbnail;
mStartX = otherOptions.mStartX;
mStartY = otherOptions.mStartY;
@@ -686,6 +760,8 @@
break;
case ANIM_THUMBNAIL_SCALE_UP:
case ANIM_THUMBNAIL_SCALE_DOWN:
+ case ANIM_THUMBNAIL_ASPECT_SCALE_UP:
+ case ANIM_THUMBNAIL_ASPECT_SCALE_DOWN:
b.putParcelable(KEY_ANIM_THUMBNAIL, mThumbnail);
b.putInt(KEY_ANIM_START_X, mStartX);
b.putInt(KEY_ANIM_START_Y, mStartY);
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index da343ac..884b046 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -122,7 +122,6 @@
import android.os.UserManager;
import android.os.storage.IMountService;
import android.os.storage.StorageManager;
-import android.phone.PhoneManager;
import android.print.IPrintManager;
import android.print.PrintManager;
import android.service.fingerprint.IFingerprintService;
@@ -570,11 +569,6 @@
return new TelecommManager(ctx.getOuterContext());
}});
- registerService(PHONE_SERVICE, new ServiceFetcher() {
- public Object createService(ContextImpl ctx) {
- return new PhoneManager(ctx.getOuterContext());
- }});
-
registerService(UI_MODE_SERVICE, new ServiceFetcher() {
public Object createService(ContextImpl ctx) {
return new UiModeManager();
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 1664408..69e1710 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -119,7 +119,7 @@
public void activityDestroyed(IBinder token) throws RemoteException;
public String getCallingPackage(IBinder token) throws RemoteException;
public ComponentName getCallingActivity(IBinder token) throws RemoteException;
- public List<IAppTask> getAppTasks() throws RemoteException;
+ public List<IAppTask> getAppTasks(String callingPackage) throws RemoteException;
public int addAppTask(IBinder activityToken, Intent intent,
ActivityManager.TaskDescription description, Bitmap thumbnail) throws RemoteException;
public Point getAppTaskThumbnailSize() throws RemoteException;
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 2b97c6b..07e9a94 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -58,7 +58,7 @@
void cancelNotificationFromListener(in INotificationListener token, String pkg, String tag, int id);
void cancelNotificationsFromListener(in INotificationListener token, in String[] keys);
- ParceledListSlice getActiveNotificationsFromListener(in INotificationListener token);
+ ParceledListSlice getActiveNotificationsFromListener(in INotificationListener token, in String[] keys);
void requestHintsFromListener(in INotificationListener token, int hints);
int getHintsFromListener(in INotificationListener token);
@@ -71,4 +71,4 @@
oneway void setZenModeCondition(in Condition condition);
oneway void setAutomaticZenModeConditions(in Uri[] conditionIds);
Condition[] getAutomaticZenModeConditions();
-}
\ No newline at end of file
+}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 41bbb87..b17309f 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -126,7 +126,7 @@
* message containing an Nfc record with MIME type {@link #MIME_TYPE_PROVISIONING_NFC}.
*/
public static final String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME
- = "android.app.extra.DEVICE_ADMIN_PACKAGE_NAME";
+ = "android.app.extra.deviceAdminPackageName";
/**
* A String extra holding the default name of the profile that is created during managed profile
@@ -149,7 +149,7 @@
* It is usually used to avoid that the user has to enter their email address twice.
*/
public static final String EXTRA_PROVISIONING_EMAIL_ADDRESS
- = "android.app.extra.MANAGED_PROFILE_EMAIL_ADDRESS";
+ = "android.app.extra.ManagedProfileEmailAddress";
/**
* A String extra holding the time zone {@link android.app.AlarmManager} that the device
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index a13a928..ebb1f77 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -2203,8 +2203,6 @@
* @see android.media.MediaRouter
* @see #TELEPHONY_SERVICE
* @see android.telephony.TelephonyManager
- * @see #PHONE_SERVICE
- * @see android.phone.PhoneManager
* @see #INPUT_METHOD_SERVICE
* @see android.view.inputmethod.InputMethodManager
* @see #UI_MODE_SERVICE
@@ -2558,16 +2556,6 @@
/**
* Use with {@link #getSystemService} to retrieve a
- * {@link android.phone.PhoneManager} to manage phone-related features
- * of the device.
- *
- * @see #getSystemService
- * @see android.phone.PhoneManager
- */
- public static final String PHONE_SERVICE = "phone_service"; // "phone" used by telephony.
-
- /**
- * Use with {@link #getSystemService} to retrieve a
* {@link android.text.ClipboardManager} for accessing and modifying
* the contents of the global clipboard.
*
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 56b7164..5492775 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1217,6 +1217,14 @@
/**
* Feature for {@link #getSystemAvailableFeatures} and
+ * {@link #hasSystemFeature}: The heart rate sensor on this device is an Electrocargiogram.
+ */
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_SENSOR_HEART_RATE_ECG =
+ "android.hardware.sensor.heartrate.ecg";
+
+ /**
+ * Feature for {@link #getSystemAvailableFeatures} and
* {@link #hasSystemFeature}: The device includes a relative humidity sensor.
*/
@SdkConstant(SdkConstantType.FEATURE)
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index d19418b..e63fd07 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -533,6 +533,18 @@
public static final int DENSITY_DPI_UNDEFINED = 0;
/**
+ * Value for {@link #densityDpi} for resources that scale to any density (vector drawables).
+ * {@hide}
+ */
+ public static final int DENSITY_DPI_ANY = 0xfffe;
+
+ /**
+ * Value for {@link #densityDpi} for resources that are not meant to be scaled.
+ * {@hide}
+ */
+ public static final int DENSITY_DPI_NONE = 0xffff;
+
+ /**
* The target screen density being rendered to,
* corresponding to
* <a href="{@docRoot}guide/topics/resources/providing-resources.html#DensityQualifier">density</a>
@@ -1453,7 +1465,7 @@
}
switch (config.densityDpi) {
- case 0:
+ case DENSITY_DPI_UNDEFINED:
break;
case 120:
parts.add("ldpi");
@@ -1476,6 +1488,11 @@
case 640:
parts.add("xxxhdpi");
break;
+ case DENSITY_DPI_ANY:
+ parts.add("anydpi");
+ break;
+ case DENSITY_DPI_NONE:
+ parts.add("nodpi");
default:
parts.add(config.densityDpi + "dpi");
break;
diff --git a/core/java/android/hardware/hdmi/HdmiControlManager.java b/core/java/android/hardware/hdmi/HdmiControlManager.java
index 3c61e39..4b5ced9 100644
--- a/core/java/android/hardware/hdmi/HdmiControlManager.java
+++ b/core/java/android/hardware/hdmi/HdmiControlManager.java
@@ -48,6 +48,12 @@
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_OSD_MESSAGE = "android.hardware.hdmi.action.OSD_MESSAGE";
+ // --- Messages for ACTION_OSD_MESSAGE ---
+ /**
+ * Message that ARC enabled device is connected to invalid port (non-ARC port).
+ */
+ public static final int OSD_MESSAGE_ARC_CONNECTED_INVALID_PORT = 1;
+
/**
* Used as an extra field in the intent {@link #ACTION_OSD_MESSAGE}. Contains the ID of
* the message to display on screen.
diff --git a/core/java/android/net/VpnService.java b/core/java/android/net/VpnService.java
index 99bccd0..b023b0b 100644
--- a/core/java/android/net/VpnService.java
+++ b/core/java/android/net/VpnService.java
@@ -523,7 +523,8 @@
*
* If this method is called at least once, only applications added through this method (and
* no others) are allowed access. Else (if this method is never called), all applications
- * are allowed by default.
+ * are allowed by default. If some applications are added, other, un-added applications
+ * will use networking as if the VPN wasn't running.
*
* A {@link Builder} may have only a set of allowed applications OR a set of disallowed
* ones, but not both. Calling this method after {@link #addDisallowedApplication} has
@@ -548,7 +549,7 @@
* Adds an application that's denied access to the VPN connection.
*
* By default, all applications are allowed access, except for those denied through this
- * method.
+ * method. Denied applications will use networking as if the VPN wasn't running.
*
* A {@link Builder} may have only a set of allowed applications OR a set of disallowed
* ones, but not both. Calling this method after {@link #addAllowedApplication} has already
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index 119f7f6..4651d7e 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -307,10 +307,22 @@
* @return An array of active notifications, sorted in natural order.
*/
public StatusBarNotification[] getActiveNotifications() {
+ return getActiveNotifications(null);
+ }
+
+ /**
+ * Request one or more notifications by key. Useful if you have been keeping track of
+ * notifications but didn't want to retain the bits, and now need to go back and extract
+ * more data out of those notifications.
+ *
+ * @return An array of notifications corresponding to the requested keys, in the
+ * same order as the key list.
+ */
+ public StatusBarNotification[] getActiveNotifications(String[] keys) {
if (!isBound()) return null;
try {
ParceledListSlice<StatusBarNotification> parceledList =
- getNotificationInterface().getActiveNotificationsFromListener(mWrapper);
+ getNotificationInterface().getActiveNotificationsFromListener(mWrapper, keys);
List<StatusBarNotification> list = parceledList.getList();
int N = list.size();
diff --git a/core/java/android/transition/Visibility.java b/core/java/android/transition/Visibility.java
index 81c69d1..0b02552 100644
--- a/core/java/android/transition/Visibility.java
+++ b/core/java/android/transition/Visibility.java
@@ -84,7 +84,7 @@
public Visibility(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.VisibilityTransition);
- int mode = a.getInt(R.styleable.VisibilityTransition_visibilityMode, 0);
+ int mode = a.getInt(R.styleable.VisibilityTransition_transitionVisibilityMode, 0);
a.recycle();
if (mode != 0) {
setMode(mode);
@@ -97,7 +97,7 @@
*
* @param mode The behavior supported by this transition, a combination of
* {@link #MODE_IN} and {@link #MODE_OUT}.
- * @attr ref android.R.styleable#VisibilityTransition_visibilityMode
+ * @attr ref android.R.styleable#VisibilityTransition_transitionVisibilityMode
*/
public void setMode(int mode) {
if ((mode & ~(MODE_IN | MODE_OUT)) != 0) {
@@ -111,7 +111,7 @@
*
* Returns whether appearing and/or disappearing Views are supported. A combination of
* {@link #MODE_IN} and {@link #MODE_OUT}.
- * @attr ref android.R.styleable#VisibilityTransition_visibilityMode
+ * @attr ref android.R.styleable#VisibilityTransition_transitionVisibilityMode
*/
public int getMode() {
return mMode;
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index a410aa9..ceea9f8 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -179,6 +179,18 @@
private static native void nSetHighContrastText(long renderer, boolean highContrastText);
@Override
+ public void insertReorderBarrier() {
+ nInsertReorderBarrier(mRenderer, true);
+ }
+
+ @Override
+ public void insertInorderBarrier() {
+ nInsertReorderBarrier(mRenderer, false);
+ }
+
+ private static native void nInsertReorderBarrier(long renderer, boolean enableReorder);
+
+ @Override
public int onPreDraw(Rect dirty) {
if (dirty != null) {
return nPrepareDirty(mRenderer, dirty.left, dirty.top, dirty.right, dirty.bottom,
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 7deb9c8..5d6d998 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -93,6 +93,8 @@
int startHeight);
void overridePendingAppTransitionThumb(in Bitmap srcThumb, int startX, int startY,
IRemoteCallback startedCallback, boolean scaleUp);
+ void overridePendingAppTransitionAspectScaledThumb(in Bitmap srcThumb, int startX,
+ int startY, IRemoteCallback startedCallback, boolean scaleUp);
void executeAppTransition();
void setAppStartingWindow(IBinder token, String pkg, int theme,
in CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes,
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 19dd583..854e6be 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -3072,7 +3072,7 @@
boolean more = false;
final long drawingTime = getDrawingTime();
-
+ if (usingRenderNodeProperties) canvas.insertReorderBarrier();
// Only use the preordered list if not HW accelerated, since the HW pipeline will do the
// draw reordering internally
final ArrayList<View> preorderedList = usingRenderNodeProperties
@@ -3099,6 +3099,7 @@
more |= drawChild(canvas, child, drawingTime);
}
}
+ if (usingRenderNodeProperties) canvas.insertInorderBarrier();
if (debugDraw()) {
onDebugDraw(canvas);
diff --git a/core/java/android/widget/Toolbar.java b/core/java/android/widget/Toolbar.java
index 0b15eb6..818efaa 100644
--- a/core/java/android/widget/Toolbar.java
+++ b/core/java/android/widget/Toolbar.java
@@ -156,6 +156,12 @@
private boolean mCollapsible;
+ private final Runnable mShowOverflowMenuRunnable = new Runnable() {
+ @Override public void run() {
+ showOverflowMenu();
+ }
+ };
+
public Toolbar(Context context) {
this(context, null);
}
@@ -404,6 +410,7 @@
ensureLogoView();
if (mLogoView.getParent() == null) {
addSystemView(mLogoView);
+ updateChildVisibilityForExpandedActionView(mLogoView);
}
} else if (mLogoView != null && mLogoView.getParent() != null) {
removeView(mLogoView);
@@ -545,6 +552,7 @@
}
if (mTitleTextView.getParent() == null) {
addSystemView(mTitleTextView);
+ updateChildVisibilityForExpandedActionView(mTitleTextView);
}
} else if (mTitleTextView != null && mTitleTextView.getParent() != null) {
removeView(mTitleTextView);
@@ -598,6 +606,7 @@
}
if (mSubtitleTextView.getParent() == null) {
addSystemView(mSubtitleTextView);
+ updateChildVisibilityForExpandedActionView(mSubtitleTextView);
}
} else if (mSubtitleTextView != null && mSubtitleTextView.getParent() != null) {
removeView(mSubtitleTextView);
@@ -728,6 +737,7 @@
ensureNavButtonView();
if (mNavButtonView.getParent() == null) {
addSystemView(mNavButtonView);
+ updateChildVisibilityForExpandedActionView(mNavButtonView);
}
} else if (mNavButtonView != null && mNavButtonView.getParent() != null) {
removeView(mNavButtonView);
@@ -979,6 +989,13 @@
@Override
protected Parcelable onSaveInstanceState() {
SavedState state = new SavedState(super.onSaveInstanceState());
+
+ if (mExpandedMenuPresenter != null && mExpandedMenuPresenter.mCurrentExpandedItem != null) {
+ state.expandedMenuItemId = mExpandedMenuPresenter.mCurrentExpandedItem.getItemId();
+ }
+
+ state.isOverflowOpen = isOverflowMenuShowing();
+
return state;
}
@@ -986,6 +1003,29 @@
protected void onRestoreInstanceState(Parcelable state) {
final SavedState ss = (SavedState) state;
super.onRestoreInstanceState(ss.getSuperState());
+
+ final Menu menu = mMenuView != null ? mMenuView.peekMenu() : null;
+ if (ss.expandedMenuItemId != 0 && mExpandedMenuPresenter != null && menu != null) {
+ final MenuItem item = menu.findItem(ss.expandedMenuItemId);
+ if (item != null) {
+ item.expandActionView();
+ }
+ }
+
+ if (ss.isOverflowOpen) {
+ postShowOverflowMenu();
+ }
+ }
+
+ private void postShowOverflowMenu() {
+ removeCallbacks(mShowOverflowMenuRunnable);
+ post(mShowOverflowMenuRunnable);
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ removeCallbacks(mShowOverflowMenuRunnable);
}
/**
@@ -1591,6 +1631,13 @@
}
}
+ private void updateChildVisibilityForExpandedActionView(View child) {
+ final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+ if (lp.mViewType != LayoutParams.EXPANDED && child != mMenuView) {
+ child.setVisibility(mExpandedActionView != null ? GONE : VISIBLE);
+ }
+ }
+
/**
* Force the toolbar to collapse to zero-height during measurement if
* it could be considered "empty" (no visible elements with nonzero measured size)
@@ -1673,8 +1720,13 @@
}
static class SavedState extends BaseSavedState {
+ public int expandedMenuItemId;
+ public boolean isOverflowOpen;
+
public SavedState(Parcel source) {
super(source);
+ expandedMenuItemId = source.readInt();
+ isOverflowOpen = source.readInt() != 0;
}
public SavedState(Parcelable superState) {
@@ -1684,6 +1736,8 @@
@Override
public void writeToParcel(Parcel out, int flags) {
super.writeToParcel(out, flags);
+ out.writeInt(expandedMenuItemId);
+ out.writeInt(isOverflowOpen ? 1 : 0);
}
public static final Creator<SavedState> CREATOR = new Creator<SavedState>() {
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index b06edc5..71cf391 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -34,8 +34,8 @@
import android.os.UserHandle;
import android.os.storage.IMountService;
import android.os.storage.StorageManager;
-import android.phone.PhoneManager;
import android.provider.Settings;
+import android.telecomm.TelecommManager;
import android.text.TextUtils;
import android.util.Log;
import android.view.IWindowManager;
@@ -1440,7 +1440,7 @@
}
int textId;
- if (getPhoneManager().isInAPhoneCall()) {
+ if (getTelecommManager().isInCall()) {
// show "return to call" text and show phone icon
textId = R.string.lockscreen_return_to_call;
int phoneCallIcon = showIcon ? R.drawable.stat_sys_phone_call : 0;
@@ -1458,11 +1458,11 @@
* on various lockscreens.
*/
public void resumeCall() {
- getPhoneManager().showCallScreen(false);
+ getTelecommManager().showInCallScreen(false);
}
- private PhoneManager getPhoneManager() {
- return (PhoneManager) mContext.getSystemService(Context.PHONE_SERVICE);
+ private TelecommManager getTelecommManager() {
+ return (TelecommManager) mContext.getSystemService(Context.TELECOMM_SERVICE);
}
private void finishBiometricWeak() {
diff --git a/core/jni/android/graphics/Shader.cpp b/core/jni/android/graphics/Shader.cpp
index e02aa5e..6146fff 100644
--- a/core/jni/android/graphics/Shader.cpp
+++ b/core/jni/android/graphics/Shader.cpp
@@ -66,6 +66,7 @@
} else {
shader->resetLocalMatrix();
}
+ shader->setGenerationID(shader->getGenerationID() + 1);
}
}
diff --git a/core/jni/android_hardware_camera2_DngCreator.cpp b/core/jni/android_hardware_camera2_DngCreator.cpp
index a728455..31c7b9f 100644
--- a/core/jni/android_hardware_camera2_DngCreator.cpp
+++ b/core/jni/android_hardware_camera2_DngCreator.cpp
@@ -653,6 +653,119 @@
return OK;
}
+/**
+ * Write CFA pattern for given CFA enum into cfaOut. cfaOut must have length >= 4.
+ * Returns OK on success, or a negative error code if the CFA enum was invalid.
+ */
+static status_t convertCFA(uint8_t cfaEnum, /*out*/uint8_t* cfaOut) {
+ camera_metadata_enum_android_sensor_info_color_filter_arrangement_t cfa =
+ static_cast<camera_metadata_enum_android_sensor_info_color_filter_arrangement_t>(
+ cfaEnum);
+ switch(cfa) {
+ case ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGGB: {
+ cfaOut[0] = 0;
+ cfaOut[1] = 1;
+ cfaOut[2] = 1;
+ cfaOut[3] = 2;
+ break;
+ }
+ case ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GRBG: {
+ cfaOut[0] = 1;
+ cfaOut[1] = 0;
+ cfaOut[2] = 2;
+ cfaOut[3] = 1;
+ break;
+ }
+ case ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GBRG: {
+ cfaOut[0] = 1;
+ cfaOut[1] = 2;
+ cfaOut[2] = 0;
+ cfaOut[3] = 1;
+ break;
+ }
+ case ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_BGGR: {
+ cfaOut[0] = 2;
+ cfaOut[1] = 1;
+ cfaOut[2] = 1;
+ cfaOut[3] = 0;
+ break;
+ }
+ default: {
+ return BAD_VALUE;
+ }
+ }
+ return OK;
+}
+
+/**
+ * Convert the CFA layout enum to an OpcodeListBuilder::CfaLayout enum, defaults to
+ * RGGB for an unknown enum.
+ */
+static OpcodeListBuilder::CfaLayout convertCFAEnumToOpcodeLayout(uint8_t cfaEnum) {
+ camera_metadata_enum_android_sensor_info_color_filter_arrangement_t cfa =
+ static_cast<camera_metadata_enum_android_sensor_info_color_filter_arrangement_t>(
+ cfaEnum);
+ switch(cfa) {
+ case ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGGB: {
+ return OpcodeListBuilder::CFA_RGGB;
+ }
+ case ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GRBG: {
+ return OpcodeListBuilder::CFA_GRBG;
+ }
+ case ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GBRG: {
+ return OpcodeListBuilder::CFA_GBRG;
+ }
+ case ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_BGGR: {
+ return OpcodeListBuilder::CFA_BGGR;
+ }
+ default: {
+ return OpcodeListBuilder::CFA_RGGB;
+ }
+ }
+}
+
+/**
+ * For each color plane, find the corresponding noise profile coefficients given in the
+ * per-channel noise profile. If multiple channels in the CFA correspond to a color in the color
+ * plane, this method takes the pair of noise profile coefficients with the higher S coefficient.
+ *
+ * perChannelNoiseProfile - numChannels * 2 noise profile coefficients.
+ * cfa - numChannels color channels corresponding to each of the per-channel noise profile
+ * coefficients.
+ * numChannels - the number of noise profile coefficient pairs and color channels given in
+ * the perChannelNoiseProfile and cfa arguments, respectively.
+ * planeColors - the color planes in the noise profile output.
+ * numPlanes - the number of planes in planeColors and pairs of coefficients in noiseProfile.
+ * noiseProfile - 2 * numPlanes doubles containing numPlanes pairs of noise profile coefficients.
+ *
+ * returns OK, or a negative error code on failure.
+ */
+static status_t generateNoiseProfile(const double* perChannelNoiseProfile, uint8_t* cfa,
+ size_t numChannels, const uint8_t* planeColors, size_t numPlanes,
+ /*out*/double* noiseProfile) {
+
+ for (size_t p = 0; p < numPlanes; ++p) {
+ size_t S = p * 2;
+ size_t O = p * 2 + 1;
+
+ noiseProfile[S] = 0;
+ noiseProfile[O] = 0;
+ bool uninitialized = true;
+ for (size_t c = 0; c < numChannels; ++c) {
+ if (cfa[c] == planeColors[p] && perChannelNoiseProfile[c * 2] > noiseProfile[S]) {
+ noiseProfile[S] = perChannelNoiseProfile[c * 2];
+ noiseProfile[O] = perChannelNoiseProfile[c * 2 + 1];
+ uninitialized = false;
+ }
+ }
+ if (uninitialized) {
+ ALOGE("%s: No valid NoiseProfile coefficients for color plane %u", __FUNCTION__, p);
+ return BAD_VALUE;
+ }
+ }
+ return OK;
+}
+
// ----------------------------------------------------------------------------
extern "C" {
@@ -745,6 +858,8 @@
uint32_t imageHeight = 0;
OpcodeListBuilder::CfaLayout opcodeCfaLayout = OpcodeListBuilder::CFA_RGGB;
+ uint8_t cfaPlaneColor[3] = {0, 1, 2};
+ uint8_t cfaEnum = -1;
// TODO: Greensplit.
// TODO: Add remaining non-essential tags
@@ -841,49 +956,23 @@
camera_metadata_entry entry =
characteristics.find(ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT);
BAIL_IF_EMPTY(entry, env, TAG_CFAPATTERN, writer);
- camera_metadata_enum_android_sensor_info_color_filter_arrangement_t cfa =
- static_cast<camera_metadata_enum_android_sensor_info_color_filter_arrangement_t>(
- entry.data.u8[0]);
- switch(cfa) {
- case ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGGB: {
- uint8_t cfa[4] = {0, 1, 1, 2};
- BAIL_IF_INVALID(writer->addEntry(TAG_CFAPATTERN, 4, cfa, TIFF_IFD_0),
- env, TAG_CFAPATTERN, writer);
- opcodeCfaLayout = OpcodeListBuilder::CFA_RGGB;
- break;
- }
- case ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GRBG: {
- uint8_t cfa[4] = {1, 0, 2, 1};
- BAIL_IF_INVALID(writer->addEntry(TAG_CFAPATTERN, 4, cfa, TIFF_IFD_0),
- env, TAG_CFAPATTERN, writer);
- opcodeCfaLayout = OpcodeListBuilder::CFA_GRBG;
- break;
- }
- case ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GBRG: {
- uint8_t cfa[4] = {1, 2, 0, 1};
- BAIL_IF_INVALID(writer->addEntry(TAG_CFAPATTERN, 4, cfa, TIFF_IFD_0),
- env, TAG_CFAPATTERN, writer);
- opcodeCfaLayout = OpcodeListBuilder::CFA_GBRG;
- break;
- }
- case ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_BGGR: {
- uint8_t cfa[4] = {2, 1, 1, 0};
- BAIL_IF_INVALID(writer->addEntry(TAG_CFAPATTERN, 4, cfa, TIFF_IFD_0),
- env, TAG_CFAPATTERN, writer);
- opcodeCfaLayout = OpcodeListBuilder::CFA_BGGR;
- break;
- }
- default: {
- jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
- "Invalid metadata for tag %d", TAG_CFAPATTERN);
- return;
- }
+
+ const int cfaLength = 4;
+ cfaEnum = entry.data.u8[0];
+ uint8_t cfa[cfaLength];
+ if ((err = convertCFA(cfaEnum, /*out*/cfa)) != OK) {
+ jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
+ "Invalid metadata for tag %d", TAG_CFAPATTERN);
}
+
+ BAIL_IF_INVALID(writer->addEntry(TAG_CFAPATTERN, cfaLength, cfa, TIFF_IFD_0), env,
+ TAG_CFAPATTERN, writer);
+
+ opcodeCfaLayout = convertCFAEnumToOpcodeLayout(cfaEnum);
}
{
// Set CFA plane color
- uint8_t cfaPlaneColor[3] = {0, 1, 2};
BAIL_IF_INVALID(writer->addEntry(TAG_CFAPLANECOLOR, 3, cfaPlaneColor, TIFF_IFD_0),
env, TAG_CFAPLANECOLOR, writer);
}
@@ -1298,10 +1387,33 @@
camera_metadata_entry entry =
results.find(ANDROID_SENSOR_NOISE_PROFILE);
+ const status_t numPlaneColors = 3;
+ const status_t numCfaChannels = 4;
+
+ uint8_t cfaOut[numCfaChannels];
+ if ((err = convertCFA(cfaEnum, /*out*/cfaOut)) != OK) {
+ jniThrowException(env, "java/lang/IllegalArgumentException",
+ "Invalid CFA from camera characteristics");
+ return;
+ }
+
+ double noiseProfile[numPlaneColors * 2];
+
if (entry.count > 0) {
- BAIL_IF_INVALID(writer->addEntry(TAG_NOISEPROFILE, entry.count,
- entry.data.d, TIFF_IFD_0), env,
- TAG_NOISEPROFILE, writer);
+ if (entry.count != numCfaChannels * 2) {
+ ALOGW("%s: Invalid entry count %u for noise profile returned in characteristics,"
+ " no noise profile tag written...", __FUNCTION__, entry.count);
+ } else {
+ if ((err = generateNoiseProfile(entry.data.d, cfaOut, numCfaChannels,
+ cfaPlaneColor, numPlaneColors, /*out*/ noiseProfile)) == OK) {
+
+ BAIL_IF_INVALID(writer->addEntry(TAG_NOISEPROFILE, numPlaneColors * 2,
+ noiseProfile, TIFF_IFD_0), env, TAG_NOISEPROFILE, writer);
+ } else {
+ ALOGW("%s: Error converting coefficients for noise profile, no noise profile"
+ " tag written...", __FUNCTION__);
+ }
+ }
} else {
ALOGW("%s: No noise profile found in result metadata. Image quality may be reduced.",
__FUNCTION__);
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index afcfaf6..6080f2a 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -104,6 +104,12 @@
renderer->setHighContrastText(highContrastText);
}
+static void android_view_GLES20Canvas_insertReorderBarrier(JNIEnv* env, jobject clazz,
+ jlong rendererPtr, jboolean reorderEnable) {
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
+ renderer->insertReorderBarrier(reorderEnable);
+}
+
static int android_view_GLES20Canvas_prepare(JNIEnv* env, jobject clazz,
jlong rendererPtr, jboolean opaque) {
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
@@ -859,6 +865,7 @@
{ "nDestroyRenderer", "(J)V", (void*) android_view_GLES20Canvas_destroyRenderer },
{ "nSetViewport", "(JII)V", (void*) android_view_GLES20Canvas_setViewport },
{ "nSetHighContrastText","(JZ)V", (void*) android_view_GLES20Canvas_setHighContrastText },
+ { "nInsertReorderBarrier","(JZ)V", (void*) android_view_GLES20Canvas_insertReorderBarrier },
{ "nPrepare", "(JZ)I", (void*) android_view_GLES20Canvas_prepare },
{ "nPrepareDirty", "(JIIIIZ)I", (void*) android_view_GLES20Canvas_prepareDirty },
{ "nFinish", "(J)V", (void*) android_view_GLES20Canvas_finish },
diff --git a/core/res/res/anim/launch_task_behind_background.xml b/core/res/res/anim/launch_task_behind_target.xml
similarity index 100%
rename from core/res/res/anim/launch_task_behind_background.xml
rename to core/res/res/anim/launch_task_behind_target.xml
diff --git a/core/res/res/values-sw600dp/dimens.xml b/core/res/res/values-sw600dp/dimens.xml
index 3180e58..c0d9995 100644
--- a/core/res/res/values-sw600dp/dimens.xml
+++ b/core/res/res/values-sw600dp/dimens.xml
@@ -19,9 +19,9 @@
-->
<resources>
<!-- The width that is used when creating thumbnails of applications. -->
- <dimen name="thumbnail_width">512dp</dimen>
+ <dimen name="thumbnail_width">360dp</dimen>
<!-- The height that is used when creating thumbnails of applications. -->
- <dimen name="thumbnail_height">512dp</dimen>
+ <dimen name="thumbnail_height">360dp</dimen>
<!-- The maximum number of action buttons that should be permitted within
an action bar/action mode. This will be used to determine how many
showAsAction="ifRoom" items can fit. "always" items can override this. -->
diff --git a/core/res/res/values-television/styles.xml b/core/res/res/values-television/styles.xml
deleted file mode 100644
index 4c0562f..0000000
--- a/core/res/res/values-television/styles.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<!-- 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.
--->
-
-<resources>
- <style name="Lighting">
- <item name="lightY">-300dp</item>
- <item name="ambientShadowAlpha">0.4</item>
- <item name="spotShadowAlpha">0.4</item>
- </style>
-</resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index cc8d7cf..e88fe0a 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -1952,7 +1952,7 @@
<!-- When opening an activity in a new task using Intent/FLAG_ACTIVITY_LAUNCH_BEHIND,
this is the animation that is run on the activity of the new task (which is
entering the screen and then leaving). -->
- <attr name="launchTaskBehindBackgroundAnimation" format="reference" />
+ <attr name="launchTaskBehindTargetAnimation" format="reference" />
<!-- When opening an activity in a new task using Intent.FLAG_ACTIVITY_LAUNCH_BEHIND,
this is the animation that is run on the activity of the old task (which is
already on the screen and then stays on). -->
@@ -5531,7 +5531,7 @@
resource are available in addition to the specific attributes of Fade
described here. -->
<declare-styleable name="Fade">
- <!-- Equivalent to <code>visibilityMode</code>, fadingMode works only
+ <!-- Equivalent to <code>transitionVisibilityMode</code>, fadingMode works only
with the Fade transition. -->
<attr name="fadingMode">
<!-- Fade will only fade appearing items in. -->
@@ -5567,7 +5567,7 @@
<declare-styleable name="VisibilityTransition">
<!-- Changes whether the transition supports appearing and/or disappearing Views.
Corresponds to {@link android.transition.Visibility#setMode(int)}. -->
- <attr name="visibilityMode">
+ <attr name="transitionVisibilityMode">
<!-- Only appearing Views will be supported. -->
<flag name="mode_in" value="1" />
<!-- Only disappearing Views will be supported. -->
diff --git a/core/res/res/values/colors_material.xml b/core/res/res/values/colors_material.xml
index 2348951..c9292eb 100644
--- a/core/res/res/values/colors_material.xml
+++ b/core/res/res/values/colors_material.xml
@@ -46,10 +46,14 @@
<color name="hint_foreground_material_dark">@color/bright_foreground_disabled_material_dark</color>
<color name="hint_foreground_material_light">@color/bright_foreground_disabled_material_light</color>
+
<!-- TODO: This is 40% alpha on the default accent color. -->
- <color name="highlighted_text_material_dark">#6640c4ff</color>
+ <color name="highlighted_text_material_dark">#6680cbc4</color>
<!-- TODO: This is 40% alpha on the default accent color. -->
- <color name="highlighted_text_material_light">#6640c4ff</color>
+ <color name="highlighted_text_material_light">#66009688</color>
+
+ <color name="link_text_material_dark">@color/material_deep_teal_200</color>
+ <color name="link_text_material_light">@color/material_deep_teal_500</color>
<!-- Text & foreground colors -->
<eat-comment />
@@ -71,114 +75,33 @@
<!-- Primary & accent colors -->
<eat-comment />
- <color name="material_red_100">#fff4c7c3</color>
- <color name="material_red_300">#ffe67c73</color>
- <color name="material_red_500">#ffdb4437</color>
- <color name="material_red_700">#ffc53929</color>
- <color name="material_red_A200">#ffff5252</color>
- <color name="material_red_A400">#ffff1744</color>
-
- <color name="material_blue_100">#ffc6dafc</color>
- <color name="material_blue_300">#ff7baaf7</color>
- <color name="material_blue_500">#ff4285f4</color>
- <color name="material_blue_700">#ff3367d6</color>
- <color name="material_blue_A200">#ff448aff</color>
- <color name="material_blue_A400">#ff2979ff</color>
-
- <color name="material_light_blue_A200">#ff40c4ff</color>
-
- <color name="material_teal_100">#ffb2ebf2</color>
- <color name="material_teal_300">#ff4dd0e1</color>
- <color name="material_teal_500">#ff00bcd4</color>
- <color name="material_teal_700">#ff0097a7</color>
- <color name="material_teal_A200">#ff18ffff</color>
- <color name="material_teal_A400">#ff00e5ff</color>
-
- <color name="material_deep_teal_A200">#ff80cbc4</color>
- <color name="material_deep_teal_A500">#ff009688</color>
-
- <color name="material_green_100">#ffb7e1cd</color>
- <color name="material_green_300">#ff57bb8a</color>
- <color name="material_green_500">#ff0f9d58</color>
- <color name="material_green_700">#ff0b8043</color>
- <color name="material_green_A200">#ff69f0ae</color>
- <color name="material_green_A400">#ff00e676</color>
-
- <color name="material_lime_100">#fff0f4c3</color>
- <color name="material_lime_300">#ffdce775</color>
- <color name="material_lime_500">#ffcddc39</color>
- <color name="material_lime_700">#ffafb42b</color>
- <color name="material_lime_A200">#ffeeff41</color>
- <color name="material_lime_A400">#ffc6ff00</color>
-
- <color name="material_yellow_100">#fffce8b2</color>
- <color name="material_yellow_300">#fff7cb4d</color>
- <color name="material_yellow_500">#fff4b400</color>
- <color name="material_yellow_700">#fff09300</color>
- <color name="material_yellow_A200">#ffffcd40</color>
- <color name="material_yellow_A400">#ffffbc00</color>
-
- <color name="material_orange_100">#ffffe0b2</color>
- <color name="material_orange_300">#ffffb74d</color>
- <color name="material_orange_500">#ffff9800</color>
- <color name="material_orange_700">#fff57c00</color>
- <color name="material_orange_A200">#ffffab40</color>
- <color name="material_orange_A400">#ffff9100</color>
-
- <color name="material_deep_orange_100">#fff4c7c3</color>
- <color name="material_deep_orange_300">#ffe67c73</color>
- <color name="material_deep_orange_500">#ffff5722</color>
- <color name="material_deep_orange_700">#ffc53929</color>
- <color name="material_deep_orange_A200">#ffff5252</color>
- <color name="material_deep_orange_A400">#ffff1744</color>
-
- <!-- Neutral colors -->
- <eat-comment />
-
- <color name="material_grey_50">#fffafafa</color>
- <color name="material_grey_100">#fff5f5f5</color>
- <color name="material_grey_300">#ffeeeeee</color>
- <color name="material_grey_500">#ffa3a3a3</color>
- <color name="material_grey_600">#ff757575</color>
- <color name="material_grey_700">#ff717171</color>
- <color name="material_grey_900">#ff212121</color>
+ <color name="material_deep_teal_200">#ff80cbc4</color>
+ <color name="material_deep_teal_500">#ff009688</color>
<color name="material_blue_grey_50">#ffeceff1</color>
<color name="material_blue_grey_100">#ffcfd8dc</color>
- <color name="material_blue_grey_300">#ff90a4ae</color>
- <color name="material_blue_grey_400">#ff78909c</color>
- <color name="material_blue_grey_500">#ff607d8b</color>
- <color name="material_blue_grey_600">#ff546e7a</color>
- <color name="material_blue_grey_700">#ff455a64</color>
<color name="material_blue_grey_800">#ff37474f</color>
- <!-- Primary color used by Settings -->
<color name="material_blue_grey_900">#ff263238</color>
- <!-- Primary dark color used by Settings -->
<color name="material_blue_grey_950">#ff21272b</color>
- <color name="material_brown_100">#ffd7ccc8</color>
- <color name="material_brown_300">#ffa1887f</color>
- <color name="material_brown_500">#ff795548</color>
- <color name="material_brown_700">#ff5d4037</color>
-
<!-- Time picker defaults when no theme is set -->
<eat-comment />
<color name="timepicker_default_background_material">@color/primary_text_default_material_light</color>
<color name="timepicker_default_text_color_material">@color/black</color>
- <color name="timepicker_default_ampm_selected_background_color_material">@color/material_light_blue_A200</color>
+ <color name="timepicker_default_ampm_selected_background_color_material">@color/material_deep_teal_200</color>
<color name="timepicker_default_ampm_unselected_background_color_material">@color/transparent</color>
- <color name="timepicker_default_selector_color_material">@color/material_light_blue_A200</color>
+ <color name="timepicker_default_selector_color_material">@color/material_deep_teal_200</color>
<color name="timepicker_default_numbers_background_color_material">@color/transparent</color>
<!-- DatePicker colors -->
<eat-comment />
- <color name="datepicker_default_header_selector_background_material_light">@android:color/white</color>
+ <color name="datepicker_default_header_selector_background_material_light">@color/white</color>
<color name="datepicker_default_header_selector_background_material_dark">#ff303030</color>
<color name="datepicker_default_header_dayofweek_background_color_material_light">#999999</color>
- <color name="datepicker_default_header_dayofweek_background_color_material_dark">@android:color/white</color>
+ <color name="datepicker_default_header_dayofweek_background_color_material_dark">@color/white</color>
<color name="datepicker_default_normal_text_color_material_light">#ff999999</color>
<color name="datepicker_default_normal_text_color_material_dark">@android:color/white</color>
@@ -192,8 +115,8 @@
<color name="datepicker_default_pressed_text_color_material_light">#0099cc</color>
<color name="datepicker_default_pressed_text_color_material_dark">#0099cc</color>
- <color name="datepicker_default_circle_background_color_material_light">@android:color/holo_blue_light</color>
- <color name="datepicker_default_circle_background_color_material_dark">@android:color/holo_blue_light</color>
+ <color name="datepicker_default_circle_background_color_material_light">@color/material_deep_teal_500</color>
+ <color name="datepicker_default_circle_background_color_material_dark">@color/material_deep_teal_200</color>
<color name="datepicker_default_view_animator_color_material_light">#f2f2f2</color>
<color name="datepicker_default_view_animator_color_material_dark">#ff303030</color>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index f2466f7..07874c7 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2211,7 +2211,7 @@
<public type="attr" name="actionModeShareDrawable" />
<public type="attr" name="actionModeFindDrawable" />
<public type="attr" name="actionModeWebSearchDrawable" />
- <public type="attr" name="visibilityMode" />
+ <public type="attr" name="transitionVisibilityMode" />
<public type="attr" name="minimumHorizontalAngle" />
<public type="attr" name="minimumVerticalAngle" />
<public type="attr" name="maximumAngle" />
@@ -2232,7 +2232,7 @@
<public type="attr" name="multiArch" />
<public type="attr" name="touchscreenBlocksFocus" />
<public type="attr" name="windowElevation" />
- <public type="attr" name="launchTaskBehindBackgroundAnimation" />
+ <public type="attr" name="launchTaskBehindTargetAnimation" />
<public type="attr" name="launchTaskBehindSourceAnimation" />
<public type="attr" name="restrictionType" />
<public type="attr" name="dayOfWeekBackgroundColor" />
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 8fc9bac..bb0be48 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -82,7 +82,7 @@
<item name="activityCloseExitAnimation">@anim/activity_close_exit</item>
<item name="taskOpenEnterAnimation">@anim/task_open_enter</item>
<item name="taskOpenExitAnimation">@anim/task_open_exit</item>
- <item name="launchTaskBehindBackgroundAnimation">@anim/launch_task_behind_background</item>
+ <item name="launchTaskBehindTargetAnimation">@anim/launch_task_behind_target</item>
<item name="launchTaskBehindSourceAnimation">@anim/launch_task_behind_source</item>
<item name="taskCloseEnterAnimation">@anim/task_close_enter</item>
<item name="taskCloseExitAnimation">@anim/task_close_exit</item>
diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml
index 7a208f7..a79bd0a 100644
--- a/core/res/res/values/themes_material.xml
+++ b/core/res/res/values/themes_material.xml
@@ -64,8 +64,8 @@
<item name="textColorHintInverse">@color/hint_foreground_material_light</item>
<item name="textColorHighlight">@color/highlighted_text_material_dark</item>
<item name="textColorHighlightInverse">@color/highlighted_text_material_light</item>
- <item name="textColorLink">@color/material_teal_500</item>
- <item name="textColorLinkInverse">@color/material_teal_500</item>
+ <item name="textColorLink">@color/link_text_material_dark</item>
+ <item name="textColorLinkInverse">@color/link_text_material_light</item>
<item name="textColorSearchUrl">@color/search_url_text_material_dark</item>
<item name="textColorAlertDialogListItem">@color/primary_text_material_dark</item>
@@ -371,7 +371,7 @@
<!-- Color palette -->
<item name="colorPrimaryDark">@color/material_blue_grey_900</item>
<item name="colorPrimary">@color/material_blue_grey_800</item>
- <item name="colorAccent">@color/material_deep_teal_A200</item>
+ <item name="colorAccent">@color/material_deep_teal_200</item>
<item name="colorControlNormal">?attr/textColorSecondary</item>
<item name="colorControlActivated">?attr/colorAccent</item>
@@ -406,8 +406,8 @@
<item name="textColorHintInverse">@color/hint_foreground_material_dark</item>
<item name="textColorHighlight">@color/highlighted_text_material_light</item>
<item name="textColorHighlightInverse">@color/highlighted_text_material_dark</item>
- <item name="textColorLink">@color/material_teal_500</item>
- <item name="textColorLinkInverse">@color/material_teal_500</item>
+ <item name="textColorLink">@color/link_text_material_light</item>
+ <item name="textColorLinkInverse">@color/link_text_material_dark</item>
<item name="textColorSearchUrl">@color/search_url_text_material_light</item>
<item name="textColorAlertDialogListItem">@color/primary_text_material_light</item>
@@ -713,7 +713,7 @@
<!-- Color palette -->
<item name="colorPrimaryDark">@color/material_blue_grey_100</item>
<item name="colorPrimary">@color/material_blue_grey_50</item>
- <item name="colorAccent">@color/material_deep_teal_A500</item>
+ <item name="colorAccent">@color/material_deep_teal_500</item>
<item name="colorControlNormal">?attr/textColorSecondary</item>
<item name="colorControlActivated">?attr/colorAccent</item>
@@ -758,8 +758,8 @@
<item name="textColorHintInverse">@color/hint_foreground_material_dark</item>
<item name="textColorHighlight">@color/highlighted_text_material_light</item>
<item name="textColorHighlightInverse">@color/highlighted_text_material_dark</item>
- <item name="textColorLink">@color/material_teal_500</item>
- <item name="textColorLinkInverse">@color/material_teal_500</item>
+ <item name="textColorLink">@color/link_text_material_light</item>
+ <item name="textColorLinkInverse">@color/link_text_material_dark</item>
<item name="textColorSearchUrl">@color/search_url_text_material_light</item>
<item name="textColorAlertDialogListItem">@color/primary_text_material_light</item>
@@ -796,8 +796,8 @@
<item name="textColorHintInverse">@color/hint_foreground_material_light</item>
<item name="textColorHighlight">@color/highlighted_text_material_dark</item>
<item name="textColorHighlightInverse">@color/highlighted_text_material_light</item>
- <item name="textColorLink">@color/material_teal_500</item>
- <item name="textColorLinkInverse">@color/material_teal_500</item>
+ <item name="textColorLink">@color/link_text_material_dark</item>
+ <item name="textColorLinkInverse">@color/link_text_material_light</item>
<item name="textColorSearchUrl">@color/search_url_text_material_dark</item>
<item name="textColorAlertDialogListItem">@color/primary_text_material_dark</item>
@@ -1214,7 +1214,7 @@
<style name="Theme.Material.Settings" parent="Theme.Material.Light.DarkActionBar">
<item name="colorPrimary">@color/material_blue_grey_900</item>
<item name="colorPrimaryDark">@color/material_blue_grey_950</item>
- <item name="colorAccent">@color/material_deep_teal_A500</item>
+ <item name="colorAccent">@color/material_deep_teal_500</item>
<item name="dialogTheme">@style/Theme.Material.Settings.Dialog</item>
<item name="alertDialogTheme">@style/Theme.Material.Settings.Dialog.Alert</item>
@@ -1226,7 +1226,7 @@
<style name="Theme.Material.Settings.BaseDialog" parent="Theme.Material.Light.BaseDialog">
<item name="colorPrimary">@color/material_blue_grey_900</item>
<item name="colorPrimaryDark">@color/material_blue_grey_950</item>
- <item name="colorAccent">@color/material_deep_teal_A500</item>
+ <item name="colorAccent">@color/material_deep_teal_500</item>
</style>
<style name="Theme.Material.Settings.Dialog" parent="Theme.Material.Settings.BaseDialog" />
@@ -1234,7 +1234,7 @@
<style name="Theme.Material.Settings.Dialog.BaseAlert" parent="Theme.Material.Light.Dialog.BaseAlert">
<item name="colorPrimary">@color/material_blue_grey_900</item>
<item name="colorPrimaryDark">@color/material_blue_grey_950</item>
- <item name="colorAccent">@color/material_deep_teal_A500</item>
+ <item name="colorAccent">@color/material_deep_teal_500</item>
</style>
<style name="Theme.Material.Settings.Dialog.Alert" parent="Theme.Material.Settings.Dialog.BaseAlert" />
@@ -1242,19 +1242,19 @@
<style name="Theme.Material.Settings.Dialog.Presentation" parent="Theme.Material.Light.Dialog.Presentation">
<item name="colorPrimary">@color/material_blue_grey_900</item>
<item name="colorPrimaryDark">@color/material_blue_grey_950</item>
- <item name="colorAccent">@color/material_deep_teal_A500</item>
+ <item name="colorAccent">@color/material_deep_teal_500</item>
</style>
<style name="Theme.Material.Settings.SearchBar" parent="Theme.Material.Light.SearchBar">
<item name="colorPrimary">@color/material_blue_grey_900</item>
<item name="colorPrimaryDark">@color/material_blue_grey_950</item>
- <item name="colorAccent">@color/material_deep_teal_A500</item>
+ <item name="colorAccent">@color/material_deep_teal_500</item>
</style>
<style name="Theme.Material.Settings.CompactMenu" parent="Theme.Material.Light.CompactMenu">
<item name="colorPrimary">@color/material_blue_grey_900</item>
<item name="colorPrimaryDark">@color/material_blue_grey_950</item>
- <item name="colorAccent">@color/material_deep_teal_A500</item>
+ <item name="colorAccent">@color/material_deep_teal_500</item>
</style>
</resources>
diff --git a/data/sounds/AudioPackage10.mk b/data/sounds/AudioPackage10.mk
index 879e57a..68a87f2 100644
--- a/data/sounds/AudioPackage10.mk
+++ b/data/sounds/AudioPackage10.mk
@@ -22,16 +22,16 @@
$(LOCAL_PATH)/effects/ogg/KeypressDelete_48k.ogg:system/media/audio/ui/KeypressDelete.ogg \
$(LOCAL_PATH)/effects/ogg/KeypressInvalid_48k.ogg:system/media/audio/ui/KeypressInvalid.ogg \
$(LOCAL_PATH)/effects/ogg/KeypressReturn_48k.ogg:system/media/audio/ui/KeypressReturn.ogg \
- $(LOCAL_PATH)/effects/ogg/VideoRecord_48k.ogg:system/media/audio/ui/VideoRecord.ogg \
+ $(LOCAL_PATH)/effects/material/ogg/VideoRecord_48k.ogg:system/media/audio/ui/VideoRecord.ogg \
$(LOCAL_PATH)/effects/ogg/camera_click_48k.ogg:system/media/audio/ui/camera_click.ogg \
$(LOCAL_PATH)/effects/ogg/camera_focus.ogg:system/media/audio/ui/camera_focus.ogg \
- $(LOCAL_PATH)/effects/ogg/LowBattery.ogg:system/media/audio/ui/LowBattery.ogg \
+ $(LOCAL_PATH)/effects/material/ogg/LowBattery_48k.ogg:system/media/audio/ui/LowBattery.ogg \
$(LOCAL_PATH)/effects/ogg/Dock.ogg:system/media/audio/ui/Dock.ogg \
$(LOCAL_PATH)/effects/ogg/Undock.ogg:system/media/audio/ui/Undock.ogg \
$(LOCAL_PATH)/effects/ogg/Lock_48k.ogg:system/media/audio/ui/Lock.ogg \
$(LOCAL_PATH)/effects/ogg/Unlock_48k.ogg:system/media/audio/ui/Unlock.ogg \
$(LOCAL_PATH)/effects/ogg/Trusted_48k.ogg:system/media/audio/ui/Trusted.ogg \
- $(LOCAL_PATH)/effects/ogg/WirelessChargingStarted.ogg:system/media/audio/ui/WirelessChargingStarted.ogg \
+ $(LOCAL_PATH)/effects/material/ogg/WirelessChargingStarted_48k.ogg:system/media/audio/ui/WirelessChargingStarted.ogg \
$(LOCAL_PATH)/notifications/ogg/Adara.ogg:system/media/audio/notifications/Adara.ogg \
$(LOCAL_PATH)/notifications/ogg/Alya.ogg:system/media/audio/notifications/Alya.ogg \
$(LOCAL_PATH)/notifications/ogg/Arcturus.ogg:system/media/audio/notifications/Arcturus.ogg \
diff --git a/data/sounds/AudioPackage11.mk b/data/sounds/AudioPackage11.mk
index 03e205b..f19ed30 100644
--- a/data/sounds/AudioPackage11.mk
+++ b/data/sounds/AudioPackage11.mk
@@ -22,16 +22,16 @@
$(LOCAL_PATH)/effects/ogg/KeypressDelete_48k.ogg:system/media/audio/ui/KeypressDelete.ogg \
$(LOCAL_PATH)/effects/ogg/KeypressInvalid_48k.ogg:system/media/audio/ui/KeypressInvalid.ogg \
$(LOCAL_PATH)/effects/ogg/KeypressReturn_48k.ogg:system/media/audio/ui/KeypressReturn.ogg \
- $(LOCAL_PATH)/effects/ogg/VideoRecord_48k.ogg:system/media/audio/ui/VideoRecord.ogg \
+ $(LOCAL_PATH)/effects/material/ogg/VideoRecord_48k.ogg:system/media/audio/ui/VideoRecord.ogg \
$(LOCAL_PATH)/effects/ogg/camera_click_48k.ogg:system/media/audio/ui/camera_click.ogg \
$(LOCAL_PATH)/effects/ogg/camera_focus.ogg:system/media/audio/ui/camera_focus.ogg \
- $(LOCAL_PATH)/effects/ogg/LowBattery.ogg:system/media/audio/ui/LowBattery.ogg \
+ $(LOCAL_PATH)/effects/material/ogg/LowBattery_48k.ogg:system/media/audio/ui/LowBattery.ogg \
$(LOCAL_PATH)/effects/ogg/Dock.ogg:system/media/audio/ui/Dock.ogg \
$(LOCAL_PATH)/effects/ogg/Undock.ogg:system/media/audio/ui/Undock.ogg \
$(LOCAL_PATH)/effects/ogg/Lock_48k.ogg:system/media/audio/ui/Lock.ogg \
$(LOCAL_PATH)/effects/ogg/Unlock_48k.ogg:system/media/audio/ui/Unlock.ogg \
$(LOCAL_PATH)/effects/ogg/Trusted_48k.ogg:system/media/audio/ui/Trusted.ogg \
- $(LOCAL_PATH)/effects/ogg/WirelessChargingStarted.ogg:system/media/audio/ui/WirelessChargingStarted.ogg \
+ $(LOCAL_PATH)/effects/material/ogg/WirelessChargingStarted_48k.ogg:system/media/audio/ui/WirelessChargingStarted.ogg \
$(LOCAL_PATH)/notifications/ogg/Adara.ogg:system/media/audio/notifications/Adara.ogg \
$(LOCAL_PATH)/notifications/ogg/Alya.ogg:system/media/audio/notifications/Alya.ogg \
$(LOCAL_PATH)/notifications/ogg/Arcturus.ogg:system/media/audio/notifications/Arcturus.ogg \
diff --git a/data/sounds/AudioPackage12.mk b/data/sounds/AudioPackage12.mk
index c37c392..c13689d 100644
--- a/data/sounds/AudioPackage12.mk
+++ b/data/sounds/AudioPackage12.mk
@@ -12,8 +12,8 @@
NOTIFICATION_FILES := Ariel Ceres Carme Elara Europa Iapetus Io Rhea Salacia Titan Tethys
RINGTONE_FILES := Callisto Dione Ganymede Luna Oberon Phobos Sedna Titania Triton Umbriel
EFFECT_FILES := Effect_Tick KeypressReturn KeypressInvalid KeypressDelete KeypressSpacebar KeypressStandard \
- VideoRecord camera_click camera_focus LowBattery Dock Undock Lock Unlock WirelessChargingStarted \
- Trusted
+ camera_click camera_focus Dock Undock Lock Unlock Trusted
+MATERIAL_EFFECT_FILES := VideoRecord LowBattery WirelessChargingStarted
PRODUCT_COPY_FILES += $(foreach fn,$(ALARM_FILES),\
$(LOCAL_PATH)/alarms/ogg/$(fn).ogg:system/media/audio/alarms/$(fn).ogg)
@@ -26,3 +26,5 @@
PRODUCT_COPY_FILES += $(foreach fn,$(EFFECT_FILES),\
$(LOCAL_PATH)/effects/ogg/$(fn).ogg:system/media/audio/ui/$(fn).ogg)
+PRODUCT_COPY_FILES += $(foreach fn,$(MATERIAL_EFFECT_FILES),\
+ $(LOCAL_PATH)/effects/material/ogg/$(fn).ogg:system/media/audio/ui/$(fn).ogg)
diff --git a/data/sounds/AudioPackage12_48.mk b/data/sounds/AudioPackage12_48.mk
index 2a5efb0..6d86baf 100644
--- a/data/sounds/AudioPackage12_48.mk
+++ b/data/sounds/AudioPackage12_48.mk
@@ -12,7 +12,8 @@
NOTIFICATION_FILES := Ariel Ceres Carme Elara Europa Iapetus Io Rhea Salacia Titan Tethys
RINGTONE_FILES := Callisto Dione Ganymede Luna Oberon Phobos Sedna Titania Triton Umbriel
EFFECT_FILES := Effect_Tick KeypressReturn KeypressInvalid KeypressDelete KeypressSpacebar KeypressStandard \
- VideoRecord camera_click Lock Unlock Trusted
+ camera_click Lock Unlock Trusted
+MATERIAL_EFFECT_FILES := VideoRecord LowBattery WirelessChargingStarted
# Alarms not yet available in 48 kHz
PRODUCT_COPY_FILES += $(foreach fn,$(ALARM_FILES),\
@@ -26,11 +27,11 @@
PRODUCT_COPY_FILES += $(foreach fn,$(EFFECT_FILES),\
$(LOCAL_PATH)/effects/ogg/$(fn)_48k.ogg:system/media/audio/ui/$(fn).ogg)
+PRODUCT_COPY_FILES += $(foreach fn,$(MATERIAL_EFFECT_FILES),\
+ $(LOCAL_PATH)/effects/material/ogg/$(fn)_48k.ogg:system/media/audio/ui/$(fn).ogg)
# no gold-plated version yet
PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/effects/ogg/camera_focus.ogg:system/media/audio/ui/camera_focus.ogg \
- $(LOCAL_PATH)/effects/ogg/LowBattery.ogg:system/media/audio/ui/LowBattery.ogg \
- $(LOCAL_PATH)/effects/ogg/WirelessChargingStarted.ogg:system/media/audio/ui/WirelessChargingStarted.ogg \
$(LOCAL_PATH)/effects/ogg/Dock.ogg:system/media/audio/ui/Dock.ogg \
$(LOCAL_PATH)/effects/ogg/Undock.ogg:system/media/audio/ui/Undock.ogg
\ No newline at end of file
diff --git a/data/sounds/AudioPackage13.mk b/data/sounds/AudioPackage13.mk
new file mode 100644
index 0000000..57fe762
--- /dev/null
+++ b/data/sounds/AudioPackage13.mk
@@ -0,0 +1,33 @@
+#
+# Audio Package 13 - L
+#
+# Include this file in a product makefile to include these audio files
+#
+#
+
+LOCAL_PATH := frameworks/base/data/sounds
+
+# Simple files that do not require renaming
+ALARM_FILES := Alarm1 Alarm2 Alarm3 Alarm4 Alarm5 Alarm6 Alarm7 Alarm8 Timer
+NOTIFICATION_FILES := Notification1 Notification2 Notification3 Notification4 \
+ Notification5 Notification6 Notification7 Notification8 Notification9 \
+ Notification10 Notification11
+RINGTONE_FILES := Ringtone1 Ringtone2 Ringtone3 Ringtone4 Ringtone5 Ringtone6 \
+ Ringtone7 Ringtone8 Ringtone9 Ringtone10 Ringtone11 Ringtone12
+EFFECT_FILES := Effect_Tick KeypressReturn KeypressInvalid KeypressDelete KeypressSpacebar KeypressStandard \
+ camera_click camera_focus Dock Undock Lock Unlock Trusted
+MATERIAL_EFFECT_FILES := VideoRecord WirelessChargingStarted LowBattery
+
+PRODUCT_COPY_FILES += $(foreach fn,$(ALARM_FILES),\
+ $(LOCAL_PATH)/alarms/material/ogg/$(fn).ogg:system/media/audio/alarms/$(fn).ogg)
+
+PRODUCT_COPY_FILES += $(foreach fn,$(NOTIFICATION_FILES),\
+ $(LOCAL_PATH)/notifications/material/ogg/$(fn).ogg:system/media/audio/notifications/$(fn).ogg)
+
+PRODUCT_COPY_FILES += $(foreach fn,$(RINGTONE_FILES),\
+ $(LOCAL_PATH)/ringtones/material/ogg/$(fn).ogg:system/media/audio/ringtones/$(fn).ogg)
+
+PRODUCT_COPY_FILES += $(foreach fn,$(EFFECT_FILES),\
+ $(LOCAL_PATH)/effects/ogg/$(fn).ogg:system/media/audio/ui/$(fn).ogg)
+PRODUCT_COPY_FILES += $(foreach fn,$(MATERIAL_EFFECT_FILES),\
+ $(LOCAL_PATH)/effects/material/ogg/$(fn).ogg:system/media/audio/ui/$(fn).ogg)
diff --git a/data/sounds/AudioPackage13_48.mk b/data/sounds/AudioPackage13_48.mk
new file mode 100644
index 0000000..187bccb
--- /dev/null
+++ b/data/sounds/AudioPackage13_48.mk
@@ -0,0 +1,39 @@
+#
+# Audio Package 13 - L (48kHz)
+#
+# Include this file in a product makefile to include these audio files
+#
+#
+
+LOCAL_PATH := frameworks/base/data/sounds
+
+# Simple files that do not require renaming
+ALARM_FILES := Alarm1 Alarm2 Alarm3 Alarm4 Alarm5 Alarm6 Alarm7 Alarm8 Timer
+NOTIFICATION_FILES := Notification1 Notification2 Notification3 Notification4 \
+ Notification5 Notification6 Notification7 Notification8 Notification9 \
+ Notification10 Notification11
+RINGTONE_FILES := Ringtone1 Ringtone2 Ringtone3 Ringtone4 Ringtone5 Ringtone6 \
+ Ringtone7 Ringtone8 Ringtone9 Ringtone10 Ringtone11 Ringtone12
+EFFECT_FILES := Effect_Tick KeypressReturn KeypressInvalid KeypressDelete KeypressSpacebar KeypressStandard \
+ camera_click Lock Unlock Trusted
+MATERIAL_EFFECT_FILES := VideoRecord WirelessChargingStarted LowBattery
+
+PRODUCT_COPY_FILES += $(foreach fn,$(ALARM_FILES),\
+ $(LOCAL_PATH)/alarms/material/ogg/$(fn)_48k.ogg:system/media/audio/alarms/$(fn).ogg)
+
+PRODUCT_COPY_FILES += $(foreach fn,$(NOTIFICATION_FILES),\
+ $(LOCAL_PATH)/notifications/material/ogg/$(fn)_48k.ogg:system/media/audio/notifications/$(fn).ogg)
+
+PRODUCT_COPY_FILES += $(foreach fn,$(RINGTONE_FILES),\
+ $(LOCAL_PATH)/ringtones/material/ogg/$(fn)_48k.ogg:system/media/audio/ringtones/$(fn).ogg)
+
+PRODUCT_COPY_FILES += $(foreach fn,$(EFFECT_FILES),\
+ $(LOCAL_PATH)/effects/ogg/$(fn)_48k.ogg:system/media/audio/ui/$(fn).ogg)
+PRODUCT_COPY_FILES += $(foreach fn,$(MATERIAL_EFFECT_FILES),\
+ $(LOCAL_PATH)/effects/material/ogg/$(fn)_48k.ogg:system/media/audio/ui/$(fn).ogg)
+
+# no gold-plated version yet
+PRODUCT_COPY_FILES += \
+ $(LOCAL_PATH)/effects/ogg/camera_focus.ogg:system/media/audio/ui/camera_focus.ogg \
+ $(LOCAL_PATH)/effects/ogg/Dock.ogg:system/media/audio/ui/Dock.ogg \
+ $(LOCAL_PATH)/effects/ogg/Undock.ogg:system/media/audio/ui/Undock.ogg
\ No newline at end of file
diff --git a/data/sounds/AudioPackage6.mk b/data/sounds/AudioPackage6.mk
index 3205c0e..89b5f1b 100644
--- a/data/sounds/AudioPackage6.mk
+++ b/data/sounds/AudioPackage6.mk
@@ -18,10 +18,10 @@
$(LOCAL_PATH)/effects/ogg/KeypressDelete.ogg:system/media/audio/ui/KeypressDelete.ogg \
$(LOCAL_PATH)/effects/ogg/KeypressInvalid.ogg:system/media/audio/ui/KeypressInvalid.ogg \
$(LOCAL_PATH)/effects/ogg/KeypressReturn.ogg:system/media/audio/ui/KeypressReturn.ogg \
- $(LOCAL_PATH)/effects/ogg/VideoRecord.ogg:system/media/audio/ui/VideoRecord.ogg \
+ $(LOCAL_PATH)/effects/material/ogg/VideoRecord.ogg:system/media/audio/ui/VideoRecord.ogg \
$(LOCAL_PATH)/effects/ogg/camera_click.ogg:system/media/audio/ui/camera_click.ogg \
$(LOCAL_PATH)/effects/ogg/camera_focus.ogg:system/media/audio/ui/camera_focus.ogg \
- $(LOCAL_PATH)/effects/ogg/LowBattery.ogg:system/media/audio/ui/LowBattery.ogg \
+ $(LOCAL_PATH)/effects/material/ogg/LowBattery.ogg:system/media/audio/ui/LowBattery.ogg \
$(LOCAL_PATH)/effects/ogg/Dock.ogg:system/media/audio/ui/Dock.ogg \
$(LOCAL_PATH)/effects/ogg/Undock.ogg:system/media/audio/ui/Undock.ogg \
$(LOCAL_PATH)/effects/ogg/Lock.ogg:system/media/audio/ui/Lock.ogg \
diff --git a/data/sounds/AudioPackage7.mk b/data/sounds/AudioPackage7.mk
index c92c1d0..065fb84 100644
--- a/data/sounds/AudioPackage7.mk
+++ b/data/sounds/AudioPackage7.mk
@@ -20,10 +20,10 @@
$(LOCAL_PATH)/effects/ogg/KeypressDelete_120.ogg:system/media/audio/ui/KeypressDelete.ogg \
$(LOCAL_PATH)/effects/ogg/KeypressInvalid_120.ogg:system/media/audio/ui/KeypressInvalid.ogg \
$(LOCAL_PATH)/effects/ogg/KeypressReturn_120.ogg:system/media/audio/ui/KeypressReturn.ogg \
- $(LOCAL_PATH)/effects/ogg/VideoRecord.ogg:system/media/audio/ui/VideoRecord.ogg \
+ $(LOCAL_PATH)/effects/material/ogg/VideoRecord.ogg:system/media/audio/ui/VideoRecord.ogg \
$(LOCAL_PATH)/effects/ogg/camera_click.ogg:system/media/audio/ui/camera_click.ogg \
$(LOCAL_PATH)/effects/ogg/camera_focus.ogg:system/media/audio/ui/camera_focus.ogg \
- $(LOCAL_PATH)/effects/ogg/LowBattery.ogg:system/media/audio/ui/LowBattery.ogg \
+ $(LOCAL_PATH)/effects/material/ogg/LowBattery.ogg:system/media/audio/ui/LowBattery.ogg \
$(LOCAL_PATH)/effects/ogg/Dock.ogg:system/media/audio/ui/Dock.ogg \
$(LOCAL_PATH)/effects/ogg/Undock.ogg:system/media/audio/ui/Undock.ogg \
$(LOCAL_PATH)/effects/ogg/Lock.ogg:system/media/audio/ui/Lock.ogg \
diff --git a/data/sounds/AudioPackage8.mk b/data/sounds/AudioPackage8.mk
index b8be4e3e..070381d 100644
--- a/data/sounds/AudioPackage8.mk
+++ b/data/sounds/AudioPackage8.mk
@@ -22,10 +22,10 @@
$(LOCAL_PATH)/effects/ogg/KeypressDelete.ogg:system/media/audio/ui/KeypressDelete.ogg \
$(LOCAL_PATH)/effects/ogg/KeypressInvalid.ogg:system/media/audio/ui/KeypressInvalid.ogg \
$(LOCAL_PATH)/effects/ogg/KeypressReturn.ogg:system/media/audio/ui/KeypressReturn.ogg \
- $(LOCAL_PATH)/effects/ogg/VideoRecord.ogg:system/media/audio/ui/VideoRecord.ogg \
+ $(LOCAL_PATH)/effects/material/ogg/VideoRecord.ogg:system/media/audio/ui/VideoRecord.ogg \
$(LOCAL_PATH)/effects/ogg/camera_click.ogg:system/media/audio/ui/camera_click.ogg \
$(LOCAL_PATH)/effects/ogg/camera_focus.ogg:system/media/audio/ui/camera_focus.ogg \
- $(LOCAL_PATH)/effects/ogg/LowBattery.ogg:system/media/audio/ui/LowBattery.ogg \
+ $(LOCAL_PATH)/effects/material/ogg/LowBattery.ogg:system/media/audio/ui/LowBattery.ogg \
$(LOCAL_PATH)/effects/ogg/Dock.ogg:system/media/audio/ui/Dock.ogg \
$(LOCAL_PATH)/effects/ogg/Undock.ogg:system/media/audio/ui/Undock.ogg \
$(LOCAL_PATH)/effects/ogg/Lock.ogg:system/media/audio/ui/Lock.ogg \
diff --git a/data/sounds/AudioPackage9.mk b/data/sounds/AudioPackage9.mk
index 9b761bc..0673811 100644
--- a/data/sounds/AudioPackage9.mk
+++ b/data/sounds/AudioPackage9.mk
@@ -22,10 +22,10 @@
$(LOCAL_PATH)/effects/ogg/KeypressDelete.ogg:system/media/audio/ui/KeypressDelete.ogg \
$(LOCAL_PATH)/effects/ogg/KeypressInvalid.ogg:system/media/audio/ui/KeypressInvalid.ogg \
$(LOCAL_PATH)/effects/ogg/KeypressReturn.ogg:system/media/audio/ui/KeypressReturn.ogg \
- $(LOCAL_PATH)/effects/ogg/VideoRecord.ogg:system/media/audio/ui/VideoRecord.ogg \
+ $(LOCAL_PATH)/effects/material/ogg/VideoRecord.ogg:system/media/audio/ui/VideoRecord.ogg \
$(LOCAL_PATH)/effects/ogg/camera_click.ogg:system/media/audio/ui/camera_click.ogg \
$(LOCAL_PATH)/effects/ogg/camera_focus.ogg:system/media/audio/ui/camera_focus.ogg \
- $(LOCAL_PATH)/effects/ogg/LowBattery.ogg:system/media/audio/ui/LowBattery.ogg \
+ $(LOCAL_PATH)/effects/material/ogg/LowBattery.ogg:system/media/audio/ui/LowBattery.ogg \
$(LOCAL_PATH)/effects/ogg/Dock.ogg:system/media/audio/ui/Dock.ogg \
$(LOCAL_PATH)/effects/ogg/Undock.ogg:system/media/audio/ui/Undock.ogg \
$(LOCAL_PATH)/effects/ogg/Lock.ogg:system/media/audio/ui/Lock.ogg \
diff --git a/data/sounds/alarms/material/ogg/Alarm1.ogg b/data/sounds/alarms/material/ogg/Alarm1.ogg
new file mode 100644
index 0000000..87ecfeb
--- /dev/null
+++ b/data/sounds/alarms/material/ogg/Alarm1.ogg
Binary files differ
diff --git a/data/sounds/alarms/material/ogg/Alarm1_48k.ogg b/data/sounds/alarms/material/ogg/Alarm1_48k.ogg
new file mode 100644
index 0000000..7ca6faa
--- /dev/null
+++ b/data/sounds/alarms/material/ogg/Alarm1_48k.ogg
Binary files differ
diff --git a/data/sounds/alarms/material/ogg/Alarm2.ogg b/data/sounds/alarms/material/ogg/Alarm2.ogg
new file mode 100644
index 0000000..0d96853f
--- /dev/null
+++ b/data/sounds/alarms/material/ogg/Alarm2.ogg
Binary files differ
diff --git a/data/sounds/alarms/material/ogg/Alarm2_48k.ogg b/data/sounds/alarms/material/ogg/Alarm2_48k.ogg
new file mode 100644
index 0000000..133fcb5
--- /dev/null
+++ b/data/sounds/alarms/material/ogg/Alarm2_48k.ogg
Binary files differ
diff --git a/data/sounds/alarms/material/ogg/Alarm3.ogg b/data/sounds/alarms/material/ogg/Alarm3.ogg
new file mode 100644
index 0000000..d381448
--- /dev/null
+++ b/data/sounds/alarms/material/ogg/Alarm3.ogg
Binary files differ
diff --git a/data/sounds/alarms/material/ogg/Alarm3_48k.ogg b/data/sounds/alarms/material/ogg/Alarm3_48k.ogg
new file mode 100644
index 0000000..a53fbb8
--- /dev/null
+++ b/data/sounds/alarms/material/ogg/Alarm3_48k.ogg
Binary files differ
diff --git a/data/sounds/alarms/material/ogg/Alarm4.ogg b/data/sounds/alarms/material/ogg/Alarm4.ogg
new file mode 100644
index 0000000..4529aa8
--- /dev/null
+++ b/data/sounds/alarms/material/ogg/Alarm4.ogg
Binary files differ
diff --git a/data/sounds/alarms/material/ogg/Alarm4_48k.ogg b/data/sounds/alarms/material/ogg/Alarm4_48k.ogg
new file mode 100644
index 0000000..ac8781d
--- /dev/null
+++ b/data/sounds/alarms/material/ogg/Alarm4_48k.ogg
Binary files differ
diff --git a/data/sounds/alarms/material/ogg/Alarm5.ogg b/data/sounds/alarms/material/ogg/Alarm5.ogg
new file mode 100644
index 0000000..61582d5
--- /dev/null
+++ b/data/sounds/alarms/material/ogg/Alarm5.ogg
Binary files differ
diff --git a/data/sounds/alarms/material/ogg/Alarm5_48k.ogg b/data/sounds/alarms/material/ogg/Alarm5_48k.ogg
new file mode 100644
index 0000000..0f0ff03
--- /dev/null
+++ b/data/sounds/alarms/material/ogg/Alarm5_48k.ogg
Binary files differ
diff --git a/data/sounds/alarms/material/ogg/Alarm6.ogg b/data/sounds/alarms/material/ogg/Alarm6.ogg
new file mode 100644
index 0000000..245c4ce
--- /dev/null
+++ b/data/sounds/alarms/material/ogg/Alarm6.ogg
Binary files differ
diff --git a/data/sounds/alarms/material/ogg/Alarm6_48k.ogg b/data/sounds/alarms/material/ogg/Alarm6_48k.ogg
new file mode 100644
index 0000000..b8abc3a
--- /dev/null
+++ b/data/sounds/alarms/material/ogg/Alarm6_48k.ogg
Binary files differ
diff --git a/data/sounds/alarms/material/ogg/Alarm7.ogg b/data/sounds/alarms/material/ogg/Alarm7.ogg
new file mode 100644
index 0000000..0b489bd
--- /dev/null
+++ b/data/sounds/alarms/material/ogg/Alarm7.ogg
Binary files differ
diff --git a/data/sounds/alarms/material/ogg/Alarm7_48k.ogg b/data/sounds/alarms/material/ogg/Alarm7_48k.ogg
new file mode 100644
index 0000000..0fdeab6
--- /dev/null
+++ b/data/sounds/alarms/material/ogg/Alarm7_48k.ogg
Binary files differ
diff --git a/data/sounds/alarms/material/ogg/Alarm8.ogg b/data/sounds/alarms/material/ogg/Alarm8.ogg
new file mode 100644
index 0000000..053b008
--- /dev/null
+++ b/data/sounds/alarms/material/ogg/Alarm8.ogg
Binary files differ
diff --git a/data/sounds/alarms/material/ogg/Alarm8_48k.ogg b/data/sounds/alarms/material/ogg/Alarm8_48k.ogg
new file mode 100644
index 0000000..2107172
--- /dev/null
+++ b/data/sounds/alarms/material/ogg/Alarm8_48k.ogg
Binary files differ
diff --git a/data/sounds/alarms/material/ogg/Timer.ogg b/data/sounds/alarms/material/ogg/Timer.ogg
new file mode 100644
index 0000000..97519aa
--- /dev/null
+++ b/data/sounds/alarms/material/ogg/Timer.ogg
Binary files differ
diff --git a/data/sounds/alarms/material/ogg/Timer_48k.ogg b/data/sounds/alarms/material/ogg/Timer_48k.ogg
new file mode 100644
index 0000000..bd30280
--- /dev/null
+++ b/data/sounds/alarms/material/ogg/Timer_48k.ogg
Binary files differ
diff --git a/data/sounds/effects/material/ogg/LowBattery.ogg b/data/sounds/effects/material/ogg/LowBattery.ogg
new file mode 100644
index 0000000..9dbce2b
--- /dev/null
+++ b/data/sounds/effects/material/ogg/LowBattery.ogg
Binary files differ
diff --git a/data/sounds/effects/material/ogg/LowBattery_48k.ogg b/data/sounds/effects/material/ogg/LowBattery_48k.ogg
new file mode 100644
index 0000000..f60f2b1
--- /dev/null
+++ b/data/sounds/effects/material/ogg/LowBattery_48k.ogg
Binary files differ
diff --git a/data/sounds/effects/material/ogg/VideoRecord.ogg b/data/sounds/effects/material/ogg/VideoRecord.ogg
new file mode 100644
index 0000000..e98fabc
--- /dev/null
+++ b/data/sounds/effects/material/ogg/VideoRecord.ogg
Binary files differ
diff --git a/data/sounds/effects/material/ogg/VideoRecord_48k.ogg b/data/sounds/effects/material/ogg/VideoRecord_48k.ogg
new file mode 100644
index 0000000..b1eb780
--- /dev/null
+++ b/data/sounds/effects/material/ogg/VideoRecord_48k.ogg
Binary files differ
diff --git a/data/sounds/effects/material/ogg/WirelessChargingStarted.ogg b/data/sounds/effects/material/ogg/WirelessChargingStarted.ogg
new file mode 100644
index 0000000..db5d2cb
--- /dev/null
+++ b/data/sounds/effects/material/ogg/WirelessChargingStarted.ogg
Binary files differ
diff --git a/data/sounds/effects/material/ogg/WirelessChargingStarted_48k.ogg b/data/sounds/effects/material/ogg/WirelessChargingStarted_48k.ogg
new file mode 100644
index 0000000..adacd47
--- /dev/null
+++ b/data/sounds/effects/material/ogg/WirelessChargingStarted_48k.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification1.ogg b/data/sounds/notifications/material/ogg/Notification1.ogg
new file mode 100644
index 0000000..fc61f70
--- /dev/null
+++ b/data/sounds/notifications/material/ogg/Notification1.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification10.ogg b/data/sounds/notifications/material/ogg/Notification10.ogg
new file mode 100644
index 0000000..347c38d
--- /dev/null
+++ b/data/sounds/notifications/material/ogg/Notification10.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification10_48k.ogg b/data/sounds/notifications/material/ogg/Notification10_48k.ogg
new file mode 100644
index 0000000..1de91de
--- /dev/null
+++ b/data/sounds/notifications/material/ogg/Notification10_48k.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification11.ogg b/data/sounds/notifications/material/ogg/Notification11.ogg
new file mode 100644
index 0000000..ea83b5b
--- /dev/null
+++ b/data/sounds/notifications/material/ogg/Notification11.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification11_48k.ogg b/data/sounds/notifications/material/ogg/Notification11_48k.ogg
new file mode 100644
index 0000000..dba0416
--- /dev/null
+++ b/data/sounds/notifications/material/ogg/Notification11_48k.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification1_48k.ogg b/data/sounds/notifications/material/ogg/Notification1_48k.ogg
new file mode 100644
index 0000000..b2ab648
--- /dev/null
+++ b/data/sounds/notifications/material/ogg/Notification1_48k.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification2.ogg b/data/sounds/notifications/material/ogg/Notification2.ogg
new file mode 100644
index 0000000..0e54844
--- /dev/null
+++ b/data/sounds/notifications/material/ogg/Notification2.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification2_48k.ogg b/data/sounds/notifications/material/ogg/Notification2_48k.ogg
new file mode 100644
index 0000000..4c4af31
--- /dev/null
+++ b/data/sounds/notifications/material/ogg/Notification2_48k.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification3.ogg b/data/sounds/notifications/material/ogg/Notification3.ogg
new file mode 100644
index 0000000..ff17500
--- /dev/null
+++ b/data/sounds/notifications/material/ogg/Notification3.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification3_48k.ogg b/data/sounds/notifications/material/ogg/Notification3_48k.ogg
new file mode 100644
index 0000000..b138284
--- /dev/null
+++ b/data/sounds/notifications/material/ogg/Notification3_48k.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification4.ogg b/data/sounds/notifications/material/ogg/Notification4.ogg
new file mode 100644
index 0000000..ec6e7cb
--- /dev/null
+++ b/data/sounds/notifications/material/ogg/Notification4.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification4_48k.ogg b/data/sounds/notifications/material/ogg/Notification4_48k.ogg
new file mode 100644
index 0000000..2be9332
--- /dev/null
+++ b/data/sounds/notifications/material/ogg/Notification4_48k.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification5.ogg b/data/sounds/notifications/material/ogg/Notification5.ogg
new file mode 100644
index 0000000..f7386a7
--- /dev/null
+++ b/data/sounds/notifications/material/ogg/Notification5.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification5_48k.ogg b/data/sounds/notifications/material/ogg/Notification5_48k.ogg
new file mode 100644
index 0000000..0ffba07
--- /dev/null
+++ b/data/sounds/notifications/material/ogg/Notification5_48k.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification6.ogg b/data/sounds/notifications/material/ogg/Notification6.ogg
new file mode 100644
index 0000000..e4dcf28
--- /dev/null
+++ b/data/sounds/notifications/material/ogg/Notification6.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification6_48k.ogg b/data/sounds/notifications/material/ogg/Notification6_48k.ogg
new file mode 100644
index 0000000..2891de6
--- /dev/null
+++ b/data/sounds/notifications/material/ogg/Notification6_48k.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification7.ogg b/data/sounds/notifications/material/ogg/Notification7.ogg
new file mode 100644
index 0000000..ce94e21
--- /dev/null
+++ b/data/sounds/notifications/material/ogg/Notification7.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification7_48k.ogg b/data/sounds/notifications/material/ogg/Notification7_48k.ogg
new file mode 100644
index 0000000..45c5f0a
--- /dev/null
+++ b/data/sounds/notifications/material/ogg/Notification7_48k.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification8.ogg b/data/sounds/notifications/material/ogg/Notification8.ogg
new file mode 100644
index 0000000..d7c810d
--- /dev/null
+++ b/data/sounds/notifications/material/ogg/Notification8.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification8_48k.ogg b/data/sounds/notifications/material/ogg/Notification8_48k.ogg
new file mode 100644
index 0000000..8b9703e
--- /dev/null
+++ b/data/sounds/notifications/material/ogg/Notification8_48k.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification9.ogg b/data/sounds/notifications/material/ogg/Notification9.ogg
new file mode 100644
index 0000000..e05a529
--- /dev/null
+++ b/data/sounds/notifications/material/ogg/Notification9.ogg
Binary files differ
diff --git a/data/sounds/notifications/material/ogg/Notification9_48k.ogg b/data/sounds/notifications/material/ogg/Notification9_48k.ogg
new file mode 100644
index 0000000..599b3fc
--- /dev/null
+++ b/data/sounds/notifications/material/ogg/Notification9_48k.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone1.ogg b/data/sounds/ringtones/material/ogg/Ringtone1.ogg
new file mode 100644
index 0000000..87a05ee
--- /dev/null
+++ b/data/sounds/ringtones/material/ogg/Ringtone1.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone10.ogg b/data/sounds/ringtones/material/ogg/Ringtone10.ogg
new file mode 100644
index 0000000..5e312d2
--- /dev/null
+++ b/data/sounds/ringtones/material/ogg/Ringtone10.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone10_48k.ogg b/data/sounds/ringtones/material/ogg/Ringtone10_48k.ogg
new file mode 100644
index 0000000..cd02cbc
--- /dev/null
+++ b/data/sounds/ringtones/material/ogg/Ringtone10_48k.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone11.ogg b/data/sounds/ringtones/material/ogg/Ringtone11.ogg
new file mode 100644
index 0000000..4786b18
--- /dev/null
+++ b/data/sounds/ringtones/material/ogg/Ringtone11.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone11_48k.ogg b/data/sounds/ringtones/material/ogg/Ringtone11_48k.ogg
new file mode 100644
index 0000000..6b39351
--- /dev/null
+++ b/data/sounds/ringtones/material/ogg/Ringtone11_48k.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone12.ogg b/data/sounds/ringtones/material/ogg/Ringtone12.ogg
new file mode 100644
index 0000000..ff889e6
--- /dev/null
+++ b/data/sounds/ringtones/material/ogg/Ringtone12.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone12_48k.ogg b/data/sounds/ringtones/material/ogg/Ringtone12_48k.ogg
new file mode 100644
index 0000000..68bc35e
--- /dev/null
+++ b/data/sounds/ringtones/material/ogg/Ringtone12_48k.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone1_48k.ogg b/data/sounds/ringtones/material/ogg/Ringtone1_48k.ogg
new file mode 100644
index 0000000..ebf8f32
--- /dev/null
+++ b/data/sounds/ringtones/material/ogg/Ringtone1_48k.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone2.ogg b/data/sounds/ringtones/material/ogg/Ringtone2.ogg
new file mode 100644
index 0000000..b5893bd
--- /dev/null
+++ b/data/sounds/ringtones/material/ogg/Ringtone2.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone2_48k.ogg b/data/sounds/ringtones/material/ogg/Ringtone2_48k.ogg
new file mode 100644
index 0000000..e44d01e
--- /dev/null
+++ b/data/sounds/ringtones/material/ogg/Ringtone2_48k.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone3.ogg b/data/sounds/ringtones/material/ogg/Ringtone3.ogg
new file mode 100644
index 0000000..193e566
--- /dev/null
+++ b/data/sounds/ringtones/material/ogg/Ringtone3.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone3_48k.ogg b/data/sounds/ringtones/material/ogg/Ringtone3_48k.ogg
new file mode 100644
index 0000000..583a1d7
--- /dev/null
+++ b/data/sounds/ringtones/material/ogg/Ringtone3_48k.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone4.ogg b/data/sounds/ringtones/material/ogg/Ringtone4.ogg
new file mode 100644
index 0000000..173f73d
--- /dev/null
+++ b/data/sounds/ringtones/material/ogg/Ringtone4.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone4_48k.ogg b/data/sounds/ringtones/material/ogg/Ringtone4_48k.ogg
new file mode 100644
index 0000000..c98a437
--- /dev/null
+++ b/data/sounds/ringtones/material/ogg/Ringtone4_48k.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone5.ogg b/data/sounds/ringtones/material/ogg/Ringtone5.ogg
new file mode 100644
index 0000000..dd9bc5b
--- /dev/null
+++ b/data/sounds/ringtones/material/ogg/Ringtone5.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone5_48k.ogg b/data/sounds/ringtones/material/ogg/Ringtone5_48k.ogg
new file mode 100644
index 0000000..44855dc
--- /dev/null
+++ b/data/sounds/ringtones/material/ogg/Ringtone5_48k.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone6.ogg b/data/sounds/ringtones/material/ogg/Ringtone6.ogg
new file mode 100644
index 0000000..cf7d1cb
--- /dev/null
+++ b/data/sounds/ringtones/material/ogg/Ringtone6.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone6_48k.ogg b/data/sounds/ringtones/material/ogg/Ringtone6_48k.ogg
new file mode 100644
index 0000000..8abbf98
--- /dev/null
+++ b/data/sounds/ringtones/material/ogg/Ringtone6_48k.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone7.ogg b/data/sounds/ringtones/material/ogg/Ringtone7.ogg
new file mode 100644
index 0000000..e7ff9f4
--- /dev/null
+++ b/data/sounds/ringtones/material/ogg/Ringtone7.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone7_48k.ogg b/data/sounds/ringtones/material/ogg/Ringtone7_48k.ogg
new file mode 100644
index 0000000..1ce7d33
--- /dev/null
+++ b/data/sounds/ringtones/material/ogg/Ringtone7_48k.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone8.ogg b/data/sounds/ringtones/material/ogg/Ringtone8.ogg
new file mode 100644
index 0000000..8aeb3a0
--- /dev/null
+++ b/data/sounds/ringtones/material/ogg/Ringtone8.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone8_48k.ogg b/data/sounds/ringtones/material/ogg/Ringtone8_48k.ogg
new file mode 100644
index 0000000..a2f7f49
--- /dev/null
+++ b/data/sounds/ringtones/material/ogg/Ringtone8_48k.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone9.ogg b/data/sounds/ringtones/material/ogg/Ringtone9.ogg
new file mode 100644
index 0000000..145f474
--- /dev/null
+++ b/data/sounds/ringtones/material/ogg/Ringtone9.ogg
Binary files differ
diff --git a/data/sounds/ringtones/material/ogg/Ringtone9_48k.ogg b/data/sounds/ringtones/material/ogg/Ringtone9_48k.ogg
new file mode 100644
index 0000000..7f2e274
--- /dev/null
+++ b/data/sounds/ringtones/material/ogg/Ringtone9_48k.ogg
Binary files differ
diff --git a/docs/html/_redirects.yaml b/docs/html/_redirects.yaml
index c5b6c24..45e2fed 100644
--- a/docs/html/_redirects.yaml
+++ b/docs/html/_redirects.yaml
@@ -59,6 +59,9 @@
- from: /guide/google/gcm/server-javadoc/...
to: /reference/com/google/android/gcm/server/package-summary.html
+- from: /google/play-services/auth.html
+ to: /google/auth/http-auth.html
+
- from: /guide/google/play/services.html
to: /google/play-services/index.html
diff --git a/docs/html/google/auth/http-auth.jd b/docs/html/google/auth/http-auth.jd
index 3b2a83f..804ba12 100644
--- a/docs/html/google/auth/http-auth.jd
+++ b/docs/html/google/auth/http-auth.jd
@@ -342,9 +342,9 @@
"{@docRoot}reference/com/google/android/gms/auth/GoogleAuthUtil.html#getToken(android.content.Context,%20java.lang.String,%20java.lang.String)">
{@code GoogleAuthUtil.getToken()}</a>, you must provide the app {@link android.content.Context},
the account name retrieved from the account picker, and the scope for your auth
-token request. The above sample code (and the attached sample) defines these arguments with
-class members that the host activity passes to
-the {@link android.os.AsyncTask} class constructor.</p>
+token request. The above sample code (and the attached sample) defines these
+arguments with class members that the host activity passes to the {@link android.os.AsyncTask} class constructor. For more information about setting the scope, see
+the <a href="#SpecifyingScopes">Specifying Scopes</a> section below. </p>
<p class="note"><strong>Note:</strong>
As shown by the {@code fetchToken()} method above, you must handle
@@ -397,8 +397,32 @@
"{@docRoot}reference/com/google/android/gms/auth/GoogleAuthUtil.html#getToken(android.content.Context,%20java.lang.String,%20java.lang.String)">
{@code GoogleAuthUtil.getToken()}</a>.</p>
-
-
+<h3 id="SpecifyingScopes">Specifying scopes</h3>
+<p>The scope string is used to specify which Google services can be accessed by
+ an app using the requested auth token. An auth token can be associated with
+ multiple scopes.</p>
+<p>When specifying the scopes in your auth token request, prefix the
+ scope string with {@code "oauth2:"} followed by a list of one or more OAuth scope
+ values. Use a space to separate each scope value in the list. To see a list of
+ valid OAuth scope values for Google services, browse
+ the <a href="https://developers.google.com/oauthplayground/"
+ class="external-link">OAuth 2.0 Playground</a>.</p>
+<p class="note"><strong>Tip:</strong> Specify {@code "oauth2:<scope>"}
+ for a single scope. Specify
+ {@code "oauth2:<scope1> <scope2> <scopeN>"} for multiple
+ scopes (using a space to separate each scope).</p>
+<p>For example, to access the Google Books API, the scope is
+ {@code "oauth2:https://www.googleapis.com/auth/books"}. To add an additional
+ scope, say for Google+ login, your code might look like this:</p>
+<pre>
+private final static String BOOKS_API_SCOPE
+ = "https://www.googleapis.com/auth/books";
+private fina; static String GPLUS_SCOPE
+ = "https://www.googleapis.com/auth/plus.login";
+private final static String mScopes
+ = "oauth2:" + BOOKS_API_SCOPE + " " + GPLUS_SCOPE;
+String token = GoogleAuthUtil.getToken(mActivity, mEmail, mScopes);
+</pre>
<h2 id="HandleExceptions">Handle Exceptions</h2>
diff --git a/docs/html/guide/topics/renderscript/compute.jd b/docs/html/guide/topics/renderscript/compute.jd
index 297a2dc..2e7ce56 100644
--- a/docs/html/guide/topics/renderscript/compute.jd
+++ b/docs/html/guide/topics/renderscript/compute.jd
@@ -159,8 +159,7 @@
<ul>
<li><strong>{@link android.renderscript}</strong> - The APIs in this class package are
- available on devices running Android 3.0 (API level 11) and higher. These are the original APIs
- for RenderScript and are not currently being updated.</li>
+ available on devices running Android 3.0 (API level 11) and higher. </li>
<li><strong>{@link android.support.v8.renderscript}</strong> - The APIs in this package are
available through a <a href="{@docRoot}tools/support-library/features.html#v8">Support
Library</a>, which allows you to use them on devices running Android 2.2 (API level 8) and
@@ -168,8 +167,8 @@
</ul>
<p>We strongly recommend using the Support Library APIs for accessing RenderScript because they
- include the latest improvements to the RenderScript compute framework and provide a wider range
- of device compatibility.</p>
+ provide a wider range of device compatibility. Developers targeting specific versions of
+ Android can use {@link android.renderscript} if necessary.</p>
<h3 id="ide-setup">Using the RenderScript Support Library APIs</h3>
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index f3af8f6..f18694b 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -243,6 +243,12 @@
/** @hide */
public void setHighContrastText(boolean highContrastText) {}
+ /** @hide */
+ public void insertReorderBarrier() {}
+
+ /** @hide */
+ public void insertInorderBarrier() {}
+
/**
* @hide
*/
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index 9ac6927..042da5b 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -119,7 +119,7 @@
* <dd>Defines path string. This is using exactly same format as "d" attribute
* in the SVG's path data. This is defined in the viewport space.</dd>
* <dt><code>android:fillColor</code></dt>
- * <dd>Defines the color to fill the path (black if not present).</dd>
+ * <dd>Defines the color to fill the path (none if not present).</dd>
* <dt><code>android:strokeColor</code></dt>
* <dd>Defines the color to draw the path outline (none if not present).</dd>
* <dt><code>android:strokeWidth</code></dt>
@@ -862,7 +862,7 @@
}
mRenderPath.addPath(path, mFinalPathMatrix);
- if (fullPath.mFillColor != 0) {
+ if (fullPath.mFillColor != Color.TRANSPARENT) {
if (mFillPaint == null) {
mFillPaint = new Paint();
mFillPaint.setColorFilter(mColorFilter);
@@ -873,7 +873,7 @@
canvas.drawPath(mRenderPath, mFillPaint);
}
- if (fullPath.mStrokeColor != 0) {
+ if (fullPath.mStrokeColor != Color.TRANSPARENT) {
if (mStrokePaint == null) {
mStrokePaint = new Paint();
mStrokePaint.setColorFilter(mColorFilter);
@@ -1237,9 +1237,9 @@
// Variables below need to be copied (deep copy if applicable) for mutation.
private int[] mThemeAttrs;
- int mStrokeColor = 0;
+ int mStrokeColor = Color.TRANSPARENT;
float mStrokeWidth = 0;
- int mFillColor = Color.BLACK;
+ int mFillColor = Color.TRANSPARENT;
int mFillRule;
float mTrimPathStart = 0;
float mTrimPathEnd = 1;
diff --git a/include/androidfw/ResourceTypes.h b/include/androidfw/ResourceTypes.h
index 1af497c..11568d2 100644
--- a/include/androidfw/ResourceTypes.h
+++ b/include/androidfw/ResourceTypes.h
@@ -954,6 +954,7 @@
DENSITY_XHIGH = ACONFIGURATION_DENSITY_XHIGH,
DENSITY_XXHIGH = ACONFIGURATION_DENSITY_XXHIGH,
DENSITY_XXXHIGH = ACONFIGURATION_DENSITY_XXXHIGH,
+ DENSITY_ANY = ACONFIGURATION_DENSITY_ANY,
DENSITY_NONE = ACONFIGURATION_DENSITY_NONE
};
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 239d682..3f014ef 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -2206,13 +2206,30 @@
if (screenType || o.screenType) {
if (density != o.density) {
- // density is tough. Any density is potentially useful
+ // Use the system default density (DENSITY_MEDIUM, 160dpi) if none specified.
+ const int thisDensity = density ? density : int(ResTable_config::DENSITY_MEDIUM);
+ const int otherDensity = o.density ? o.density : int(ResTable_config::DENSITY_MEDIUM);
+
+ // We always prefer DENSITY_ANY over scaling a density bucket.
+ if (thisDensity == ResTable_config::DENSITY_ANY) {
+ return true;
+ } else if (otherDensity == ResTable_config::DENSITY_ANY) {
+ return false;
+ }
+
+ int requestedDensity = requested->density;
+ if (requested->density == 0 ||
+ requested->density == ResTable_config::DENSITY_ANY) {
+ requestedDensity = ResTable_config::DENSITY_MEDIUM;
+ }
+
+ // DENSITY_ANY is now dealt with. We should look to
+ // pick a density bucket and potentially scale it.
+ // Any density is potentially useful
// because the system will scale it. Scaling down
// is generally better than scaling up.
- // Default density counts as 160dpi (the system default)
- // TODO - remove 160 constants
- int h = (density?density:160);
- int l = (o.density?o.density:160);
+ int h = thisDensity;
+ int l = otherDensity;
bool bImBigger = true;
if (l > h) {
int t = h;
@@ -2221,17 +2238,16 @@
bImBigger = false;
}
- int reqValue = (requested->density?requested->density:160);
- if (reqValue >= h) {
+ if (requestedDensity >= h) {
// requested value higher than both l and h, give h
return bImBigger;
}
- if (l >= reqValue) {
+ if (l >= requestedDensity) {
// requested value lower than both l and h, give l
return !bImBigger;
}
// saying that scaling down is 2x better than up
- if (((2 * l) - reqValue) * h > reqValue * reqValue) {
+ if (((2 * l) - requestedDensity) * h > requestedDensity * requestedDensity) {
return !bImBigger;
} else {
return bImBigger;
@@ -2702,6 +2718,9 @@
case ResTable_config::DENSITY_NONE:
res.append("nodpi");
break;
+ case ResTable_config::DENSITY_ANY:
+ res.append("anydpi");
+ break;
default:
res.appendFormat("%ddpi", dtohs(density));
break;
diff --git a/libs/androidfw/tests/Android.mk b/libs/androidfw/tests/Android.mk
index 4ff6eec..a10c387 100644
--- a/libs/androidfw/tests/Android.mk
+++ b/libs/androidfw/tests/Android.mk
@@ -21,8 +21,9 @@
LOCAL_PATH:= $(call my-dir)
testFiles := \
ByteBucketArray_test.cpp \
+ Config_test.cpp \
+ ConfigLocale_test.cpp \
Idmap_test.cpp \
- ResourceTypes_test.cpp \
ResTable_test.cpp \
Split_test.cpp \
TypeWrappers_test.cpp \
diff --git a/libs/androidfw/tests/ResourceTypes_test.cpp b/libs/androidfw/tests/ConfigLocale_test.cpp
similarity index 90%
rename from libs/androidfw/tests/ResourceTypes_test.cpp
rename to libs/androidfw/tests/ConfigLocale_test.cpp
index f00a2d9..4999594 100644
--- a/libs/androidfw/tests/ResourceTypes_test.cpp
+++ b/libs/androidfw/tests/ConfigLocale_test.cpp
@@ -21,7 +21,7 @@
#include <gtest/gtest.h>
namespace android {
-TEST(ResourceTypesTest, ResourceConfig_packAndUnpack2LetterLanguage) {
+TEST(ConfigLocaleTest, packAndUnpack2LetterLanguage) {
ResTable_config config;
config.packLanguage("en");
@@ -44,7 +44,7 @@
EXPECT_EQ(0, out[3]);
}
-TEST(ResourceTypesTest, ResourceConfig_packAndUnpack2LetterRegion) {
+TEST(ConfigLocaleTest, packAndUnpack2LetterRegion) {
ResTable_config config;
config.packRegion("US");
@@ -59,7 +59,7 @@
EXPECT_EQ(0, out[3]);
}
-TEST(ResourceTypesTest, ResourceConfig_packAndUnpack3LetterLanguage) {
+TEST(ConfigLocaleTest, packAndUnpack3LetterLanguage) {
ResTable_config config;
config.packLanguage("eng");
@@ -75,7 +75,7 @@
EXPECT_EQ(0, out[3]);
}
-TEST(ResourceTypesTest, ResourceConfig_packAndUnpack3LetterLanguageAtOffset16) {
+TEST(ConfigLocaleTest, packAndUnpack3LetterLanguageAtOffset16) {
ResTable_config config;
config.packLanguage("tgp");
@@ -88,8 +88,8 @@
// which is equivalent to:
// 1 [0] [1] [2]
// 1-01111-00110-10011
- EXPECT_EQ(0xbc, config.language[0]);
- EXPECT_EQ(0xd3, config.language[1]);
+ EXPECT_EQ(char(0xbc), config.language[0]);
+ EXPECT_EQ(char(0xd3), config.language[1]);
char out[4] = { 1, 1, 1, 1};
config.unpackLanguage(out);
@@ -99,7 +99,7 @@
EXPECT_EQ(0, out[3]);
}
-TEST(ResourceTypesTest, ResourceConfig_packAndUnpack3LetterRegion) {
+TEST(ConfigLocaleTest, packAndUnpack3LetterRegion) {
ResTable_config config;
config.packRegion("419");
@@ -131,7 +131,7 @@
}
}
-TEST(ResourceTypesTest, IsMoreSpecificThan) {
+TEST(ConfigLocaleTest, IsMoreSpecificThan) {
ResTable_config l;
ResTable_config r;
@@ -170,7 +170,7 @@
EXPECT_TRUE(r.isMoreSpecificThan(l));
}
-TEST(ResourceTypesTest, setLocale) {
+TEST(ConfigLocaleTest, setLocale) {
ResTable_config test;
test.setBcp47Locale("en-US");
EXPECT_EQ('e', test.language[0]);
diff --git a/libs/androidfw/tests/Config_test.cpp b/libs/androidfw/tests/Config_test.cpp
new file mode 100644
index 0000000..ef30df4
--- /dev/null
+++ b/libs/androidfw/tests/Config_test.cpp
@@ -0,0 +1,103 @@
+/*
+ * 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.
+ */
+
+#include <androidfw/ResourceTypes.h>
+#include <utils/Log.h>
+#include <utils/String8.h>
+#include <utils/Vector.h>
+
+#include "TestHelpers.h"
+#include <gtest/gtest.h>
+
+namespace android {
+
+static ResTable_config selectBest(const ResTable_config& target,
+ const Vector<ResTable_config>& configs) {
+ ResTable_config bestConfig;
+ memset(&bestConfig, 0, sizeof(bestConfig));
+ const size_t configCount = configs.size();
+ for (size_t i = 0; i < configCount; i++) {
+ const ResTable_config& thisConfig = configs[i];
+ if (!thisConfig.match(target)) {
+ continue;
+ }
+
+ if (thisConfig.isBetterThan(bestConfig, &target)) {
+ bestConfig = thisConfig;
+ }
+ }
+ return bestConfig;
+}
+
+static ResTable_config buildDensityConfig(int density) {
+ ResTable_config config;
+ memset(&config, 0, sizeof(config));
+ config.density = uint16_t(density);
+ config.sdkVersion = 4;
+ return config;
+}
+
+TEST(ConfigTest, shouldSelectBestDensity) {
+ ResTable_config deviceConfig;
+ memset(&deviceConfig, 0, sizeof(deviceConfig));
+ deviceConfig.density = ResTable_config::DENSITY_XHIGH;
+ deviceConfig.sdkVersion = 21;
+
+ Vector<ResTable_config> configs;
+
+ ResTable_config expectedBest = buildDensityConfig(ResTable_config::DENSITY_HIGH);
+ configs.add(expectedBest);
+ ASSERT_EQ(expectedBest, selectBest(deviceConfig, configs));
+
+ expectedBest = buildDensityConfig(ResTable_config::DENSITY_XXHIGH);
+ configs.add(expectedBest);
+ ASSERT_EQ(expectedBest, selectBest(deviceConfig, configs));
+
+ expectedBest = buildDensityConfig(int(ResTable_config::DENSITY_XXHIGH) - 20);
+ configs.add(expectedBest);
+ ASSERT_EQ(expectedBest, selectBest(deviceConfig, configs));
+
+ configs.add(buildDensityConfig(int(ResTable_config::DENSITY_HIGH) + 20));
+ ASSERT_EQ(expectedBest, selectBest(deviceConfig, configs));
+
+ expectedBest = buildDensityConfig(ResTable_config::DENSITY_XHIGH);
+ configs.add(expectedBest);
+ ASSERT_EQ(expectedBest, selectBest(deviceConfig, configs));
+
+ expectedBest = buildDensityConfig(ResTable_config::DENSITY_ANY);
+ expectedBest.sdkVersion = 21;
+ configs.add(expectedBest);
+ ASSERT_EQ(expectedBest, selectBest(deviceConfig, configs));
+}
+
+TEST(ConfigTest, shouldSelectBestDensityWhenNoneSpecified) {
+ ResTable_config deviceConfig;
+ memset(&deviceConfig, 0, sizeof(deviceConfig));
+ deviceConfig.sdkVersion = 21;
+
+ Vector<ResTable_config> configs;
+ configs.add(buildDensityConfig(ResTable_config::DENSITY_HIGH));
+
+ ResTable_config expectedBest = buildDensityConfig(ResTable_config::DENSITY_MEDIUM);
+ configs.add(expectedBest);
+ ASSERT_EQ(expectedBest, selectBest(deviceConfig, configs));
+
+ expectedBest = buildDensityConfig(ResTable_config::DENSITY_ANY);
+ configs.add(expectedBest);
+ ASSERT_EQ(expectedBest, selectBest(deviceConfig, configs));
+}
+
+} // namespace android.
diff --git a/libs/androidfw/tests/TestHelpers.h b/libs/androidfw/tests/TestHelpers.h
index 75a233a..fe2e5ce 100644
--- a/libs/androidfw/tests/TestHelpers.h
+++ b/libs/androidfw/tests/TestHelpers.h
@@ -3,6 +3,7 @@
#include <ostream>
+#include <androidfw/ResourceTypes.h>
#include <utils/String8.h>
#include <utils/String16.h>
@@ -14,4 +15,16 @@
return out << android::String8(str).string();
}
+namespace android {
+
+static inline bool operator==(const android::ResTable_config& a, const android::ResTable_config& b) {
+ return memcmp(&a, &b, sizeof(a)) == 0;
+}
+
+static inline ::std::ostream& operator<<(::std::ostream& out, const android::ResTable_config& c) {
+ return out << c.toString().string();
+}
+
+} // namespace android
+
#endif // __TEST_HELPERS_H
diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp
index 6461ee7..d8932ce 100644
--- a/libs/hwui/DisplayList.cpp
+++ b/libs/hwui/DisplayList.cpp
@@ -89,11 +89,9 @@
layers.clear();
}
-void DisplayListData::addChild(DrawRenderNodeOp* op) {
- LOG_ALWAYS_FATAL_IF(!op->renderNode(), "DrawRenderNodeOp with no render node!");
-
- mChildren.push(op);
+size_t DisplayListData::addChild(DrawRenderNodeOp* op) {
mReferenceHolders.push(op->renderNode());
+ return mChildren.add(op);
}
}; // namespace uirenderer
diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h
index acfa98e..dea109c 100644
--- a/libs/hwui/DisplayList.h
+++ b/libs/hwui/DisplayList.h
@@ -115,13 +115,24 @@
* Data structure that holds the list of commands used in display list stream
*/
class DisplayListData {
+ friend class DisplayListRenderer;
public:
+ struct Chunk {
+ // range of included ops in DLD::displayListOps
+ size_t beginOpIndex;
+ size_t endOpIndex;
+
+ // range of included children in DLD::mChildren
+ size_t beginChildIndex;
+ size_t endChildIndex;
+
+ // whether children with non-zero Z in the chunk should be reordered
+ bool reorderChildren;
+ };
+
DisplayListData();
~DisplayListData();
- // allocator into which all ops were allocated
- LinearAllocator allocator;
-
// pointers to all ops within display list, pointing into allocator data
Vector<DisplayListOp*> displayListOps;
@@ -138,13 +149,12 @@
Vector<const SkRegion*> regions;
Vector<Layer*> layers;
Vector<Functor*> functors;
- bool hasDrawOps;
- bool isEmpty() {
- return !displayListOps.size();
+ const Vector<Chunk>& getChunks() const {
+ return chunks;
}
- void addChild(DrawRenderNodeOp* childOp);
+ size_t addChild(DrawRenderNodeOp* childOp);
const Vector<DrawRenderNodeOp*>& children() { return mChildren; }
void refProperty(CanvasPropertyPrimitive* prop) {
@@ -155,12 +165,25 @@
mReferenceHolders.push(prop);
}
+ size_t getUsedSize() {
+ return allocator.usedSize();
+ }
+ bool isEmpty() {
+ return !hasDrawOps;
+ }
+
private:
Vector< sp<VirtualLightRefBase> > mReferenceHolders;
// list of children display lists for quick, non-drawing traversal
Vector<DrawRenderNodeOp*> mChildren;
+ Vector<Chunk> chunks;
+
+ // allocator into which all ops were allocated
+ LinearAllocator allocator;
+ bool hasDrawOps;
+
void cleanupResources();
};
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 5f533a7..8818510 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -1445,6 +1445,7 @@
class DrawRenderNodeOp : public DrawBoundedOp {
friend class RenderNode; // grant RenderNode access to info of child
+ friend class DisplayListData; // grant DisplayListData access to info of child
public:
DrawRenderNodeOp(RenderNode* renderNode, int flags, const mat4& transformFromParent)
: DrawBoundedOp(0, 0, renderNode->getWidth(), renderNode->getHeight(), 0),
@@ -1452,13 +1453,14 @@
virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
bool useQuickReject) {
- if (mRenderNode && mRenderNode->isRenderable() && !mSkipInOrderDraw) {
+ if (mRenderNode->isRenderable() && !mSkipInOrderDraw) {
mRenderNode->defer(deferStruct, level + 1);
}
}
+
virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
bool useQuickReject) {
- if (mRenderNode && mRenderNode->isRenderable() && !mSkipInOrderDraw) {
+ if (mRenderNode->isRenderable() && !mSkipInOrderDraw) {
mRenderNode->replay(replayStruct, level + 1);
}
}
@@ -1469,7 +1471,7 @@
}
virtual void output(int level, uint32_t logFlags) const {
- OP_LOG("Draw Display List %p, flags %#x", mRenderNode, mFlags);
+ OP_LOG("Draw RenderNode %p %s, flags %#x", mRenderNode, mRenderNode->getName(), mFlags);
if (mRenderNode && (logFlags & kOpLogFlag_Recurse)) {
mRenderNode->output(level + 1);
}
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 9a9c544..5892978 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -33,10 +33,10 @@
DisplayListRenderer::DisplayListRenderer()
: mCaches(Caches::getInstance())
- , mDisplayListData(0)
+ , mDisplayListData(NULL)
, mTranslateX(0.0f)
, mTranslateY(0.0f)
- , mHasTranslate(false)
+ , mDeferredBarrierType(kBarrier_None)
, mHighContrastText(false)
, mRestoreSaveCount(-1) {
}
@@ -68,6 +68,7 @@
initializeSaveStack(0, 0, getWidth(), getHeight(), Vector3());
+ mDeferredBarrierType = kBarrier_InOrder;
mDirtyClip = opaque;
mRestoreSaveCount = -1;
@@ -75,8 +76,8 @@
}
void DisplayListRenderer::finish() {
- insertRestoreToCount();
- insertTranslate();
+ flushRestoreToCount();
+ flushTranslate();
}
void DisplayListRenderer::interrupt() {
@@ -104,13 +105,13 @@
}
mRestoreSaveCount--;
- insertTranslate();
+ flushTranslate();
StatefulBaseRenderer::restore();
}
void DisplayListRenderer::restoreToCount(int saveCount) {
mRestoreSaveCount = saveCount;
- insertTranslate();
+ flushTranslate();
StatefulBaseRenderer::restoreToCount(saveCount);
}
@@ -123,10 +124,10 @@
void DisplayListRenderer::translate(float dx, float dy, float dz) {
// ignore dz, not used at defer time
- mHasTranslate = true;
+ mHasDeferredTranslate = true;
mTranslateX += dx;
mTranslateY += dy;
- insertRestoreToCount();
+ flushRestoreToCount();
StatefulBaseRenderer::translate(dx, dy, dz);
}
@@ -174,16 +175,12 @@
}
status_t DisplayListRenderer::drawRenderNode(RenderNode* renderNode, Rect& dirty, int32_t flags) {
+ LOG_ALWAYS_FATAL_IF(!renderNode, "missing rendernode");
+
// dirty is an out parameter and should not be recorded,
// it matters only when replaying the display list
DrawRenderNodeOp* op = new (alloc()) DrawRenderNodeOp(renderNode, flags, *currentTransform());
- int opIndex = addDrawOp(op);
- mDisplayListData->addChild(op);
-
- if (renderNode->stagingProperties().isProjectionReceiver()) {
- // use staging property, since recording on UI thread
- mDisplayListData->projectionReceiveIndex = opIndex;
- }
+ addRenderNodeOp(op);
return DrawGlInfo::kStatusDone;
}
@@ -428,30 +425,60 @@
addStateOp(new (alloc()) SetupPaintFilterOp(clearBits, setBits));
}
-void DisplayListRenderer::insertRestoreToCount() {
+void DisplayListRenderer::insertReorderBarrier(bool enableReorder) {
+ flushRestoreToCount();
+ flushTranslate();
+ mDeferredBarrierType = enableReorder ? kBarrier_OutOfOrder : kBarrier_InOrder;
+}
+
+void DisplayListRenderer::flushRestoreToCount() {
if (mRestoreSaveCount >= 0) {
- DisplayListOp* op = new (alloc()) RestoreToCountOp(mRestoreSaveCount);
- mDisplayListData->displayListOps.add(op);
+ addOpAndUpdateChunk(new (alloc()) RestoreToCountOp(mRestoreSaveCount));
mRestoreSaveCount = -1;
}
}
-void DisplayListRenderer::insertTranslate() {
- if (mHasTranslate) {
+void DisplayListRenderer::flushTranslate() {
+ if (mHasDeferredTranslate) {
if (mTranslateX != 0.0f || mTranslateY != 0.0f) {
- DisplayListOp* op = new (alloc()) TranslateOp(mTranslateX, mTranslateY);
- mDisplayListData->displayListOps.add(op);
+ addOpAndUpdateChunk(new (alloc()) TranslateOp(mTranslateX, mTranslateY));
mTranslateX = mTranslateY = 0.0f;
}
- mHasTranslate = false;
+ mHasDeferredTranslate = false;
}
}
-int DisplayListRenderer::addStateOp(StateOp* op) {
- return addOpInternal(op);
+size_t DisplayListRenderer::addOpAndUpdateChunk(DisplayListOp* op) {
+ int insertIndex = mDisplayListData->displayListOps.add(op);
+ if (mDeferredBarrierType != kBarrier_None) {
+ // op is first in new chunk
+ mDisplayListData->chunks.push();
+ DisplayListData::Chunk& newChunk = mDisplayListData->chunks.editTop();
+ newChunk.beginOpIndex = insertIndex;
+ newChunk.endOpIndex = insertIndex + 1;
+ newChunk.reorderChildren = (mDeferredBarrierType == kBarrier_OutOfOrder);
+
+ int nextChildIndex = mDisplayListData->children().size();
+ newChunk.beginChildIndex = newChunk.endChildIndex = nextChildIndex;
+ mDeferredBarrierType = kBarrier_None;
+ } else {
+ // standard case - append to existing chunk
+ mDisplayListData->chunks.editTop().endOpIndex = insertIndex + 1;
+ }
+ return insertIndex;
}
-int DisplayListRenderer::addDrawOp(DrawOp* op) {
+size_t DisplayListRenderer::flushAndAddOp(DisplayListOp* op) {
+ flushRestoreToCount();
+ flushTranslate();
+ return addOpAndUpdateChunk(op);
+}
+
+size_t DisplayListRenderer::addStateOp(StateOp* op) {
+ return flushAndAddOp(op);
+}
+
+size_t DisplayListRenderer::addDrawOp(DrawOp* op) {
Rect localBounds;
if (op->getLocalBounds(localBounds)) {
bool rejected = quickRejectConservative(localBounds.left, localBounds.top,
@@ -460,7 +487,22 @@
}
mDisplayListData->hasDrawOps = true;
- return addOpInternal(op);
+ return flushAndAddOp(op);
+}
+
+size_t DisplayListRenderer::addRenderNodeOp(DrawRenderNodeOp* op) {
+ int opIndex = addDrawOp(op);
+ int childIndex = mDisplayListData->addChild(op);
+
+ // update the chunk's child indices
+ DisplayListData::Chunk& chunk = mDisplayListData->chunks.editTop();
+ chunk.endChildIndex = childIndex + 1;
+
+ if (op->renderNode()->stagingProperties().isProjectionReceiver()) {
+ // use staging property, since recording on UI thread
+ mDisplayListData->projectionReceiveIndex = opIndex;
+ }
+ return opIndex;
}
}; // namespace uirenderer
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index b5c0159..e9c937cb 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -57,6 +57,8 @@
DisplayListRenderer();
virtual ~DisplayListRenderer();
+ void insertReorderBarrier(bool enableReorder);
+
DisplayListData* finishRecording();
// ----------------------------------------------------------------------------
@@ -154,19 +156,27 @@
mHighContrastText = highContrastText;
}
private:
- void insertRestoreToCount();
- void insertTranslate();
+ enum DeferredBarrierType {
+ kBarrier_None,
+ kBarrier_InOrder,
+ kBarrier_OutOfOrder,
+ };
+
+ void flushRestoreToCount();
+ void flushTranslate();
+ void flushReorderBarrier();
LinearAllocator& alloc() { return mDisplayListData->allocator; }
// Each method returns final index of op
- int addStateOp(StateOp* op);
- int addDrawOp(DrawOp* op);
- int addOpInternal(DisplayListOp* op) {
- insertRestoreToCount();
- insertTranslate();
- return mDisplayListData->displayListOps.add(op);
- }
+ size_t addOpAndUpdateChunk(DisplayListOp* op);
+ // flushes any deferred operations, and appends the op
+ size_t flushAndAddOp(DisplayListOp* op);
+
+ size_t addStateOp(StateOp* op);
+ size_t addDrawOp(DrawOp* op);
+ size_t addRenderNodeOp(DrawRenderNodeOp* op);
+
template<class T>
inline const T* refBuffer(const T* srcBuffer, int32_t count) {
@@ -205,11 +215,17 @@
if (!paint) return NULL;
const SkPaint* paintCopy = mPaintMap.valueFor(paint);
- if (paintCopy == NULL || paintCopy->getGenerationID() != paint->getGenerationID()) {
- paintCopy = new SkPaint(*paint);
+ if (paintCopy == NULL
+ || paintCopy->getGenerationID() != paint->getGenerationID()
+ // We can't compare shader pointers because that will always
+ // change as we do partial copying via wrapping. However, if the
+ // shader changes the paint generationID will have changed and
+ // so we don't hit this comparison anyway
+ || !(paint->getShader() && paintCopy->getShader()
+ && paint->getShader()->getGenerationID() == paintCopy->getShader()->getGenerationID())) {
+ paintCopy = copyPaint(paint);
// replaceValueFor() performs an add if the entry doesn't exist
mPaintMap.replaceValueFor(paint, paintCopy);
- mDisplayListData->paints.add(paintCopy);
}
return paintCopy;
@@ -218,8 +234,15 @@
inline SkPaint* copyPaint(const SkPaint* paint) {
if (!paint) return NULL;
SkPaint* paintCopy = new SkPaint(*paint);
+ if (paint->getShader()) {
+ SkShader* shaderCopy = SkShader::CreateLocalMatrixShader(
+ paint->getShader(), paint->getShader()->getLocalMatrix());
+ paintCopy->setShader(shaderCopy);
+ paintCopy->setGenerationID(paint->getGenerationID());
+ shaderCopy->setGenerationID(paint->getShader()->getGenerationID());
+ shaderCopy->unref();
+ }
mDisplayListData->paints.add(paintCopy);
-
return paintCopy;
}
@@ -277,7 +300,8 @@
float mTranslateX;
float mTranslateY;
- bool mHasTranslate;
+ bool mHasDeferredTranslate;
+ DeferredBarrierType mDeferredBarrierType;
bool mHighContrastText;
int mRestoreSaveCount;
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 977744f..658265d 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -95,6 +95,7 @@
properties().debugOutputProperties(level);
int flags = DisplayListOp::kOpLogFlag_Recurse;
if (mDisplayListData) {
+ // TODO: consider printing the chunk boundaries here
for (unsigned int i = 0; i < mDisplayListData->displayListOps.size(); i++) {
mDisplayListData->displayListOps[i]->output(level, flags);
}
@@ -106,10 +107,10 @@
int RenderNode::getDebugSize() {
int size = sizeof(RenderNode);
if (mStagingDisplayListData) {
- size += mStagingDisplayListData->allocator.usedSize();
+ size += mStagingDisplayListData->getUsedSize();
}
if (mDisplayListData && mDisplayListData != mStagingDisplayListData) {
- size += mDisplayListData->allocator.usedSize();
+ size += mDisplayListData->getUsedSize();
}
return size;
}
@@ -593,15 +594,16 @@
issueOperations<ReplayOperationHandler>(replayStruct.mRenderer, handler);
}
-void RenderNode::buildZSortedChildList(Vector<ZDrawRenderNodeOpPair>& zTranslatedNodes) {
- if (mDisplayListData == NULL || mDisplayListData->children().size() == 0) return;
+void RenderNode::buildZSortedChildList(const DisplayListData::Chunk& chunk,
+ Vector<ZDrawRenderNodeOpPair>& zTranslatedNodes) {
+ if (chunk.beginChildIndex == chunk.endChildIndex) return;
- for (unsigned int i = 0; i < mDisplayListData->children().size(); i++) {
+ for (unsigned int i = chunk.beginChildIndex; i < chunk.endChildIndex; i++) {
DrawRenderNodeOp* childOp = mDisplayListData->children()[i];
RenderNode* child = childOp->mRenderNode;
float childZ = child->properties().getZ();
- if (!MathUtils::isZero(childZ)) {
+ if (!MathUtils::isZero(childZ) && chunk.reorderChildren) {
zTranslatedNodes.add(ZDrawRenderNodeOpPair(childZ, childOp));
childOp->mSkipInOrderDraw = true;
} else if (!child->properties().getProjectBackwards()) {
@@ -610,7 +612,7 @@
}
}
- // Z sort 3d children (stable-ness makes z compare fall back to standard drawing order)
+ // Z sort any 3d children (stable-ness makes z compare fall back to standard drawing order)
std::stable_sort(zTranslatedNodes.begin(), zTranslatedNodes.end());
}
@@ -871,32 +873,35 @@
handler(new (alloc) DrawLayerOp(mLayer, 0, 0),
renderer.getSaveCount() - 1, properties().getClipToBounds());
} else {
- Vector<ZDrawRenderNodeOpPair> zTranslatedNodes;
- buildZSortedChildList(zTranslatedNodes);
-
- // for 3d root, draw children with negative z values
- int shadowRestoreTo = issueOperationsOfNegZChildren(zTranslatedNodes, renderer, handler);
-
DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance();
- const int saveCountOffset = renderer.getSaveCount() - 1;
- const int projectionReceiveIndex = mDisplayListData->projectionReceiveIndex;
- const int size = static_cast<int>(mDisplayListData->displayListOps.size());
- for (int i = 0; i < size; i++) {
- DisplayListOp *op = mDisplayListData->displayListOps[i];
+ for (size_t chunkIndex = 0; chunkIndex < mDisplayListData->getChunks().size(); chunkIndex++) {
+ const DisplayListData::Chunk& chunk = mDisplayListData->getChunks()[chunkIndex];
+ Vector<ZDrawRenderNodeOpPair> zTranslatedNodes;
+ buildZSortedChildList(chunk, zTranslatedNodes);
+
+ // for 3d root, draw children with negative z values
+ int shadowRestoreTo = issueOperationsOfNegZChildren(zTranslatedNodes,
+ renderer, handler);
+ const int saveCountOffset = renderer.getSaveCount() - 1;
+ const int projectionReceiveIndex = mDisplayListData->projectionReceiveIndex;
+
+ for (int opIndex = chunk.beginOpIndex; opIndex < chunk.endOpIndex; opIndex++) {
+ DisplayListOp *op = mDisplayListData->displayListOps[opIndex];
#if DEBUG_DISPLAY_LIST
- op->output(level + 1);
+ op->output(level + 1);
#endif
- logBuffer.writeCommand(level, op->name());
- handler(op, saveCountOffset, properties().getClipToBounds());
+ logBuffer.writeCommand(level, op->name());
+ handler(op, saveCountOffset, properties().getClipToBounds());
- if (CC_UNLIKELY(i == projectionReceiveIndex && mProjectedNodes.size() > 0)) {
- issueOperationsOfProjectedChildren(renderer, handler);
+ if (CC_UNLIKELY(!mProjectedNodes.isEmpty() && opIndex == projectionReceiveIndex)) {
+ issueOperationsOfProjectedChildren(renderer, handler);
+ }
}
- }
- // for 3d root, draw children with positive z values
- issueOperationsOfPosZChildren(shadowRestoreTo, zTranslatedNodes, renderer, handler);
+ // for 3d root, draw children with positive z values
+ issueOperationsOfPosZChildren(shadowRestoreTo, zTranslatedNodes, renderer, handler);
+ }
}
}
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index afa17d5..18402b2 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -114,7 +114,7 @@
ANDROID_API int getDebugSize();
bool isRenderable() const {
- return mDisplayListData && mDisplayListData->hasDrawOps;
+ return mDisplayListData && !mDisplayListData->isEmpty();
}
bool hasProjectionReceiver() const {
@@ -199,7 +199,8 @@
template <class T>
inline void setViewProperties(OpenGLRenderer& renderer, T& handler);
- void buildZSortedChildList(Vector<ZDrawRenderNodeOpPair>& zTranslatedNodes);
+ void buildZSortedChildList(const DisplayListData::Chunk& chunk,
+ Vector<ZDrawRenderNodeOpPair>& zTranslatedNodes);
template<class T>
inline void issueDrawShadowOperation(const Matrix4& transformFromParent, T& handler);
diff --git a/libs/hwui/SpotShadow.cpp b/libs/hwui/SpotShadow.cpp
index cb20a0b..2178cc7 100644
--- a/libs/hwui/SpotShadow.cpp
+++ b/libs/hwui/SpotShadow.cpp
@@ -647,7 +647,7 @@
if (lightToPolyZ != 0) {
// If any caster's vertex is almost above the light, we just keep it as 95%
// of the height of the light.
- ratioZ = MathUtils::min(polyVertex.z / lightToPolyZ, CASTER_Z_CAP_RATIO);
+ ratioZ = MathUtils::clamp(polyVertex.z / lightToPolyZ, 0.0f, CASTER_Z_CAP_RATIO);
}
outline.x = polyVertex.x - ratioZ * (lightCenter.x - polyVertex.x);
@@ -669,6 +669,10 @@
void SpotShadow::createSpotShadow(bool isCasterOpaque, const Vector3& lightCenter,
float lightSize, const Vector3* poly, int polyLength, const Vector3& polyCentroid,
VertexBuffer& shadowTriangleStrip) {
+ if (CC_UNLIKELY(lightCenter.z <= 0)) {
+ ALOGW("Relative Light Z is not positive. No spot shadow!");
+ return;
+ }
OutlineData outlineData[polyLength];
Vector2 outlineCentroid;
// Calculate the projected outline for each polygon's vertices from the light center.
@@ -787,7 +791,7 @@
// The ratio can be simulated by using the inverse of maximum of ratioVI for
// all (V).
distOutline = (outlineData[i].position - outlineCentroid).length();
- if (distOutline == 0) {
+ if (CC_UNLIKELY(distOutline == 0)) {
// If the outline has 0 area, then there is no spot shadow anyway.
ALOGW("Outline has 0 area, no spot shadow!");
return;
diff --git a/libs/hwui/utils/MathUtils.h b/libs/hwui/utils/MathUtils.h
index 00448b8..d89859b 100644
--- a/libs/hwui/utils/MathUtils.h
+++ b/libs/hwui/utils/MathUtils.h
@@ -76,6 +76,11 @@
return a < b ? a : b;
}
+ template<typename T>
+ static inline T clamp(T a, T minValue, T maxValue) {
+ return min(max(a, minValue), maxValue);
+ }
+
inline static float lerp(float v1, float v2, float t) {
return v1 + ((v2 - v1) * t);
}
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 0af2457..dae539b 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -2912,13 +2912,13 @@
}
private boolean isInCommunication() {
- boolean isInAPhoneCall = false;
+ boolean IsInCall = false;
TelecommManager telecommManager =
(TelecommManager) mContext.getSystemService(Context.TELECOMM_SERVICE);
- isInAPhoneCall = telecommManager.isInAPhoneCall();
+ IsInCall = telecommManager.isInCall();
- return (isInAPhoneCall || getMode() == AudioManager.MODE_IN_COMMUNICATION);
+ return (IsInCall || getMode() == AudioManager.MODE_IN_COMMUNICATION);
}
/**
diff --git a/media/java/android/media/projection/MediaProjectionInfo.java b/media/java/android/media/projection/MediaProjectionInfo.java
index 7ebc31f..5a65e65 100644
--- a/media/java/android/media/projection/MediaProjectionInfo.java
+++ b/media/java/android/media/projection/MediaProjectionInfo.java
@@ -20,6 +20,8 @@
import android.os.Parcelable;
import android.os.UserHandle;
+import java.util.Objects;
+
/** @hide */
public final class MediaProjectionInfo implements Parcelable {
private final String mPackageName;
@@ -44,6 +46,21 @@
}
@Override
+ public boolean equals(Object o) {
+ if (o instanceof MediaProjectionInfo) {
+ final MediaProjectionInfo other = (MediaProjectionInfo) o;
+ return Objects.equals(other.mPackageName, mPackageName)
+ && Objects.equals(other.mUserHandle, mUserHandle);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mPackageName, mUserHandle);
+ }
+
+ @Override
public String toString() {
return "MediaProjectionInfo{mPackageName="
+ mPackageName + ", mUserHandle="
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index 45aa6d6..13937e2 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -1170,16 +1170,19 @@
*/
public void selectTrack(int type, String trackId) {
if (type == TvTrackInfo.TYPE_AUDIO) {
- if (trackId != null && !mAudioTracks.contains(trackId)) {
+ if (trackId != null && !containsTrack(mAudioTracks, trackId)) {
Log.w(TAG, "Invalid audio trackId: " + trackId);
+ return;
}
} else if (type == TvTrackInfo.TYPE_VIDEO) {
- if (trackId != null && !mVideoTracks.contains(trackId)) {
+ if (trackId != null && !containsTrack(mVideoTracks, trackId)) {
Log.w(TAG, "Invalid video trackId: " + trackId);
+ return;
}
} else if (type == TvTrackInfo.TYPE_SUBTITLE) {
- if (trackId != null && !mSubtitleTracks.contains(trackId)) {
+ if (trackId != null && !containsTrack(mSubtitleTracks, trackId)) {
Log.w(TAG, "Invalid subtitle trackId: " + trackId);
+ return;
}
} else {
throw new IllegalArgumentException("invalid type: " + type);
@@ -1195,6 +1198,15 @@
}
}
+ private boolean containsTrack(List<TvTrackInfo> tracks, String trackId) {
+ for (TvTrackInfo track : tracks) {
+ if (track.getId().equals(trackId)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
/**
* Returns the list of tracks for a given type. Returns {@code null} if the information is
* not available.
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index 4efbc30..72a6f88 100644
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -1051,9 +1051,11 @@
}
private final void runOnMainThread(Runnable action) {
- if (mHandler.getLooper().isCurrentThread()) {
+ if (mHandler.getLooper().isCurrentThread() && mSessionCallback != null) {
action.run();
} else {
+ // Posts the runnable if this is not called from the main thread or the session
+ // is not initialized yet.
mHandler.post(action);
}
}
diff --git a/media/java/android/media/tv/TvView.java b/media/java/android/media/tv/TvView.java
index 7110db9..d058d64 100644
--- a/media/java/android/media/tv/TvView.java
+++ b/media/java/android/media/tv/TvView.java
@@ -858,6 +858,7 @@
mSession.setStreamVolume(mStreamVolume);
}
} else {
+ mSessionCallback = null;
if (mListener != null) {
mListener.onConnectionFailed(mInputId);
}
@@ -869,6 +870,8 @@
if (this != mSessionCallback) {
return;
}
+ mOverlayViewCreated = false;
+ mOverlayViewFrame = null;
mSessionCallback = null;
mSession = null;
if (mListener != null) {
diff --git a/packages/CaptivePortalLogin/res/values/styles.xml b/packages/CaptivePortalLogin/res/values/styles.xml
index 7ccd3d3..4a99638 100644
--- a/packages/CaptivePortalLogin/res/values/styles.xml
+++ b/packages/CaptivePortalLogin/res/values/styles.xml
@@ -16,7 +16,7 @@
<style name="AppTheme" parent="AppBaseTheme">
<!-- All customizations that are NOT specific to a particular API-level can go here. -->
<!-- Setting's theme's accent color makes ProgressBar useless, reset back. -->
- <item name="android:colorAccent">@*android:color/material_light_blue_A200</item>
+ <item name="android:colorAccent">@*android:color/material_deep_teal_500</item>
</style>
</resources>
diff --git a/packages/DocumentsUI/res/layout-sw720dp/activity.xml b/packages/DocumentsUI/res/layout-sw720dp/activity.xml
index c33932d..1cffd17 100644
--- a/packages/DocumentsUI/res/layout-sw720dp/activity.xml
+++ b/packages/DocumentsUI/res/layout-sw720dp/activity.xml
@@ -54,7 +54,7 @@
android:layout_weight="1"
android:orientation="vertical"
android:elevation="8dp"
- android:background="@*android:color/material_grey_50">
+ android:background="@color/material_grey_50">
<com.android.documentsui.DirectoryContainerView
android:id="@+id/container_directory"
@@ -66,7 +66,7 @@
android:id="@+id/container_save"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:background="@*android:color/material_grey_50"
+ android:background="@color/material_grey_50"
android:elevation="8dp" />
</LinearLayout>
diff --git a/packages/DocumentsUI/res/layout/activity.xml b/packages/DocumentsUI/res/layout/activity.xml
index d580821..120168e 100644
--- a/packages/DocumentsUI/res/layout/activity.xml
+++ b/packages/DocumentsUI/res/layout/activity.xml
@@ -51,7 +51,7 @@
android:id="@+id/container_save"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:background="@*android:color/material_grey_50"
+ android:background="@color/material_grey_50"
android:elevation="8dp" />
</LinearLayout>
diff --git a/packages/DocumentsUI/res/layout/fragment_directory.xml b/packages/DocumentsUI/res/layout/fragment_directory.xml
index c8c707e..4717839 100644
--- a/packages/DocumentsUI/res/layout/fragment_directory.xml
+++ b/packages/DocumentsUI/res/layout/fragment_directory.xml
@@ -17,7 +17,7 @@
<com.android.documentsui.DirectoryView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:background="@*android:color/material_grey_50">
+ android:background="@color/material_grey_50">
<TextView
android:id="@android:id/empty"
diff --git a/packages/DocumentsUI/res/values/colors.xml b/packages/DocumentsUI/res/values/colors.xml
index 08159c4..7442b09 100644
--- a/packages/DocumentsUI/res/values/colors.xml
+++ b/packages/DocumentsUI/res/values/colors.xml
@@ -15,10 +15,11 @@
-->
<resources>
+ <color name="material_grey_50">#fffafafa</color>
+ <color name="material_grey_300">#ffeeeeee</color>
<!-- Half-alpha of material_teal_500 -->
<color name="accent_color_overlay">#8800bcd4</color>
- <color name="grid_item_background">@*android:color/material_grey_300</color>
-
+ <color name="grid_item_background">@color/material_grey_300</color>
</resources>
diff --git a/packages/DocumentsUI/res/values/styles.xml b/packages/DocumentsUI/res/values/styles.xml
index 573081c..5cfe046 100644
--- a/packages/DocumentsUI/res/values/styles.xml
+++ b/packages/DocumentsUI/res/values/styles.xml
@@ -25,7 +25,7 @@
<item name="android:colorPrimaryDark">@*android:color/material_blue_grey_900</item>
<item name="android:colorPrimary">@*android:color/material_blue_grey_800</item>
- <item name="android:colorAccent">@*android:color/material_teal_500</item>
+ <item name="android:colorAccent">@*android:color/material_deep_teal_500</item>
<item name="android:windowActionBar">false</item>
<item name="android:windowNoTitle">true</item>
diff --git a/packages/Keyguard/res/values/donottranslate.xml b/packages/Keyguard/res/values/donottranslate.xml
index 2f54406..a4d0ff7 100644
--- a/packages/Keyguard/res/values/donottranslate.xml
+++ b/packages/Keyguard/res/values/donottranslate.xml
@@ -19,7 +19,7 @@
<string name="abbrev_wday_month_day_no_year">EEEEMMMMd</string>
<!-- Skeleton string format for displaying the date when an alarm is set. -->
- <string name="abbrev_wday_month_day_no_year_alarm">EEEMMMMd</string>
+ <string name="abbrev_wday_month_day_no_year_alarm">EEEMMMd</string>
<!-- Skeleton string format for displaying the time in 12-hour format. -->
<string name="clock_12hr_format">hm</string>
diff --git a/packages/PrintSpooler/res/layout/preview_page.xml b/packages/PrintSpooler/res/layout/preview_page.xml
index 76dd76b..df9848b 100644
--- a/packages/PrintSpooler/res/layout/preview_page.xml
+++ b/packages/PrintSpooler/res/layout/preview_page.xml
@@ -32,7 +32,7 @@
android:id="@+id/page_footer"
android:layout_width="fill_parent"
android:layout_height="@dimen/preview_page_footer_height"
- android:background="@*android:color/material_grey_500"
+ android:background="@color/material_grey_500"
android:orientation="horizontal">
<TextView
diff --git a/packages/PrintSpooler/res/values/colors.xml b/packages/PrintSpooler/res/values/colors.xml
index de74a41..d1bec32 100644
--- a/packages/PrintSpooler/res/values/colors.xml
+++ b/packages/PrintSpooler/res/values/colors.xml
@@ -24,4 +24,6 @@
<color name="promoted_action_background_color">#FF80CBC4</color>
+ <color name="material_grey_500">#ffa3a3a3</color>
+
</resources>
diff --git a/packages/PrintSpooler/res/values/themes.xml b/packages/PrintSpooler/res/values/themes.xml
index 08702291..db319e9 100644
--- a/packages/PrintSpooler/res/values/themes.xml
+++ b/packages/PrintSpooler/res/values/themes.xml
@@ -16,10 +16,7 @@
<resources>
- <style name="PrintActivity" parent="@android:style/Theme.Material">
- <item name="android:colorPrimary">@*android:color/material_blue_grey_900</item>
- <item name="android:colorPrimaryDark">@*android:color/material_blue_grey_950</item>
- <item name="android:colorAccent">@*android:color/material_deep_teal_A500</item>
+ <style name="PrintActivity" parent="@android:style/Theme.Material.Settings">
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowContentOverlay">@null</item>
diff --git a/packages/SettingsProvider/AndroidManifest.xml b/packages/SettingsProvider/AndroidManifest.xml
index 783aa03..469b776 100644
--- a/packages/SettingsProvider/AndroidManifest.xml
+++ b/packages/SettingsProvider/AndroidManifest.xml
@@ -16,6 +16,7 @@
android:multiprocess="false"
android:exported="true"
android:writePermission="android.permission.WRITE_SETTINGS"
+ android:singleUser="true"
android:initOrder="100" />
</application>
</manifest>
diff --git a/packages/SystemUI/res/anim/recents_from_launcher_enter.xml b/packages/SystemUI/res/anim/recents_from_launcher_enter.xml
index 305a82f..4e1d66d 100644
--- a/packages/SystemUI/res/anim/recents_from_launcher_enter.xml
+++ b/packages/SystemUI/res/anim/recents_from_launcher_enter.xml
@@ -20,9 +20,9 @@
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false"
android:zAdjustment="normal">
- <alpha android:fromAlpha="1.0" android:toAlpha="1.0"
+ <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
android:fillEnabled="true"
android:fillBefore="true" android:fillAfter="true"
android:interpolator="@android:interpolator/linear"
- android:duration="200"/>
+ android:duration="100"/>
</set>
diff --git a/packages/SystemUI/res/anim/recents_from_launcher_exit.xml b/packages/SystemUI/res/anim/recents_from_launcher_exit.xml
index 863591f..afab78d 100644
--- a/packages/SystemUI/res/anim/recents_from_launcher_exit.xml
+++ b/packages/SystemUI/res/anim/recents_from_launcher_exit.xml
@@ -24,5 +24,5 @@
android:fillEnabled="true"
android:fillBefore="true" android:fillAfter="true"
android:interpolator="@android:interpolator/linear_out_slow_in"
- android:duration="200"/>
+ android:duration="100"/>
</set>
diff --git a/packages/SystemUI/res/anim/recents_to_launcher_enter.xml b/packages/SystemUI/res/anim/recents_to_launcher_enter.xml
index adcefe0..4e1d66d 100644
--- a/packages/SystemUI/res/anim/recents_to_launcher_enter.xml
+++ b/packages/SystemUI/res/anim/recents_to_launcher_enter.xml
@@ -23,6 +23,6 @@
<alpha android:fromAlpha="0.0" android:toAlpha="1.0"
android:fillEnabled="true"
android:fillBefore="true" android:fillAfter="true"
- android:interpolator="@android:interpolator/fast_out_linear_in"
- android:duration="200"/>
+ android:interpolator="@android:interpolator/linear"
+ android:duration="100"/>
</set>
diff --git a/packages/SystemUI/res/anim/recents_to_launcher_exit.xml b/packages/SystemUI/res/anim/recents_to_launcher_exit.xml
index 863591f..afab78d 100644
--- a/packages/SystemUI/res/anim/recents_to_launcher_exit.xml
+++ b/packages/SystemUI/res/anim/recents_to_launcher_exit.xml
@@ -24,5 +24,5 @@
android:fillEnabled="true"
android:fillBefore="true" android:fillAfter="true"
android:interpolator="@android:interpolator/linear_out_slow_in"
- android:duration="200"/>
+ android:duration="100"/>
</set>
diff --git a/packages/SystemUI/res/layout/recents_task_view.xml b/packages/SystemUI/res/layout/recents_task_view.xml
index 5253ee0..4cb8498 100644
--- a/packages/SystemUI/res/layout/recents_task_view.xml
+++ b/packages/SystemUI/res/layout/recents_task_view.xml
@@ -23,45 +23,7 @@
android:id="@+id/task_view_thumbnail"
android:layout_width="match_parent"
android:layout_height="match_parent" />
- <com.android.systemui.recents.views.TaskViewHeader
- android:id="@+id/task_view_bar"
- android:layout_width="match_parent"
- android:layout_height="@dimen/recents_task_bar_height"
- android:layout_gravity="top|center_horizontal">
- <com.android.systemui.recents.views.FixedSizeImageView
- android:id="@+id/application_icon"
- android:layout_width="@dimen/recents_task_view_application_icon_size"
- android:layout_height="@dimen/recents_task_view_application_icon_size"
- android:layout_marginStart="8dp"
- android:layout_gravity="center_vertical|start"
- android:padding="8dp"
- android:background="@drawable/recents_button_bg" />
- <TextView
- android:id="@+id/activity_description"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical|start"
- android:layout_marginStart="64dp"
- android:layout_marginEnd="64dp"
- android:textSize="16sp"
- android:textColor="#ffffffff"
- android:text="@string/recents_empty_message"
- android:fontFamily="sans-serif-medium"
- android:singleLine="true"
- android:maxLines="2"
- android:ellipsize="marquee"
- android:fadingEdge="horizontal" />
- <com.android.systemui.recents.views.FixedSizeImageView
- android:id="@+id/dismiss_task"
- android:layout_width="48dp"
- android:layout_height="48dp"
- android:layout_marginEnd="4dp"
- android:layout_gravity="center_vertical|end"
- android:padding="12dp"
- android:background="@drawable/recents_button_bg"
- android:visibility="invisible"
- android:src="@drawable/recents_dismiss_light" />
- </com.android.systemui.recents.views.TaskViewHeader>
+ <include layout="@layout/recents_task_view_header" />
<FrameLayout
android:id="@+id/lock_to_app_fab"
android:layout_width="48dp"
diff --git a/packages/SystemUI/res/layout/recents_task_view_header.xml b/packages/SystemUI/res/layout/recents_task_view_header.xml
new file mode 100644
index 0000000..f1d8ad0
--- /dev/null
+++ b/packages/SystemUI/res/layout/recents_task_view_header.xml
@@ -0,0 +1,55 @@
+<?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.
+-->
+<com.android.systemui.recents.views.TaskViewHeader
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/task_view_bar"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/recents_task_bar_height"
+ android:layout_gravity="top|center_horizontal">
+ <com.android.systemui.recents.views.FixedSizeImageView
+ android:id="@+id/application_icon"
+ android:layout_width="@dimen/recents_task_view_application_icon_size"
+ android:layout_height="@dimen/recents_task_view_application_icon_size"
+ android:layout_marginStart="8dp"
+ android:layout_gravity="center_vertical|start"
+ android:padding="8dp"
+ android:background="@drawable/recents_button_bg" />
+ <TextView
+ android:id="@+id/activity_description"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical|start"
+ android:layout_marginStart="64dp"
+ android:layout_marginEnd="64dp"
+ android:textSize="16sp"
+ android:textColor="#ffffffff"
+ android:text="@string/recents_empty_message"
+ android:fontFamily="sans-serif-medium"
+ android:singleLine="true"
+ android:maxLines="2"
+ android:ellipsize="marquee"
+ android:fadingEdge="horizontal" />
+ <com.android.systemui.recents.views.FixedSizeImageView
+ android:id="@+id/dismiss_task"
+ android:layout_width="48dp"
+ android:layout_height="48dp"
+ android:layout_marginEnd="4dp"
+ android:layout_gravity="center_vertical|end"
+ android:padding="12dp"
+ android:background="@drawable/recents_button_bg"
+ android:visibility="invisible"
+ android:src="@drawable/recents_dismiss_light" />
+</com.android.systemui.recents.views.TaskViewHeader>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/status_bar_expanded_header.xml b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
index f4f26a2..ef8a426 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
@@ -102,6 +102,7 @@
android:singleLine="true"
android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Date"
android:layout_below="@id/clock"
+ systemui:datePattern="@string/abbrev_wday_month_day_no_year_alarm"
/>
<com.android.systemui.statusbar.policy.DateView android:id="@+id/date_expanded"
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 52dc000..fa00ebf 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -126,7 +126,7 @@
<integer name="recents_animate_task_bar_enter_duration">275</integer>
<!-- The animation delay for animating the first task in. This should roughly be the animation
duration of the transition in to recents. -->
- <integer name="recents_animate_task_bar_enter_delay">225</integer>
+ <integer name="recents_animate_task_bar_enter_delay">300</integer>
<!-- The min animation duration for animating the task bar out. -->
<integer name="recents_animate_task_exit_to_home_duration">225</integer>
<!-- The min animation duration for animating the task bar out. -->
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index c8db284..0af693d 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -115,9 +115,6 @@
<!-- Diameter of outer shape drawable shown in navbar search. Should be 1/2 of above value -->
<dimen name="navbar_search_outerring_radius">170dp</dimen>
- <!-- Threshold for swipe-up gesture to activate search dialog -->
- <dimen name="navbar_search_up_threshhold">40dip</dimen>
-
<!-- Height of search panel including navigation bar height -->
<dimen name="navbar_search_panel_height">230dip</dimen>
@@ -420,7 +417,7 @@
<dimen name="search_card_peek_height">100dp</dimen>
<!-- How far the user needs to drag up to invoke search. -->
- <dimen name="search_panel_threshold">150dp</dimen>
+ <dimen name="search_panel_threshold">100dp</dimen>
<!-- The width/height of the phone/camera/unlock icon on keyguard. -->
<dimen name="keyguard_affordance_height">56dp</dimen>
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index ad568b8..f4d0669 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -1323,9 +1323,7 @@
// (like recents). Temporary enable/disable (e.g. the "back" button) are
// done in KeyguardHostView.
flags |= StatusBarManager.DISABLE_RECENT;
- if (!isAssistantAvailable()) {
- flags |= StatusBarManager.DISABLE_SEARCH;
- }
+ flags |= StatusBarManager.DISABLE_SEARCH;
}
if (isShowingAndNotOccluded()) {
flags |= StatusBarManager.DISABLE_HOME;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
index 6cd0f39..f503657 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
@@ -239,7 +239,8 @@
@Override
public void onDetailItemDisconnect(Item item) {
if (item == null || item.tag == null) return;
- mController.stopCasting();
+ final CastDevice device = (CastDevice) item.tag;
+ mController.stopCasting(device);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
index 354eb55..8710aa2 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
@@ -22,6 +22,7 @@
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Bitmap;
@@ -29,6 +30,7 @@
import android.graphics.Rect;
import android.os.Handler;
import android.os.UserHandle;
+import android.view.LayoutInflater;
import android.view.View;
import com.android.systemui.R;
import com.android.systemui.RecentsComponent;
@@ -41,6 +43,7 @@
import com.android.systemui.recents.model.TaskStack;
import com.android.systemui.recents.views.TaskStackView;
import com.android.systemui.recents.views.TaskStackViewLayoutAlgorithm;
+import com.android.systemui.recents.views.TaskViewHeader;
import com.android.systemui.recents.views.TaskViewTransform;
import java.util.ArrayList;
@@ -86,6 +89,10 @@
int mNavBarHeight;
int mNavBarWidth;
+ // Header (for transition)
+ TaskViewHeader mHeaderBar;
+ TaskStackView mDummyStackView;
+
// Variables to keep track of if we need to start recents after binding
View mStatusBarView;
boolean mTriggeredFromAltTab;
@@ -114,6 +121,7 @@
public void onStart() {
// Initialize some static datastructures
TaskStackViewLayoutAlgorithm.initializeCurve();
+ reloadHeaderBarLayout();
}
public void onBootCompleted() {
@@ -169,7 +177,7 @@
void showRelativeAffiliatedTask(boolean showNextTask) {
TaskStack stack = RecentsTaskLoader.getShallowTaskStack(mSystemServicesProxy,
- Integer.MAX_VALUE);
+ Integer.MAX_VALUE, mContext.getResources());
// Return early if there are no tasks
if (stack.getTaskCount() == 0) return;
@@ -250,6 +258,28 @@
mSystemInsets.set(0, mStatusBarHeight, 0, mNavBarHeight);
}
sLastScreenshot = null;
+ reloadHeaderBarLayout();
+ }
+
+ /** Prepares the header bar layout. */
+ void reloadHeaderBarLayout() {
+ // Inflate the header bar layout so that we can rebind and draw it for the transition
+ Resources res = mContext.getResources();
+ TaskStack stack = new TaskStack();
+ mDummyStackView = new TaskStackView(mContext, stack);
+ TaskStackViewLayoutAlgorithm algo = mDummyStackView.getStackAlgorithm();
+ Rect taskStackBounds = new Rect(mTaskStackBounds);
+ taskStackBounds.bottom -= mSystemInsets.bottom;
+ algo.computeRects(mWindowRect.width(), mWindowRect.height(), taskStackBounds);
+ Rect taskViewSize = algo.getUntransformedTaskViewSize();
+ int taskBarHeight = res.getDimensionPixelSize(R.dimen.recents_task_bar_height);
+ LayoutInflater inflater = LayoutInflater.from(mContext);
+ mHeaderBar = (TaskViewHeader) inflater.inflate(R.layout.recents_task_view_header, null,
+ false);
+ mHeaderBar.measure(
+ View.MeasureSpec.makeMeasureSpec(taskViewSize.width(), View.MeasureSpec.EXACTLY),
+ View.MeasureSpec.makeMeasureSpec(taskBarHeight, View.MeasureSpec.EXACTLY));
+ mHeaderBar.layout(0, 0, taskViewSize.width(), taskBarHeight);
}
/** Gets the top task. */
@@ -361,27 +391,37 @@
}
}
- // If the screenshot fails, then load the first task thumbnail and use that
- Bitmap firstThumbnail = mSystemServicesProxy.getTaskThumbnail(topTask.id);
- if (firstThumbnail != null) {
- // Update the destination rect
- Rect toTaskRect = getThumbnailTransitionRect(topTask.id, isTopTaskHome);
- if (toTaskRect.width() > 0 && toTaskRect.height() > 0) {
- // Create the new thumbnail for the animation down
- // XXX: We should find a way to optimize this so we don't need to create a new bitmap
- Bitmap thumbnail = Bitmap.createBitmap(toTaskRect.width(), toTaskRect.height(),
- Bitmap.Config.ARGB_8888);
- int size = Math.min(firstThumbnail.getWidth(), firstThumbnail.getHeight());
- Canvas c = new Canvas(thumbnail);
- c.drawBitmap(firstThumbnail, new Rect(0, 0, size, size),
- new Rect(0, 0, toTaskRect.width(), toTaskRect.height()), null);
- c.setBitmap(null);
- // Recycle the old thumbnail
- firstThumbnail.recycle();
- mStartAnimationTriggered = false;
- return ActivityOptions.makeThumbnailScaleDownAnimation(mStatusBarView,
- thumbnail, toTaskRect.left, toTaskRect.top, this);
+ // Update the destination rect
+ Task toTask = new Task();
+ TaskViewTransform toTransform = getThumbnailTransitionTransform(topTask.id, isTopTaskHome,
+ toTask);
+ if (toTransform != null && toTask.key != null) {
+ Rect toTaskRect = toTransform.rect;
+ ActivityInfo info = mSystemServicesProxy.getActivityInfo(
+ toTask.key.baseIntent.getComponent(), toTask.key.userId);
+ if (toTask.activityIcon == null) {
+ toTask.activityIcon = mSystemServicesProxy.getActivityIcon(info,
+ toTask.key.userId);
}
+ if (toTask.activityLabel == null) {
+ toTask.activityLabel = mSystemServicesProxy.getActivityLabel(info);
+ }
+
+ Bitmap thumbnail = Bitmap.createBitmap(toTaskRect.width(), toTaskRect.height(),
+ Bitmap.Config.ARGB_8888);
+ if (Constants.DebugFlags.App.EnableTransitionThumbnailDebugMode) {
+ thumbnail.eraseColor(0xFFff0000);
+ } else {
+ Canvas c = new Canvas(thumbnail);
+ c.scale(toTransform.scale, toTransform.scale);
+ mHeaderBar.rebindToTask(toTask);
+ mHeaderBar.draw(c);
+ c.setBitmap(null);
+ }
+
+ mStartAnimationTriggered = false;
+ return ActivityOptions.makeThumbnailAspectScaleDownAnimation(mStatusBarView,
+ thumbnail, toTaskRect.left, toTaskRect.top, this);
}
// If both the screenshot and thumbnail fails, then just fall back to the default transition
@@ -389,21 +429,18 @@
}
/** Returns the transition rect for the given task id. */
- Rect getThumbnailTransitionRect(int runningTaskId, boolean isTopTaskHome) {
+ TaskViewTransform getThumbnailTransitionTransform(int runningTaskId, boolean isTopTaskHome,
+ Task runningTaskOut) {
// Get the stack of tasks that we are animating into
- TaskStack stack = RecentsTaskLoader.getShallowTaskStack(mSystemServicesProxy, -1);
+ TaskStack stack = RecentsTaskLoader.getShallowTaskStack(mSystemServicesProxy, -1,
+ mContext.getResources());
if (stack.getTaskCount() == 0) {
- return new Rect();
+ return null;
}
// Get the stack
- TaskStackView tsv = new TaskStackView(mContext, stack);
- TaskStackViewLayoutAlgorithm algo = tsv.getStackAlgorithm();
- Rect taskStackBounds = new Rect(mTaskStackBounds);
- taskStackBounds.bottom -= mSystemInsets.bottom;
- tsv.computeRects(mWindowRect.width(), mWindowRect.height(), taskStackBounds,
- mTriggeredFromAltTab, isTopTaskHome);
- tsv.getScroller().setStackScrollToInitialState();
+ mDummyStackView.updateMinMaxScrollForStack(stack, mTriggeredFromAltTab, isTopTaskHome);
+ mDummyStackView.getScroller().setStackScrollToInitialState();
// Find the running task in the TaskStack
Task task = null;
@@ -415,6 +452,7 @@
Task t = tasks.get(i);
if (t.key.id == runningTaskId) {
task = t;
+ runningTaskOut.copyFrom(t);
break;
}
}
@@ -425,8 +463,9 @@
}
// Get the transform for the running task
- mTmpTransform = algo.getStackTransform(task, tsv.getScroller().getStackScroll(), mTmpTransform, null);
- return new Rect(mTmpTransform.rect);
+ mTmpTransform = mDummyStackView.getStackAlgorithm().getStackTransform(task,
+ mDummyStackView.getScroller().getStackScroll(), mTmpTransform, null);
+ return mTmpTransform;
}
/** Starts the recents activity */
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Constants.java b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
index 3709c43..6f4cf6b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Constants.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
@@ -27,6 +27,8 @@
public static class App {
// Enables the screenshot app->Recents transition
public static final boolean EnableScreenshotAppTransition = false;
+ // Enables debug drawing for the transition thumbnail
+ public static final boolean EnableTransitionThumbnailDebugMode = false;
// Enables the filtering of tasks according to their grouping
public static final boolean EnableTaskFiltering = false;
// Enables clipping of tasks against each other
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index 7fafe7a..a5b845d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -384,7 +384,6 @@
// Private API calls to make the shadows look better
try {
- Utilities.setShadowProperty("ambientShadowStrength", String.valueOf(35f));
Utilities.setShadowProperty("ambientRatio", String.valueOf(1.5f));
} catch (IllegalAccessException e) {
e.printStackTrace();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index 5390daf..b29f3780 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -174,6 +174,7 @@
int minNumTasksToQuery = 10;
int numTasksToQuery = Math.max(minNumTasksToQuery, numLatestTasks);
List<ActivityManager.RecentTaskInfo> tasks = mAm.getRecentTasksForUser(numTasksToQuery,
+ ActivityManager.RECENT_IGNORE_HOME_STACK_TASKS |
ActivityManager.RECENT_IGNORE_UNAVAILABLE |
ActivityManager.RECENT_INCLUDE_PROFILES |
ActivityManager.RECENT_WITH_EXCLUDED, userId);
@@ -185,11 +186,6 @@
// NOTE: The order of these checks happens in the expected order of the traversal of the
// tasks
- // Skip tasks from this Recents package
- if (t.baseIntent.getComponent().getPackageName().equals(mRecentsPackage)) {
- iter.remove();
- continue;
- }
// Check the first non-recents task, include this task even if it is marked as excluded
// from recents. In other words, only remove excluded tasks if it is not the first task
boolean isExcluded = (t.baseIntent.getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
@@ -199,11 +195,6 @@
continue;
}
isFirstValidTask = false;
- // Skip tasks in the home stack
- if (isInHomeStack(t.persistentId)) {
- iter.remove();
- continue;
- }
}
return tasks.subList(0, Math.min(tasks.size(), numLatestTasks));
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
index 0e2f370..b93c126 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
@@ -18,6 +18,7 @@
import android.app.ActivityManager;
import android.content.ComponentCallbacks2;
+import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.res.Resources;
@@ -31,6 +32,7 @@
import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.misc.SystemServicesProxy;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
@@ -171,9 +173,9 @@
// Load the application icon if it is stale or we haven't cached one yet
if (cachedIcon == null) {
ActivityInfo info = ssp.getActivityInfo(t.key.baseIntent.getComponent(),
- t.userId);
+ t.key.userId);
if (info != null) {
- cachedIcon = ssp.getActivityIcon(info, t.userId);
+ cachedIcon = ssp.getActivityIcon(info, t.key.userId);
}
if (cachedIcon == null) {
cachedIcon = mDefaultApplicationIcon;
@@ -228,8 +230,10 @@
static RecentsTaskLoader sInstance;
SystemServicesProxy mSystemServicesProxy;
+ DrawableLruCache mTaskDescriptionIconCache;
DrawableLruCache mApplicationIconCache;
BitmapLruCache mThumbnailCache;
+ StringLruCache mActivityLabelCache;
TaskResourceLoadQueue mLoadQueue;
TaskResourceLoader mLoader;
@@ -270,8 +274,10 @@
mSystemServicesProxy = new SystemServicesProxy(context);
mPackageMonitor = new RecentsPackageMonitor();
mLoadQueue = new TaskResourceLoadQueue();
+ mTaskDescriptionIconCache = new DrawableLruCache(iconCacheSize);
mApplicationIconCache = new DrawableLruCache(iconCacheSize);
mThumbnailCache = new BitmapLruCache(thumbnailCacheSize);
+ mActivityLabelCache = new StringLruCache(100);
mLoader = new TaskResourceLoader(mLoadQueue, mApplicationIconCache, mThumbnailCache,
mDefaultThumbnail, mDefaultApplicationIcon);
}
@@ -313,6 +319,7 @@
RecentsConfiguration config = RecentsConfiguration.getInstance();
Resources res = context.getResources();
LinkedHashSet<Task> tasksToLoad = new LinkedHashSet<Task>();
+ ArrayList<Task> tasksToAdd = new ArrayList<Task>();
TaskStack stack = new TaskStack();
SpaceNode root = new SpaceNode();
root.setStack(stack);
@@ -325,55 +332,80 @@
int taskCount = tasks.size();
for (int i = 0; i < taskCount; i++) {
ActivityManager.RecentTaskInfo t = tasks.get(i);
- ActivityInfo info = ssp.getActivityInfo(t.baseIntent.getComponent(), t.userId);
- if (info == null) continue;
+ Task.TaskKey taskKey = new Task.TaskKey(t.persistentId, t.baseIntent, t.userId,
+ t.firstActiveTime, t.lastActiveTime);
+ ComponentName cn = t.baseIntent.getComponent();
+ ActivityInfo info = null;
ActivityManager.TaskDescription av = t.taskDescription;
- String activityLabel = null;
+ String activityLabel = null;
Drawable activityIcon = mDefaultApplicationIcon;
int activityColor = config.taskBarViewDefaultBackgroundColor;
+ boolean loadedActivityIcon = false;
if (av != null) {
- activityLabel = (av.getLabel() != null ? av.getLabel() : ssp.getActivityLabel(info));
- activityIcon = (av.getIcon() != null) ?
+ activityLabel = av.getLabel();
+ activityIcon = mTaskDescriptionIconCache.getAndInvalidateIfModified(taskKey);
+ if (activityIcon == null) {
+ activityIcon = (av.getIcon() != null) ?
ssp.getBadgedIcon(new BitmapDrawable(res, av.getIcon()), t.userId) : null;
+ if (activityIcon != null) {
+ mTaskDescriptionIconCache.put(taskKey, activityIcon);
+ }
+ }
if (av.getPrimaryColor() != 0) {
activityColor = av.getPrimaryColor();
}
- } else {
- activityLabel = ssp.getActivityLabel(info);
+ loadedActivityIcon = (activityIcon != null);
+ }
+ // If there is no activity label, then try and read it from the label cache before
+ // loading it from the system
+ if (activityLabel == null) {
+ activityLabel = mActivityLabelCache.getAndInvalidateIfModified(taskKey);
+ if (activityLabel == null) {
+ if (info == null) {
+ info = ssp.getActivityInfo(cn, t.userId);
+ }
+ activityLabel = ssp.getActivityLabel(info);
+ mActivityLabelCache.put(taskKey, activityLabel);
+ }
}
// Create a new task
- Task task = new Task(t.persistentId, (t.id > -1), t.baseIntent, t.affiliatedTaskId,
- t.affiliatedTaskColor, activityLabel, activityIcon, activityColor, t.userId,
- t.firstActiveTime, t.lastActiveTime, (i == (taskCount - 1)),
+ Task task = new Task(taskKey, (t.id > -1), t.affiliatedTaskId, t.affiliatedTaskColor,
+ activityLabel, activityIcon, activityColor, (i == (taskCount - 1)),
config.lockToAppEnabled);
// Preload the specified number of apps
if (i >= (taskCount - preloadCount)) {
- // Load the icon from the cache if possible
- task.applicationIcon = mApplicationIconCache.getAndInvalidateIfModified(task.key);
- if (task.applicationIcon == null) {
- // Load the icon from the system
- task.applicationIcon = ssp.getActivityIcon(info, task.userId);
- if (task.applicationIcon != null) {
- mApplicationIconCache.put(task.key, task.applicationIcon);
+ // Load the icon from the cache if possible (only if we don't have an activity icon)
+ if (!loadedActivityIcon) {
+ task.applicationIcon =
+ mApplicationIconCache.getAndInvalidateIfModified(taskKey);
+ if (task.applicationIcon == null) {
+ // Load the icon from the system
+ if (info == null) {
+ info = ssp.getActivityInfo(cn, t.userId);
+ }
+ task.applicationIcon = ssp.getActivityIcon(info, taskKey.userId);
+ if (task.applicationIcon != null) {
+ mApplicationIconCache.put(taskKey, task.applicationIcon);
+ }
}
- }
- if (task.applicationIcon == null) {
- // Either the task has changed since the last active time, or it was not
- // previously cached, so try and load the task anew.
- tasksToLoad.add(task);
+ if (task.applicationIcon == null) {
+ // Either the task has changed since the last active time, or it was not
+ // previously cached, so try and load the task anew.
+ tasksToLoad.add(task);
+ }
}
// Load the thumbnail from the cache if possible
- task.thumbnail = mThumbnailCache.getAndInvalidateIfModified(task.key);
+ task.thumbnail = mThumbnailCache.getAndInvalidateIfModified(taskKey);
if (task.thumbnail == null) {
// Load the thumbnail from the system
- task.thumbnail = ssp.getTaskThumbnail(task.key.id);
+ task.thumbnail = ssp.getTaskThumbnail(taskKey.id);
if (task.thumbnail != null) {
task.thumbnail.setHasAlpha(false);
- mThumbnailCache.put(task.key, task.thumbnail);
+ mThumbnailCache.put(taskKey, task.thumbnail);
}
}
if (task.thumbnail == null) {
@@ -384,10 +416,11 @@
}
// Add the task to the stack
- stack.addTask(task);
+ tasksToAdd.add(task);
}
// Simulate the groupings that we describe
+ stack.setTasks(tasksToAdd);
stack.createAffiliatedGroupings(config);
// Start the task loader and add all the tasks we need to load
@@ -401,21 +434,29 @@
}
/** Creates a lightweight stack of the current recent tasks, without thumbnails and icons. */
- public static TaskStack getShallowTaskStack(SystemServicesProxy ssp, int numTasks) {
+ public static TaskStack getShallowTaskStack(SystemServicesProxy ssp, int numTasks,
+ Resources resources) {
RecentsConfiguration config = RecentsConfiguration.getInstance();
List<ActivityManager.RecentTaskInfo> tasks = getRecentTasks(ssp, numTasks);
+ ArrayList<Task> tasksToAdd = new ArrayList<Task>();
TaskStack stack = new TaskStack();
int taskCount = tasks.size();
for (int i = 0; i < taskCount; i++) {
ActivityManager.RecentTaskInfo t = tasks.get(i);
- ActivityInfo info = ssp.getActivityInfo(t.baseIntent.getComponent(), t.userId);
- if (info == null) continue;
+ ActivityManager.TaskDescription av = t.taskDescription;
- stack.addTask(new Task(t.persistentId, true, t.baseIntent, t.affiliatedTaskId,
- t.affiliatedTaskColor, null, null, 0, 0, t.firstActiveTime, t.lastActiveTime,
- (i == (taskCount - 1)), config.lockToAppEnabled));
+ BitmapDrawable icon = null;
+ if (av.getIcon() != null) {
+ icon = new BitmapDrawable(resources, av.getIcon());
+ }
+ Task.TaskKey taskKey = new Task.TaskKey(t.persistentId, t.baseIntent, t.userId,
+ t.firstActiveTime, t.lastActiveTime);
+ tasksToAdd.add(new Task(taskKey, true, t.affiliatedTaskId, t.affiliatedTaskColor,
+ av.getLabel(), icon, av.getPrimaryColor(), (i == (taskCount - 1)),
+ config.lockToAppEnabled));
}
+ stack.setTasks(tasksToAdd);
stack.createAffiliatedGroupings(config);
return stack;
}
@@ -484,18 +525,23 @@
// We are leaving recents, so trim the data a bit
mThumbnailCache.trimToSize(mMaxThumbnailCacheSize / 2);
mApplicationIconCache.trimToSize(mMaxIconCacheSize / 2);
+ mTaskDescriptionIconCache.trimToSize(mMaxIconCacheSize / 2);
break;
case ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW:
case ComponentCallbacks2.TRIM_MEMORY_MODERATE:
// We are going to be low on memory
mThumbnailCache.trimToSize(mMaxThumbnailCacheSize / 4);
mApplicationIconCache.trimToSize(mMaxIconCacheSize / 4);
+ mTaskDescriptionIconCache.trimToSize(mMaxIconCacheSize / 4);
break;
case ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL:
case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:
// We are low on memory, so release everything
mThumbnailCache.evictAll();
mApplicationIconCache.evictAll();
+ mTaskDescriptionIconCache.evictAll();
+ // The cache is small, only clear the label cache when we are critical
+ mActivityLabelCache.evictAll();
break;
default:
break;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/StringLruCache.java b/packages/SystemUI/src/com/android/systemui/recents/model/StringLruCache.java
new file mode 100644
index 0000000..b06c454
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/StringLruCache.java
@@ -0,0 +1,32 @@
+/*
+ * 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 com.android.systemui.recents.model;
+
+/**
+ * The String LRU cache.
+ */
+class StringLruCache extends KeyStoreLruCache<String> {
+ public StringLruCache(int cacheSize) {
+ super(cacheSize);
+ }
+
+ @Override
+ protected int computeSize(String s) {
+ // The cache size is measured in number of strings
+ return 1;
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
index f6c3a7e..977db60 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
@@ -88,7 +88,6 @@
public boolean isActive;
public boolean lockToThisTask;
public boolean lockToTaskEnabled;
- public int userId;
TaskCallbacks mCb;
@@ -96,13 +95,12 @@
// Only used by RecentsService for task rect calculations.
}
- public Task(int id, boolean isActive, Intent intent, int taskAffiliation, int taskAffiliationColor,
- String activityTitle, Drawable activityIcon, int colorPrimary, int userId,
- long firstActiveTime, long lastActiveTime, boolean lockToThisTask,
- boolean lockToTaskEnabled) {
- boolean isInAffiliationGroup = (taskAffiliation != id);
+ public Task(TaskKey key, boolean isActive, int taskAffiliation, int taskAffiliationColor,
+ String activityTitle, Drawable activityIcon, int colorPrimary,
+ boolean lockToThisTask, boolean lockToTaskEnabled) {
+ boolean isInAffiliationGroup = (taskAffiliation != key.id);
boolean hasAffiliationGroupColor = isInAffiliationGroup && (taskAffiliationColor != 0);
- this.key = new TaskKey(id, intent, userId, firstActiveTime, lastActiveTime);
+ this.key = key;
this.taskAffiliation = taskAffiliation;
this.taskAffiliationColor = taskAffiliationColor;
this.activityLabel = activityTitle;
@@ -113,7 +111,20 @@
this.isActive = isActive;
this.lockToThisTask = lockToTaskEnabled && lockToThisTask;
this.lockToTaskEnabled = lockToTaskEnabled;
- this.userId = userId;
+ }
+
+ /** Copies the other task. */
+ public void copyFrom(Task o) {
+ this.key = o.key;
+ this.taskAffiliation = o.taskAffiliation;
+ this.taskAffiliationColor = o.taskAffiliationColor;
+ this.activityLabel = o.activityLabel;
+ this.activityIcon = o.activityIcon;
+ this.colorPrimary = o.colorPrimary;
+ this.useLightOnPrimaryColor = o.useLightOnPrimaryColor;
+ this.isActive = o.isActive;
+ this.lockToThisTask = o.lockToThisTask;
+ this.lockToTaskEnabled = o.lockToTaskEnabled;
}
/** Set the callbacks */
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
index 98bf151..1e47b50 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
@@ -92,7 +92,10 @@
/** Returns the index of this task in the list of filtered tasks */
int indexOf(Task t) {
- return mTaskIndices.get(t.key);
+ if (mTaskIndices.containsKey(t.key)) {
+ return mTaskIndices.get(t.key);
+ }
+ return -1;
}
/** Returns the size of the list of filtered tasks */
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index 07a7e74..1dd484b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -408,14 +408,26 @@
int thumbnailHeight = transform.rect.height();
if (task.thumbnail != null && thumbnailWidth > 0 && thumbnailHeight > 0 &&
task.thumbnail.getWidth() > 0 && task.thumbnail.getHeight() > 0) {
- // Resize the thumbnail to the size of the view that we are animating from
- Bitmap b = Bitmap.createBitmap(thumbnailWidth, thumbnailHeight,
- Bitmap.Config.ARGB_8888);
- Canvas c = new Canvas(b);
- c.drawBitmap(task.thumbnail,
- new Rect(0, 0, task.thumbnail.getWidth(), task.thumbnail.getHeight()),
- new Rect(0, 0, thumbnailWidth, thumbnailHeight), null);
- c.setBitmap(null);
+ Bitmap b;
+ if (tv != null) {
+ // Disable any focused state before we draw the header
+ if (tv.isFocusedTask()) {
+ tv.unsetFocusedTask();
+ }
+
+ b = Bitmap.createBitmap(thumbnailWidth, thumbnailHeight, Bitmap.Config.ARGB_8888);
+ if (Constants.DebugFlags.App.EnableTransitionThumbnailDebugMode) {
+ b.eraseColor(0xFFff0000);
+ } else {
+ Canvas c = new Canvas(b);
+ c.scale(tv.getScaleX(), tv.getScaleY());
+ tv.mHeaderView.draw(c);
+ c.setBitmap(null);
+ }
+ } else {
+ // Notify the system to skip the thumbnail layer by using an ALPHA_8 bitmap
+ b = Bitmap.createBitmap(thumbnailWidth, thumbnailHeight, Bitmap.Config.ALPHA_8);
+ }
ActivityOptions.OnAnimationStartedListener animStartedListener = null;
if (lockToTask) {
animStartedListener = new ActivityOptions.OnAnimationStartedListener() {
@@ -434,7 +446,7 @@
}
};
}
- opts = ActivityOptions.makeThumbnailScaleUpAnimation(sourceView,
+ opts = ActivityOptions.makeThumbnailAspectScaleUpAnimation(sourceView,
b, offsetX, offsetY, animStartedListener);
}
@@ -472,7 +484,15 @@
if (tv == null) {
post(launchRunnable);
} else {
- stackView.startLaunchTaskAnimation(tv, launchRunnable);
+ if (!task.group.isFrontMostTask(task)) {
+ // For affiliated tasks that are behind other tasks, we must animate the front cards
+ // out of view before starting the task transition
+ stackView.startLaunchTaskAnimation(tv, launchRunnable);
+ } else {
+ // Otherwise, we can start the task transition immediately
+ stackView.startLaunchTaskAnimation(tv, null);
+ postDelayed(launchRunnable, 17);
+ }
}
}
@@ -485,7 +505,7 @@
intent.setComponent(intent.resolveActivity(getContext().getPackageManager()));
TaskStackBuilder.create(getContext())
.addNextIntentWithParentStack(intent).startActivities(null,
- new UserHandle(t.userId));
+ new UserHandle(t.key.userId));
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index aee558f..861011f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -460,7 +460,17 @@
}
/**
- * This is called with the full window width and height to allow stack view children to
+ * This is ONLY used from AlternateRecentsComponent to update the dummy stack view for purposes
+ * of getting the task rect to animate to.
+ */
+ public void updateMinMaxScrollForStack(TaskStack stack, boolean launchedWithAltTab,
+ boolean launchedFromHome) {
+ mStack = stack;
+ updateMinMaxScroll(false, launchedWithAltTab, launchedFromHome);
+ }
+
+ /**
+ * This is called with the full window width and height to allow stack view children to
* perform the full screen transition down.
*/
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java
index f0bdfa2..31fc701 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java
@@ -33,7 +33,7 @@
public class TaskStackViewLayoutAlgorithm {
// These are all going to change
- static final float StackPeekMinScale = 0.825f; // The min scale of the last card in the peek area
+ static final float StackPeekMinScale = 0.8f; // The min scale of the last card in the peek area
RecentsConfiguration mConfig;
@@ -157,7 +157,7 @@
public TaskViewTransform getStackTransform(Task task, float stackScroll, TaskViewTransform transformOut,
TaskViewTransform prevTransform) {
// Return early if we have an invalid index
- if (task == null) {
+ if (task == null || !mTaskProgressMap.containsKey(task.key)) {
transformOut.reset();
return transformOut;
}
@@ -200,6 +200,15 @@
}
/**
+ * Returns the untransformed task view size.
+ */
+ public Rect getUntransformedTaskViewSize() {
+ Rect tvSize = new Rect(mTaskRect);
+ tvSize.offsetTo(0, 0);
+ return tvSize;
+ }
+
+ /**
* Returns the scroll to such task top = 1f;
*/
float getStackScrollForTask(Task t) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index e514c90..dfbcce1 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -235,7 +235,6 @@
int initialDim = getDim();
if (mConfig.launchedFromAppWithScreenshot) {
if (isTaskViewLaunchTargetTask) {
- mHeaderView.prepareEnterRecentsAnimation();
// Hide the footer during the transition in, and animate it out afterwards?
if (mFooterView != null) {
mFooterView.animateFooterVisibility(false, 0);
@@ -246,8 +245,6 @@
} else if (mConfig.launchedFromAppWithThumbnail) {
if (isTaskViewLaunchTargetTask) {
- // Hide the front most task bar view so we can animate it in
- mHeaderView.prepareEnterRecentsAnimation();
// Hide the action button if it exists
mActionButtonView.setAlpha(0f);
// Set the dim to 0 so we can animate it in
@@ -306,7 +303,6 @@
mViewBounds.animateClipBottom(getMeasuredHeight() - (windowInsetTop + size), duration);
}
// Animate the task bar of the first task view
- mHeaderView.startEnterRecentsAnimation(0, null);
animate()
.scaleX(taskScale)
.scaleY(taskScale)
@@ -352,9 +348,8 @@
} else if (mConfig.launchedFromAppWithThumbnail) {
if (mTask.isLaunchTarget) {
- // Animate the task bar of the first task view
- mHeaderView.startEnterRecentsAnimation(mConfig.taskBarEnterAnimDelay,
- mThumbnailView.enableTaskBarClipAsRunnable(mHeaderView));
+ // Enable the task bar clip
+ mThumbnailView.enableTaskBarClip(mHeaderView);
// Animate the dim/overlay
if (Constants.DebugFlags.App.EnableThumbnailAlphaOnFrontmost) {
// Animate the thumbnail alpha before the dim animation (to prevent updating the
@@ -475,14 +470,13 @@
}
/** Animates this task view as it exits recents */
- void startLaunchTaskAnimation(final Runnable r, boolean isLaunchingTask,
+ void startLaunchTaskAnimation(final Runnable postAnimRunnable, boolean isLaunchingTask,
boolean occludesLaunchTarget) {
if (isLaunchingTask) {
- // Disable the thumbnail clip and animate the bar out for the window animation out
- mHeaderView.startLaunchTaskAnimation(mThumbnailView.disableTaskBarClipAsRunnable(), r,
- mIsFocused);
+ // Disable the thumbnail clip
+ mThumbnailView.disableTaskBarClip();
// Animate the thumbnail alpha back into full opacity for the window animation out
- mThumbnailView.startLaunchTaskAnimation();
+ mThumbnailView.startLaunchTaskAnimation(postAnimRunnable);
// Animate the dim
if (mDim > 0) {
@@ -493,7 +487,11 @@
}
// Animate the action button away
- mActionButtonView.animate().alpha(0f)
+ float toScale = 0.9f;
+ mActionButtonView.animate()
+ .alpha(0f)
+ .scaleX(toScale)
+ .scaleY(toScale)
.setStartDelay(0)
.setDuration(mConfig.taskBarExitAnimDuration)
.setInterpolator(mConfig.fastOutLinearInInterpolator)
@@ -706,22 +704,30 @@
}
/**
+ * Unsets the focused task explicitly.
+ */
+ void unsetFocusedTask() {
+ mIsFocused = false;
+ if (mFocusAnimationsEnabled) {
+ // Un-focus the header bar
+ mHeaderView.onTaskViewFocusChanged(false);
+ }
+
+ // Update the thumbnail alpha with the focus
+ mThumbnailView.onFocusChanged(false);
+ // Call the callback
+ mCb.onTaskViewFocusChanged(this, false);
+ invalidate();
+ }
+
+ /**
* Updates the explicitly focused state when the view focus changes.
*/
@Override
protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
if (!gainFocus) {
- mIsFocused = false;
- if (mFocusAnimationsEnabled) {
- // Un-focus the header bar
- mHeaderView.onTaskViewFocusChanged(false);
- }
- // Update the thumbnail alpha with the focus
- mThumbnailView.onFocusChanged(false);
- // Call the callback
- mCb.onTaskViewFocusChanged(this, false);
- invalidate();
+ unsetFocusedTask();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
index d39f64e..1743433 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
@@ -49,7 +49,7 @@
/* The task bar view */
-class TaskViewHeader extends FrameLayout {
+public class TaskViewHeader extends FrameLayout {
RecentsConfiguration mConfig;
@@ -156,8 +156,11 @@
// Draw the highlight at the top edge (but put the bottom edge just out of view)
float offset = (float) Math.ceil(mConfig.taskViewHighlightPx / 2f);
float radius = mConfig.taskViewRoundedCornerRadiusPx;
+ int count = canvas.save(Canvas.CLIP_SAVE_FLAG);
+ canvas.clipRect(0, 0, getMeasuredWidth(), getMeasuredHeight());
canvas.drawRoundRect(-offset, 0f, (float) getMeasuredWidth() + offset,
getMeasuredHeight() + radius, radius, radius, sHighlightPaint);
+ canvas.restoreToCount(count);
}
}
@@ -178,7 +181,7 @@
}
/** Binds the bar view to the task */
- void rebindToTask(Task t) {
+ public void rebindToTask(Task t) {
// If an activity icon is defined, then we use that as the primary icon to show in the bar,
// otherwise, we fall back to the application icon
if (t.activityIcon != null) {
@@ -212,51 +215,6 @@
mApplicationIcon.setImageDrawable(null);
}
- /** Prepares this task view for the enter-recents animations. This is called earlier in the
- * first layout because the actual animation into recents may take a long time. */
- void prepareEnterRecentsAnimation() {
- setVisibility(View.INVISIBLE);
- }
-
- /** Animates this task bar as it enters recents */
- void startEnterRecentsAnimation(int delay, Runnable postAnimRunnable) {
- // Animate the task bar of the first task view
- setVisibility(View.VISIBLE);
- setAlpha(0f);
- animate()
- .alpha(1f)
- .setStartDelay(delay)
- .setInterpolator(mConfig.linearOutSlowInInterpolator)
- .setDuration(mConfig.taskBarEnterAnimDuration)
- .withEndAction(postAnimRunnable)
- .withLayer()
- .start();
- }
-
- /** Animates this task bar as it exits recents */
- void startLaunchTaskAnimation(Runnable preAnimRunnable, final Runnable postAnimRunnable,
- boolean isFocused) {
- if (isFocused) {
- onTaskViewFocusChanged(false);
- }
-
- // Animate the task bar out of the first task view
- animate()
- .alpha(0f)
- .setStartDelay(0)
- .setInterpolator(mConfig.linearOutSlowInInterpolator)
- .setDuration(mConfig.taskBarExitAnimDuration)
- .withStartAction(preAnimRunnable)
- .withEndAction(new Runnable() {
- @Override
- public void run() {
- post(postAnimRunnable);
- }
- })
- .withLayer()
- .start();
- }
-
/** Animates this task bar dismiss button when launching a task. */
void startLaunchTaskDismissAnimation() {
if (mDismissButton.getVisibility() == View.VISIBLE) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
index f223bf3..fe36987 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
@@ -64,25 +64,10 @@
setClipBounds(mClipRect);
}
- /** Convenience method to enable task bar clipping as a runnable. */
- Runnable enableTaskBarClipAsRunnable(final View taskBar) {
- return new Runnable() {
- @Override
- public void run() {
- enableTaskBarClip(taskBar);
- }
- };
- }
-
/** Disables the task bar clipping. */
- Runnable disableTaskBarClipAsRunnable() {
- return new Runnable() {
- @Override
- public void run() {
- mClipRect.set(0, 0, getMeasuredWidth(), getMeasuredHeight());
- setClipBounds(mClipRect);
- }
- };
+ void disableTaskBarClip() {
+ mClipRect.set(0, 0, getMeasuredWidth(), getMeasuredHeight());
+ setClipBounds(mClipRect);
}
/** Binds the thumbnail view to the screenshot. */
@@ -140,8 +125,8 @@
}
/** Animates this task thumbnail as it exits recents */
- void startLaunchTaskAnimation() {
- startFadeAnimation(1f, 0, mConfig.taskBarExitAnimDuration, null);
+ void startLaunchTaskAnimation(Runnable postAnimRunnable) {
+ startFadeAnimation(1f, 0, mConfig.taskBarExitAnimDuration, postAnimRunnable);
}
/** Animates the thumbnail alpha. */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 57df1d8..8b50a36 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -21,7 +21,6 @@
import android.animation.TimeInterpolator;
import android.app.ActivityManager;
import android.app.ActivityManagerNative;
-import android.app.ActivityThread;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.TaskStackBuilder;
@@ -32,16 +31,12 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
-import android.content.pm.IPackageManager;
-import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.UserInfo;
import android.content.res.Configuration;
import android.database.ContentObserver;
-import android.graphics.Rect;
import android.graphics.drawable.Drawable;
-import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Handler;
@@ -114,7 +109,6 @@
protected static final int MSG_CANCEL_PRELOAD_RECENT_APPS = 1023;
protected static final int MSG_SHOW_NEXT_AFFILIATED_TASK = 1024;
protected static final int MSG_SHOW_PREV_AFFILIATED_TASK = 1025;
- protected static final int MSG_OPEN_SEARCH_PANEL = 1026;
protected static final int MSG_CLOSE_SEARCH_PANEL = 1027;
protected static final int MSG_SHOW_HEADS_UP = 1028;
protected static final int MSG_HIDE_HEADS_UP = 1029;
@@ -580,7 +574,7 @@
}
- protected void applyLegacyRowBackground(StatusBarNotification sbn,
+ protected void applyColorsAndBackgrounds(StatusBarNotification sbn,
NotificationData.Entry entry) {
int version = 0;
try {
@@ -603,6 +597,14 @@
entry.row.setTintColor(color);
}
}
+
+ if (entry.icon != null) {
+ if (version >= Build.VERSION_CODES.L) {
+ entry.icon.setColorFilter(mContext.getResources().getColor(android.R.color.white));
+ } else {
+ entry.icon.setColorFilter(null);
+ }
+ }
}
public boolean isMediaNotification(NotificationData.Entry entry) {
@@ -751,9 +753,9 @@
@Override
public void showSearchPanel() {
- int msg = MSG_OPEN_SEARCH_PANEL;
- mHandler.removeMessages(msg);
- mHandler.sendEmptyMessage(msg);
+ if (mSearchPanelView != null && mSearchPanelView.isAssistantAvailable()) {
+ mSearchPanelView.show(true, true);
+ }
}
@Override
@@ -966,12 +968,6 @@
case MSG_SHOW_PREV_AFFILIATED_TASK:
showRecentsPreviousAffiliatedTask();
break;
- case MSG_OPEN_SEARCH_PANEL:
- if (DEBUG) Log.d(TAG, "opening search panel");
- if (mSearchPanelView != null && mSearchPanelView.isAssistantAvailable()) {
- mSearchPanelView.show(true, true);
- }
- break;
case MSG_CLOSE_SEARCH_PANEL:
if (DEBUG) Log.d(TAG, "closing search panel");
if (mSearchPanelView != null && mSearchPanelView.isShowing()) {
@@ -1257,7 +1253,7 @@
entry.expandedPublic = publicViewLocal;
entry.setBigContentView(bigContentViewLocal);
- applyLegacyRowBackground(sbn, entry);
+ applyColorsAndBackgrounds(sbn, entry);
// Restore previous flags.
if (hasUserChangedExpansion) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/DelegateViewHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/DelegateViewHelper.java
index 3a82753..628aab8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/DelegateViewHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/DelegateViewHelper.java
@@ -20,8 +20,7 @@
import android.graphics.RectF;
import android.view.MotionEvent;
import android.view.View;
-
-import com.android.systemui.R;
+import android.view.ViewConfiguration;
public class DelegateViewHelper {
private View mDelegateView;
@@ -107,8 +106,8 @@
public void setSourceView(View view) {
mSourceView = view;
if (mSourceView != null) {
- mTriggerThreshhold = mSourceView.getContext().getResources()
- .getDimension(R.dimen.navbar_search_up_threshhold);
+ mTriggerThreshhold =
+ ViewConfiguration.get(mSourceView.getContext()).getScaledPagingTouchSlop();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index cb2d40a..c0b171a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -29,7 +29,6 @@
import android.os.Bundle;
import android.os.RemoteException;
import android.os.UserHandle;
-import android.phone.PhoneManager;
import android.provider.MediaStore;
import android.telecomm.TelecommManager;
import android.util.AttributeSet;
@@ -324,13 +323,12 @@
}
public void launchPhone() {
- TelecommManager tm = TelecommManager.from(mContext);
- if (tm.isInAPhoneCall()) {
- final PhoneManager pm = (PhoneManager) mContext.getSystemService(Context.PHONE_SERVICE);
+ final TelecommManager tm = TelecommManager.from(mContext);
+ if (tm.isInCall()) {
AsyncTask.execute(new Runnable() {
@Override
public void run() {
- pm.showCallScreen(false /* showDialpad */);
+ tm.showInCallScreen(false /* showDialpad */);
}
});
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarViewTaskSwitchHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarViewTaskSwitchHelper.java
index 3c20d1f..b633453 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarViewTaskSwitchHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarViewTaskSwitchHelper.java
@@ -33,10 +33,11 @@
private final int mMinFlingVelocity;
private boolean mInterceptTouches;
private int mTouchDownX;
+ private int mTouchDownY;
public NavigationBarViewTaskSwitchHelper(Context context) {
ViewConfiguration configuration = ViewConfiguration.get(context);
- mScrollTouchSlop = configuration.getScaledTouchSlop();
+ mScrollTouchSlop = 4 * configuration.getScaledTouchSlop();
mMinFlingVelocity = configuration.getScaledMinimumFlingVelocity();
mTaskSwitcherDetector = new GestureDetector(context, this);
}
@@ -58,12 +59,19 @@
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN: {
mTouchDownX = (int) event.getX();
+ mTouchDownY = (int) event.getY();
mInterceptTouches = false;
break;
}
case MotionEvent.ACTION_MOVE: {
int x = (int) event.getX();
- if (Math.abs(x - mTouchDownX) > mScrollTouchSlop) {
+ int y = (int) event.getY();
+ int xDiff = Math.abs(x - mTouchDownX);
+ int yDiff = Math.abs(y - mTouchDownY);
+ boolean exceededTouchSlop = !mIsVertical
+ ? xDiff > mScrollTouchSlop && xDiff > yDiff
+ : yDiff > mScrollTouchSlop && yDiff > xDiff;
+ if (exceededTouchSlop) {
mInterceptTouches = true;
return true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index e1beb08..387abc3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -58,7 +58,7 @@
private static final int CAP_HEIGHT = 1456;
private static final int FONT_HEIGHT = 2163;
- private static final float HEADER_RUBBERBAND_FACTOR = 2.15f;
+ private static final float HEADER_RUBBERBAND_FACTOR = 2.05f;
private static final float LOCK_ICON_ACTIVE_SCALE = 1.2f;
private KeyguardAffordanceHelper mAfforanceHelper;
@@ -1665,7 +1665,7 @@
@Override
protected boolean fullyExpandedClearAllVisible() {
return mNotificationStackScroller.isDismissViewNotGone()
- && mNotificationStackScroller.isScrolledToBottom();
+ && mNotificationStackScroller.isScrolledToBottom() && !mTwoFingerQsExpand;
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index f427ec4..3338f6a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -298,9 +298,7 @@
*/
public boolean onBackPressed() {
if (mBouncer.isShowing()) {
- mBouncer.hide(false /* destroyView */);
- mPhoneStatusBar.showKeyguard();
- updateStates();
+ reset();
return true;
}
return false;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastController.java
index eb5804a..7713e57 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastController.java
@@ -25,7 +25,7 @@
void setCurrentUserId(int currentUserId);
Set<CastDevice> getCastDevices();
void startCasting(CastDevice device);
- void stopCasting();
+ void stopCasting(CastDevice device);
public interface Callback {
void onCastDevicesChanged();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java
index 22179e0..eb0be05 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java
@@ -19,15 +19,25 @@
import static android.media.MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY;
import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.media.MediaRouter;
import android.media.MediaRouter.RouteInfo;
+import android.media.projection.MediaProjectionInfo;
+import android.media.projection.MediaProjectionManager;
+import android.os.Handler;
+import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
+import com.android.systemui.R;
+
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Objects;
import java.util.Set;
import java.util.UUID;
@@ -41,12 +51,19 @@
private final MediaRouter mMediaRouter;
private final ArrayMap<String, RouteInfo> mRoutes = new ArrayMap<>();
private final Object mDiscoveringLock = new Object();
+ private final MediaProjectionManager mProjectionManager;
+ private final Object mProjectionLock = new Object();
private boolean mDiscovering;
+ private MediaProjectionInfo mProjection;
public CastControllerImpl(Context context) {
mContext = context;
mMediaRouter = (MediaRouter) context.getSystemService(Context.MEDIA_ROUTER_SERVICE);
+ mProjectionManager = (MediaProjectionManager)
+ context.getSystemService(Context.MEDIA_PROJECTION_SERVICE);
+ mProjection = mProjectionManager.getActiveProjectionInfo();
+ mProjectionManager.addCallback(mProjectionCallback, new Handler());
if (DEBUG) Log.d(TAG, "new CastController()");
}
@@ -59,6 +76,7 @@
final RouteInfo route = mRoutes.valueAt(i);
pw.print(" "); pw.println(routeToString(route));
}
+ pw.print(" mProjection="); pw.println(mProjection);
}
@Override
@@ -95,6 +113,18 @@
@Override
public Set<CastDevice> getCastDevices() {
final ArraySet<CastDevice> devices = new ArraySet<CastDevice>();
+ synchronized (mProjectionLock) {
+ if (mProjection != null) {
+ final CastDevice device = new CastDevice();
+ device.id = mProjection.getPackageName();
+ device.name = getAppName(mProjection.getPackageName());
+ device.description = mContext.getString(R.string.quick_settings_casting);
+ device.state = CastDevice.STATE_CONNECTED;
+ device.tag = mProjection;
+ devices.add(device);
+ return devices;
+ }
+ }
synchronized(mRoutes) {
for (RouteInfo route : mRoutes.values()) {
final CastDevice device = new CastDevice();
@@ -122,9 +152,55 @@
}
@Override
- public void stopCasting() {
- if (DEBUG) Log.d(TAG, "stopCasting");
- mMediaRouter.getDefaultRoute().select();
+ public void stopCasting(CastDevice device) {
+ final boolean isProjection = device.tag instanceof MediaProjectionInfo;
+ if (DEBUG) Log.d(TAG, "stopCasting isProjection=" + isProjection);
+ if (isProjection) {
+ final MediaProjectionInfo projection = (MediaProjectionInfo) device.tag;
+ if (Objects.equals(mProjectionManager.getActiveProjectionInfo(), projection)) {
+ mProjectionManager.stopActiveProjection();
+ } else {
+ Log.w(TAG, "Projection is no longer active: " + projection);
+ }
+ } else {
+ mMediaRouter.getDefaultRoute().select();
+ }
+ }
+
+ private void setProjection(MediaProjectionInfo projection, boolean started) {
+ boolean changed = false;
+ final MediaProjectionInfo oldProjection = mProjection;
+ synchronized (mProjectionLock) {
+ final boolean isCurrent = Objects.equals(projection, mProjection);
+ if (started && !isCurrent) {
+ mProjection = projection;
+ changed = true;
+ } else if (!started && isCurrent) {
+ mProjection = null;
+ changed = true;
+ }
+ }
+ if (changed) {
+ if (DEBUG) Log.d(TAG, "setProjection: " + oldProjection + " -> " + mProjection);
+ fireOnCastDevicesChanged();
+ }
+ }
+
+ private String getAppName(String packageName) {
+ final PackageManager pm = mContext.getPackageManager();
+ try {
+ final ApplicationInfo appInfo = pm.getApplicationInfo(packageName, 0);
+ if (appInfo != null) {
+ final CharSequence label = appInfo.loadLabel(pm);
+ if (!TextUtils.isEmpty(label)) {
+ return label.toString();
+ }
+ }
+ Log.w(TAG, "No label found for package: " + packageName);
+ } catch (NameNotFoundException e) {
+ Log.w(TAG, "Error getting appName for package: " + packageName, e);
+ }
+ return packageName;
}
private void updateRemoteDisplays() {
@@ -202,4 +278,17 @@
updateRemoteDisplays();
}
};
+
+ private final MediaProjectionManager.Callback mProjectionCallback
+ = new MediaProjectionManager.Callback() {
+ @Override
+ public void onStart(MediaProjectionInfo info) {
+ setProjection(info, true);
+ }
+
+ @Override
+ public void onStop(MediaProjectionInfo info) {
+ setProjection(info, false);
+ }
+ };
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 68a02cf..82efd1d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -2150,7 +2150,15 @@
}
public int getDismissViewHeight() {
- return mDismissView.getHeight() + mPaddingBetweenElementsNormal;
+ int height = mDismissView.getHeight() + mPaddingBetweenElementsNormal;
+
+ // Hack: Accommodate for additional distance when we only have one notification and the
+ // dismiss all button.
+ if (getNotGoneChildCount() == 2 && getLastChildNotGone() == mDismissView
+ && getFirstChildNotGone() instanceof ActivatableNotificationView) {
+ height += mCollapseSecondCardPadding;
+ }
+ return height;
}
public float getBottomMostNotificationBottom() {
diff --git a/phone/java/android/phone/PhoneManager.java b/phone/java/android/phone/PhoneManager.java
deleted file mode 100644
index f61b054..0000000
--- a/phone/java/android/phone/PhoneManager.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * 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.phone;
-
-import android.content.Context;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.util.Log;
-
-import com.android.internal.telecomm.ITelecommService;
-
-/**
- * Exposes call-related functionality for use by phone and dialer apps.
- */
-public final class PhoneManager {
- private static final String TAG = PhoneManager.class.getSimpleName();
-
- private final Context mContext;
-
- /**
- * @hide
- */
- public PhoneManager(Context context) {
- Context appContext = context.getApplicationContext();
- if (appContext != null) {
- mContext = appContext;
- } else {
- mContext = context;
- }
- }
-
- /**
- * Processes the specified dial string as an MMI code.
- * <p>
- * Requires that the method-caller be set as the system dialer app.
- * </p>
- *
- * @param dialString The digits to dial.
- * @return True if the digits were processed as an MMI code, false otherwise.
- */
- public boolean handlePinMmi(String dialString) {
- ITelecommService service = getTelecommService();
- if (service != null) {
- try {
- return service.handlePinMmi(dialString);
- } catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelecommService#handlePinMmi", e);
- }
- }
- return false;
- }
-
- /**
- * Removes the missed-call notification if one is present.
- * <p>
- * Requires that the method-caller be set as the system dialer app.
- * </p>
- */
- public void cancelMissedCallsNotification() {
- ITelecommService service = getTelecommService();
- if (service != null) {
- try {
- service.cancelMissedCallsNotification();
- } catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelecommService#cancelMissedCallsNotification", e);
- }
- }
- }
-
- /**
- * Brings the in-call screen to the foreground if there is an ongoing call. If there is
- * currently no ongoing call, then this method does nothing.
- * <p>
- * Requires that the method-caller be set as the system dialer app or have the
- * {@link android.Manifest.permission#READ_PHONE_STATE} permission.
- * </p>
- *
- * @param showDialpad Brings up the in-call dialpad as part of showing the in-call screen.
- */
- public void showCallScreen(boolean showDialpad) {
- ITelecommService service = getTelecommService();
- if (service != null) {
- try {
- service.showCallScreen(showDialpad);
- } catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelecommService#showCallScreen", e);
- }
- }
- }
-
- /**
- * Returns whether there is an ongoing phone call.
- * <p>
- * Requires permission: {@link android.Manifest.permission#READ_PHONE_STATE}
- * </p>
- */
- public boolean isInAPhoneCall() {
- ITelecommService service = getTelecommService();
- if (service != null) {
- try {
- return service.isInAPhoneCall();
- } catch (RemoteException e) {
- Log.e(TAG, "Error caling ITelecommService#isInAPhoneCall", e);
- }
- }
- return false;
- }
-
- private ITelecommService getTelecommService() {
- return ITelecommService.Stub.asInterface(
- ServiceManager.getService(Context.TELECOMM_SERVICE));
- }
-}
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index 9652ebd..e240127 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -876,6 +876,13 @@
}
}
+ void doPendingInvalidatePanelMenu() {
+ if (mInvalidatePanelMenuPosted) {
+ mDecor.removeCallbacks(mInvalidatePanelMenuRunnable);
+ mInvalidatePanelMenuRunnable.run();
+ }
+ }
+
void doInvalidatePanelMenu(int featureId) {
PanelFeatureState st = getPanelState(featureId, true);
Bundle savedActionViewStates = null;
@@ -1979,6 +1986,7 @@
SparseArray<Parcelable> actionBarStates =
savedInstanceState.getSparseParcelableArray(ACTION_BAR_TAG);
if (actionBarStates != null) {
+ doPendingInvalidatePanelMenu();
mDecorContentParent.restoreToolbarHierarchyState(actionBarStates);
} else {
Log.w(TAG, "Missing saved instance states for action bar views! " +
@@ -3468,17 +3476,15 @@
mDecorContentParent.setLogo(mLogoRes);
}
- // Post the panel invalidate for later; avoid application onCreateOptionsMenu
+ // Invalidate if the panel menu hasn't been created before this.
+ // Panel menu invalidation is deferred avoiding application onCreateOptionsMenu
// being called in the middle of onCreate or similar.
- mDecor.post(new Runnable() {
- public void run() {
- // Invalidate if the panel menu hasn't been created before this.
- PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false);
- if (!isDestroyed() && (st == null || st.menu == null)) {
- invalidatePanelMenu(FEATURE_ACTION_BAR);
- }
- }
- });
+ // A pending invalidation will typically be resolved before the posted message
+ // would run normally in order to satisfy instance state restoration.
+ PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false);
+ if (!isDestroyed() && (st == null || st.menu == null)) {
+ invalidatePanelMenu(FEATURE_ACTION_BAR);
+ }
} else {
mTitleView = (TextView)findViewById(R.id.title);
if (mTitleView != null) {
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index c10d929..20206b9 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -2978,7 +2978,10 @@
boolean immersiveSticky = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
boolean navAllowedHidden = immersive || immersiveSticky;
navTranslucent &= !immersiveSticky; // transient trumps translucent
- navTranslucent &= areTranslucentBarsAllowed();
+ boolean isKeyguardShowing = isStatusBarKeyguard() && !mHideLockScreen;
+ if (!isKeyguardShowing) {
+ navTranslucent &= areTranslucentBarsAllowed();
+ }
// When the navigation bar isn't visible, we put up a fake
// input window to catch all touch events. This way we can
@@ -3102,7 +3105,9 @@
boolean statusBarTransient = (sysui & View.STATUS_BAR_TRANSIENT) != 0;
boolean statusBarTranslucent = (sysui
& (View.STATUS_BAR_TRANSLUCENT | View.SYSTEM_UI_TRANSPARENT)) != 0;
- statusBarTranslucent &= areTranslucentBarsAllowed();
+ if (!isKeyguardShowing) {
+ statusBarTranslucent &= areTranslucentBarsAllowed();
+ }
// If the status bar is hidden, we don't want to cause
// windows behind it to scroll.
@@ -4274,7 +4279,7 @@
result &= ~ACTION_PASS_TO_USER;
break;
}
- if (telecommManager.isInAPhoneCall()
+ if (telecommManager.isInCall()
&& (result & ACTION_PASS_TO_USER) == 0) {
// If we are in call but we decided not to pass the key to
// the application, just pass it to the session service.
@@ -4349,7 +4354,7 @@
telecommManager.silenceRinger();
} else if ((mIncallPowerBehavior
& Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0
- && telecommManager.isInAPhoneCall() && interactive) {
+ && telecommManager.isInCall() && interactive) {
// Otherwise, if "Power button ends call" is enabled,
// the Power button will hang up any current active call.
hungUp = telecommManager.endCall();
@@ -4392,7 +4397,7 @@
if (down) {
TelecommManager telecommManager = getTelecommService();
if (telecommManager != null) {
- if (telecommManager.isInAPhoneCall()) {
+ if (telecommManager.isInCall()) {
// Suppress PLAY/PAUSE toggle when phone is ringing or in-call
// to avoid music playback.
break;
@@ -5611,7 +5616,7 @@
vis = (vis & ~flags) | (oldVis & flags);
}
- if (!areTranslucentBarsAllowed()) {
+ if (!areTranslucentBarsAllowed() && transWin != mStatusBar) {
vis &= ~(View.NAVIGATION_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSLUCENT
| View.SYSTEM_UI_TRANSPARENT);
}
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index ad8f446..8dd6420 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -2167,41 +2167,53 @@
if (DBG) log("releasing NetworkRequest " + request);
nri.unlinkDeathRecipient();
mNetworkRequests.remove(request);
- // tell the network currently servicing this that it's no longer interested
- NetworkAgentInfo affectedNetwork = mNetworkForRequestId.get(nri.request.requestId);
- if (affectedNetwork != null) {
- mNetworkForRequestId.remove(nri.request.requestId);
- affectedNetwork.networkRequests.remove(nri.request.requestId);
- if (VDBG) {
- log(" Removing from current network " + affectedNetwork.name() + ", leaving " +
- affectedNetwork.networkRequests.size() + " requests.");
- }
- if (nri.isRequest && nri.request.legacyType != TYPE_NONE) {
- mLegacyTypeTracker.remove(nri.request.legacyType, affectedNetwork);
- }
- }
-
if (nri.isRequest) {
+ // Find all networks that are satisfying this request and remove the request
+ // from their request lists.
+ for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
+ if (nai.networkRequests.get(nri.request.requestId) != null) {
+ nai.networkRequests.remove(nri.request.requestId);
+ if (VDBG) {
+ log(" Removing from current network " + nai.name() +
+ ", leaving " + nai.networkRequests.size() +
+ " requests.");
+ }
+ // check if has any requests remaining and if not,
+ // disconnect (unless it's a VPN).
+ boolean keep = nai.isVPN();
+ for (int i = 0; i < nai.networkRequests.size() && !keep; i++) {
+ NetworkRequest r = nai.networkRequests.valueAt(i);
+ if (mNetworkRequests.get(r).isRequest) keep = true;
+ }
+ if (!keep) {
+ if (DBG) log("no live requests for " + nai.name() + "; disconnecting");
+ nai.asyncChannel.disconnect();
+ }
+ }
+ }
+
+ // Maintain the illusion. When this request arrived, we might have preteneded
+ // that a network connected to serve it, even though the network was already
+ // connected. Now that this request has gone away, we might have to pretend
+ // that the network disconnected. LegacyTypeTracker will generate that
+ // phatom disconnect for this type.
+ NetworkAgentInfo nai = mNetworkForRequestId.get(nri.request.requestId);
+ if (nai != null) {
+ mNetworkForRequestId.remove(nri.request.requestId);
+ if (nri.request.legacyType != TYPE_NONE) {
+ mLegacyTypeTracker.remove(nri.request.legacyType, nai);
+ }
+ }
+
for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
nfi.asyncChannel.sendMessage(android.net.NetworkFactory.CMD_CANCEL_REQUEST,
nri.request);
}
-
- if (affectedNetwork != null) {
- // check if this network still has live requests - otherwise, tear down
- // TODO - probably push this to the NF/NA
- boolean keep = affectedNetwork.isVPN();
- for (int i = 0; i < affectedNetwork.networkRequests.size() && !keep; i++) {
- NetworkRequest r = affectedNetwork.networkRequests.valueAt(i);
- if (mNetworkRequests.get(r).isRequest) {
- keep = true;
- }
- }
- if (keep == false) {
- if (DBG) log("no live requests for " + affectedNetwork.name() +
- "; disconnecting");
- affectedNetwork.asyncChannel.disconnect();
- }
+ } else {
+ // listens don't have a singular affectedNetwork. Check all networks to see
+ // if this listen request applies and remove it.
+ for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
+ nai.networkRequests.remove(nri.request.requestId);
}
}
callCallbackForRequest(nri, null, ConnectivityManager.CALLBACK_RELEASED);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index dd3d862..1acbec7 100755
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -6615,6 +6615,10 @@
return false;
}
+ /**
+ * @param uri This uri must NOT contain an embedded userId.
+ * @param userId The userId in which the uri is to be resolved.
+ */
@Override
public int checkUriPermission(Uri uri, int pid, int uid,
final int modeFlags, int userId) {
@@ -6767,6 +6771,10 @@
return targetUid;
}
+ /**
+ * @param uri This uri must NOT contain an embedded userId.
+ * @param userId The userId in which the uri is to be resolved.
+ */
@Override
public int checkGrantUriPermission(int callingUid, String targetPkg, Uri uri,
final int modeFlags, int userId) {
@@ -6951,6 +6959,10 @@
grantUriPermissionUncheckedFromIntentLocked(needed, owner);
}
+ /**
+ * @param uri This uri must NOT contain an embedded userId.
+ * @param userId The userId in which the uri is to be resolved.
+ */
@Override
public void grantUriPermission(IApplicationThread caller, String targetPkg, Uri uri,
final int modeFlags, int userId) {
@@ -7053,6 +7065,10 @@
}
}
+ /**
+ * @param uri This uri must NOT contain an embedded userId.
+ * @param userId The userId in which the uri is to be resolved.
+ */
@Override
public void revokeUriPermission(IApplicationThread caller, Uri uri, final int modeFlags,
int userId) {
@@ -7151,9 +7167,16 @@
}
}
+ /**
+ * @param uri This uri must NOT contain an embedded userId.
+ * @param sourceUserId The userId in which the uri is to be resolved.
+ * @param targetUserId The userId of the app that receives the grant.
+ */
@Override
public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg, Uri uri,
final int modeFlags, int sourceUserId, int targetUserId) {
+ targetUserId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
+ targetUserId, false, ALLOW_FULL_ONLY, "grantUriPermissionFromOwner", null);
synchronized(this) {
UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
if (owner == null) {
@@ -7178,6 +7201,10 @@
}
}
+ /**
+ * @param uri This uri must NOT contain an embedded userId.
+ * @param userId The userId in which the uri is to be resolved.
+ */
@Override
public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode, int userId) {
synchronized(this) {
@@ -7318,6 +7345,10 @@
}
}
+ /**
+ * @param uri This uri must NOT contain an embedded userId.
+ * @param userId The userId in which the uri is to be resolved.
+ */
@Override
public void takePersistableUriPermission(Uri uri, final int modeFlags, int userId) {
enforceNotIsolatedCaller("takePersistableUriPermission");
@@ -7360,6 +7391,10 @@
}
}
+ /**
+ * @param uri This uri must NOT contain an embedded userId.
+ * @param userId The userId in which the uri is to be resolved.
+ */
@Override
public void releasePersistableUriPermission(Uri uri, final int modeFlags, int userId) {
enforceNotIsolatedCaller("releasePersistableUriPermission");
@@ -7516,18 +7551,10 @@
// =========================================================
@Override
- public List<IAppTask> getAppTasks() {
- final PackageManager pm = mContext.getPackageManager();
+ public List<IAppTask> getAppTasks(String callingPackage) {
int callingUid = Binder.getCallingUid();
long ident = Binder.clearCallingIdentity();
- // Compose the list of packages for this id to test against
- HashSet<String> packages = new HashSet<String>();
- String[] uidPackages = pm.getPackagesForUid(callingUid);
- for (int i = 0; i < uidPackages.length; i++) {
- packages.add(uidPackages[i]);
- }
-
synchronized(this) {
ArrayList<IAppTask> list = new ArrayList<IAppTask>();
try {
@@ -7536,13 +7563,21 @@
final int N = mRecentTasks.size();
for (int i = 0; i < N; i++) {
TaskRecord tr = mRecentTasks.get(i);
- // Skip tasks that do not match the package name
- if (packages.contains(tr.getBaseIntent().getComponent().getPackageName())) {
- ActivityManager.RecentTaskInfo taskInfo =
- createRecentTaskInfoFromTaskRecord(tr);
- AppTaskImpl taskImpl = new AppTaskImpl(taskInfo.persistentId, callingUid);
- list.add(taskImpl);
+ // Skip tasks that do not match the caller. We don't need to verify
+ // callingPackage, because we are also limiting to callingUid and know
+ // that will limit to the correct security sandbox.
+ if (tr.effectiveUid != callingUid) {
+ continue;
}
+ Intent intent = tr.getBaseIntent();
+ if (intent == null ||
+ !callingPackage.equals(intent.getComponent().getPackageName())) {
+ continue;
+ }
+ ActivityManager.RecentTaskInfo taskInfo =
+ createRecentTaskInfoFromTaskRecord(tr);
+ AppTaskImpl taskImpl = new AppTaskImpl(taskInfo.persistentId, callingUid);
+ list.add(taskImpl);
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -7706,11 +7741,17 @@
if (!allowed) {
// If the caller doesn't have the GET_TASKS permission, then only
// allow them to see a small subset of tasks -- their own and home.
- if (!tr.isHomeTask() && tr.creatorUid != callingUid) {
+ if (!tr.isHomeTask() && tr.effectiveUid != callingUid) {
if (DEBUG_RECENTS) Slog.d(TAG, "Skipping, not allowed: " + tr);
continue;
}
}
+ if ((flags & ActivityManager.RECENT_IGNORE_HOME_STACK_TASKS) != 0) {
+ if (tr.stack != null && tr.stack.isHomeStack()) {
+ if (DEBUG_RECENTS) Slog.d(TAG, "Skipping, home stack task: " + tr);
+ continue;
+ }
+ }
if (tr.autoRemoveRecents && tr.getTopActivity() == null) {
// Don't include auto remove tasks that are finished or finishing.
if (DEBUG_RECENTS) Slog.d(TAG, "Skipping, auto-remove without activity: "
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index fcbe71e..39b6375 100755
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -723,6 +723,22 @@
+ pendingOptions.getThumbnail().getHeight()));
}
break;
+ case ActivityOptions.ANIM_THUMBNAIL_ASPECT_SCALE_UP:
+ case ActivityOptions.ANIM_THUMBNAIL_ASPECT_SCALE_DOWN:
+ service.mWindowManager.overridePendingAppTransitionAspectScaledThumb(
+ pendingOptions.getThumbnail(),
+ pendingOptions.getStartX(), pendingOptions.getStartY(),
+ pendingOptions.getOnAnimationStartListener(),
+ (animationType == ActivityOptions.ANIM_THUMBNAIL_ASPECT_SCALE_UP));
+ if (intent.getSourceBounds() == null) {
+ intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
+ pendingOptions.getStartY(),
+ pendingOptions.getStartX()
+ + pendingOptions.getThumbnail().getWidth(),
+ pendingOptions.getStartY()
+ + pendingOptions.getThumbnail().getHeight()));
+ }
+ break;
default:
Slog.e(TAG, "applyOptionsLocked: Unknown animationType=" + animationType);
break;
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 4bd86e4..41ed4ce7 100755
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -3799,7 +3799,7 @@
if (activities.isEmpty()) {
continue;
}
- if (!allowed && !task.isHomeTask() && task.creatorUid != callingUid) {
+ if (!allowed && !task.isHomeTask() && task.effectiveUid != callingUid) {
continue;
}
for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 8aec392..bd8501c 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -2430,7 +2430,6 @@
r.userId, r.info.configChanges, task.voiceSession != null,
r.mLaunchTaskBehind);
}
- mWindowManager.addTask(taskId, stackId, false);
}
resumeHomeStackTask(HOME_ACTIVITY_TYPE, null);
}
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index d35e09f..7e42232 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -26,11 +26,16 @@
import android.app.ActivityManager;
import android.app.ActivityManager.TaskThumbnail;
import android.app.ActivityOptions;
+import android.app.AppGlobals;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
import android.os.UserHandle;
import android.service.voice.IVoiceInteractionSession;
import android.util.Slog;
@@ -57,6 +62,7 @@
private static final String ATTR_AUTOREMOVERECENTS = "auto_remove_recents";
private static final String ATTR_ASKEDCOMPATMODE = "asked_compat_mode";
private static final String ATTR_USERID = "user_id";
+ private static final String ATTR_EFFECTIVE_UID = "effective_uid";
private static final String ATTR_TASKTYPE = "task_type";
private static final String ATTR_FIRSTACTIVETIME = "first_active_time";
private static final String ATTR_LASTACTIVETIME = "last_active_time";
@@ -83,6 +89,7 @@
final IVoiceInteractor voiceInteractor; // Associated interactor to provide to app
Intent intent; // The original intent that started the task.
Intent affinityIntent; // Intent of affinity-moved activity that started this task.
+ int effectiveUid; // The current effective uid of the identity of this task.
ComponentName origActivity; // The non-alias activity component of the intent.
ComponentName realActivity; // The actual activity component that started the task.
long firstActiveTime; // First time this task was active.
@@ -198,7 +205,7 @@
TaskRecord(ActivityManagerService service, int _taskId, Intent _intent, Intent _affinityIntent,
String _affinity, ComponentName _realActivity, ComponentName _origActivity,
boolean _rootWasReset, boolean _autoRemoveRecents, boolean _askedCompatMode,
- int _taskType, int _userId,
+ int _taskType, int _userId, int _effectiveUid,
String _lastDescription, ArrayList<ActivityRecord> activities, long _firstActiveTime,
long _lastActiveTime, long lastTimeMoved, boolean neverRelinquishIdentity,
ActivityManager.TaskDescription _lastTaskDescription, int taskAffiliation,
@@ -222,6 +229,7 @@
taskType = _taskType;
mTaskToReturnTo = HOME_ACTIVITY_TYPE;
userId = _userId;
+ effectiveUid = _effectiveUid;
firstActiveTime = _firstActiveTime;
lastActiveTime = _lastActiveTime;
lastDescription = _lastDescription;
@@ -265,6 +273,7 @@
}
affinity = info.taskAffinity;
+ effectiveUid = info.applicationInfo.uid;
stringName = null;
if (info.targetActivity == null) {
@@ -311,7 +320,6 @@
}
userId = UserHandle.getUserId(info.applicationInfo.uid);
- creatorUid = info.applicationInfo.uid;
if ((info.flags & ActivityInfo.FLAG_AUTO_REMOVE_FROM_RECENTS) != 0) {
// If the activity itself has requested auto-remove, then just always do it.
autoRemoveRecents = true;
@@ -823,6 +831,7 @@
out.attribute(null, ATTR_AUTOREMOVERECENTS, String.valueOf(autoRemoveRecents));
out.attribute(null, ATTR_ASKEDCOMPATMODE, String.valueOf(askedCompatMode));
out.attribute(null, ATTR_USERID, String.valueOf(userId));
+ out.attribute(null, ATTR_EFFECTIVE_UID, String.valueOf(effectiveUid));
out.attribute(null, ATTR_TASKTYPE, String.valueOf(taskType));
out.attribute(null, ATTR_FIRSTACTIVETIME, String.valueOf(firstActiveTime));
out.attribute(null, ATTR_LASTACTIVETIME, String.valueOf(lastActiveTime));
@@ -881,6 +890,7 @@
boolean askedCompatMode = false;
int taskType = ActivityRecord.APPLICATION_ACTIVITY_TYPE;
int userId = 0;
+ int effectiveUid = -1;
String lastDescription = null;
long firstActiveTime = -1;
long lastActiveTime = -1;
@@ -917,6 +927,8 @@
askedCompatMode = Boolean.valueOf(attrValue);
} else if (ATTR_USERID.equals(attrName)) {
userId = Integer.valueOf(attrValue);
+ } else if (ATTR_EFFECTIVE_UID.equals(attrName)) {
+ effectiveUid = Integer.valueOf(attrValue);
} else if (ATTR_TASKTYPE.equals(attrName)) {
taskType = Integer.valueOf(attrValue);
} else if (ATTR_FIRSTACTIVETIME.equals(attrName)) {
@@ -979,10 +991,30 @@
createLastTaskDescriptionIconFilename(taskId, lastActiveTime)));
}
+ if (effectiveUid <= 0) {
+ Intent checkIntent = intent != null ? intent : affinityIntent;
+ effectiveUid = 0;
+ if (checkIntent != null) {
+ IPackageManager pm = AppGlobals.getPackageManager();
+ try {
+ ApplicationInfo ai = pm.getApplicationInfo(
+ checkIntent.getComponent().getPackageName(),
+ PackageManager.GET_UNINSTALLED_PACKAGES
+ | PackageManager.GET_DISABLED_COMPONENTS, userId);
+ if (ai != null) {
+ effectiveUid = ai.uid;
+ }
+ } catch (RemoteException e) {
+ }
+ }
+ Slog.w(TAG, "Updating task #" + taskId + " for " + checkIntent
+ + ": effectiveUid=" + effectiveUid);
+ }
+
final TaskRecord task = new TaskRecord(stackSupervisor.mService, taskId, intent,
affinityIntent, affinity, realActivity, origActivity, rootHasReset,
- autoRemoveRecents, askedCompatMode, taskType, userId, lastDescription, activities,
- firstActiveTime, lastActiveTime, lastTimeOnTop, neverRelinquishIdentity,
+ autoRemoveRecents, askedCompatMode, taskType, userId, effectiveUid, lastDescription,
+ activities, firstActiveTime, lastActiveTime, lastTimeOnTop, neverRelinquishIdentity,
taskDescription, taskAffiliation, prevTaskId, nextTaskId, taskAffiliationColor,
callingUid, callingPackage);
@@ -996,8 +1028,8 @@
void dump(PrintWriter pw, String prefix) {
pw.print(prefix); pw.print("userId="); pw.print(userId);
- pw.print(" creatorUid="); pw.print(creatorUid);
- pw.print(" mCallingUid="); pw.print(mCallingUid);
+ pw.print(" effectiveUid="); UserHandle.formatUid(pw, effectiveUid);
+ pw.print(" mCallingUid="); UserHandle.formatUid(pw, mCallingUid);
pw.print(" mCallingPackage="); pw.println(mCallingPackage);
if (affinity != null) {
pw.print(prefix); pw.print("affinity="); pw.println(affinity);
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index 949019e..9e169d9 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -152,7 +152,10 @@
*/
private static final int DELAY_RETRY_SYNC_IN_PROGRESS_IN_SECONDS = 10;
- private static final int INITIALIZATION_UNBIND_DELAY_MS = 5000;
+ /**
+ * How long to wait before considering an active sync to have timed-out, and cancelling it.
+ */
+ private static final long ACTIVE_SYNC_TIMEOUT_MILLIS = 30L * 60 * 1000; // 30 mins.
private static final String SYNC_WAKE_LOCK_PREFIX = "*sync*/";
private static final String HANDLE_SYNC_ALARM_WAKE_LOCK = "SyncManagerHandleSyncAlarm";
@@ -851,6 +854,31 @@
mSyncHandler.sendMessage(msg);
}
+ /**
+ * Post a delayed message to the handler that will result in the cancellation of the provided
+ * running sync's context.
+ */
+ private void postSyncExpiryMessage(ActiveSyncContext activeSyncContext) {
+ if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ Log.v(TAG, "posting MESSAGE_SYNC_EXPIRED in " +
+ (ACTIVE_SYNC_TIMEOUT_MILLIS/1000) + "s");
+ }
+ Message msg = mSyncHandler.obtainMessage();
+ msg.what = SyncHandler.MESSAGE_SYNC_EXPIRED;
+ msg.obj = activeSyncContext;
+ mSyncHandler.sendMessageDelayed(msg, ACTIVE_SYNC_TIMEOUT_MILLIS);
+ }
+
+ /**
+ * Remove any time-outs previously posted for the provided active sync.
+ */
+ private void removeSyncExpiryMessage(ActiveSyncContext activeSyncContext) {
+ if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ Log.v(TAG, "removing all MESSAGE_SYNC_EXPIRED for " + activeSyncContext.toString());
+ }
+ mSyncHandler.removeMessages(SyncHandler.MESSAGE_SYNC_EXPIRED, activeSyncContext);
+ }
+
class SyncHandlerMessagePayload {
public final ActiveSyncContext activeSyncContext;
public final SyncResult syncResult;
@@ -1902,6 +1930,8 @@
private static final int MESSAGE_SERVICE_CONNECTED = 4;
private static final int MESSAGE_SERVICE_DISCONNECTED = 5;
private static final int MESSAGE_CANCEL = 6;
+ /** Posted delayed in order to expire syncs that are long-running. */
+ private static final int MESSAGE_SYNC_EXPIRED = 7;
public final SyncNotificationInfo mSyncNotificationInfo = new SyncNotificationInfo();
private Long mAlarmScheduleTime = null;
@@ -2000,10 +2030,21 @@
// to also take into account the periodic syncs.
earliestFuturePollTime = scheduleReadyPeriodicSyncs();
switch (msg.what) {
+ case SyncHandler.MESSAGE_SYNC_EXPIRED:
+ ActiveSyncContext expiredContext = (ActiveSyncContext) msg.obj;
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "handleSyncHandlerMessage: MESSAGE_SYNC_EXPIRED: expiring "
+ + expiredContext);
+ }
+ cancelActiveSync(expiredContext.mSyncOperation.target,
+ expiredContext.mSyncOperation.extras);
+ nextPendingSyncTime = maybeStartNextSyncLocked();
+ break;
+
case SyncHandler.MESSAGE_CANCEL: {
SyncStorageEngine.EndPoint payload = (SyncStorageEngine.EndPoint) msg.obj;
Bundle extras = msg.peekData();
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "handleSyncHandlerMessage: MESSAGE_SERVICE_CANCEL: "
+ payload + " bundle: " + extras);
}
@@ -2653,6 +2694,13 @@
new ActiveSyncContext(op, insertStartSyncEvent(op), targetUid);
activeSyncContext.mSyncInfo = mSyncStorageEngine.addActiveSync(activeSyncContext);
mActiveSyncContexts.add(activeSyncContext);
+ if (!activeSyncContext.mSyncOperation.isInitialization() &&
+ !activeSyncContext.mSyncOperation.isExpedited() &&
+ !activeSyncContext.mSyncOperation.isManual() &&
+ !activeSyncContext.mSyncOperation.isIgnoreSettings()) {
+ // Post message to expire this sync if it runs for too long.
+ postSyncExpiryMessage(activeSyncContext);
+ }
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "dispatchSyncOperation: starting " + activeSyncContext);
}
@@ -2757,9 +2805,7 @@
} else {
Log.d(TAG, "failed sync operation " + syncOperation + ", " + syncResult);
// the operation failed so increase the backoff time
- if (!syncResult.syncAlreadyInProgress) {
- increaseBackoffSetting(syncOperation);
- }
+ increaseBackoffSetting(syncOperation);
// reschedule the sync if so indicated by the syncResult
maybeRescheduleSync(syncResult, syncOperation);
historyMessage = ContentResolver.syncErrorToString(
@@ -2768,7 +2814,6 @@
downstreamActivity = 0;
upstreamActivity = 0;
}
-
setDelayUntilTime(syncOperation, syncResult.delayUntil);
} else {
if (isLoggable) {
@@ -2794,7 +2839,6 @@
stopSyncEvent(activeSyncContext.mHistoryRowId, syncOperation, historyMessage,
upstreamActivity, downstreamActivity, elapsedTime);
-
// Check for full-resync and schedule it after closing off the last sync.
if (info.target_provider) {
if (syncResult != null && syncResult.tooManyDeletions) {
@@ -2833,6 +2877,7 @@
mActiveSyncContexts.remove(activeSyncContext);
mSyncStorageEngine.removeActiveSync(activeSyncContext.mSyncInfo,
activeSyncContext.mSyncOperation.target.userId);
+ removeSyncExpiryMessage(activeSyncContext);
}
/**
diff --git a/services/core/java/com/android/server/content/SyncOperation.java b/services/core/java/com/android/server/content/SyncOperation.java
index 9a4abce..35827cc 100644
--- a/services/core/java/com/android/server/content/SyncOperation.java
+++ b/services/core/java/com/android/server/content/SyncOperation.java
@@ -273,6 +273,14 @@
return extras.getBoolean(ContentResolver.SYNC_EXTRAS_DISALLOW_METERED, false);
}
+ public boolean isManual() {
+ return extras.getBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, false);
+ }
+
+ public boolean isIgnoreSettings() {
+ return extras.getBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_SETTINGS, false);
+ }
+
/** Changed in V3. */
public static String toKey(SyncStorageEngine.EndPoint info, Bundle extras) {
StringBuilder sb = new StringBuilder();
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index 935714c..10a47d8 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -22,6 +22,7 @@
import static android.hardware.hdmi.HdmiControlManager.ONE_TOUCH_RECORD_CEC_DISABLED;
import static android.hardware.hdmi.HdmiControlManager.ONE_TOUCH_RECORD_CHECK_RECORDER_CONNECTION;
import static android.hardware.hdmi.HdmiControlManager.ONE_TOUCH_RECORD_FAIL_TO_RECORD_DISPLAYED_SCREEN;
+import static android.hardware.hdmi.HdmiControlManager.OSD_MESSAGE_ARC_CONNECTED_INVALID_PORT;
import static android.hardware.hdmi.HdmiControlManager.TIMER_RECORDING_RESULT_EXTRA_CEC_DISABLED;
import static android.hardware.hdmi.HdmiControlManager.TIMER_RECORDING_RESULT_EXTRA_CHECK_RECORDER_CONNECTION;
import static android.hardware.hdmi.HdmiControlManager.TIMER_RECORDING_RESULT_EXTRA_FAIL_TO_RECORD_SELECTED_SOURCE;
@@ -29,7 +30,6 @@
import static android.hardware.hdmi.HdmiControlManager.TIMER_RECORDING_TYPE_DIGITAL;
import static android.hardware.hdmi.HdmiControlManager.TIMER_RECORDING_TYPE_EXTERNAL;
-import android.content.Intent;
import android.hardware.hdmi.HdmiControlManager;
import android.hardware.hdmi.HdmiDeviceInfo;
import android.hardware.hdmi.HdmiRecordSources;
@@ -39,7 +39,6 @@
import android.media.AudioSystem;
import android.os.RemoteException;
import android.os.SystemProperties;
-import android.os.UserHandle;
import android.provider.Settings.Global;
import android.util.ArraySet;
import android.util.Slog;
@@ -57,7 +56,6 @@
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
-import java.util.Locale;
/**
* Represent a logical device of type TV residing in Android system.
@@ -70,8 +68,9 @@
@ServiceThreadOnly
private boolean mArcEstablished = false;
- // Whether ARC feature is enabled or not.
- private boolean mArcFeatureEnabled = false;
+ // Whether ARC feature is enabled or not. The default value is true.
+ // TODO: once adding system setting for it, read the value to it.
+ private boolean mArcFeatureEnabled = true;
// Whether System audio mode is activated or not.
// This becomes true only when all system audio sequences are finished.
@@ -642,19 +641,26 @@
// If there is AVR, initiate System Audio Auto initiation action,
// which turns on and off system audio according to last system
// audio setting.
- if (mSystemAudioActivated && getAvrDeviceInfo() != null) {
- addAndStartAction(new SystemAudioAutoInitiationAction(
- HdmiCecLocalDeviceTv.this,
- getAvrDeviceInfo().getLogicalAddress()));
- if (mArcEstablished) {
- startArcAction(true);
- }
+ HdmiDeviceInfo avr = getAvrDeviceInfo();
+ if (avr != null) {
+ onNewAvrAdded(avr);
}
}
});
addAndStartAction(action);
}
+ @ServiceThreadOnly
+ void onNewAvrAdded(HdmiDeviceInfo avr) {
+ assertRunOnServiceThread();
+ if (getSystemAudioModeSetting()) {
+ addAndStartAction(new SystemAudioAutoInitiationAction(this, avr.getLogicalAddress()));
+ }
+ if (isArcFeatureEnabled()) {
+ startArcAction(true);
+ }
+ }
+
// Clear all device info.
@ServiceThreadOnly
private void clearDeviceInfoList() {
@@ -757,6 +763,7 @@
assertRunOnServiceThread();
if (mArcFeatureEnabled != enabled) {
+ mArcFeatureEnabled = enabled;
if (enabled) {
if (!mArcEstablished) {
startArcAction(true);
@@ -766,7 +773,6 @@
startArcAction(false);
}
}
- mArcFeatureEnabled = enabled;
}
}
@@ -777,13 +783,18 @@
}
@ServiceThreadOnly
- private void startArcAction(boolean enabled) {
+ void startArcAction(boolean enabled) {
assertRunOnServiceThread();
HdmiDeviceInfo info = getAvrDeviceInfo();
if (info == null) {
+ Slog.w(TAG, "Failed to start arc action; No AVR device.");
return;
}
- if (!isConnectedToArcPort(info.getPhysicalAddress())) {
+ if (!canStartArcUpdateAction(info.getLogicalAddress(), enabled)) {
+ Slog.w(TAG, "Failed to start arc action; ARC configuration check failed.");
+ if (enabled && !isConnectedToArcPort(info.getPhysicalAddress())) {
+ displayOsd(OSD_MESSAGE_ARC_CONNECTED_INVALID_PORT);
+ }
return;
}
@@ -801,6 +812,10 @@
}
}
+ private boolean isDirectConnectAddress(int physicalAddress) {
+ return (physicalAddress & Constants.ROUTING_PATH_TOP_MASK) == physicalAddress;
+ }
+
void setAudioStatus(boolean mute, int volume) {
synchronized (mLock) {
mSystemAudioMute = mute;
@@ -857,6 +872,15 @@
@ServiceThreadOnly
protected boolean handleInitiateArc(HdmiCecMessage message) {
assertRunOnServiceThread();
+
+ if (!canStartArcUpdateAction(message.getSource(), true)) {
+ mService.maySendFeatureAbortCommand(message, Constants.ABORT_REFUSED);
+ if (!isConnectedToArcPort(message.getSource())) {
+ displayOsd(OSD_MESSAGE_ARC_CONNECTED_INVALID_PORT);
+ }
+ return true;
+ }
+
// In case where <Initiate Arc> is started by <Request ARC Initiation>
// need to clean up RequestArcInitiationAction.
removeAction(RequestArcInitiationAction.class);
@@ -866,10 +890,29 @@
return true;
}
+ private boolean canStartArcUpdateAction(int avrAddress, boolean shouldCheckArcFeatureEnabled) {
+ HdmiDeviceInfo avr = getAvrDeviceInfo();
+ if (avr != null
+ && (avrAddress == avr.getLogicalAddress())
+ && isConnectedToArcPort(avr.getPhysicalAddress())
+ && isDirectConnectAddress(avr.getPhysicalAddress())) {
+ if (shouldCheckArcFeatureEnabled) {
+ return isArcFeatureEnabled();
+ } else {
+ return true;
+ }
+ } else {
+ return false;
+ }
+ }
+
@Override
@ServiceThreadOnly
protected boolean handleTerminateArc(HdmiCecMessage message) {
assertRunOnServiceThread();
+ // In cast of termination, do not check ARC configuration in that AVR device
+ // might be removed already.
+
// In case where <Terminate Arc> is started by <Request ARC Termination>
// need to clean up RequestArcInitiationAction.
removeAction(RequestArcTerminationAction.class);
@@ -1000,7 +1043,7 @@
* Return a list of all {@link HdmiDeviceInfo}.
*
* <p>Declared as package-private. accessed by {@link HdmiControlService} only.
- * This is not thread-safe. For thread safety, call {@link #getSafeExternalInputs} which
+ * This is not thread-safe. For thread safety, call {@link #getSafeExternalInputsLocked} which
* does not include local device.
*/
@ServiceThreadOnly
@@ -1116,7 +1159,7 @@
*
* This is not thread-safe. For thread safety, call {@link #getSafeCecDeviceInfo(int)}.
*
- * @param address logical address of the device to be retrieved
+ * @param logicalAddress logical address of the device to be retrieved
* @return {@link HdmiDeviceInfo} matched with the given {@code logicalAddress}.
* Returns null if no logical address matched
*/
@@ -1388,11 +1431,10 @@
return mService.isPowerStandbyOrTransient();
}
+ @ServiceThreadOnly
void displayOsd(int messageId) {
- Intent intent = new Intent(HdmiControlManager.ACTION_OSD_MESSAGE);
- intent.putExtra(HdmiControlManager.EXTRA_MESSAGE_ID, messageId);
- mService.getContext().sendBroadcastAsUser(intent, UserHandle.ALL,
- HdmiControlService.PERMISSION);
+ assertRunOnServiceThread();
+ mService.displayOsd(messageId);
}
// Seq #54 and #55
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecMessageBuilder.java b/services/core/java/com/android/server/hdmi/HdmiCecMessageBuilder.java
index b53cd45..9a51e3c 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecMessageBuilder.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecMessageBuilder.java
@@ -54,8 +54,8 @@
static HdmiCecMessage buildFeatureAbortCommand(int src, int dest, int originalOpcode,
int reason) {
byte[] params = new byte[] {
- (byte) originalOpcode,
- (byte) reason,
+ (byte) (originalOpcode & 0xFF),
+ (byte) (reason & 0xFF),
};
return buildCommand(src, dest, Constants.MESSAGE_FEATURE_ABORT, params);
}
@@ -110,9 +110,9 @@
// Hdmi CEC uses lower-cased ISO 639-2 (3 letters code).
String normalized = language.toLowerCase();
byte[] params = new byte[] {
- (byte) normalized.charAt(0),
- (byte) normalized.charAt(1),
- (byte) normalized.charAt(2),
+ (byte) (normalized.charAt(0) & 0xFF),
+ (byte) (normalized.charAt(1) & 0xFF),
+ (byte) (normalized.charAt(2) & 0xFF),
};
// <Set Menu Language> is broadcast message.
return buildCommand(src, Constants.ADDR_BROADCAST,
@@ -155,7 +155,7 @@
(byte) ((address >> 8) & 0xFF),
(byte) (address & 0xFF),
// One byte device type
- (byte) deviceType
+ (byte) (deviceType & 0xFF)
};
// <Report Physical Address> is broadcast message.
return buildCommand(src, Constants.ADDR_BROADCAST,
@@ -194,7 +194,7 @@
*/
static HdmiCecMessage buildCecVersion(int src, int dest, int version) {
byte[] params = new byte[] {
- (byte) version
+ (byte) (version & 0xFF)
};
return buildCommand(src, dest, Constants.MESSAGE_CEC_VERSION, params);
}
@@ -332,7 +332,7 @@
*/
static HdmiCecMessage buildReportPowerStatus(int src, int dest, int powerStatus) {
byte[] param = new byte[] {
- (byte) (powerStatus)
+ (byte) (powerStatus & 0xFF)
};
return buildCommand(src, dest, Constants.MESSAGE_REPORT_POWER_STATUS, param);
}
@@ -347,7 +347,7 @@
*/
static HdmiCecMessage buildReportMenuStatus(int src, int dest, int menuStatus) {
byte[] param = new byte[] {
- (byte) (menuStatus)
+ (byte) (menuStatus & 0xFF)
};
return buildCommand(src, dest, Constants.MESSAGE_MENU_STATUS, param);
}
@@ -391,7 +391,7 @@
* @return newly created {@link HdmiCecMessage}
*/
static HdmiCecMessage buildUserControlPressed(int src, int dest, int uiCommand) {
- return buildUserControlPressed(src, dest, new byte[] { (byte) uiCommand });
+ return buildUserControlPressed(src, dest, new byte[] { (byte) (uiCommand & 0xFF) });
}
/**
@@ -594,7 +594,7 @@
private static byte[] physicalAddressToParam(int physicalAddress) {
return new byte[] {
- (byte) (physicalAddress >> 8),
+ (byte) ((physicalAddress >> 8) & 0xFF),
(byte) (physicalAddress & 0xFF)
};
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 3021285..fcccfc0 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -606,7 +606,7 @@
* Whether a device of the specified physical address is connected to ARC enabled port.
*/
boolean isConnectedToArcPort(int physicalAddress) {
- int portId = mPortIdMap.get(physicalAddress);
+ int portId = pathToPortId(physicalAddress);
if (portId != Constants.INVALID_PORT_ID) {
return mPortInfoMap.get(portId).isArcSupported();
}
@@ -1980,4 +1980,13 @@
return mMhlInputChangeEnabled;
}
}
+
+ @ServiceThreadOnly
+ void displayOsd(int messageId) {
+ assertRunOnServiceThread();
+ Intent intent = new Intent(HdmiControlManager.ACTION_OSD_MESSAGE);
+ intent.putExtra(HdmiControlManager.EXTRA_MESSAGE_ID, messageId);
+ getContext().sendBroadcastAsUser(intent, UserHandle.ALL,
+ HdmiControlService.PERMISSION);
+ }
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiLogger.java b/services/core/java/com/android/server/hdmi/HdmiLogger.java
index 93ccfe1..cb72bc1 100644
--- a/services/core/java/com/android/server/hdmi/HdmiLogger.java
+++ b/services/core/java/com/android/server/hdmi/HdmiLogger.java
@@ -16,6 +16,7 @@
package com.android.server.hdmi;
+import android.annotation.Nullable;
import android.os.SystemClock;
import android.util.Pair;
import android.util.Slog;
@@ -47,7 +48,7 @@
long curTime = SystemClock.uptimeMillis();
Pair<Long, Integer> timing = mWarningTimingCache.get(logMessage);
if (shouldLogNow(timing, curTime)) {
- Slog.w(mTag, buildMessage(logMessage, timing, curTime));
+ Slog.w(mTag, buildMessage(logMessage, timing));
mWarningTimingCache.put(logMessage, new Pair<>(curTime, 1));
} else {
increaseLogCount(mWarningTimingCache, logMessage);
@@ -58,16 +59,16 @@
long curTime = SystemClock.uptimeMillis();
Pair<Long, Integer> timing = mErrorTimingCache.get(logMessage);
if (shouldLogNow(timing, curTime)) {
- Slog.e(mTag, buildMessage(logMessage, timing, curTime));
+ Slog.e(mTag, buildMessage(logMessage, timing));
mErrorTimingCache.put(logMessage, new Pair<>(curTime, 1));
} else {
increaseLogCount(mErrorTimingCache, logMessage);
}
}
- private String buildMessage(String message, Pair<Long, Integer> timing, long curTime) {
+ private String buildMessage(String message, @Nullable Pair<Long, Integer> timing) {
return new StringBuilder()
- .append("[").append(timing == null ? curTime : timing.second).append("]:")
+ .append("[").append(timing == null ? 1 : timing.second).append("]:")
.append(message).toString();
}
@@ -78,7 +79,7 @@
}
}
- private boolean shouldLogNow(Pair<Long, Integer> timing, long curTime) {
+ private boolean shouldLogNow(@Nullable Pair<Long, Integer> timing, long curTime) {
return timing == null || curTime - timing.first > ERROR_LOG_DURATTION_MILLIS;
}
}
diff --git a/services/core/java/com/android/server/hdmi/NewDeviceAction.java b/services/core/java/com/android/server/hdmi/NewDeviceAction.java
index a5fdbea..2074085 100644
--- a/services/core/java/com/android/server/hdmi/NewDeviceAction.java
+++ b/services/core/java/com/android/server/hdmi/NewDeviceAction.java
@@ -103,8 +103,8 @@
requestVendorId();
return true;
} else if (opcode == Constants.MESSAGE_FEATURE_ABORT) {
- int requestOpcode = params[1] & 0xFF;
- if (requestOpcode == Constants.MESSAGE_SET_OSD_NAME) {
+ int requestOpcode = params[0] & 0xFF;
+ if (requestOpcode == Constants.MESSAGE_GIVE_OSD_NAME) {
requestVendorId();
return true;
}
@@ -116,8 +116,8 @@
finish();
return true;
} else if (opcode == Constants.MESSAGE_FEATURE_ABORT) {
- int requestOpcode = params[1] & 0xFF;
- if (requestOpcode == Constants.MESSAGE_DEVICE_VENDOR_ID) {
+ int requestOpcode = params[0] & 0xFF;
+ if (requestOpcode == Constants.MESSAGE_GIVE_DEVICE_VENDOR_ID) {
addDeviceInfo();
finish();
return true;
@@ -152,30 +152,19 @@
if (mDisplayName == null) {
mDisplayName = HdmiUtils.getDefaultDeviceName(mDeviceLogicalAddress);
}
- tv().addCecDevice(new HdmiDeviceInfo(
+ HdmiDeviceInfo deviceInfo = new HdmiDeviceInfo(
mDeviceLogicalAddress, mDevicePhysicalAddress,
tv().getPortId(mDevicePhysicalAddress),
HdmiUtils.getTypeFromAddress(mDeviceLogicalAddress),
- mVendorId, mDisplayName));
+ mVendorId, mDisplayName);
+ tv().addCecDevice(deviceInfo);
if (HdmiUtils.getTypeFromAddress(mDeviceLogicalAddress)
== HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM) {
- if (tv().getSystemAudioModeSetting()) {
- addAndStartAction(new SystemAudioAutoInitiationAction(localDevice(),
- mDeviceLogicalAddress));
- }
-
- if (shouldTryArcInitiation()) {
- addAndStartAction(new RequestArcInitiationAction(localDevice(),
- mDeviceLogicalAddress));
- }
+ tv().onNewAvrAdded(deviceInfo);
}
}
- private boolean shouldTryArcInitiation() {
- return tv().isConnectedToArcPort(mDevicePhysicalAddress) && tv().isArcFeatureEnabled();
- }
-
@Override
public void handleTimerEvent(int state) {
if (mState == STATE_NONE || mState != state) {
diff --git a/services/core/java/com/android/server/hdmi/RequestArcAction.java b/services/core/java/com/android/server/hdmi/RequestArcAction.java
index 9c530a3..17c2d6c 100644
--- a/services/core/java/com/android/server/hdmi/RequestArcAction.java
+++ b/services/core/java/com/android/server/hdmi/RequestArcAction.java
@@ -17,7 +17,6 @@
package com.android.server.hdmi;
import android.hardware.hdmi.HdmiDeviceInfo;
-
import android.util.Slog;
/**
@@ -57,11 +56,17 @@
switch (opcode) {
// Handles only <Feature Abort> here and, both <Initiate ARC> and <Terminate ARC>
// are handled in HdmiControlService itself because both can be
- // received wihtout <Request ARC Initiation> or <Request ARC Termination>.
+ // received without <Request ARC Initiation> or <Request ARC Termination>.
case Constants.MESSAGE_FEATURE_ABORT:
- disableArcTransmission();
- finish();
- return true;
+ int originalOpcode = cmd.getParams()[0] & 0xFF;
+ if (originalOpcode == Constants.MESSAGE_REQUEST_ARC_INITIATION
+ || originalOpcode == Constants.MESSAGE_REQUEST_ARC_TERMINATION) {
+ disableArcTransmission();
+ finish();
+ return true;
+ } else {
+ return false;
+ }
default:
Slog.w(TAG, "Unsupported opcode:" + cmd.toString());
}
diff --git a/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java b/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java
index 9f7f98a..c1c6b91 100644
--- a/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java
+++ b/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java
@@ -110,10 +110,14 @@
int opcode = cmd.getOpcode();
if (opcode == Constants.MESSAGE_FEATURE_ABORT) {
- setArcStatus(false);
+ int originalOpcode = cmd.getParams()[0] & 0xFF;
+ if (originalOpcode == Constants.MESSAGE_REPORT_ARC_INITIATED) {
+ setArcStatus(false);
+ finish();
+ return true;
+ }
}
- finish();
- return true;
+ return false;
}
@Override
diff --git a/services/core/java/com/android/server/hdmi/SystemAudioAction.java b/services/core/java/com/android/server/hdmi/SystemAudioAction.java
index 7e45a99..ac2c7b9 100644
--- a/services/core/java/com/android/server/hdmi/SystemAudioAction.java
+++ b/services/core/java/com/android/server/hdmi/SystemAudioAction.java
@@ -127,7 +127,8 @@
switch (mState) {
case STATE_WAIT_FOR_SET_SYSTEM_AUDIO_MODE:
if (cmd.getOpcode() == Constants.MESSAGE_FEATURE_ABORT
- && cmd.getParams()[0] == Constants.MESSAGE_SYSTEM_AUDIO_MODE_REQUEST) {
+ && (cmd.getParams()[0] & 0xFF)
+ == Constants.MESSAGE_SYSTEM_AUDIO_MODE_REQUEST) {
setSystemAudioMode(false);
finishWithCallback(HdmiControlManager.RESULT_EXCEPTION);
return true;
diff --git a/services/core/java/com/android/server/hdmi/VolumeControlAction.java b/services/core/java/com/android/server/hdmi/VolumeControlAction.java
index 01c6f3e..ddc267a 100644
--- a/services/core/java/com/android/server/hdmi/VolumeControlAction.java
+++ b/services/core/java/com/android/server/hdmi/VolumeControlAction.java
@@ -156,10 +156,14 @@
handleReportAudioStatus(cmd);
return true;
case Constants.MESSAGE_FEATURE_ABORT:
- // TODO: handle feature abort.
- finish();
- return true;
- default:
+ int originalOpcode = cmd.getParams()[0] & 0xFF;
+ if (originalOpcode == Constants.MESSAGE_USER_CONTROL_PRESSED
+ || originalOpcode == Constants.MESSAGE_USER_CONTROL_RELEASED) {
+ // TODO: handle feature abort.
+ finish();
+ return true;
+ }
+ default: // fall through
return false;
}
}
diff --git a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
index 69d1dc9..8ec9b254 100644
--- a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
+++ b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
@@ -111,7 +111,6 @@
@Override
public void binderDied() {
synchronized (mLock) {
- unlinkDeathRecipientLocked(callback);
removeCallback(callback);
}
}
@@ -125,7 +124,7 @@
private void removeCallback(IMediaProjectionWatcherCallback callback) {
synchronized (mLock) {
unlinkDeathRecipientLocked(callback);
- removeCallback(callback);
+ mCallbackDelegate.remove(callback);
}
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index c390f9b..6fd4eb7 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -1277,21 +1277,29 @@
* should be used.
*
* @param token The binder for the listener, to check that the caller is allowed
+ * @param keys An array of notification keys to fetch, or null to fetch everything
* @returns The return value will contain the notifications specified in keys, in that
* order, or if keys is null, all the notifications, in natural order.
*/
@Override
public ParceledListSlice<StatusBarNotification> getActiveNotificationsFromListener(
- INotificationListener token) {
+ INotificationListener token, String[] keys) {
synchronized (mNotificationList) {
final ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token);
final ArrayList<StatusBarNotification> list
= new ArrayList<StatusBarNotification>();
- final int N = mNotificationList.size();
+ final boolean getKeys = keys != null;
+ final int N = getKeys ? keys.length : mNotificationList.size();
+ list.ensureCapacity(N);
for (int i=0; i<N; i++) {
- StatusBarNotification sbn = mNotificationList.get(i).sbn;
- if (isVisibleToListener(sbn, info)) {
- list.add(sbn);
+ final NotificationRecord r = getKeys
+ ? mNotificationsByKey.get(keys[i])
+ : mNotificationList.get(i);
+ if (r != null) {
+ StatusBarNotification sbn = r.sbn;
+ if (isVisibleToListener(sbn, info)) {
+ list.add(sbn);
+ }
}
}
return new ParceledListSlice<StatusBarNotification>(list);
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index f6ec86d..aabb8f7 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -19,7 +19,6 @@
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Bitmap;
-import android.graphics.Point;
import android.graphics.Rect;
import android.os.Debug;
import android.os.Handler;
@@ -46,7 +45,7 @@
import static com.android.internal.R.styleable.WindowAnimation_activityCloseExitAnimation;
import static com.android.internal.R.styleable.WindowAnimation_taskOpenEnterAnimation;
import static com.android.internal.R.styleable.WindowAnimation_taskOpenExitAnimation;
-import static com.android.internal.R.styleable.WindowAnimation_launchTaskBehindBackgroundAnimation;
+import static com.android.internal.R.styleable.WindowAnimation_launchTaskBehindTargetAnimation;
import static com.android.internal.R.styleable.WindowAnimation_launchTaskBehindSourceAnimation;
import static com.android.internal.R.styleable.WindowAnimation_taskCloseEnterAnimation;
import static com.android.internal.R.styleable.WindowAnimation_taskCloseExitAnimation;
@@ -111,11 +110,14 @@
* The new window will show briefly and then be gone. */
public static final int TRANSIT_TASK_OPEN_BEHIND = 16;
+ /** Fraction of animation at which the recents thumbnail stays completely transparent */
+ private static final float RECENTS_THUMBNAIL_FADEIN_FRACTION = 0.7f;
/** Fraction of animation at which the recents thumbnail becomes completely transparent */
- private static final float RECENTS_THUMBNAIL_FADEOUT_FRACTION = 0.25f;
+ private static final float RECENTS_THUMBNAIL_FADEOUT_FRACTION = 0.3f;
private static final int DEFAULT_APP_TRANSITION_DURATION = 250;
- private static final int THUMBNAIL_APP_TRANSITION_DURATION = 275;
+ private static final int THUMBNAIL_APP_TRANSITION_DURATION = 300;
+ private static final int THUMBNAIL_APP_TRANSITION_ALPHA_DURATION = 325;
private final Context mContext;
private final Handler mH;
@@ -127,6 +129,8 @@
private static final int NEXT_TRANSIT_TYPE_SCALE_UP = 2;
private static final int NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP = 3;
private static final int NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN = 4;
+ private static final int NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP = 5;
+ private static final int NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN = 6;
private int mNextAppTransitionType = NEXT_TRANSIT_TYPE_NONE;
// These are the possible states for the enter/exit activities during a thumbnail transition
@@ -146,6 +150,7 @@
private int mNextAppTransitionStartY;
private int mNextAppTransitionStartWidth;
private int mNextAppTransitionStartHeight;
+ private Rect mNextAppTransitionInsets = new Rect();
private Rect mTmpFromClipRect = new Rect();
private Rect mTmpToClipRect = new Rect();
@@ -158,7 +163,8 @@
private final int mConfigShortAnimTime;
private final Interpolator mDecelerateInterpolator;
- private final Interpolator mThumbnailFadeoutInterpolator;
+ private final Interpolator mThumbnailFadeInInterpolator;
+ private final Interpolator mThumbnailFadeOutInterpolator;
private final Interpolator mThumbnailFastOutSlowInInterpolator;
private int mCurrentUserId = 0;
@@ -172,14 +178,25 @@
com.android.internal.R.interpolator.decelerate_cubic);
mThumbnailFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
com.android.internal.R.interpolator.fast_out_slow_in);
- mThumbnailFadeoutInterpolator = new Interpolator() {
+ mThumbnailFadeInInterpolator = new Interpolator() {
+ @Override
+ public float getInterpolation(float input) {
+ // Linear response for first fraction, then complete after that.
+ if (input < RECENTS_THUMBNAIL_FADEIN_FRACTION) {
+ return 0f;
+ }
+ return (input - RECENTS_THUMBNAIL_FADEIN_FRACTION) /
+ (1f - RECENTS_THUMBNAIL_FADEIN_FRACTION);
+ }
+ };
+ mThumbnailFadeOutInterpolator = new Interpolator() {
@Override
public float getInterpolation(float input) {
// Linear response for first fraction, then complete after that.
if (input < RECENTS_THUMBNAIL_FADEOUT_FRACTION) {
return input / RECENTS_THUMBNAIL_FADEOUT_FRACTION;
}
- return 1.0f;
+ return 1f;
}
};
}
@@ -233,9 +250,23 @@
return mNextAppTransitionThumbnail;
}
- void getStartingPoint(Point outPoint) {
- outPoint.x = mNextAppTransitionStartX;
- outPoint.y = mNextAppTransitionStartY;
+ /** Returns whether the next thumbnail transition is aspect scaled up. */
+ boolean isNextThumbnailTransitionAspectScaled() {
+ return mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP ||
+ mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN;
+ }
+
+ /** Returns whether the next thumbnail transition is scaling up. */
+ boolean isNextThumbnailTransitionScaleUp() {
+ return mNextAppTransitionScaleUp;
+ }
+
+ int getStartingX() {
+ return mNextAppTransitionStartX;
+ }
+
+ int getStartingY() {
+ return mNextAppTransitionStartY;
}
void prepare() {
@@ -372,7 +403,7 @@
scale.setInterpolator(mDecelerateInterpolator);
Animation alpha = new AlphaAnimation(0, 1);
- alpha.setInterpolator(mThumbnailFadeoutInterpolator);
+ alpha.setInterpolator(mThumbnailFadeOutInterpolator);
AnimationSet set = new AnimationSet(false);
set.addAnimation(scale);
@@ -417,7 +448,9 @@
*/
Animation prepareThumbnailAnimationWithDuration(Animation a, int appWidth, int appHeight,
int duration, Interpolator interpolator) {
- a.setDuration(duration);
+ if (duration > 0) {
+ a.setDuration(duration);
+ }
a.setFillAfter(true);
a.setInterpolator(interpolator);
a.initialize(appWidth, appHeight, appWidth, appHeight);
@@ -468,50 +501,73 @@
* This animation runs for the thumbnail that gets cross faded with the enter/exit activity
* when a thumbnail is specified with the activity options.
*/
- Animation createThumbnailScaleAnimationLocked(int appWidth, int appHeight, int transit) {
+ Animation createThumbnailAspectScaleAnimationLocked(int appWidth, int appHeight,
+ int deviceWidth, int transit) {
Animation a;
final int thumbWidthI = mNextAppTransitionThumbnail.getWidth();
final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1;
final int thumbHeightI = mNextAppTransitionThumbnail.getHeight();
final float thumbHeight = thumbHeightI > 0 ? thumbHeightI : 1;
+ float scaleW = deviceWidth / thumbWidth;
+ float unscaledWidth = deviceWidth;
+ float unscaledHeight = thumbHeight * scaleW;
+ float unscaledStartY = mNextAppTransitionStartY - (unscaledHeight - thumbHeight) / 2f;
if (mNextAppTransitionScaleUp) {
- // Animation for the thumbnail zooming from its initial size to the full screen
- float scaleW = appWidth / thumbWidth;
- float scaleH = appHeight / thumbHeight;
- Animation scale = new ScaleAnimation(1, scaleW, 1, scaleH,
- computePivot(mNextAppTransitionStartX, 1 / scaleW),
- computePivot(mNextAppTransitionStartY, 1 / scaleH));
- scale.setInterpolator(mDecelerateInterpolator);
-
+ // Animation up from the thumbnail to the full screen
+ Animation scale = new ScaleAnimation(1f, scaleW, 1f, scaleW,
+ mNextAppTransitionStartX + (thumbWidth / 2f),
+ mNextAppTransitionStartY + (thumbHeight / 2f));
+ scale.setInterpolator(mThumbnailFastOutSlowInInterpolator);
+ scale.setDuration(THUMBNAIL_APP_TRANSITION_DURATION);
Animation alpha = new AlphaAnimation(1, 0);
- alpha.setInterpolator(mThumbnailFadeoutInterpolator);
+ alpha.setInterpolator(mThumbnailFadeOutInterpolator);
+ alpha.setDuration(THUMBNAIL_APP_TRANSITION_ALPHA_DURATION);
+ Animation translate = new TranslateAnimation(0, 0, 0, -unscaledStartY +
+ mNextAppTransitionInsets.top);
+ translate.setInterpolator(mThumbnailFastOutSlowInInterpolator);
+ translate.setDuration(THUMBNAIL_APP_TRANSITION_DURATION);
// This AnimationSet uses the Interpolators assigned above.
AnimationSet set = new AnimationSet(false);
set.addAnimation(scale);
set.addAnimation(alpha);
+ set.addAnimation(translate);
a = set;
} else {
- // Animation for the thumbnail zooming down from the full screen to its final size
- float scaleW = appWidth / thumbWidth;
- float scaleH = appHeight / thumbHeight;
- a = new ScaleAnimation(scaleW, 1, scaleH, 1,
- computePivot(mNextAppTransitionStartX, 1 / scaleW),
- computePivot(mNextAppTransitionStartY, 1 / scaleH));
- }
+ // Animation down from the full screen to the thumbnail
+ Animation scale = new ScaleAnimation(scaleW, 1f, scaleW, 1f,
+ mNextAppTransitionStartX + (thumbWidth / 2f),
+ mNextAppTransitionStartY + (thumbHeight / 2f));
+ scale.setInterpolator(mThumbnailFastOutSlowInInterpolator);
+ scale.setDuration(THUMBNAIL_APP_TRANSITION_DURATION);
+ Animation alpha = new AlphaAnimation(0f, 1f);
+ alpha.setInterpolator(mThumbnailFadeInInterpolator);
+ alpha.setDuration(THUMBNAIL_APP_TRANSITION_ALPHA_DURATION);
+ Animation translate = new TranslateAnimation(0, 0, -unscaledStartY +
+ mNextAppTransitionInsets.top, 0);
+ translate.setInterpolator(mThumbnailFastOutSlowInInterpolator);
+ translate.setDuration(THUMBNAIL_APP_TRANSITION_DURATION);
- return prepareThumbnailAnimation(a, appWidth, appHeight, transit);
+ // This AnimationSet uses the Interpolators assigned above.
+ AnimationSet set = new AnimationSet(false);
+ set.addAnimation(scale);
+ set.addAnimation(alpha);
+ set.addAnimation(translate);
+ a = set;
+
+ }
+ return prepareThumbnailAnimationWithDuration(a, appWidth, appHeight, 0,
+ mThumbnailFastOutSlowInInterpolator);
}
/**
* This alternate animation is created when we are doing a thumbnail transition, for the
* activity that is leaving, and the activity that is entering.
*/
- Animation createAlternateThumbnailEnterExitAnimationLocked(int thumbTransitState, int appWidth,
- int appHeight, int orientation, int transit,
- Rect containingFrame, Rect contentInsets,
- boolean isFullScreen) {
+ Animation createAspectScaledThumbnailEnterExitAnimationLocked(int thumbTransitState,
+ int appWidth, int appHeight, int orientation, int transit, Rect containingFrame,
+ Rect contentInsets, boolean isFullScreen) {
Animation a;
final int thumbWidthI = mNextAppTransitionThumbnail.getWidth();
final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1;
@@ -524,7 +580,7 @@
switch (thumbTransitState) {
case THUMBNAIL_TRANSITION_ENTER_SCALE_UP: {
- // Entering app scales up with the thumbnail
+ // App window scaling up to become full screen
if (orientation == Configuration.ORIENTATION_PORTRAIT) {
// In portrait, we scale the width and clip to the top/left square
scale = thumbWidth / appWidth;
@@ -550,16 +606,15 @@
mTmpFromClipRect.right = (mTmpFromClipRect.left + unscaledThumbWidth);
mTmpToClipRect.set(containingFrame);
}
+ mNextAppTransitionInsets.set(contentInsets);
Animation scaleAnim = new ScaleAnimation(scale, 1, scale, 1,
computePivot(mNextAppTransitionStartX, scale),
computePivot(mNextAppTransitionStartY, scale));
- Animation alphaAnim = new AlphaAnimation(1, 1);
Animation clipAnim = new ClipRectAnimation(mTmpFromClipRect, mTmpToClipRect);
Animation translateAnim = new TranslateAnimation(0, 0, -scaledTopDecor, 0);
AnimationSet set = new AnimationSet(true);
- set.addAnimation(alphaAnim);
set.addAnimation(clipAnim);
set.addAnimation(scaleAnim);
set.addAnimation(translateAnim);
@@ -567,26 +622,29 @@
break;
}
case THUMBNAIL_TRANSITION_EXIT_SCALE_UP: {
- // Exiting app while the thumbnail is scaling up should fade
+ // Previous app window during the scale up
if (transit == TRANSIT_WALLPAPER_INTRA_OPEN) {
- // Fade out while bringing up selected activity. This keeps the
- // current activity from showing through a launching wallpaper
+ // Fade out the source activity if we are animating to a wallpaper
// activity.
a = new AlphaAnimation(1, 0);
} else {
- // noop animation
a = new AlphaAnimation(1, 1);
}
break;
}
case THUMBNAIL_TRANSITION_ENTER_SCALE_DOWN: {
- // Entering the other app, it should just be visible while we scale the thumbnail
- // down above it
- a = new AlphaAnimation(1, 1);
+ // Target app window during the scale down
+ if (transit == TRANSIT_WALLPAPER_INTRA_OPEN) {
+ // Fade in the destination activity if we are animating from a wallpaper
+ // activity.
+ a = new AlphaAnimation(0, 1);
+ } else {
+ a = new AlphaAnimation(1, 1);
+ }
break;
}
case THUMBNAIL_TRANSITION_EXIT_SCALE_DOWN: {
- // Exiting the current app, the app should scale down with the thumbnail
+ // App window scaling down from full screen
if (orientation == Configuration.ORIENTATION_PORTRAIT) {
// In portrait, we scale the width and clip to the top/left square
scale = thumbWidth / appWidth;
@@ -612,16 +670,15 @@
}
mTmpToClipRect.right = (mTmpToClipRect.left + unscaledThumbWidth);
}
+ mNextAppTransitionInsets.set(contentInsets);
Animation scaleAnim = new ScaleAnimation(1, scale, 1, scale,
computePivot(mNextAppTransitionStartX, scale),
computePivot(mNextAppTransitionStartY, scale));
- Animation alphaAnim = new AlphaAnimation(1, 1);
Animation clipAnim = new ClipRectAnimation(mTmpFromClipRect, mTmpToClipRect);
Animation translateAnim = new TranslateAnimation(0, 0, 0, -scaledTopDecor);
AnimationSet set = new AnimationSet(true);
- set.addAnimation(alphaAnim);
set.addAnimation(clipAnim);
set.addAnimation(scaleAnim);
set.addAnimation(translateAnim);
@@ -639,6 +696,46 @@
}
/**
+ * This animation runs for the thumbnail that gets cross faded with the enter/exit activity
+ * when a thumbnail is specified with the activity options.
+ */
+ Animation createThumbnailScaleAnimationLocked(int appWidth, int appHeight, int transit) {
+ Animation a;
+ final int thumbWidthI = mNextAppTransitionThumbnail.getWidth();
+ final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1;
+ final int thumbHeightI = mNextAppTransitionThumbnail.getHeight();
+ final float thumbHeight = thumbHeightI > 0 ? thumbHeightI : 1;
+
+ if (mNextAppTransitionScaleUp) {
+ // Animation for the thumbnail zooming from its initial size to the full screen
+ float scaleW = appWidth / thumbWidth;
+ float scaleH = appHeight / thumbHeight;
+ Animation scale = new ScaleAnimation(1, scaleW, 1, scaleH,
+ computePivot(mNextAppTransitionStartX, 1 / scaleW),
+ computePivot(mNextAppTransitionStartY, 1 / scaleH));
+ scale.setInterpolator(mDecelerateInterpolator);
+
+ Animation alpha = new AlphaAnimation(1, 0);
+ alpha.setInterpolator(mThumbnailFadeOutInterpolator);
+
+ // This AnimationSet uses the Interpolators assigned above.
+ AnimationSet set = new AnimationSet(false);
+ set.addAnimation(scale);
+ set.addAnimation(alpha);
+ a = set;
+ } else {
+ // Animation for the thumbnail zooming down from the full screen to its final size
+ float scaleW = appWidth / thumbWidth;
+ float scaleH = appHeight / thumbHeight;
+ a = new ScaleAnimation(scaleW, 1, scaleH, 1,
+ computePivot(mNextAppTransitionStartX, 1 / scaleW),
+ computePivot(mNextAppTransitionStartY, 1 / scaleH));
+ }
+
+ return prepareThumbnailAnimation(a, appWidth, appHeight, transit);
+ }
+
+ /**
* This animation is created when we are doing a thumbnail transition, for the activity that is
* leaving, and the activity that is entering.
*/
@@ -747,12 +844,26 @@
mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN) {
mNextAppTransitionScaleUp =
(mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP);
- a = createAlternateThumbnailEnterExitAnimationLocked(
+ a = createThumbnailEnterExitAnimationLocked(getThumbnailTransitionState(enter),
+ appWidth, appHeight, transit);
+ if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
+ String animName = mNextAppTransitionScaleUp ?
+ "ANIM_THUMBNAIL_SCALE_UP" : "ANIM_THUMBNAIL_SCALE_DOWN";
+ Slog.v(TAG, "applyAnimation:"
+ + " anim=" + a + " nextAppTransition=" + animName
+ + " transit=" + transit + " isEntrance=" + enter
+ + " Callers=" + Debug.getCallers(3));
+ }
+ } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP ||
+ mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN) {
+ mNextAppTransitionScaleUp =
+ (mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP);
+ a = createAspectScaledThumbnailEnterExitAnimationLocked(
getThumbnailTransitionState(enter), appWidth, appHeight, orientation,
transit, containingFrame, contentInsets, isFullScreen);
if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
String animName = mNextAppTransitionScaleUp ?
- "ANIM_THUMBNAIL_SCALE_UP" : "ANIM_THUMBNAIL_SCALE_DOWN";
+ "ANIM_THUMBNAIL_ASPECT_SCALE_UP" : "ANIM_THUMBNAIL_ASPECT_SCALE_DOWN";
Slog.v(TAG, "applyAnimation:"
+ " anim=" + a + " nextAppTransition=" + animName
+ " transit=" + transit + " isEntrance=" + enter
@@ -814,7 +925,7 @@
case TRANSIT_TASK_OPEN_BEHIND:
animAttr = enter
? WindowAnimation_launchTaskBehindSourceAnimation
- : WindowAnimation_launchTaskBehindBackgroundAnimation;
+ : WindowAnimation_launchTaskBehindTargetAnimation;
}
a = animAttr != 0 ? loadAnimationAttr(lp, animAttr) : null;
if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG,
@@ -881,6 +992,23 @@
}
}
+ void overridePendingAppTransitionAspectScaledThumb(Bitmap srcThumb, int startX, int startY,
+ IRemoteCallback startedCallback, boolean scaleUp) {
+ if (isTransitionSet()) {
+ mNextAppTransitionType = scaleUp ? NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP
+ : NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN;
+ mNextAppTransitionPackage = null;
+ mNextAppTransitionThumbnail = srcThumb;
+ mNextAppTransitionScaleUp = scaleUp;
+ mNextAppTransitionStartX = startX;
+ mNextAppTransitionStartY = startY;
+ postAnimationCallback();
+ mNextAppTransitionCallback = startedCallback;
+ } else {
+ postAnimationCallback();
+ }
+ }
+
@Override
public String toString() {
return "mNextAppTransition=0x" + Integer.toHexString(mNextAppTransition);
@@ -966,6 +1094,10 @@
return "NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP";
case NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN:
return "NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN";
+ case NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP:
+ return "NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP";
+ case NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN:
+ return "NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN";
default:
return "unknown type=" + mNextAppTransitionType;
}
@@ -998,6 +1130,8 @@
break;
case NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP:
case NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN:
+ case NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP:
+ case NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN:
pw.print(" mNextAppTransitionThumbnail=");
pw.print(mNextAppTransitionThumbnail);
pw.print(" mNextAppTransitionStartX=");
diff --git a/services/core/java/com/android/server/wm/AppWindowAnimator.java b/services/core/java/com/android/server/wm/AppWindowAnimator.java
index 5b05d53..ef74205 100644
--- a/services/core/java/com/android/server/wm/AppWindowAnimator.java
+++ b/services/core/java/com/android/server/wm/AppWindowAnimator.java
@@ -64,8 +64,17 @@
int thumbnailX;
int thumbnailY;
int thumbnailLayer;
+ int thumbnailForceAboveLayer;
Animation thumbnailAnimation;
final Transformation thumbnailTransformation = new Transformation();
+ // This flag indicates that the destruction of the thumbnail surface is synchronized with
+ // another animation, so do not pre-emptively destroy the thumbnail surface when the animation
+ // completes
+ boolean deferThumbnailDestruction;
+ // This is the thumbnail surface that has been bestowed upon this animator, and when the
+ // surface for this animator's animation is complete, we will destroy the thumbnail surface
+ // as well. Do not animate or do anything with this surface.
+ SurfaceControl deferredThumbnail;
/** WindowStateAnimator from mAppAnimator.allAppWindows as of last performLayout */
ArrayList<WindowStateAnimator> mAllAppWinAnimators = new ArrayList<WindowStateAnimator>();
@@ -121,7 +130,9 @@
animation = null;
animating = true;
}
- clearThumbnail();
+ if (!deferThumbnailDestruction) {
+ clearThumbnail();
+ }
if (mAppToken.deferClearAllDrawn) {
mAppToken.allDrawn = false;
mAppToken.deferClearAllDrawn = false;
@@ -135,6 +146,13 @@
}
}
+ public void clearDeferredThumbnail() {
+ if (deferredThumbnail != null) {
+ deferredThumbnail.destroy();
+ deferredThumbnail = null;
+ }
+ }
+
void updateLayers() {
final int N = mAppToken.allAppWindows.size();
final int adj = animLayerAdjustment;
@@ -184,10 +202,14 @@
+ "][" + tmpFloats[Matrix.MSKEW_X]
+ "," + tmpFloats[Matrix.MSCALE_Y] + "]", null);
thumbnail.setAlpha(thumbnailTransformation.getAlpha());
- // The thumbnail is layered below the window immediately above this
- // token's anim layer.
- thumbnail.setLayer(thumbnailLayer + WindowManagerService.WINDOW_LAYER_MULTIPLIER
- - WindowManagerService.LAYER_OFFSET_THUMBNAIL);
+ if (thumbnailForceAboveLayer > 0) {
+ thumbnail.setLayer(thumbnailForceAboveLayer + 1);
+ } else {
+ // The thumbnail is layered below the window immediately above this
+ // token's anim layer.
+ thumbnail.setLayer(thumbnailLayer + WindowManagerService.WINDOW_LAYER_MULTIPLIER
+ - WindowManagerService.LAYER_OFFSET_THUMBNAIL);
+ }
thumbnail.setMatrix(tmpFloats[Matrix.MSCALE_X], tmpFloats[Matrix.MSKEW_Y],
tmpFloats[Matrix.MSKEW_X], tmpFloats[Matrix.MSCALE_Y]);
}
@@ -202,7 +224,9 @@
TAG, "Stepped animation in " + mAppToken + ": more=" + more + ", xform=" + transformation);
if (!more) {
animation = null;
- clearThumbnail();
+ if (!deferThumbnailDestruction) {
+ clearThumbnail();
+ }
if (WindowManagerService.DEBUG_ANIM) Slog.v(
TAG, "Finished animation in " + mAppToken + " @ " + currentTime);
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 32f3707..e144bde 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -95,7 +95,6 @@
import android.provider.Settings;
import android.util.DisplayMetrics;
import android.util.EventLog;
-import android.util.FloatMath;
import android.util.Log;
import android.util.SparseArray;
import android.util.Pair;
@@ -4038,6 +4037,15 @@
}
@Override
+ public void overridePendingAppTransitionAspectScaledThumb(Bitmap srcThumb, int startX,
+ int startY, IRemoteCallback startedCallback, boolean scaleUp) {
+ synchronized(mWindowMap) {
+ mAppTransition.overridePendingAppTransitionAspectScaledThumb(srcThumb, startX,
+ startY, startedCallback, scaleUp);
+ }
+ }
+
+ @Override
public void executeAppTransition() {
if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
"executeAppTransition()")) {
@@ -8893,7 +8901,9 @@
}
AppWindowToken topOpeningApp = null;
+ AppWindowToken topClosingApp = null;
int topOpeningLayer = 0;
+ int topClosingLayer = 0;
NN = mOpeningApps.size();
for (i=0; i<NN; i++) {
@@ -8901,8 +8911,8 @@
final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now opening app" + wtoken);
appAnimator.clearThumbnail();
- wtoken.inPendingTransaction = false;
appAnimator.animation = null;
+ wtoken.inPendingTransaction = false;
setTokenVisibilityLocked(wtoken, animLp, true, transit, false, voiceInteraction);
wtoken.updateReportedVisibilityLocked();
wtoken.waitingToShow = false;
@@ -8931,10 +8941,11 @@
NN = mClosingApps.size();
for (i=0; i<NN; i++) {
AppWindowToken wtoken = mClosingApps.valueAt(i);
+ final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now closing app " + wtoken);
- wtoken.mAppAnimator.clearThumbnail();
+ appAnimator.clearThumbnail();
+ appAnimator.animation = null;
wtoken.inPendingTransaction = false;
- wtoken.mAppAnimator.animation = null;
setTokenVisibilityLocked(wtoken, animLp, false, transit, false, voiceInteraction);
wtoken.updateReportedVisibilityLocked();
wtoken.waitingToHide = false;
@@ -8943,14 +8954,30 @@
// gotten drawn.
wtoken.allDrawn = true;
wtoken.deferClearAllDrawn = false;
+
+ if (animLp != null) {
+ int layer = -1;
+ for (int j=0; j<wtoken.windows.size(); j++) {
+ WindowState win = wtoken.windows.get(j);
+ if (win.mWinAnimator.mAnimLayer > layer) {
+ layer = win.mWinAnimator.mAnimLayer;
+ }
+ }
+ if (topClosingApp == null || layer > topClosingLayer) {
+ topClosingApp = wtoken;
+ topClosingLayer = layer;
+ }
+ }
}
- boolean useAlternateThumbnailAnimation = true;
- AppWindowAnimator appAnimator =
- topOpeningApp == null ? null : topOpeningApp.mAppAnimator;
+ AppWindowAnimator openingAppAnimator = (topOpeningApp == null) ? null :
+ topOpeningApp.mAppAnimator;
+ AppWindowAnimator closingAppAnimator = (topClosingApp == null) ? null :
+ topClosingApp.mAppAnimator;
Bitmap nextAppTransitionThumbnail = mAppTransition.getNextAppTransitionThumbnail();
- if (!useAlternateThumbnailAnimation && nextAppTransitionThumbnail != null
- && appAnimator != null && appAnimator.animation != null) {
+ if (nextAppTransitionThumbnail != null
+ && openingAppAnimator != null && openingAppAnimator.animation != null &&
+ nextAppTransitionThumbnail.getConfig() != Config.ALPHA_8) {
// This thumbnail animation is very special, we need to have
// an extra surface with the thumbnail included with the animation.
Rect dirty = new Rect(0, 0, nextAppTransitionThumbnail.getWidth(),
@@ -8959,34 +8986,61 @@
// TODO(multi-display): support other displays
final DisplayContent displayContent = getDefaultDisplayContentLocked();
final Display display = displayContent.getDisplay();
+ final DisplayInfo displayInfo = displayContent.getDisplayInfo();
+
+ // Create a new surface for the thumbnail
SurfaceControl surfaceControl = new SurfaceControl(mFxSession,
- "thumbnail anim",
- dirty.width(), dirty.height(),
+ "thumbnail anim", dirty.width(), dirty.height(),
PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
surfaceControl.setLayerStack(display.getLayerStack());
- appAnimator.thumbnail = surfaceControl;
- if (SHOW_TRANSACTIONS) Slog.i(TAG, " THUMBNAIL " + surfaceControl + ": CREATE");
+ if (SHOW_TRANSACTIONS) {
+ Slog.i(TAG, " THUMBNAIL " + surfaceControl + ": CREATE");
+ }
+
+ // Draw the thumbnail onto the surface
Surface drawSurface = new Surface();
drawSurface.copyFrom(surfaceControl);
Canvas c = drawSurface.lockCanvas(dirty);
c.drawBitmap(nextAppTransitionThumbnail, 0, 0, null);
drawSurface.unlockCanvasAndPost(c);
drawSurface.release();
- appAnimator.thumbnailLayer = topOpeningLayer;
- DisplayInfo displayInfo = getDefaultDisplayInfoLocked();
- Animation anim = mAppTransition.createThumbnailScaleAnimationLocked(
- displayInfo.appWidth, displayInfo.appHeight, transit);
- appAnimator.thumbnailAnimation = anim;
+
+ // Get the thumbnail animation
+ Animation anim;
+ if (mAppTransition.isNextThumbnailTransitionAspectScaled()) {
+ // For the new aspect-scaled transition, we want it to always show
+ // above the animating opening/closing window, and we want to
+ // synchronize its thumbnail surface with the surface for the
+ // open/close animation (only on the way down)
+ anim = mAppTransition.createThumbnailAspectScaleAnimationLocked(
+ displayInfo.appWidth, displayInfo.appHeight,
+ displayInfo.logicalWidth, transit);
+ openingAppAnimator.thumbnailForceAboveLayer = Math.max(topOpeningLayer,
+ topClosingLayer);
+ openingAppAnimator.deferThumbnailDestruction =
+ !mAppTransition.isNextThumbnailTransitionScaleUp();
+ if (openingAppAnimator.deferThumbnailDestruction) {
+ if (closingAppAnimator != null &&
+ closingAppAnimator.animation != null) {
+ closingAppAnimator.deferredThumbnail = surfaceControl;
+ }
+ }
+ } else {
+ anim = mAppTransition.createThumbnailScaleAnimationLocked(
+ displayInfo.appWidth, displayInfo.appHeight, transit);
+ }
anim.restrictDuration(MAX_ANIMATION_DURATION);
anim.scaleCurrentDuration(getTransitionAnimationScaleLocked());
- Point p = new Point();
- mAppTransition.getStartingPoint(p);
- appAnimator.thumbnailX = p.x;
- appAnimator.thumbnailY = p.y;
+
+ openingAppAnimator.thumbnail = surfaceControl;
+ openingAppAnimator.thumbnailLayer = topOpeningLayer;
+ openingAppAnimator.thumbnailAnimation = anim;
+ openingAppAnimator.thumbnailX = mAppTransition.getStartingX();
+ openingAppAnimator.thumbnailY = mAppTransition.getStartingY();
} catch (OutOfResourcesException e) {
Slog.e(TAG, "Can't allocate thumbnail/Canvas surface w=" + dirty.width()
+ " h=" + dirty.height(), e);
- appAnimator.clearThumbnail();
+ openingAppAnimator.clearThumbnail();
}
}
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 7bf090a..38433ae 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -902,6 +902,11 @@
mWin.mHasSurface = false;
mDrawState = NO_SURFACE;
}
+
+ // Destroy any deferred thumbnail surfaces
+ if (mAppAnimator != null) {
+ mAppAnimator.clearDeferredThumbnail();
+ }
}
void destroyDeferredSurfaceLocked() {
diff --git a/telecomm/java/android/telecomm/Conference.java b/telecomm/java/android/telecomm/Conference.java
index 44accb7..879ff66 100644
--- a/telecomm/java/android/telecomm/Conference.java
+++ b/telecomm/java/android/telecomm/Conference.java
@@ -18,9 +18,7 @@
import android.telephony.DisconnectCause;
-import java.util.ArrayList;
import java.util.Collections;
-import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -43,7 +41,7 @@
private final Set<Listener> mListeners = new CopyOnWriteArraySet<>();
private final List<Connection> mChildConnections = new CopyOnWriteArrayList<>();
- private final List<Connection> mUnmodifiableChildConnection =
+ private final List<Connection> mUnmodifiableChildConnections =
Collections.unmodifiableList(mChildConnections);
private PhoneAccountHandle mPhoneAccount;
@@ -61,7 +59,7 @@
}
public final List<Connection> getConnections() {
- return mUnmodifiableChildConnection;
+ return mUnmodifiableChildConnections;
}
public final int getState() {
@@ -125,7 +123,7 @@
}
/**
- * Sets the cabilities of a conference.
+ * Sets the capabilities of a conference.
*/
public final void setCapabilities(int capabilities) {
if (capabilities != mCapabilities) {
diff --git a/telecomm/java/android/telecomm/ConnectionService.java b/telecomm/java/android/telecomm/ConnectionService.java
index b77bb18..4696815 100644
--- a/telecomm/java/android/telecomm/ConnectionService.java
+++ b/telecomm/java/android/telecomm/ConnectionService.java
@@ -39,7 +39,6 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.Set;
import java.util.UUID;
/**
@@ -79,7 +78,8 @@
private final Map<Connection, String> mIdByConnection = new HashMap<>();
private final Map<String, Conference> mConferenceById = new HashMap<>();
private final Map<Conference, String> mIdByConference = new HashMap<>();
- private final RemoteConnectionManager mRemoteConnectionManager = new RemoteConnectionManager();
+ private final RemoteConnectionManager mRemoteConnectionManager =
+ new RemoteConnectionManager(this);
private final List<Runnable> mPreInitializationConnectionRequests = new ArrayList<>();
private final ConnectionServiceAdapter mAdapter = new ConnectionServiceAdapter();
@@ -461,15 +461,9 @@
@Override
public void onConferenceableConnectionsChanged(
Connection connection, List<Connection> conferenceableConnections) {
- String id = mIdByConnection.get(connection);
- List<String> conferenceableCallIds = new ArrayList<>(conferenceableConnections.size());
- for (Connection c : conferenceableConnections) {
- if (mIdByConnection.containsKey(c)) {
- conferenceableCallIds.add(mIdByConnection.get(c));
- }
- }
- Collections.sort(conferenceableCallIds);
- mAdapter.setConferenceableConnections(id, conferenceableCallIds);
+ mAdapter.setConferenceableConnections(
+ mIdByConnection.get(connection),
+ createConnectionIdList(conferenceableConnections));
}
@Override
@@ -542,7 +536,8 @@
connection.getAudioModeIsVoip(),
connection.getStatusHints(),
connection.getDisconnectCause(),
- connection.getDisconnectMessage()));
+ connection.getDisconnectMessage(),
+ createConnectionIdList(connection.getConferenceableConnections())));
}
private void abort(String callId) {
@@ -717,6 +712,15 @@
}
/**
+ * Adds two {@code RemoteConnection}s to some {@code RemoteConference}.
+ */
+ public final void conferenceRemoteConnections(
+ RemoteConnection a,
+ RemoteConnection b) {
+ mRemoteConnectionManager.conferenceRemoteConnections(a, b);
+ }
+
+ /**
* Adds a new conference call. When a conference call is created either as a result of an
* explicit request via {@link #onConference} or otherwise, the connection service should supply
* an instance of {@link Conference} by invoking this method. A conference call provided by this
@@ -824,11 +828,17 @@
/**
* Notified that a connection has been removed from this connection service.
+ * <p>
+ * TODO: Deprecate this since we can listen to the Connection onDestroyed() to determine when
+ * it is destroyed. This then percolates down to the RemoteConference stuff, where we can also
+ * have a callback for one being added, but we don't need one for being destroyed.
*
* @param connection The connection which was removed.
*/
public void onConnectionRemoved(Connection connection) {}
+ public void onRemoteConferenceAdded(RemoteConference conference) {}
+
/**
* @hide
*/
@@ -836,6 +846,11 @@
return mIdByConference.containsKey(conference);
}
+ /** {@hide} */
+ void addRemoteConference(RemoteConference remoteConference) {
+ onRemoteConferenceAdded(remoteConference);
+ }
+
private void onAccountsInitialized() {
mAreAccountsInitialized = true;
for (Runnable r : mPreInitializationConnectionRequests) {
@@ -910,6 +925,17 @@
return getNullConference();
}
+ private List<String> createConnectionIdList(List<Connection> connections) {
+ List<String> ids = new ArrayList<>();
+ for (Connection c : connections) {
+ if (mIdByConnection.containsKey(c)) {
+ ids.add(mIdByConnection.get(c));
+ }
+ }
+ Collections.sort(ids);
+ return ids;
+ }
+
private Conference getNullConference() {
if (sNullConference == null) {
sNullConference = new Conference(null) {};
diff --git a/telecomm/java/android/telecomm/ParcelableConnection.java b/telecomm/java/android/telecomm/ParcelableConnection.java
index 812ee55..2e21d37 100644
--- a/telecomm/java/android/telecomm/ParcelableConnection.java
+++ b/telecomm/java/android/telecomm/ParcelableConnection.java
@@ -22,6 +22,9 @@
import com.android.internal.telecomm.IVideoProvider;
+import java.util.ArrayList;
+import java.util.List;
+
/**
* Information about a connection that is used between Telecomm and the ConnectionService.
* This is used to send initial Connection information to Telecomm when the connection is
@@ -29,20 +32,21 @@
* @hide
*/
public final class ParcelableConnection implements Parcelable {
- private PhoneAccountHandle mPhoneAccount;
- private int mState;
- private int mCapabilities;
- private Uri mHandle;
- private int mHandlePresentation;
- private String mCallerDisplayName;
- private int mCallerDisplayNamePresentation;
- private IVideoProvider mVideoProvider;
- private int mVideoState;
- private boolean mRequestingRingback;
- private boolean mAudioModeIsVoip;
- private StatusHints mStatusHints;
- private int mDisconnectCause;
- private String mDisconnectMessage;
+ private final PhoneAccountHandle mPhoneAccount;
+ private final int mState;
+ private final int mCapabilities;
+ private final Uri mHandle;
+ private final int mHandlePresentation;
+ private final String mCallerDisplayName;
+ private final int mCallerDisplayNamePresentation;
+ private final IVideoProvider mVideoProvider;
+ private final int mVideoState;
+ private final boolean mRequestingRingback;
+ private final boolean mAudioModeIsVoip;
+ private final StatusHints mStatusHints;
+ private final int mDisconnectCause;
+ private final String mDisconnectMessage;
+ private final List<String> mConferenceableConnectionIds;
/** @hide */
public ParcelableConnection(
@@ -59,7 +63,8 @@
boolean audioModeIsVoip,
StatusHints statusHints,
int disconnectCause,
- String disconnectMessage) {
+ String disconnectMessage,
+ List<String> conferenceableConnectionIds) {
mPhoneAccount = phoneAccount;
mState = state;
mCapabilities = capabilities;
@@ -74,6 +79,7 @@
mStatusHints = statusHints;
mDisconnectCause = disconnectCause;
mDisconnectMessage = disconnectMessage;
+ this.mConferenceableConnectionIds = conferenceableConnectionIds;
}
public PhoneAccountHandle getPhoneAccount() {
@@ -133,6 +139,10 @@
return mDisconnectMessage;
}
+ public final List<String> getConferenceableConnectionIds() {
+ return mConferenceableConnectionIds;
+ }
+
@Override
public String toString() {
return new StringBuilder()
@@ -166,6 +176,8 @@
StatusHints statusHints = source.readParcelable(classLoader);
int disconnectCauseCode = source.readInt();
String disconnectCauseMessage = source.readString();
+ List<String> conferenceableConnectionIds = new ArrayList<>();
+ source.readStringList(conferenceableConnectionIds);
return new ParcelableConnection(
phoneAccount,
@@ -181,7 +193,8 @@
audioModeIsVoip,
statusHints,
disconnectCauseCode,
- disconnectCauseMessage);
+ disconnectCauseMessage,
+ conferenceableConnectionIds);
}
@Override
@@ -214,5 +227,6 @@
destination.writeParcelable(mStatusHints, 0);
destination.writeInt(mDisconnectCause);
destination.writeString(mDisconnectMessage);
+ destination.writeStringList(mConferenceableConnectionIds);
}
}
diff --git a/telecomm/java/android/telecomm/RemoteConference.java b/telecomm/java/android/telecomm/RemoteConference.java
new file mode 100644
index 0000000..02f6de6
--- /dev/null
+++ b/telecomm/java/android/telecomm/RemoteConference.java
@@ -0,0 +1,198 @@
+/*
+ * 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.telecomm;
+
+import com.android.internal.telecomm.IConnectionService;
+
+import android.os.RemoteException;
+import android.telephony.DisconnectCause;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.CopyOnWriteArraySet;
+
+/**
+ * Represents a conference call which can contain any number of {@link Connection} objects.
+ */
+public final class RemoteConference {
+
+ public abstract static class Listener {
+ 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) {}
+ public void onConnectionRemoved(RemoteConference conference, RemoteConnection connection) {}
+ public void onCapabilitiesChanged(RemoteConference conference, int capabilities) {}
+ public void onDestroyed(RemoteConference conference) {}
+ }
+
+ private final String mId;
+ private final IConnectionService mConnectionService;
+
+ private final Set<Listener> mListeners = new CopyOnWriteArraySet<>();
+ private final List<RemoteConnection> mChildConnections = new CopyOnWriteArrayList<>();
+ private final List<RemoteConnection> mUnmodifiableChildConnections =
+ Collections.unmodifiableList(mChildConnections);
+
+ private int mState = Connection.STATE_NEW;
+ private int mDisconnectCause = DisconnectCause.NOT_VALID;
+ private int mCallCapabilities;
+ private String mDisconnectMessage;
+
+ /** {@hide} */
+ RemoteConference(String id, IConnectionService connectionService) {
+ mId = id;
+ mConnectionService = connectionService;
+ }
+
+ /** {@hide} */
+ String getId() {
+ return mId;
+ }
+
+ /** {@hide} */
+ void setDestroyed() {
+ for (RemoteConnection connection : mChildConnections) {
+ connection.setConference(null);
+ }
+ for (Listener l : mListeners) {
+ l.onDestroyed(this);
+ }
+ }
+
+ /** {@hide} */
+ void setState(int newState) {
+ if (newState != Connection.STATE_ACTIVE &&
+ newState != Connection.STATE_HOLDING &&
+ newState != Connection.STATE_DISCONNECTED) {
+ Log.w(this, "Unsupported state transition for Conference call.",
+ Connection.stateToString(newState));
+ return;
+ }
+
+ if (mState != newState) {
+ int oldState = mState;
+ mState = newState;
+ for (Listener l : mListeners) {
+ l.onStateChanged(this, oldState, newState);
+ }
+ }
+ }
+
+ /** {@hide} */
+ void addConnection(RemoteConnection connection) {
+ if (!mChildConnections.contains(connection)) {
+ mChildConnections.add(connection);
+ connection.setConference(this);
+ for (Listener l : mListeners) {
+ l.onConnectionAdded(this, connection);
+ }
+ }
+ }
+
+ /** {@hide} */
+ void removeConnection(RemoteConnection connection) {
+ if (mChildConnections.contains(connection)) {
+ mChildConnections.remove(connection);
+ connection.setConference(null);
+ for (Listener l : mListeners) {
+ l.onConnectionRemoved(this, connection);
+ }
+ }
+ }
+
+ /** {@hide} */
+ void setCallCapabilities(int capabilities) {
+ if (mCallCapabilities != capabilities) {
+ mCallCapabilities = capabilities;
+ for (Listener l : mListeners) {
+ l.onCapabilitiesChanged(this, mCallCapabilities);
+ }
+ }
+ }
+
+ /** {@hide} */
+ void setDisconnected(int cause, String message) {
+ if (mState != Connection.STATE_DISCONNECTED) {
+ mDisconnectCause = cause;
+ mDisconnectMessage = message;
+ setState(Connection.STATE_DISCONNECTED);
+ for (Listener l : mListeners) {
+ l.onDisconnected(this, cause, message);
+ }
+ }
+ }
+
+ public final List<RemoteConnection> getConnections() {
+ return mUnmodifiableChildConnections;
+ }
+
+ public final int getState() {
+ return mState;
+ }
+
+ public final int getCallCapabilities() {
+ return mCallCapabilities;
+ }
+
+ public void disconnect() {
+ try {
+ mConnectionService.disconnect(mId);
+ } catch (RemoteException e) {
+ }
+ }
+
+ public void separate(RemoteConnection connection) {
+ if (mChildConnections.contains(connection)) {
+ try {
+ mConnectionService.splitFromConference(connection.getId());
+ } catch (RemoteException e) {
+ }
+ }
+ }
+
+ public void hold() {
+ try {
+ mConnectionService.hold(mId);
+ } catch (RemoteException e) {
+ }
+ }
+
+ public void unhold() {
+ try {
+ mConnectionService.unhold(mId);
+ } catch (RemoteException e) {
+ }
+ }
+
+ public int getDisconnectCause() {
+ return mDisconnectCause;
+ }
+
+ public String getDisconnectMessage() {
+ return mDisconnectMessage;
+ }
+
+ public final void addListener(Listener listener) {
+ mListeners.add(listener);
+ }
+
+ public final void removeListener(Listener listener) {
+ mListeners.remove(listener);
+ }
+}
diff --git a/telecomm/java/android/telecomm/RemoteConnection.java b/telecomm/java/android/telecomm/RemoteConnection.java
index 70db6f5..20d1574 100644
--- a/telecomm/java/android/telecomm/RemoteConnection.java
+++ b/telecomm/java/android/telecomm/RemoteConnection.java
@@ -179,8 +179,30 @@
* @param connection The {@code RemoteConnection} invoking this method.
*/
public void onDestroyed(RemoteConnection connection) {}
+
+ /**
+ * Indicates that the {@code RemoteConnection}s with which this {@code RemoteConnection}
+ * may be asked to create a conference has changed.
+ *
+ * @param connection The {@code RemoteConnection} invoking this method.
+ * @param conferenceableConnections The {@code RemoteConnection}s with which this
+ * {@code RemoteConnection} may be asked to create a conference.
+ */
public void onConferenceableConnectionsChanged(
- RemoteConnection connection, List<RemoteConnection> conferenceableConnections) {}
+ RemoteConnection connection,
+ List<RemoteConnection> conferenceableConnections) {}
+
+ /**
+ * Indicates that the {@code RemoteConference} that this {@code RemoteConnection} is a part
+ * of has changed.
+ *
+ * @param connection The {@code RemoteConnection} invoking this method.
+ * @param conference The {@code RemoteConference} of which this {@code RemoteConnection} is
+ * a part, which may be {@code null}.
+ */
+ public void onConferenceChanged(
+ RemoteConnection connection,
+ RemoteConference conference) {}
}
private IConnectionService mConnectionService;
@@ -192,7 +214,9 @@
*/
private final Set<Listener> mListeners = Collections.newSetFromMap(
new ConcurrentHashMap<Listener, Boolean>(8, 0.9f, 1));
- private final Set<RemoteConnection> mConferenceableConnections = new HashSet<>();
+ private final List<RemoteConnection> mConferenceableConnections = new ArrayList<>();
+ private final List<RemoteConnection> mUnmodifiableconferenceableConnections =
+ Collections.unmodifiableList(mConferenceableConnections);
private int mState = Connection.STATE_NEW;
private int mDisconnectCauseCode = DisconnectCause.NOT_VALID;
@@ -209,6 +233,7 @@
private int mCallerDisplayNamePresentation;
private int mFailureCode;
private String mFailureMessage;
+ private RemoteConference mConference;
/**
* @hide
@@ -539,6 +564,37 @@
}
/**
+ * Obtain the {@code RemoteConnection}s with which this {@code RemoteConnection} may be
+ * successfully asked to create a conference with.
+ *
+ * @return The {@code RemoteConnection}s with which this {@code RemoteConnection} may be
+ * merged into a {@link RemoteConference}.
+ */
+ public List<RemoteConnection> getConferenceableConnections() {
+ return mUnmodifiableconferenceableConnections;
+ }
+
+ /**
+ * Obtain the {@code RemoteConference} that this {@code RemoteConnection} may be a part
+ * of, or {@code null} if there is no such {@code RemoteConference}.
+ *
+ * @return A {@code RemoteConference} or {@code null};
+ */
+ public RemoteConference getConference() {
+ return mConference;
+ }
+
+ /** {@hide} */
+ String getId() {
+ return mConnectionId;
+ }
+
+ /** {@hide} */
+ IConnectionService getConnectionService() {
+ return mConnectionService;
+ }
+
+ /**
* @hide
*/
void setState(int state) {
@@ -671,8 +727,17 @@
mConferenceableConnections.clear();
mConferenceableConnections.addAll(conferenceableConnections);
for (Listener l : mListeners) {
- l.onConferenceableConnectionsChanged(
- this, new ArrayList<RemoteConnection>(mConferenceableConnections));
+ l.onConferenceableConnectionsChanged(this, mUnmodifiableconferenceableConnections);
+ }
+ }
+
+ /** @hide */
+ void setConference(RemoteConference conference) {
+ if (mConference != conference) {
+ mConference = conference;
+ for (Listener l : mListeners) {
+ l.onConferenceChanged(this, conference);
+ }
}
}
diff --git a/telecomm/java/android/telecomm/RemoteConnectionManager.java b/telecomm/java/android/telecomm/RemoteConnectionManager.java
index 365ed5b..83502c5 100644
--- a/telecomm/java/android/telecomm/RemoteConnectionManager.java
+++ b/telecomm/java/android/telecomm/RemoteConnectionManager.java
@@ -28,13 +28,22 @@
* @hide
*/
public class RemoteConnectionManager {
- private Map<ComponentName, RemoteConnectionService> mRemoteConnectionServices = new HashMap<>();
+ private final Map<ComponentName, RemoteConnectionService> mRemoteConnectionServices =
+ new HashMap<>();
+ private final ConnectionService mOurConnectionServiceImpl;
- void addConnectionService(ComponentName componentName, IConnectionService connectionService) {
+ public RemoteConnectionManager(ConnectionService ourConnectionServiceImpl) {
+ mOurConnectionServiceImpl = ourConnectionServiceImpl;
+ }
+
+ void addConnectionService(
+ ComponentName componentName,
+ IConnectionService outgoingConnectionServiceRpc) {
if (!mRemoteConnectionServices.containsKey(componentName)) {
try {
- RemoteConnectionService remoteConnectionService =
- new RemoteConnectionService(connectionService);
+ RemoteConnectionService remoteConnectionService = new RemoteConnectionService(
+ outgoingConnectionServiceRpc,
+ mOurConnectionServiceImpl);
mRemoteConnectionServices.put(componentName, remoteConnectionService);
} catch (RemoteException ignored) {
}
@@ -63,4 +72,17 @@
}
return null;
}
+
+ public void conferenceRemoteConnections(RemoteConnection a, RemoteConnection b) {
+ if (a.getConnectionService() == b.getConnectionService()) {
+ try {
+ a.getConnectionService().conference(a.getId(), b.getId());
+ } catch (RemoteException e) {
+ }
+ } else {
+ Log.w(this, "Request to conference incompatible remote connections (%s,%s) (%s,%s)",
+ a.getConnectionService(), a.getId(),
+ b.getConnectionService(), b.getId());
+ }
+ }
}
diff --git a/telecomm/java/android/telecomm/RemoteConnectionService.java b/telecomm/java/android/telecomm/RemoteConnectionService.java
index 541df4e..51722fe 100644
--- a/telecomm/java/android/telecomm/RemoteConnectionService.java
+++ b/telecomm/java/android/telecomm/RemoteConnectionService.java
@@ -28,11 +28,11 @@
import com.android.internal.telecomm.IVideoProvider;
import com.android.internal.telecomm.RemoteServiceCallback;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
-import java.util.Collections;
import java.util.List;
import java.util.UUID;
@@ -43,8 +43,11 @@
*/
final class RemoteConnectionService {
- private static final RemoteConnection
- NULL_CONNECTION = new RemoteConnection("NULL", null, null);
+ private static final RemoteConnection NULL_CONNECTION =
+ new RemoteConnection("NULL", null, null);
+
+ private static final RemoteConference NULL_CONFERENCE =
+ new RemoteConference("NULL", null);
private final IConnectionServiceAdapter mServantDelegate = new IConnectionServiceAdapter() {
@Override
@@ -64,6 +67,13 @@
connection.setCallerDisplayName(
parcel.getCallerDisplayName(),
parcel.getCallerDisplayNamePresentation());
+ List<RemoteConnection> conferenceable = new ArrayList<>();
+ for (String confId : parcel.getConferenceableConnectionIds()) {
+ if (mConnectionById.containsKey(confId)) {
+ conferenceable.add(mConnectionById.get(confId));
+ }
+ }
+ connection.setConferenceableConnections(conferenceable);
// TODO: Do we need to support video providers for remote connections?
if (connection.getState() == Connection.STATE_DISCONNECTED) {
// ... then, if it was created in a disconnected state, that indicates
@@ -75,8 +85,13 @@
@Override
public void setActive(String callId) {
- findConnectionForAction(callId, "setActive")
- .setState(Connection.STATE_ACTIVE);
+ if (mConnectionById.containsKey(callId)) {
+ findConnectionForAction(callId, "setActive")
+ .setState(Connection.STATE_ACTIVE);
+ } else {
+ findConferenceForAction(callId, "setActive")
+ .setState(Connection.STATE_ACTIVE);
+ }
}
@Override
@@ -94,14 +109,24 @@
@Override
public void setDisconnected(String callId, int disconnectCause,
String disconnectMessage) {
- findConnectionForAction(callId, "setDisconnected")
- .setDisconnected(disconnectCause, disconnectMessage);
+ if (mConnectionById.containsKey(callId)) {
+ findConnectionForAction(callId, "setDisconnected")
+ .setDisconnected(disconnectCause, disconnectMessage);
+ } else {
+ findConferenceForAction(callId, "setDisconnected")
+ .setDisconnected(disconnectCause, disconnectMessage);
+ }
}
@Override
public void setOnHold(String callId) {
- findConnectionForAction(callId, "setOnHold")
- .setState(Connection.STATE_HOLDING);
+ if (mConnectionById.containsKey(callId)) {
+ findConnectionForAction(callId, "setOnHold")
+ .setState(Connection.STATE_HOLDING);
+ } else {
+ findConferenceForAction(callId, "setOnHold")
+ .setState(Connection.STATE_HOLDING);
+ }
}
@Override
@@ -112,24 +137,80 @@
@Override
public void setCallCapabilities(String callId, int callCapabilities) {
- findConnectionForAction("callId", "setCallCapabilities")
- .setCallCapabilities(callCapabilities);
+ if (mConnectionById.containsKey(callId)) {
+ findConnectionForAction(callId, "setCallCapabilities")
+ .setCallCapabilities(callCapabilities);
+ } else {
+ findConferenceForAction(callId, "setCallCapabilities")
+ .setCallCapabilities(callCapabilities);
+ }
}
@Override
public void setIsConferenced(String callId, String conferenceCallId) {
- // not supported for remote connections.
+ // Note: callId should not be null; conferenceCallId may be null
+ RemoteConnection connection =
+ findConnectionForAction(callId, "setIsConferenced");
+ if (connection != NULL_CONNECTION) {
+ if (conferenceCallId == null) {
+ // 'connection' is being split from its conference
+ if (connection.getConference() != null) {
+ connection.getConference().removeConnection(connection);
+ }
+ } else {
+ RemoteConference conference =
+ findConferenceForAction(conferenceCallId, "setIsConferenced");
+ if (conference != NULL_CONFERENCE) {
+ conference.addConnection(connection);
+ }
+ }
+ }
}
@Override
- public void addConferenceCall(String callId, ParcelableConference parcelableConference) {
- // not supported for remote connections.
+ public void addConferenceCall(
+ final String callId,
+ ParcelableConference parcel) {
+ RemoteConference conference = new RemoteConference(callId,
+ mOutgoingConnectionServiceRpc);
+
+ for (String id : parcel.getConnectionIds()) {
+ RemoteConnection c = mConnectionById.get(id);
+ if (c != null) {
+ conference.addConnection(c);
+ }
+ }
+
+ if (conference.getConnections().size() == 0) {
+ // A conference was created, but none of its connections are ones that have been
+ // created by, and therefore being tracked by, this remote connection service. It
+ // is of no interest to us.
+ return;
+ }
+
+ conference.setState(parcel.getState());
+ conference.setCallCapabilities(parcel.getCapabilities());
+ mConferenceById.put(callId, conference);
+ conference.addListener(new RemoteConference.Listener() {
+ @Override
+ public void onDestroyed(RemoteConference c) {
+ mConferenceById.remove(callId);
+ maybeDisconnectAdapter();
+ }
+ });
+
+ mOurConnectionServiceImpl.addRemoteConference(conference);
}
@Override
public void removeCall(String callId) {
- findConnectionForAction(callId, "removeCall")
- .setDestroyed();
+ if (mConnectionById.containsKey(callId)) {
+ findConnectionForAction(callId, "removeCall")
+ .setDestroyed();
+ } else {
+ findConferenceForAction(callId, "removeCall")
+ .setDestroyed();
+ }
}
@Override
@@ -193,13 +274,15 @@
@Override
public final void setConferenceableConnections(
String callId, List<String> conferenceableConnectionIds) {
+ List<RemoteConnection> conferenceable = new ArrayList<>();
+ for (String id : conferenceableConnectionIds) {
+ if (mConnectionById.containsKey(id)) {
+ conferenceable.add(mConnectionById.get(id));
+ }
+ }
- // TODO: When we support more than 1 remote connection, this should
- // loop through the incoming list of connection IDs and acquire the list
- // of remote connections which correspond to the IDs. That list should
- // be set onto the remote connections.
findConnectionForAction(callId, "setConferenceableConnections")
- .setConferenceableConnections(Collections.<RemoteConnection>emptyList());
+ .setConferenceableConnections(conferenceable);
}
};
@@ -212,24 +295,33 @@
for (RemoteConnection c : mConnectionById.values()) {
c.setDestroyed();
}
+ for (RemoteConference c : mConferenceById.values()) {
+ c.setDestroyed();
+ }
mConnectionById.clear();
+ mConferenceById.clear();
mPendingConnections.clear();
- mConnectionService.asBinder().unlinkToDeath(mDeathRecipient, 0);
+ mOutgoingConnectionServiceRpc.asBinder().unlinkToDeath(mDeathRecipient, 0);
}
};
- private final IConnectionService mConnectionService;
+ private final IConnectionService mOutgoingConnectionServiceRpc;
+ private final ConnectionService mOurConnectionServiceImpl;
private final Map<String, RemoteConnection> mConnectionById = new HashMap<>();
+ private final Map<String, RemoteConference> mConferenceById = new HashMap<>();
private final Set<RemoteConnection> mPendingConnections = new HashSet<>();
- RemoteConnectionService(IConnectionService connectionService) throws RemoteException {
- mConnectionService = connectionService;
- mConnectionService.asBinder().linkToDeath(mDeathRecipient, 0);
+ RemoteConnectionService(
+ IConnectionService outgoingConnectionServiceRpc,
+ ConnectionService ourConnectionServiceImpl) throws RemoteException {
+ mOutgoingConnectionServiceRpc = outgoingConnectionServiceRpc;
+ mOutgoingConnectionServiceRpc.asBinder().linkToDeath(mDeathRecipient, 0);
+ mOurConnectionServiceImpl = ourConnectionServiceImpl;
}
@Override
public String toString() {
- return "[RemoteCS - " + mConnectionService.asBinder().toString() + "]";
+ return "[RemoteCS - " + mOutgoingConnectionServiceRpc.asBinder().toString() + "]";
}
final RemoteConnection createRemoteConnection(
@@ -245,13 +337,13 @@
request.getVideoState());
try {
if (mConnectionById.isEmpty()) {
- mConnectionService.addConnectionServiceAdapter(mServant.getStub());
+ mOutgoingConnectionServiceRpc.addConnectionServiceAdapter(mServant.getStub());
}
RemoteConnection connection =
- new RemoteConnection(id, mConnectionService, newRequest);
+ new RemoteConnection(id, mOutgoingConnectionServiceRpc, newRequest);
mPendingConnections.add(connection);
mConnectionById.put(id, connection);
- mConnectionService.createConnection(
+ mOutgoingConnectionServiceRpc.createConnection(
connectionManagerPhoneAccount,
id,
newRequest,
@@ -260,12 +352,7 @@
@Override
public void onDestroyed(RemoteConnection connection) {
mConnectionById.remove(id);
- if (mConnectionById.isEmpty()) {
- try {
- mConnectionService.removeConnectionServiceAdapter(mServant.getStub());
- } catch (RemoteException e) {
- }
- }
+ maybeDisconnectAdapter();
}
});
return connection;
@@ -283,4 +370,22 @@
Log.w(this, "%s - Cannot find Connection %s", action, callId);
return NULL_CONNECTION;
}
+
+ private RemoteConference findConferenceForAction(
+ String callId, String action) {
+ if (mConferenceById.containsKey(callId)) {
+ return mConferenceById.get(callId);
+ }
+ Log.w(this, "%s - Cannot find Conference %s", action, callId);
+ return NULL_CONFERENCE;
+ }
+
+ private void maybeDisconnectAdapter() {
+ if (mConnectionById.isEmpty() && mConferenceById.isEmpty()) {
+ try {
+ mOutgoingConnectionServiceRpc.removeConnectionServiceAdapter(mServant.getStub());
+ } catch (RemoteException e) {
+ }
+ }
+ }
}
diff --git a/telecomm/java/android/telecomm/TelecommManager.java b/telecomm/java/android/telecomm/TelecommManager.java
index e59fea1..178a25f 100644
--- a/telecomm/java/android/telecomm/TelecommManager.java
+++ b/telecomm/java/android/telecomm/TelecommManager.java
@@ -17,7 +17,6 @@
import android.annotation.SystemApi;
import android.content.ComponentName;
import android.content.Context;
-
import android.os.Bundle;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -394,14 +393,15 @@
/**
* Returns whether there is an ongoing phone call (can be in dialing, ringing, active or holding
* states).
- *
- * @hide
+ * <p>
+ * Requires permission: {@link android.Manifest.permission#READ_PHONE_STATE}
+ * </p>
*/
@SystemApi
- public boolean isInAPhoneCall() {
+ public boolean isInCall() {
try {
if (isServiceConnected()) {
- return getTelecommService().isInAPhoneCall();
+ return getTelecommService().isInCall();
}
} catch (RemoteException e) {
Log.e(TAG, "RemoteException attempting to get default phone app.", e);
@@ -541,6 +541,67 @@
}
}
+ /**
+ * Processes the specified dial string as an MMI code.
+ * MMI codes are any sequence of characters entered into the dialpad that contain a "*" or "#".
+ * Some of these sequences launch special behavior through handled by Telephony.
+ * <p>
+ * Requires that the method-caller be set as the system dialer app.
+ * </p>
+ *
+ * @param dialString The digits to dial.
+ * @return True if the digits were processed as an MMI code, false otherwise.
+ */
+ public boolean handleMmi(String dialString) {
+ ITelecommService service = getTelecommService();
+ if (service != null) {
+ try {
+ return service.handlePinMmi(dialString);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling ITelecommService#handlePinMmi", e);
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Removes the missed-call notification if one is present.
+ * <p>
+ * Requires that the method-caller be set as the system dialer app.
+ * </p>
+ */
+ public void cancelMissedCallsNotification() {
+ ITelecommService service = getTelecommService();
+ if (service != null) {
+ try {
+ service.cancelMissedCallsNotification();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling ITelecommService#cancelMissedCallsNotification", e);
+ }
+ }
+ }
+
+ /**
+ * Brings the in-call screen to the foreground if there is an ongoing call. If there is
+ * currently no ongoing call, then this method does nothing.
+ * <p>
+ * Requires that the method-caller be set as the system dialer app or have the
+ * {@link android.Manifest.permission#READ_PHONE_STATE} permission.
+ * </p>
+ *
+ * @param showDialpad Brings up the in-call dialpad as part of showing the in-call screen.
+ */
+ public void showInCallScreen(boolean showDialpad) {
+ ITelecommService service = getTelecommService();
+ if (service != null) {
+ try {
+ service.showInCallScreen(showDialpad);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling ITelecommService#showCallScreen", e);
+ }
+ }
+ }
+
private ITelecommService getTelecommService() {
return ITelecommService.Stub.asInterface(ServiceManager.getService(TELECOMM_SERVICE_NAME));
}
diff --git a/telecomm/java/com/android/internal/telecomm/ITelecommService.aidl b/telecomm/java/com/android/internal/telecomm/ITelecommService.aidl
index 3c1dea6..0ac5078 100644
--- a/telecomm/java/com/android/internal/telecomm/ITelecommService.aidl
+++ b/telecomm/java/com/android/internal/telecomm/ITelecommService.aidl
@@ -32,7 +32,7 @@
*
* @param showDialpad if true, make the dialpad visible initially.
*/
- void showCallScreen(boolean showDialpad);
+ void showInCallScreen(boolean showDialpad);
/**
* @see TelecommManager#getDefaultOutgoingPhoneAccount
@@ -79,9 +79,9 @@
void silenceRinger();
/**
- * @see TelecommManager#isInAPhoneCall
+ * @see TelecommManager#isInCall
*/
- boolean isInAPhoneCall();
+ boolean isInCall();
/**
* @see TelecomManager#isRinging
@@ -99,12 +99,12 @@
void acceptRingingCall();
/**
- * @see PhoneManager#cancelMissedCallsNotification
+ * @see TelecommManager#cancelMissedCallsNotification
*/
void cancelMissedCallsNotification();
/**
- * @see PhoneManager#handlePinMmi
+ * @see TelecommManager#handleMmi
*/
boolean handlePinMmi(String dialString);
diff --git a/telephony/java/android/telephony/IccOpenLogicalChannelResponse.java b/telephony/java/android/telephony/IccOpenLogicalChannelResponse.java
index e9db030..dbe38ea 100644
--- a/telephony/java/android/telephony/IccOpenLogicalChannelResponse.java
+++ b/telephony/java/android/telephony/IccOpenLogicalChannelResponse.java
@@ -24,14 +24,23 @@
* Response to the {@link TelephonyManager#iccOpenLogicalChannel} command.
*/
public class IccOpenLogicalChannelResponse implements Parcelable {
- // Indicates an invalid channel.
+ /**
+ * Indicates an invalid channel.
+ */
public static int INVALID_CHANNEL = -1;
- // Possible status values.
- public static int NO_ERROR = 1;
- public static int MISSING_RESOURCE = 2;
- public static int NO_SUCH_ELEMENT = 3;
- public static int UNKNOWN_ERROR = 4;
+ /**
+ * Possible status values returned by open channel command.
+ *
+ * STATUS_NO_ERROR: Open channel command returned successfully.
+ * STATUS_MISSING_RESOURCE: No logical channels available.
+ * STATUS_NO_SUCH_ELEMENT: AID not found on UICC.
+ * STATUS_UNKNOWN_ERROR: Unknown error in open channel command.
+ */
+ public static int STATUS_NO_ERROR = 1;
+ public static int STATUS_MISSING_RESOURCE = 2;
+ public static int STATUS_NO_SUCH_ELEMENT = 3;
+ public static int STATUS_UNKNOWN_ERROR = 4;
private final int mChannel;
private final int mStatus;
diff --git a/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfActivity.java b/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfActivity.java
index 6633787..78e360b 100644
--- a/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfActivity.java
+++ b/tests/FrameworkPerf/src/com/android/frameworkperf/FrameworkPerfActivity.java
@@ -20,6 +20,7 @@
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
+import android.graphics.Color;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
@@ -199,6 +200,7 @@
mLocalCheckBox = (CheckBox)findViewById(R.id.local);
mLog = (TextView)findViewById(R.id.log);
+ mLog.setTextColor(Color.RED);
PowerManager pm = (PowerManager)getSystemService(POWER_SERVICE);
mPartialWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Scheduler");
diff --git a/tools/aapt/AaptConfig.cpp b/tools/aapt/AaptConfig.cpp
index 69a9c7f..32a0cd3 100644
--- a/tools/aapt/AaptConfig.cpp
+++ b/tools/aapt/AaptConfig.cpp
@@ -255,6 +255,8 @@
!= ResTable_config::SCREENLONG_ANY
|| config->density != ResTable_config::DENSITY_DEFAULT) {
minSdk = SDK_DONUT;
+ } else if ((config->density == ResTable_config::DENSITY_ANY)) {
+ minSdk = SDK_L;
}
if (minSdk > config->sdkVersion) {
@@ -477,6 +479,11 @@
return true;
}
+ if (strcmp(name, "anydpi") == 0) {
+ if (out) out->density = ResTable_config::DENSITY_ANY;
+ return true;
+ }
+
if (strcmp(name, "nodpi") == 0) {
if (out) out->density = ResTable_config::DENSITY_NONE;
return true;
diff --git a/tools/aapt/Bundle.h b/tools/aapt/Bundle.h
index 1439f14..af49461 100644
--- a/tools/aapt/Bundle.h
+++ b/tools/aapt/Bundle.h
@@ -24,6 +24,7 @@
SDK_HONEYCOMB_MR2 = 13,
SDK_ICE_CREAM_SANDWICH = 14,
SDK_ICE_CREAM_SANDWICH_MR1 = 15,
+ SDK_L = 21,
};
/*
diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index f8bc2ae..2604e97 100644
--- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -221,6 +221,12 @@
}
@Override
+ public void overridePendingAppTransitionAspectScaledThumb(Bitmap srcThumb, int startX,
+ int startY, IRemoteCallback startedCallback, boolean scaleUp) {
+ // TODO Auto-generated method stub
+ }
+
+ @Override
public void pauseKeyDispatching(IBinder arg0) throws RemoteException {
// TODO Auto-generated method stub