Merge "Notification cleanup"
diff --git a/api/current.txt b/api/current.txt
index d474464..d42be65 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5667,6 +5667,7 @@
method public int describeContents();
method public void setActions(java.util.List<android.app.RemoteAction>);
method public void setAspectRatio(float);
+ method public void setSourceRectHint(android.graphics.Rect);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.app.PictureInPictureArgs> CREATOR;
}
diff --git a/api/system-current.txt b/api/system-current.txt
index 5923261..cd71f1e 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -5859,6 +5859,7 @@
method public int describeContents();
method public void setActions(java.util.List<android.app.RemoteAction>);
method public void setAspectRatio(float);
+ method public void setSourceRectHint(android.graphics.Rect);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.app.PictureInPictureArgs> CREATOR;
}
@@ -11393,6 +11394,7 @@
field public static final int INSTALL_FAILED_PACKAGE_CHANGED = -23; // 0xffffffe9
field public static final int INSTALL_FAILED_PERMISSION_MODEL_DOWNGRADE = -26; // 0xffffffe6
field public static final int INSTALL_FAILED_REPLACE_COULDNT_DELETE = -10; // 0xfffffff6
+ field public static final int INSTALL_FAILED_SANDBOX_VERSION_DOWNGRADE = -27; // 0xffffffe5
field public static final int INSTALL_FAILED_SHARED_USER_INCOMPATIBLE = -8; // 0xfffffff8
field public static final int INSTALL_FAILED_TEST_ONLY = -15; // 0xfffffff1
field public static final int INSTALL_FAILED_UPDATE_INCOMPATIBLE = -7; // 0xfffffff9
diff --git a/api/test-current.txt b/api/test-current.txt
index 3c5bb26..a3a6161 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -5678,6 +5678,7 @@
method public int describeContents();
method public void setActions(java.util.List<android.app.RemoteAction>);
method public void setAspectRatio(float);
+ method public void setSourceRectHint(android.graphics.Rect);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.app.PictureInPictureArgs> CREATOR;
}
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java
index 6d4b812..2a2fdbd 100644
--- a/core/java/android/accounts/AccountManager.java
+++ b/core/java/android/accounts/AccountManager.java
@@ -336,7 +336,7 @@
*
* @see #addOnAccountsUpdatedListener
*
- * @deprecated use #addOnAccountsUpdatedListener to get account updates in runtime.
+ * @deprecated use {@link #addOnAccountsUpdatedListener} to get account updates in runtime.
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
@BroadcastBehavior(includeBackground = true)
@@ -888,9 +888,9 @@
* This method requires the caller to have a signature match with the authenticator that owns
* the specified account.
*
- * @param account The account for which visibility data should be returned.
+ * @param account The account for which visibility data should be returned
*
- * @return Map from package names to visibility for given account.
+ * @return Map from package names to visibility for given account
*/
public Map<String, Integer> getPackagesAndVisibilityForAccount(Account account) {
try {
@@ -913,11 +913,11 @@
*
* <p>
*
- * @param packageName Package name.
- * @param accountType Account type.
+ * @param packageName Package name
+ * @param accountType {@link Account} type
*
- * @return Map with visibility for all accounts of given type.
- * See {@link #getAccountVisibility} for possilbe values.
+ * @return Map with visibility for all accounts of given type
+ * See {@link #getAccountVisibility} for possible values
*/
public Map<Account, Integer> getAccountsAndVisibilityForPackage(String packageName,
String accountType) {
@@ -932,7 +932,7 @@
}
/**
- * Set visibility value of given account to certain packageName.
+ * Set visibility value of given account to certain package.
* Package name must match installed application, or be equal to
* {@link #PACKAGE_NAME_KEY_LEGACY_VISIBLE} or {@link #PACKAGE_NAME_KEY_LEGACY_NOT_VISIBLE}.
* <p>
@@ -948,11 +948,11 @@
* This method requires the caller to have a signature match with the authenticator that owns
* the specified account.
*
- * @param account Account to update visibility
- * @param packageName Package name of the application to modify account visibility.
- * @param visibility - new visibility value.
+ * @param account {@link Account} to update visibility
+ * @param packageName Package name of the application to modify account visibility
+ * @param visibility New visibility value
*
- * @return True if visibility value was succesfully updated.
+ * @return True, if visibility value was successfully updated.
*/
public boolean setAccountVisibility(Account account, String packageName,
@AccountVisibility int visibility) {
@@ -978,10 +978,10 @@
* This method requires the caller to have a signature match with the authenticator that owns
* the specified account.
*
- * @param account Account to get visibility.
+ * @param account {@link Account} to get visibility
* @param packageName Package name of the application to get account visibility
*
- * @return int Visibility for given account and package.
+ * @return int Visibility of given account.
*/
public @AccountVisibility int getAccountVisibility(Account account, String packageName) {
if (account == null)
diff --git a/core/java/android/app/ActionBar.java b/core/java/android/app/ActionBar.java
index 1294325..0e8326d 100644
--- a/core/java/android/app/ActionBar.java
+++ b/core/java/android/app/ActionBar.java
@@ -1069,6 +1069,11 @@
}
/** @hide */
+ public boolean closeOptionsMenu() {
+ return false;
+ }
+
+ /** @hide */
public boolean invalidateOptionsMenu() {
return false;
}
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index e149868..4fd3f39 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -3557,7 +3557,8 @@
* closed, this method does nothing.
*/
public void closeOptionsMenu() {
- if (mWindow.hasFeature(Window.FEATURE_OPTIONS_PANEL)) {
+ if (mWindow.hasFeature(Window.FEATURE_OPTIONS_PANEL) &&
+ (mActionBar == null || !mActionBar.closeOptionsMenu())) {
mWindow.closePanel(Window.FEATURE_OPTIONS_PANEL);
}
}
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index e89dc0b..b4e6bd5 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -808,6 +808,11 @@
public final void scheduleReceiver(Intent intent, ActivityInfo info,
CompatibilityInfo compatInfo, int resultCode, String data, Bundle extras,
boolean sync, int sendingUser, int processState) {
+ // TODO: Debugging added for bug:36406078 . Remove when done
+ if (Log.isLoggable("36406078", Log.DEBUG)) {
+ Log.d(TAG, "scheduleReceiver");
+ }
+
updateProcessState(processState, false);
ReceiverData r = new ReceiverData(intent, resultCode, data, extras,
sync, false, mAppThread.asBinder(), sendingUser);
@@ -894,6 +899,11 @@
CompatibilityInfo compatInfo, Map services, Bundle coreSettings,
String buildSerial) {
+ // TODO: Debugging added for bug:36406078 . Remove when done
+ if (Log.isLoggable("36406078", Log.DEBUG)) {
+ Log.d(TAG, "bindApplication: " + processName);
+ }
+
if (services != null) {
// Setup the service cache in the ServiceManager
ServiceManager.initServiceCache(services);
@@ -3229,6 +3239,10 @@
if (receiver.getPendingResult() != null) {
data.finish();
}
+ // TODO: Debugging added for bug:36406078 . Remove when done
+ if (Log.isLoggable("36406078", Log.DEBUG)) {
+ Log.d(TAG, "handleReceiver done");
+ }
}
// Instantiate a BackupAgent and tell it that it's alive
@@ -5764,6 +5778,10 @@
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
+ // TODO: Debugging added for bug:36406078 . Remove when done
+ if (Log.isLoggable("36406078", Log.DEBUG)) {
+ Log.d(TAG, "handleBindApplication done");
+ }
}
/*package*/ final void finishInstrumentation(int resultCode, Bundle results) {
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 5ea2480..43cad5b 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -57,6 +57,7 @@
void createNotificationChannelGroups(String pkg, in ParceledListSlice channelGroupList);
void createNotificationChannels(String pkg, in ParceledListSlice channelsList);
+ void createNotificationChannelsForPackage(String pkg, int uid, in ParceledListSlice channelsList);
ParceledListSlice getNotificationChannelGroupsForPackage(String pkg, int uid, boolean includeDeleted);
NotificationChannelGroup getNotificationChannelGroupForPackage(String groupId, String pkg, int uid);
void updateNotificationChannelForPackage(String pkg, int uid, in NotificationChannel channel);
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 097df31..75998f2 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -453,19 +453,6 @@
}
/**
- * @hide
- */
- public void createNotificationChannelsForPackage(String pkg,
- @NonNull List<NotificationChannel> channels) {
- INotificationManager service = getService();
- try {
- service.createNotificationChannels(pkg, new ParceledListSlice(channels));
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
* Returns the notification channel settings for a given channel id.
*/
public NotificationChannel getNotificationChannel(String channelId) {
diff --git a/core/java/android/app/PictureInPictureArgs.java b/core/java/android/app/PictureInPictureArgs.java
index fbdcbf4..0ce5eeb 100644
--- a/core/java/android/app/PictureInPictureArgs.java
+++ b/core/java/android/app/PictureInPictureArgs.java
@@ -17,6 +17,7 @@
package android.app;
import android.annotation.Nullable;
+import android.graphics.Rect;
import android.os.Parcel;
import android.os.Parcelable;
@@ -35,11 +36,19 @@
private Float mAspectRatio;
/**
- * The set of actions that are associated with this activity when in picture in picture.
+ * The set of actions that are associated with this activity when in picture-in-picture.
*/
@Nullable
private List<RemoteAction> mUserActions;
+ /**
+ * The source bounds hint used when entering picture-in-picture, relative to the window bounds.
+ * We can use this internally for the transition into picture-in-picture to ensure that a
+ * particular source rect is visible throughout the whole transition.
+ */
+ @Nullable
+ private Rect mSourceRectHint;
+
PictureInPictureArgs(Parcel in) {
if (in.readInt() != 0) {
mAspectRatio = in.readFloat();
@@ -48,6 +57,9 @@
mUserActions = new ArrayList<>();
in.readParcelableList(mUserActions, RemoteAction.class.getClassLoader());
}
+ if (in.readInt() != 0) {
+ mSourceRectHint = Rect.CREATOR.createFromParcel(in);
+ }
}
/**
@@ -79,6 +91,9 @@
if (otherArgs.hasSetActions()) {
mUserActions = otherArgs.mUserActions;
}
+ if (otherArgs.hasSourceBoundsHint()) {
+ mSourceRectHint = new Rect(otherArgs.getSourceRectHint());
+ }
}
/**
@@ -137,9 +152,43 @@
return mUserActions != null;
}
+ /**
+ * Sets the source bounds hint. These bounds are only used when an activity first enters
+ * picture-in-picture, and describe the bounds in window coordinates of activity entering
+ * picture-in-picture that will be visible following the transition. For the best effect, these
+ * bounds should also match the aspect ratio in the arguments.
+ */
+ public void setSourceRectHint(Rect launchBounds) {
+ if (launchBounds == null) {
+ mSourceRectHint = null;
+ } else {
+ mSourceRectHint = new Rect(launchBounds);
+ }
+ }
+
+ /**
+ * @return the launch bounds
+ * @hide
+ */
+ public Rect getSourceRectHint() {
+ return mSourceRectHint;
+ }
+
+ /**
+ * @return whether there are launch bounds set
+ * @hide
+ */
+ public boolean hasSourceBoundsHint() {
+ return mSourceRectHint != null && !mSourceRectHint.isEmpty();
+ }
+
@Override
public PictureInPictureArgs clone() {
- return new PictureInPictureArgs(mAspectRatio, mUserActions);
+ PictureInPictureArgs args = new PictureInPictureArgs(mAspectRatio, mUserActions);
+ if (mSourceRectHint != null) {
+ args.setSourceRectHint(mSourceRectHint);
+ }
+ return args;
}
@Override
@@ -161,6 +210,12 @@
} else {
out.writeInt(0);
}
+ if (mSourceRectHint != null) {
+ out.writeInt(1);
+ mSourceRectHint.writeToParcel(out, 0);
+ } else {
+ out.writeInt(0);
+ }
}
public static final Creator<PictureInPictureArgs> CREATOR =
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index bb35928..71db5d3 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1069,6 +1069,16 @@
public static final int INSTALL_FAILED_PERMISSION_MODEL_DOWNGRADE = -26;
/**
+ * Installation return code: this is passed to the
+ * {@link IPackageInstallObserver} if the new package attempts to downgrade the
+ * target sandbox version of the app.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int INSTALL_FAILED_SANDBOX_VERSION_DOWNGRADE = -27;
+
+ /**
* Installation parse return code: this is passed to the
* {@link IPackageInstallObserver} if the parser was given a path that is
* not a file, or does not end with the expected '.apk' extension.
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 6dedbde..5494377 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -50,7 +50,7 @@
* <li>The real display area specifies the part of the display that contains content
* including the system decorations. Even so, the real display area may be smaller than the
* physical size of the display if the window manager is emulating a smaller display
- * using (adb shell wm size). Use the following methods to query the
+ * using (adb shell am display-size). Use the following methods to query the
* real display area: {@link #getRealSize}, {@link #getRealMetrics}.</li>
* </ul>
* </p><p>
@@ -947,7 +947,7 @@
* The size is adjusted based on the current rotation of the display.
* </p><p>
* The real size may be smaller than the physical size of the screen when the
- * window manager is emulating a smaller display (using adb shell wm size).
+ * window manager is emulating a smaller display (using adb shell am display-size).
* </p>
*
* @param outSize Set to the real size of the display.
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index f559d42..e590739 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -114,6 +114,9 @@
SurfaceSession mSurfaceSession;
SurfaceControl mSurfaceControl;
+ // In the case of format changes we switch out the surface in-place
+ // we need to preserve the old one until the new one has drawn.
+ SurfaceControl mDeferredDestroySurfaceControl;
final Rect mTmpRect = new Rect();
final Configuration mConfiguration = new Configuration();
@@ -475,6 +478,7 @@
if (creating) {
mSurfaceSession = new SurfaceSession(viewRoot.mSurface);
+ mDeferredDestroySurfaceControl = mSurfaceControl;
mSurfaceControl = new SurfaceControl(mSurfaceSession,
"SurfaceView - " + viewRoot.getTitle().toString(),
mSurfaceWidth, mSurfaceHeight, mFormat,
@@ -676,6 +680,12 @@
Log.i(TAG, System.identityHashCode(this) + " "
+ "finishedDrawing");
}
+
+ if (mDeferredDestroySurfaceControl != null) {
+ mDeferredDestroySurfaceControl.destroy();
+ mDeferredDestroySurfaceControl = null;
+ }
+
mHandler.sendEmptyMessage(DRAW_FINISHED_MSG);
}
diff --git a/core/java/com/android/internal/app/ToolbarActionBar.java b/core/java/com/android/internal/app/ToolbarActionBar.java
index 74424f6..7ce5fc3 100644
--- a/core/java/com/android/internal/app/ToolbarActionBar.java
+++ b/core/java/com/android/internal/app/ToolbarActionBar.java
@@ -419,6 +419,11 @@
}
@Override
+ public boolean closeOptionsMenu() {
+ return mDecorToolbar.hideOverflowMenu();
+ }
+
+ @Override
public boolean invalidateOptionsMenu() {
mDecorToolbar.getViewGroup().removeCallbacks(mMenuInvalidator);
mDecorToolbar.getViewGroup().postOnAnimation(mMenuInvalidator);
diff --git a/core/java/com/android/internal/notification/SystemNotificationChannels.java b/core/java/com/android/internal/notification/SystemNotificationChannels.java
index c840f26..ef20750 100644
--- a/core/java/com/android/internal/notification/SystemNotificationChannels.java
+++ b/core/java/com/android/internal/notification/SystemNotificationChannels.java
@@ -14,10 +14,13 @@
package com.android.internal.notification;
+import android.app.INotificationManager;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context;
+import android.content.pm.ParceledListSlice;
+import android.os.RemoteException;
import android.provider.Settings;
import com.android.internal.R;
@@ -69,6 +72,8 @@
context.getString(R.string.notification_channel_car_mode),
NotificationManager.IMPORTANCE_LOW));
+ channelsList.add(newAccountChannel(context));
+
channelsList.add(new NotificationChannel(
DEVELOPER,
context.getString(R.string.notification_channel_developer),
@@ -121,15 +126,23 @@
NotificationManager.IMPORTANCE_MIN));
nm.createNotificationChannels(channelsList);
- createAccountChannelForPackage(context.getPackageName(), context);
}
- public static void createAccountChannelForPackage(String pkg, Context context) {
- final NotificationManager nm = context.getSystemService(NotificationManager.class);
- nm.createNotificationChannelsForPackage(pkg, Arrays.asList(new NotificationChannel(
+ public static void createAccountChannelForPackage(String pkg, int uid, Context context) {
+ final INotificationManager iNotificationManager = NotificationManager.getService();
+ try {
+ iNotificationManager.createNotificationChannelsForPackage(pkg, uid,
+ new ParceledListSlice(Arrays.asList(newAccountChannel(context))));
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ private static NotificationChannel newAccountChannel(Context context) {
+ return new NotificationChannel(
ACCOUNT,
context.getString(R.string.notification_channel_account),
- NotificationManager.IMPORTANCE_LOW)));
+ NotificationManager.IMPORTANCE_LOW);
}
private SystemNotificationChannels() {}
diff --git a/core/java/com/android/internal/view/menu/CascadingMenuPopup.java b/core/java/com/android/internal/view/menu/CascadingMenuPopup.java
index 1de0af6..ebcec5c 100644
--- a/core/java/com/android/internal/view/menu/CascadingMenuPopup.java
+++ b/core/java/com/android/internal/view/menu/CascadingMenuPopup.java
@@ -441,9 +441,11 @@
popupWindow.show();
+ final ListView listView = popupWindow.getListView();
+ listView.setOnKeyListener(this);
+
// If this is the root menu, show the title if requested.
if (parentInfo == null && mShowTitle && menu.getHeaderTitle() != null) {
- final ListView listView = popupWindow.getListView();
final FrameLayout titleItemView = (FrameLayout) inflater.inflate(
R.layout.popup_menu_header_item_layout, listView, false);
final TextView titleView = (TextView) titleItemView.findViewById(R.id.title);
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 64e1620e..da5d04d 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -212,6 +212,7 @@
external/giflib \
external/pdfium/public \
external/skia/include/private \
+ external/skia/src/codec \
external/skia/src/core \
external/skia/src/effects \
external/skia/src/image \
diff --git a/packages/SettingsLib/res/values/arrays.xml b/packages/SettingsLib/res/values/arrays.xml
index 9ff22c7..0bf1fa4 100644
--- a/packages/SettingsLib/res/values/arrays.xml
+++ b/packages/SettingsLib/res/values/arrays.xml
@@ -102,6 +102,19 @@
<!-- Bluetooth settings -->
+ <!-- Titles for Bluetooth AVRCP Versions -->
+ <string-array name="bluetooth_avrcp_versions">
+ <item>AVRCP 1.4 (Default)</item>
+ <item>AVRCP 1.5</item>
+ <item>AVRCP 1.6</item>
+ </string-array>
+
+ <!-- Values for Bluetooth AVRCP Versions -->
+ <string-array name="bluetooth_avrcp_version_values">
+ <item>avrcp14</item>
+ <item>avrcp15</item>
+ <item>avrcp16</item>
+ </string-array>
<!-- Titles for Bluetooth Audio Codec selection preference. [CHAR LIMIT=50] -->
<string-array name="bluetooth_a2dp_codec_titles">
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index f6c5ade..ca34bb9 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -432,6 +432,11 @@
<!-- Setting Checkbox title for disabling Bluetooth absolute volume -->
<string name="bluetooth_disable_absolute_volume">Disable absolute volume</string>
+ <!-- UI debug setting: Select Bluetooth AVRCP Version -->
+ <string name="bluetooth_select_avrcp_version_string">Bluetooth AVRCP Version</string>
+ <!-- UI debug setting: Select Bluetooth AVRCP Version -->
+ <string name="bluetooth_select_avrcp_version_dialog_title">Select Bluetooth AVRCP Version</string>
+
<!-- UI debug setting: Select Bluetooth Audio Codec -->
<string name="bluetooth_select_a2dp_codec_type">Bluetooth Audio Codec</string>
<!-- UI debug setting: Select Bluetooth Audio Codec -->
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 490e63d..01fc8ec 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -3697,11 +3697,11 @@
if (ArrayUtils.isEmpty(packageNames)) {
return null;
}
- // For app op checks related to permissions all packages in the UID
- // have the same app op state, so doesn't matter which one we pick.
- // Update: due to visibility changes we want to use package with oldest target SDK,
-
String packageName = packageNames[0];
+ if (packageNames.length == 1) {
+ return packageName;
+ }
+ // Due to visibility changes we want to use package with oldest target SDK
int oldestVersion = Integer.MAX_VALUE;
for (String name : packageNames) {
try {
@@ -5677,7 +5677,7 @@
synchronized (mUsers) {
userAccounts = mUsers.get(userId);
}
- SystemNotificationChannels.createAccountChannelForPackage(packageName, mContext);
+ SystemNotificationChannels.createAccountChannelForPackage(packageName, uid, mContext);
doNotification(userAccounts, account, null, intent, packageName, userId);
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 2be5e77..92a4b78 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -7870,10 +7870,11 @@
r.pictureInPictureArgs.copyOnlySet(args);
final float aspectRatio = r.pictureInPictureArgs.getAspectRatio();
final List<RemoteAction> actions = r.pictureInPictureArgs.getActions();
- final Rect bounds = mWindowManager.getPictureInPictureBounds(DEFAULT_DISPLAY,
+ final Rect sourceBounds = r.pictureInPictureArgs.getSourceRectHint();
+ final Rect destBounds = mWindowManager.getPictureInPictureBounds(DEFAULT_DISPLAY,
aspectRatio);
- mStackSupervisor.moveActivityToPinnedStackLocked(r, "enterPictureInPictureMode",
- bounds, true /* moveHomeStackToFront */);
+ mStackSupervisor.moveActivityToPinnedStackLocked(r, sourceBounds, destBounds,
+ true /* moveHomeStackToFront */, "enterPictureInPictureMode");
final PinnedActivityStack stack = mStackSupervisor.getStack(PINNED_STACK_ID);
stack.setPictureInPictureAspectRatio(aspectRatio);
stack.setPictureInPictureActions(actions);
@@ -10525,7 +10526,7 @@
}
@Override
- public void resizeStack(int stackId, Rect bounds, boolean allowResizeInDockedMode,
+ public void resizeStack(int stackId, Rect destBounds, boolean allowResizeInDockedMode,
boolean preserveWindows, boolean animate, int animationDuration) {
enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "resizeStack()");
long ident = Binder.clearCallingIdentity();
@@ -10535,13 +10536,14 @@
if (stackId == PINNED_STACK_ID) {
final PinnedActivityStack pinnedStack =
mStackSupervisor.getStack(PINNED_STACK_ID);
- pinnedStack.animateResizePinnedStack(bounds, animationDuration);
+ pinnedStack.animateResizePinnedStack(null /* sourceBounds */, destBounds,
+ animationDuration);
} else {
throw new IllegalArgumentException("Stack: " + stackId
+ " doesn't support animated resize.");
}
} else {
- mStackSupervisor.resizeStackLocked(stackId, bounds, null /* tempTaskBounds */,
+ mStackSupervisor.resizeStackLocked(stackId, destBounds, null /* tempTaskBounds */,
null /* tempTaskInsetBounds */, preserveWindows,
allowResizeInDockedMode, !DEFER_RESUME);
}
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 5c49dfd..97d0aa3 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -2295,17 +2295,8 @@
mResizingTasksDuringAnimation.clear();
}
- private class MoveTaskToFullscreenArgs {
- public int fromStackId;
- public boolean onTop;
- };
- // Used only to closure over the arguments to moveTasksToFullscreenStack without
- // allocation
- private MoveTaskToFullscreenArgs mMoveToFullscreenArgs = new MoveTaskToFullscreenArgs();
-
- private void moveTasksToFullscreenStackInnerLocked() {
- int fromStackId = mMoveToFullscreenArgs.fromStackId;
- boolean onTop = mMoveToFullscreenArgs.onTop;
+ private void moveTasksToFullscreenStackInSurfaceTransaction(int fromStackId,
+ boolean onTop) {
final ActivityStack stack = getStack(fromStackId);
if (stack == null) {
@@ -2379,10 +2370,8 @@
}
void moveTasksToFullscreenStackLocked(int fromStackId, boolean onTop) {
- mMoveToFullscreenArgs.fromStackId = fromStackId;
- mMoveToFullscreenArgs.onTop = onTop;
-
- mWindowManager.inSurfaceTransaction(this::moveTasksToFullscreenStackInnerLocked);
+ mWindowManager.inSurfaceTransaction(
+ () -> moveTasksToFullscreenStackInSurfaceTransaction(fromStackId, onTop));
}
void resizeDockedStackLocked(Rect dockedBounds, Rect tempDockedTaskBounds,
@@ -2498,11 +2487,7 @@
}
- // Used only to closure over the argument to removeStack without allocation.
- private int mRemoveStackStackId;
- void removeStackInnerLocked() {
- int stackId = mRemoveStackStackId;
-
+ void removeStackInSurfaceTransaction(int stackId) {
final ActivityStack stack = getStack(stackId);
if (stack == null) {
return;
@@ -2546,8 +2531,8 @@
* instead moved back onto the fullscreen stack.
*/
void removeStackLocked(int stackId) {
- mRemoveStackStackId = stackId;
- mWindowManager.inSurfaceTransaction(this::removeStackInnerLocked);
+ mWindowManager.inSurfaceTransaction(
+ () -> removeStackInSurfaceTransaction(stackId));
}
/**
@@ -2794,7 +2779,7 @@
}
}
- boolean moveTopStackActivityToPinnedStackLocked(int stackId, Rect bounds) {
+ boolean moveTopStackActivityToPinnedStackLocked(int stackId, Rect destBounds) {
final ActivityStack stack = getStack(stackId, !CREATE_IF_NEEDED, !ON_TOP);
if (stack == null) {
throw new IllegalArgumentException(
@@ -2815,13 +2800,14 @@
return false;
}
- moveActivityToPinnedStackLocked(r, "moveTopActivityToPinnedStack", bounds,
- true /* moveHomeStackToFront */);
+ moveActivityToPinnedStackLocked(r, null /* sourceBounds */, destBounds,
+ true /* moveHomeStackToFront */, "moveTopActivityToPinnedStack");
return true;
}
- void moveActivityToPinnedStackLocked(ActivityRecord r, String reason, Rect bounds,
- boolean moveHomeStackToFront) {
+ void moveActivityToPinnedStackLocked(ActivityRecord r, Rect sourceBounds, Rect destBounds,
+ boolean moveHomeStackToFront, String reason) {
+
mWindowManager.deferSurfaceLayout();
// Need to make sure the pinned stack exist so we can resize it below...
@@ -2889,7 +2875,7 @@
ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
resumeFocusedStackTopActivityLocked();
- stack.animateResizePinnedStack(bounds, -1 /* animationDuration */);
+ stack.animateResizePinnedStack(sourceBounds, destBounds, -1 /* animationDuration */);
mService.mTaskChangeNotificationController.notifyActivityPinned(r.packageName);
}
diff --git a/services/core/java/com/android/server/am/PinnedActivityStack.java b/services/core/java/com/android/server/am/PinnedActivityStack.java
index 1708fe5..32d3082 100644
--- a/services/core/java/com/android/server/am/PinnedActivityStack.java
+++ b/services/core/java/com/android/server/am/PinnedActivityStack.java
@@ -41,8 +41,9 @@
return new PinnedStackWindowController(mStackId, this, displayId, onTop, outBounds);
}
- void animateResizePinnedStack(Rect bounds, int animationDuration) {
- getWindowContainerController().animateResizePinnedStack(bounds, animationDuration);
+ void animateResizePinnedStack(Rect sourceBounds, Rect destBounds, int animationDuration) {
+ getWindowContainerController().animateResizePinnedStack(sourceBounds, destBounds,
+ animationDuration);
}
void setPictureInPictureAspectRatio(float aspectRatio) {
diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java
index f9bc12b..a947b41 100644
--- a/services/core/java/com/android/server/display/LogicalDisplay.java
+++ b/services/core/java/com/android/server/display/LogicalDisplay.java
@@ -62,18 +62,7 @@
private final int mDisplayId;
private final int mLayerStack;
- /**
- * Override information set by the window manager. Will be reported instead of {@link #mInfo}
- * if not null.
- * @see #setDisplayInfoOverrideFromWindowManagerLocked(DisplayInfo)
- * @see #getDisplayInfoLocked()
- */
- private DisplayInfo mOverrideDisplayInfo;
- /**
- * Current display info. Initialized with {@link #mBaseDisplayInfo}. Set to {@code null} if
- * needs to be updated.
- * @see #getDisplayInfoLocked()
- */
+ private DisplayInfo mOverrideDisplayInfo; // set by the window manager
private DisplayInfo mInfo;
// The display device that this logical display is based on and which
@@ -272,9 +261,6 @@
mPrimaryDisplayDeviceInfo = deviceInfo;
mInfo = null;
- // Make sure that WM will be notified of new changes. It will then decide whether to
- // apply them or not and will set the value again.
- mOverrideDisplayInfo = null;
}
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 408f85e..a1aeeea 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -1633,22 +1633,34 @@
savePolicyFile();
}
- @Override
- public void createNotificationChannels(String pkg,
- ParceledListSlice channelsList) throws RemoteException {
- checkCallerIsSystemOrSameApp(pkg);
+ private void createNotificationChannelsImpl(String pkg, int uid,
+ ParceledListSlice channelsList) {
List<NotificationChannel> channels = channelsList.getList();
final int channelsSize = channels.size();
for (int i = 0; i < channelsSize; i++) {
final NotificationChannel channel = channels.get(i);
Preconditions.checkNotNull(channel, "channel in list is null");
- mRankingHelper.createNotificationChannel(pkg, Binder.getCallingUid(), channel,
+ mRankingHelper.createNotificationChannel(pkg, uid, channel,
true /* fromTargetApp */);
}
savePolicyFile();
}
@Override
+ public void createNotificationChannels(String pkg,
+ ParceledListSlice channelsList) throws RemoteException {
+ checkCallerIsSystemOrSameApp(pkg);
+ createNotificationChannelsImpl(pkg, Binder.getCallingUid(), channelsList);
+ }
+
+ @Override
+ public void createNotificationChannelsForPackage(String pkg, int uid,
+ ParceledListSlice channelsList) throws RemoteException {
+ checkCallerIsSystem();
+ createNotificationChannelsImpl(pkg, uid, channelsList);
+ }
+
+ @Override
public NotificationChannel getNotificationChannel(String pkg, String channelId) {
checkCallerIsSystemOrSameApp(pkg);
return mRankingHelper.getNotificationChannel(
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 96e2626..25f9c30 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -16692,6 +16692,16 @@
+ " target SDK " + oldTargetSdk + " does.");
return;
}
+ // Prevent apps from downgrading their targetSandbox.
+ final int oldTargetSandbox = oldPackage.applicationInfo.targetSandboxVersion;
+ final int newTargetSandbox = pkg.applicationInfo.targetSandboxVersion;
+ if (oldTargetSandbox == 2 && newTargetSandbox != 2) {
+ res.setError(PackageManager.INSTALL_FAILED_SANDBOX_VERSION_DOWNGRADE,
+ "Package " + pkg.packageName + " new target sandbox "
+ + newTargetSandbox + " is incompatible with the previous value of"
+ + oldTargetSandbox + ".");
+ return;
+ }
// Prevent installing of child packages
if (oldPackage.parentPackage != null) {
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 111fbd3f..d1f1305 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -368,6 +368,10 @@
mEnteringAnimation = true;
mService.mActivityManagerAppTransitionNotifier.onAppTransitionFinishedLocked(token);
}
+ // If we are hidden but there is no delay needed we immediately
+ // apply the Surface transaction so that the ActivityManager
+ // can have some guarantee on the Surface state
+ // following setting the visibility.
if (hidden && !delayed) {
SurfaceControl.openTransaction();
for (int i = mChildren.size() - 1; i >= 0; i--) {
diff --git a/services/core/java/com/android/server/wm/BoundsAnimationController.java b/services/core/java/com/android/server/wm/BoundsAnimationController.java
index cd0e6cc..62414e5 100644
--- a/services/core/java/com/android/server/wm/BoundsAnimationController.java
+++ b/services/core/java/com/android/server/wm/BoundsAnimationController.java
@@ -121,8 +121,8 @@
private final int mFrozenTaskWidth;
private final int mFrozenTaskHeight;
- BoundsAnimator(AnimateBoundsUser target, Rect from, Rect to,
- boolean moveToFullScreen, boolean replacement) {
+ BoundsAnimator(AnimateBoundsUser target, Rect from, Rect to, boolean moveToFullScreen,
+ boolean replacement) {
super();
mTarget = target;
mFrom.set(from);
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 01a992f..e5b00f3 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -179,23 +179,11 @@
// Mapping from a token IBinder to a WindowToken object on this display.
private final HashMap<IBinder, WindowToken> mTokenMap = new HashMap();
- // Initial display metrics.
int mInitialDisplayWidth = 0;
int mInitialDisplayHeight = 0;
int mInitialDisplayDensity = 0;
-
- /**
- * Overridden display size. Initialized with {@link #mInitialDisplayWidth}
- * and {@link #mInitialDisplayHeight}, but can be set via shell command "adb shell wm size".
- * @see WindowManagerService#setForcedDisplaySize(int, int, int)
- */
int mBaseDisplayWidth = 0;
int mBaseDisplayHeight = 0;
- /**
- * Overridden display density for current user. Initialized with {@link #mInitialDisplayDensity}
- * but can be set from Settings or via shell command "adb shell wm density".
- * @see WindowManagerService#setForcedDisplayDensityForUser(int, int, int)
- */
int mBaseDisplayDensity = 0;
boolean mDisplayScalingDisabled;
private final DisplayInfo mDisplayInfo = new DisplayInfo();
@@ -1523,10 +1511,6 @@
void updateDisplayInfo() {
mDisplay.getDisplayInfo(mDisplayInfo);
mDisplay.getMetrics(mDisplayMetrics);
-
- // Check if display metrics changed and update base values if needed.
- updateBaseDisplayMetricsIfNeeded();
-
for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
mTaskStackContainers.get(i).updateDisplayInfo(null);
}
@@ -1542,11 +1526,10 @@
}
}
- updateBaseDisplayMetrics(mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight,
- mDisplayInfo.logicalDensityDpi);
- mInitialDisplayWidth = mDisplayInfo.logicalWidth;
- mInitialDisplayHeight = mDisplayInfo.logicalHeight;
- mInitialDisplayDensity = mDisplayInfo.logicalDensityDpi;
+ mBaseDisplayWidth = mInitialDisplayWidth = mDisplayInfo.logicalWidth;
+ mBaseDisplayHeight = mInitialDisplayHeight = mDisplayInfo.logicalHeight;
+ mBaseDisplayDensity = mInitialDisplayDensity = mDisplayInfo.logicalDensityDpi;
+ mBaseDisplayRect.set(0, 0, mBaseDisplayWidth, mBaseDisplayHeight);
}
void getLogicalDisplayRect(Rect out) {
@@ -1576,50 +1559,6 @@
}
}
- /**
- * If display metrics changed, overrides are not set and it's not just a rotation - update base
- * values.
- */
- private void updateBaseDisplayMetricsIfNeeded() {
- final int orientation = mDisplayInfo.rotation;
- final boolean rotated = (orientation == ROTATION_90 || orientation == ROTATION_270);
- final int newWidth = rotated ? mDisplayInfo.logicalHeight : mDisplayInfo.logicalWidth;
- final int newHeight = rotated ? mDisplayInfo.logicalWidth : mDisplayInfo.logicalHeight;
- int density = mDisplayInfo.logicalDensityDpi;
-
- boolean displayMetricsChanged = false;
-
- // Check if display size is not forced and changed in new display info.
- boolean isDisplaySizeForced = mBaseDisplayWidth != mInitialDisplayWidth
- || mBaseDisplayHeight != mInitialDisplayHeight;
- if (!isDisplaySizeForced) {
- displayMetricsChanged = mBaseDisplayWidth != newWidth
- || mBaseDisplayHeight != newHeight;
- }
-
- // Check if display density is not forced and changed in new display info.
- final int forcedDensity = mBaseDisplayDensity != mInitialDisplayDensity
- ? mBaseDisplayDensity : 0;
- if (forcedDensity != 0) {
- density = forcedDensity;
- } else {
- displayMetricsChanged |= mBaseDisplayDensity != mDisplayInfo.logicalDensityDpi;
- }
-
- if (displayMetricsChanged) {
- updateBaseDisplayMetrics(newWidth, newHeight, density);
- mService.reconfigureDisplayLocked(this);
- }
- }
-
- /** Update base (override) display metrics. */
- void updateBaseDisplayMetrics(int baseWidth, int baseHeight, int baseDensity) {
- mBaseDisplayWidth = baseWidth;
- mBaseDisplayHeight = baseHeight;
- mBaseDisplayDensity = baseDensity;
- mBaseDisplayRect.set(0, 0, mBaseDisplayWidth, mBaseDisplayHeight);
- }
-
void getContentRect(Rect out) {
out.set(mContentRect);
}
diff --git a/services/core/java/com/android/server/wm/PinnedStackWindowController.java b/services/core/java/com/android/server/wm/PinnedStackWindowController.java
index 34ccf87..0145454 100644
--- a/services/core/java/com/android/server/wm/PinnedStackWindowController.java
+++ b/services/core/java/com/android/server/wm/PinnedStackWindowController.java
@@ -40,29 +40,30 @@
/**
* Animates the pinned stack.
*/
- public void animateResizePinnedStack(Rect bounds, int animationDuration) {
+ public void animateResizePinnedStack(Rect sourceBounds, Rect destBounds,
+ int animationDuration) {
synchronized (mWindowMap) {
if (mContainer == null) {
throw new IllegalArgumentException("Pinned stack container not found :(");
}
// Get non-null fullscreen bounds if the bounds are null
- final boolean moveToFullscreen = bounds == null;
- bounds = getPinnedStackAnimationBounds(bounds);
+ final boolean moveToFullscreen = destBounds == null;
+ destBounds = getPinnedStackAnimationBounds(destBounds);
// If the bounds are truly null, then there was no fullscreen stack at this time, so
// animate this to the full display bounds
final Rect toBounds;
- if (bounds == null) {
+ if (destBounds == null) {
toBounds = new Rect();
mContainer.getDisplayContent().getLogicalDisplayRect(toBounds);
} else {
- toBounds = bounds;
+ toBounds = destBounds;
}
final Rect originalBounds = new Rect();
mContainer.getBounds(originalBounds);
- mContainer.setAnimatingBounds(toBounds);
+ mContainer.setAnimatingBounds(sourceBounds, toBounds);
UiThread.getHandler().post(() -> {
if (mContainer == null) {
return;
@@ -82,13 +83,17 @@
return;
}
+ final int displayId = mContainer.getDisplayContent().getDisplayId();
+ final Rect toBounds = mService.getPictureInPictureBounds(displayId, aspectRatio);
+ final Rect targetBounds = new Rect();
+ mContainer.getAnimatingBounds(targetBounds);
final PinnedStackController pinnedStackController =
mContainer.getDisplayContent().getPinnedStackController();
if (Float.compare(aspectRatio, pinnedStackController.getAspectRatio()) != 0) {
- final int displayId = mContainer.getDisplayContent().getDisplayId();
- final Rect toBounds = mService.getPictureInPictureBounds(displayId, aspectRatio);
- animateResizePinnedStack(toBounds, -1 /* duration */);
+ if (!toBounds.equals(targetBounds)) {
+ animateResizePinnedStack(null /* sourceBounds */, toBounds, -1 /* duration */);
+ }
pinnedStackController.setAspectRatio(
pinnedStackController.isValidPictureInPictureAspectRatio(aspectRatio)
? aspectRatio : -1f);
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 442cd54..dc437ea 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -19,7 +19,6 @@
import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT;
import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
-import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.HOME_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
@@ -128,6 +127,7 @@
private boolean mBoundsAnimating = false;
private boolean mBoundsAnimatingToFullscreen = false;
private Rect mBoundsAnimationTarget = new Rect();
+ private Rect mBoundsAnimationSourceBounds = new Rect();
// Temporary storage for the new bounds that should be used after the configuration change.
// Will be cleared once the client retrieves the new bounds via getBoundsForNewConfiguration().
@@ -323,15 +323,31 @@
* Sets the bounds animation target bounds. This can't currently be done in onAnimationStart()
* since that is started on the UiThread.
*/
- void setAnimatingBounds(Rect bounds) {
- if (bounds != null) {
- mBoundsAnimationTarget.set(bounds);
+ void setAnimatingBounds(Rect sourceBounds, Rect destBounds) {
+ if (sourceBounds != null) {
+ mBoundsAnimationSourceBounds.set(sourceBounds);
+ } else {
+ mBoundsAnimationSourceBounds.setEmpty();
+ }
+ if (destBounds != null) {
+ mBoundsAnimationTarget.set(destBounds);
} else {
mBoundsAnimationTarget.setEmpty();
}
}
/**
+ * @return the source bounds for the bounds animation.
+ */
+ void getAnimatingSourceBounds(Rect outBounds) {
+ if (mBoundsAnimationSourceBounds != null) {
+ outBounds.set(mBoundsAnimationSourceBounds);
+ return;
+ }
+ outBounds.setEmpty();
+ }
+
+ /**
* @return the bounds that the task stack is currently being animated towards, or the current
* stack bounds if there is no animation in progress.
*/
@@ -1465,7 +1481,6 @@
public void onAnimationEnd() {
synchronized (mService.mWindowMap) {
mBoundsAnimating = false;
- mBoundsAnimationTarget.setEmpty();
mService.requestTraversal();
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index dd2689b..fa9c2a7 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -5305,8 +5305,8 @@
if (displayContent.mBaseDisplayWidth != width
|| displayContent.mBaseDisplayHeight != height) {
Slog.i(TAG_WM, "FORCED DISPLAY SIZE: " + width + "x" + height);
- displayContent.updateBaseDisplayMetrics(width, height,
- displayContent.mBaseDisplayDensity);
+ displayContent.mBaseDisplayWidth = width;
+ displayContent.mBaseDisplayHeight = height;
}
} catch (NumberFormatException ex) {
}
@@ -5331,7 +5331,8 @@
// displayContent must not be null
private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) {
Slog.i(TAG_WM, "Using new display size: " + width + "x" + height);
- displayContent.updateBaseDisplayMetrics(width, height, displayContent.mBaseDisplayDensity);
+ displayContent.mBaseDisplayWidth = width;
+ displayContent.mBaseDisplayHeight = height;
reconfigureDisplayLocked(displayContent);
}
@@ -7316,7 +7317,6 @@
* WARNING: This method contains locks known to the State of California
* to cause Deadlocks and other conditions.
*
- *
* Begins a surface transaction with which the AM can batch operations.
* All Surface updates performed by the WindowManager following this
* will not appear on screen until after the call to
@@ -7329,7 +7329,6 @@
* from the new parent are inherited, otherwise it could be revealed
* mistakenly.
*
- *
* TODO(b/36393204): We can investigate totally replacing #deferSurfaceLayout
* with something like this but it seems that some existing cases of
* deferSurfaceLayout may be a little too broad, in particular the total
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 48de7e4..826fb45 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -67,8 +67,6 @@
import android.view.animation.AnimationUtils;
import android.view.animation.Transformation;
-import com.android.server.wm.WindowManagerService.H;
-
import java.io.PrintWriter;
import java.io.FileDescriptor;
@@ -156,6 +154,8 @@
Rect mLastClipRect = new Rect();
Rect mLastFinalClipRect = new Rect();
Rect mTmpStackBounds = new Rect();
+ private Rect mTmpAnimatingBounds = new Rect();
+ private Rect mTmpSourceBounds = new Rect();
/**
* This is rectangle of the window's surface that is not covered by
@@ -1282,6 +1282,7 @@
void setSurfaceBoundariesLocked(final boolean recoveringMemory) {
final WindowState w = mWin;
+ final LayoutParams attrs = mWin.getAttrs();
final Task task = w.getTask();
// We got resized, so block all updates until we got the new surface.
@@ -1290,7 +1291,7 @@
}
mTmpSize.set(w.mShownPosition.x, w.mShownPosition.y, 0, 0);
- calculateSurfaceBounds(w, w.getAttrs());
+ calculateSurfaceBounds(w, attrs);
mExtraHScale = (float) 1.0;
mExtraVScale = (float) 1.0;
@@ -1329,23 +1330,59 @@
float surfaceHeight = mSurfaceController.getHeight();
if (isForceScaled()) {
- int hInsets = w.getAttrs().surfaceInsets.left + w.getAttrs().surfaceInsets.right;
- int vInsets = w.getAttrs().surfaceInsets.top + w.getAttrs().surfaceInsets.bottom;
+ int hInsets = attrs.surfaceInsets.left + attrs.surfaceInsets.right;
+ int vInsets = attrs.surfaceInsets.top + attrs.surfaceInsets.bottom;
+ float surfaceContentWidth = surfaceWidth - hInsets;
+ float surfaceContentHeight = surfaceHeight - vInsets;
if (!mForceScaleUntilResize) {
mSurfaceController.forceScaleableInTransaction(true);
}
+ int posX = mTmpSize.left;
+ int posY = mTmpSize.top;
task.mStack.getDimBounds(mTmpStackBounds);
- // We want to calculate the scaling based on the content area, not based on
- // the entire surface, so that we scale in sync with windows that don't have insets.
- mExtraHScale = mTmpStackBounds.width() / (float)(surfaceWidth - hInsets);
- mExtraVScale = mTmpStackBounds.height() / (float)(surfaceHeight - vInsets);
+ task.mStack.getAnimatingSourceBounds(mTmpSourceBounds);
+ if (!mTmpSourceBounds.isEmpty()) {
+ // Get the final target stack bounds, if we are not animating, this is just the
+ // current stack bounds
+ task.mStack.getAnimatingBounds(mTmpAnimatingBounds);
+
+ // Calculate the current progress and interpolate the difference between the target
+ // and source bounds
+ float finalWidth = mTmpAnimatingBounds.width();
+ float initialWidth = mTmpSourceBounds.width();
+ float t = (surfaceContentWidth - mTmpStackBounds.width())
+ / (surfaceContentWidth - mTmpAnimatingBounds.width());
+ mExtraHScale = (initialWidth + t * (finalWidth - initialWidth)) / initialWidth;
+ mExtraVScale = mExtraHScale;
+
+ // Adjust the position to account for the inset bounds
+ posX -= (int) (t * mExtraHScale * mTmpSourceBounds.left);
+ posY -= (int) (t * mExtraVScale * mTmpSourceBounds.top);
+
+ // Always clip to the stack bounds since the surface can be larger with the current
+ // scale
+ clipRect = null;
+ finalClipRect = mTmpStackBounds;
+ } else {
+ // We want to calculate the scaling based on the content area, not based on
+ // the entire surface, so that we scale in sync with windows that don't have insets.
+ mExtraHScale = mTmpStackBounds.width() / surfaceContentWidth;
+ mExtraVScale = mTmpStackBounds.height() / surfaceContentHeight;
+
+ // Since we are scaled to fit in our previously desired crop, we can now
+ // expose the whole window in buffer space, and not risk extending
+ // past where the system would have cropped us
+ clipRect = null;
+ finalClipRect = null;
+ }
// In the case of ForceScaleToStack we scale entire tasks together,
// and so we need to scale our offsets relative to the task bounds
// or parent and child windows would fall out of alignment.
- int posX = (int) (mTmpSize.left - w.mAttrs.x * (1 - mExtraHScale));
- int posY = (int) (mTmpSize.top - w.mAttrs.y * (1 - mExtraVScale));
+ posX -= (int) (attrs.x * (1 - mExtraHScale));
+ posY -= (int) (attrs.y * (1 - mExtraVScale));
+
// Imagine we are scaling down. As we scale the buffer down, we decrease the
// distance between the surface top left, and the start of the surface contents
// (previously it was surfaceInsets.left pixels in screen space but now it
@@ -1353,17 +1390,11 @@
// non inset content at the same position, we have to shift the whole window
// forward. Likewise for scaling up, we've increased this distance, and we need
// to shift by a negative number to compensate.
- posX += w.getAttrs().surfaceInsets.left * (1 - mExtraHScale);
- posY += w.getAttrs().surfaceInsets.top * (1 - mExtraVScale);
+ posX += attrs.surfaceInsets.left * (1 - mExtraHScale);
+ posY += attrs.surfaceInsets.top * (1 - mExtraVScale);
- mSurfaceController.setPositionInTransaction((float)Math.floor(posX),
- (float)Math.floor(posY), recoveringMemory);
-
- // Since we are scaled to fit in our previously desired crop, we can now
- // expose the whole window in buffer space, and not risk extending
- // past where the system would have cropped us
- clipRect = null;
- finalClipRect = null;
+ mSurfaceController.setPositionInTransaction((float) Math.floor(posX),
+ (float) Math.floor(posY), recoveringMemory);
// Various surfaces in the scaled stack may resize at different times.
// We need to ensure for each surface, that we disable transformation matrix
diff --git a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
index 308632f..374aee1 100644
--- a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
@@ -22,7 +22,6 @@
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.nullable;
import static org.mockito.Mockito.times;
@@ -32,7 +31,6 @@
import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.AccountManagerInternal;
-import android.accounts.AuthenticatorDescription;
import android.accounts.CantAddAccountActivity;
import android.accounts.IAccountManagerResponse;
import android.app.AppOpsManager;
@@ -49,11 +47,9 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
-import android.content.pm.RegisteredServicesCacheListener;
import android.content.pm.ResolveInfo;
import android.content.pm.Signature;
import android.content.pm.UserInfo;
-import android.content.pm.RegisteredServicesCache.ServiceInfo;
import android.database.Cursor;
import android.database.DatabaseErrorHandler;
import android.database.sqlite.SQLiteDatabase;
@@ -62,6 +58,7 @@
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
+import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
import android.test.AndroidTestCase;
@@ -78,16 +75,18 @@
import org.mockito.MockitoAnnotations;
import java.io.File;
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
import java.security.GeneralSecurityException;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collection;
+import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.CyclicBarrier;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicLong;
/**
@@ -2616,6 +2615,142 @@
}
}
+ @SmallTest
+ public void testConcurrencyReadWrite() throws Exception {
+ // Test 2 threads calling getAccounts and 1 thread setAuthToken
+ unlockSystemUser();
+ String[] list = new String[]{AccountManagerServiceTestFixtures.CALLER_PACKAGE};
+ when(mMockPackageManager.getPackagesForUid(anyInt())).thenReturn(list);
+
+ Account a1 = new Account("account1",
+ AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1);
+ mAms.addAccountExplicitly(a1, "p1", null);
+ List<String> errors = Collections.synchronizedList(new ArrayList<>());
+ int readerCount = 2;
+ ExecutorService es = Executors.newFixedThreadPool(readerCount + 1);
+ AtomicLong readTotalTime = new AtomicLong(0);
+ AtomicLong writeTotalTime = new AtomicLong(0);
+ final CyclicBarrier cyclicBarrier = new CyclicBarrier(readerCount + 1);
+
+ final int loopSize = 20;
+ for (int t = 0; t < readerCount; t++) {
+ es.submit(() -> {
+ for (int i = 0; i < loopSize; i++) {
+ String logPrefix = Thread.currentThread().getName() + " " + i;
+ waitForCyclicBarrier(cyclicBarrier);
+ cyclicBarrier.reset();
+ SystemClock.sleep(1); // Ensure that writer wins
+ Log.d(TAG, logPrefix + " getAccounts started");
+ long ti = System.currentTimeMillis();
+ try {
+ Account[] accounts = mAms.getAccounts(null, mContext.getOpPackageName());
+ if (accounts == null || accounts.length != 1
+ || !AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1.equals(
+ accounts[0].type)) {
+ String msg = logPrefix + ": Unexpected accounts: " + Arrays
+ .toString(accounts);
+ Log.e(TAG, " " + msg);
+ errors.add(msg);
+ }
+ Log.d(TAG, logPrefix + " getAccounts done");
+ } catch (Exception e) {
+ String msg = logPrefix + ": getAccounts failed " + e;
+ Log.e(TAG, msg, e);
+ errors.add(msg);
+ }
+ ti = System.currentTimeMillis() - ti;
+ readTotalTime.addAndGet(ti);
+ }
+ });
+ }
+
+ es.submit(() -> {
+ for (int i = 0; i < loopSize; i++) {
+ String logPrefix = Thread.currentThread().getName() + " " + i;
+ waitForCyclicBarrier(cyclicBarrier);
+ long ti = System.currentTimeMillis();
+ Log.d(TAG, logPrefix + " setAuthToken started");
+ try {
+ mAms.setAuthToken(a1, "t1", "v" + i);
+ Log.d(TAG, logPrefix + " setAuthToken done");
+ } catch (Exception e) {
+ errors.add(logPrefix + ": setAuthToken failed: " + e);
+ }
+ ti = System.currentTimeMillis() - ti;
+ writeTotalTime.addAndGet(ti);
+ }
+ });
+ es.shutdown();
+ assertTrue("Time-out waiting for jobs to finish",
+ es.awaitTermination(10, TimeUnit.SECONDS));
+ es.shutdownNow();
+ assertTrue("Errors: " + errors, errors.isEmpty());
+ Log.i(TAG, "testConcurrencyReadWrite: readTotalTime=" + readTotalTime + " avg="
+ + (readTotalTime.doubleValue() / readerCount / loopSize));
+ Log.i(TAG, "testConcurrencyReadWrite: writeTotalTime=" + writeTotalTime + " avg="
+ + (writeTotalTime.doubleValue() / loopSize));
+ }
+
+ @SmallTest
+ public void testConcurrencyRead() throws Exception {
+ // Test 2 threads calling getAccounts
+ unlockSystemUser();
+ String[] list = new String[]{AccountManagerServiceTestFixtures.CALLER_PACKAGE};
+ when(mMockPackageManager.getPackagesForUid(anyInt())).thenReturn(list);
+
+ Account a1 = new Account("account1",
+ AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1);
+ mAms.addAccountExplicitly(a1, "p1", null);
+ List<String> errors = Collections.synchronizedList(new ArrayList<>());
+ int readerCount = 2;
+ ExecutorService es = Executors.newFixedThreadPool(readerCount + 1);
+ AtomicLong readTotalTime = new AtomicLong(0);
+
+ final int loopSize = 20;
+ for (int t = 0; t < readerCount; t++) {
+ es.submit(() -> {
+ for (int i = 0; i < loopSize; i++) {
+ String logPrefix = Thread.currentThread().getName() + " " + i;
+ Log.d(TAG, logPrefix + " getAccounts started");
+ long ti = System.currentTimeMillis();
+ try {
+ Account[] accounts = mAms.getAccounts(null, mContext.getOpPackageName());
+ if (accounts == null || accounts.length != 1
+ || !AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1.equals(
+ accounts[0].type)) {
+ String msg = logPrefix + ": Unexpected accounts: " + Arrays
+ .toString(accounts);
+ Log.e(TAG, " " + msg);
+ errors.add(msg);
+ }
+ Log.d(TAG, logPrefix + " getAccounts done");
+ } catch (Exception e) {
+ String msg = logPrefix + ": getAccounts failed " + e;
+ Log.e(TAG, msg, e);
+ errors.add(msg);
+ }
+ ti = System.currentTimeMillis() - ti;
+ readTotalTime.addAndGet(ti);
+ }
+ });
+ }
+ es.shutdown();
+ assertTrue("Time-out waiting for jobs to finish",
+ es.awaitTermination(10, TimeUnit.SECONDS));
+ es.shutdownNow();
+ assertTrue("Errors: " + errors, errors.isEmpty());
+ Log.i(TAG, "testConcurrencyRead: readTotalTime=" + readTotalTime + " avg="
+ + (readTotalTime.doubleValue() / readerCount / loopSize));
+ }
+
+ private void waitForCyclicBarrier(CyclicBarrier cyclicBarrier) {
+ try {
+ cyclicBarrier.await(LATCH_TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ } catch (Exception e) {
+ throw new IllegalStateException("Should not throw " + e, e);
+ }
+ }
+
private void waitForLatch(CountDownLatch latch) {
try {
latch.await(LATCH_TIMEOUT_MS, TimeUnit.MILLISECONDS);
diff --git a/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerTestService.java b/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerTestService.java
index a2385d6..b550cfa 100644
--- a/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerTestService.java
+++ b/tests/SoundTriggerTestApp/src/com/android/test/soundtrigger/SoundTriggerTestService.java
@@ -100,7 +100,7 @@
@Override
public void onDestroy() {
super.onDestroy();
- stopAllRecognitions();
+ stopAllRecognitionsAndUnload();
unregisterReceiver(mBroadcastReceiver);
}
@@ -171,7 +171,7 @@
@Override
public void onTaskRemoved(Intent rootIntent) {
super.onTaskRemoved(rootIntent);
- stopAllRecognitions();
+ stopAllRecognitionsAndUnload();
stopSelf();
}
@@ -197,8 +197,10 @@
}
}
- private synchronized void stopAllRecognitions() {
+ private synchronized void stopAllRecognitionsAndUnload() {
+ Log.e(TAG, "Stop all recognitions");
for (ModelInfo modelInfo : mModelInfoMap.values()) {
+ Log.e(TAG, "Loop " + modelInfo.modelUuid);
if (modelInfo.detector != null) {
Log.i(TAG, "Stopping recognition for " + modelInfo.name);
try {
@@ -206,6 +208,12 @@
} catch (Exception e) {
Log.e(TAG, "Failed to stop recognition", e);
}
+ try {
+ mSoundTriggerUtil.deleteSoundModel(modelInfo.modelUuid);
+ modelInfo.detector = null;
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to unload sound model", e);
+ }
}
}
}