Merge "Added two touch slops for easier home press (1/3)" into pi-dev
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 5bb2015..ab9c7e8 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -108,7 +108,7 @@
ResourceConfigurationChanged resource_configuration_changed = 66;
BluetoothEnabledStateChanged bluetooth_enabled_state_changed = 67;
BluetoothConnectionStateChanged bluetooth_connection_state_changed = 68;
- BluetoothA2dpAudioStateChanged bluetooth_a2dp_audio_state_changed = 69;
+ // 69 is blank but need not be.
UsbConnectorStateChanged usb_connector_state_changed = 70;
SpeakerImpedanceReported speaker_impedance_reported = 71;
HardwareFailed hardware_failed = 72;
@@ -1008,22 +1008,6 @@
}
/**
- * Logs when Bluetooth A2dp audio streaming state changes.
- *
- * Logged from:
- * TODO(b/73971848)
- */
-message BluetoothA2dpAudioStateChanged {
- // Whether or not audio is being played using Bluetooth A2dp.
- enum State {
- UNKNOWN = 0;
- PLAY = 1;
- STOP = 2;
- }
- optional State state = 1;
-}
-
-/**
* Logs when something is plugged into or removed from the USB-C connector.
*
* Logged from:
diff --git a/config/hiddenapi-vendor-list.txt b/config/hiddenapi-vendor-list.txt
index 61ae6e7..3a3a708 100644
--- a/config/hiddenapi-vendor-list.txt
+++ b/config/hiddenapi-vendor-list.txt
@@ -20,7 +20,7 @@
Landroid/app/AppOpsManager$PackageOps;->getPackageName()Ljava/lang/String;
Landroid/app/AppOpsManager$PackageOps;->getUid()I
Landroid/app/IActivityController$Stub;-><init>()V
-Landroid/app/IActivityManager;->cancelRecentsAnimation()V
+Landroid/app/IActivityManager;->cancelRecentsAnimation(Z)V
Landroid/app/IActivityManager;->cancelTaskWindowTransition(I)V
Landroid/app/IActivityManager;->closeSystemDialogs(Ljava/lang/String;)V
Landroid/app/IActivityManager;->getCurrentUser()Landroid/content/pm/UserInfo;
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index e1a02fa..919f714 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -450,7 +450,7 @@
in Intent intent, in String resolvedType, in Bundle options, int userId);
void startRecentsActivity(in Intent intent, in IAssistDataReceiver assistDataReceiver,
in IRecentsAnimationRunner recentsAnimationRunner);
- void cancelRecentsAnimation();
+ void cancelRecentsAnimation(boolean restoreHomeStackPosition);
int startActivityFromRecents(int taskId, in Bundle options);
Bundle getActivityOptions(in IBinder token);
List<IBinder> getAppTasks(in String callingPackage);
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index ddd0656..5067e19 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -73,6 +73,7 @@
ParceledListSlice getNotificationChannelsForPackage(String pkg, int uid, boolean includeDeleted);
int getNumNotificationChannelsForPackage(String pkg, int uid, boolean includeDeleted);
int getDeletedChannelCount(String pkg, int uid);
+ int getBlockedChannelCount(String pkg, int uid);
void deleteNotificationChannelGroup(String pkg, String channelGroupId);
NotificationChannelGroup getNotificationChannelGroup(String pkg, String channelGroupId);
ParceledListSlice getNotificationChannelGroups(String pkg);
diff --git a/core/java/android/view/IRecentsAnimationController.aidl b/core/java/android/view/IRecentsAnimationController.aidl
index 89684ca..c0b40c8 100644
--- a/core/java/android/view/IRecentsAnimationController.aidl
+++ b/core/java/android/view/IRecentsAnimationController.aidl
@@ -59,4 +59,9 @@
* taken.
*/
void setAnimationTargetsBehindSystemBars(boolean behindSystemBars);
+
+ /**
+ * Informs the system that the primary split-screen stack should be minimized.
+ */
+ void setSplitScreenMinimized(boolean minimized);
}
diff --git a/core/proto/OWNERS b/core/proto/OWNERS
new file mode 100644
index 0000000..ed42e2e
--- /dev/null
+++ b/core/proto/OWNERS
@@ -0,0 +1,13 @@
+# Be sure you are familiar with proto when you modify this directory.
+
+# Metrics
+bookatz@google.com
+cjyu@google.com
+jinyithu@google.com
+joeo@google.com
+kwekua@google.com
+singhtejinder@google.com
+
+# Frameworks
+ogunwale@google.com
+jjaggi@google.com
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index eebf581..02d6c9fc 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1205,7 +1205,6 @@
<java-symbol type="string" name="ssl_ca_cert_noti_by_administrator" />
<java-symbol type="string" name="ssl_ca_cert_noti_managed" />
<java-symbol type="string" name="work_profile_deleted" />
- <java-symbol type="string" name="work_profile_deleted_description" />
<java-symbol type="string" name="work_profile_deleted_details" />
<java-symbol type="string" name="work_profile_deleted_description_dpm_wipe" />
<java-symbol type="string" name="work_profile_deleted_reason_maximum_password_failure" />
diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl
index fa3f99a..12768817 100644
--- a/location/java/android/location/ILocationManager.aidl
+++ b/location/java/android/location/ILocationManager.aidl
@@ -89,6 +89,10 @@
ProviderProperties getProviderProperties(String provider);
String getNetworkProviderPackage();
+ boolean isProviderEnabledForUser(String provider, int userId);
+ boolean setProviderEnabledForUser(String provider, boolean enabled, int userId);
+ boolean isLocationEnabledForUser(int userId);
+ void setLocationEnabledForUser(boolean enabled, int userId);
void addTestProvider(String name, in ProviderProperties properties, String opPackageName);
void removeTestProvider(String provider, String opPackageName);
void setTestProviderLocation(String provider, in Location loc, String opPackageName);
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index a523958..38286a3 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -1249,40 +1249,11 @@
@SystemApi
@RequiresPermission(WRITE_SECURE_SETTINGS)
public void setLocationEnabledForUser(boolean enabled, UserHandle userHandle) {
- final List<String> allProvidersList = getAllProviders();
- // Update all providers on device plus gps and network provider when disabling location.
- Set<String> allProvidersSet = new ArraySet<>(allProvidersList.size() + 2);
- allProvidersSet.addAll(allProvidersList);
- // When disabling location, disable gps and network provider that could have been enabled by
- // location mode api.
- if (enabled == false) {
- allProvidersSet.add(GPS_PROVIDER);
- allProvidersSet.add(NETWORK_PROVIDER);
+ try {
+ mService.setLocationEnabledForUser(enabled, userHandle.getIdentifier());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
- if (allProvidersSet.isEmpty()) {
- return;
- }
- // to ensure thread safety, we write the provider name with a '+' or '-'
- // and let the SettingsProvider handle it rather than reading and modifying
- // the list of enabled providers.
- final String prefix = enabled ? "+" : "-";
- StringBuilder locationProvidersAllowed = new StringBuilder();
- for (String provider : allProvidersSet) {
- checkProvider(provider);
- if (provider.equals(PASSIVE_PROVIDER)) {
- continue;
- }
- locationProvidersAllowed.append(prefix);
- locationProvidersAllowed.append(provider);
- locationProvidersAllowed.append(",");
- }
- // Remove the trailing comma
- locationProvidersAllowed.setLength(locationProvidersAllowed.length() - 1);
- Settings.Secure.putStringForUser(
- mContext.getContentResolver(),
- Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
- locationProvidersAllowed.toString(),
- userHandle.getIdentifier());
}
/**
@@ -1295,22 +1266,11 @@
*/
@SystemApi
public boolean isLocationEnabledForUser(UserHandle userHandle) {
- final String allowedProviders = Settings.Secure.getStringForUser(
- mContext.getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
- userHandle.getIdentifier());
- if (allowedProviders == null) {
- return false;
+ try {
+ return mService.isLocationEnabledForUser(userHandle.getIdentifier());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
- final List<String> providerList = Arrays.asList(allowedProviders.split(","));
- for(String provider : getAllProviders()) {
- if (provider.equals(PASSIVE_PROVIDER)) {
- continue;
- }
- if (providerList.contains(provider)) {
- return true;
- }
- }
- return false;
}
/**
@@ -1362,9 +1322,12 @@
@SystemApi
public boolean isProviderEnabledForUser(String provider, UserHandle userHandle) {
checkProvider(provider);
- String allowedProviders = Settings.Secure.getStringForUser(mContext.getContentResolver(),
- Settings.Secure.LOCATION_PROVIDERS_ALLOWED, userHandle.getIdentifier());
- return TextUtils.delimitedStringContains(allowedProviders, ',', provider);
+
+ try {
+ return mService.isProviderEnabledForUser(provider, userHandle.getIdentifier());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
}
/**
@@ -1383,16 +1346,13 @@
public boolean setProviderEnabledForUser(
String provider, boolean enabled, UserHandle userHandle) {
checkProvider(provider);
- // to ensure thread safety, we write the provider name with a '+' or '-'
- // and let the SettingsProvider handle it rather than reading and modifying
- // the list of enabled providers.
- if (enabled) {
- provider = "+" + provider;
- } else {
- provider = "-" + provider;
+
+ try {
+ return mService.setProviderEnabledForUser(
+ provider, enabled, userHandle.getIdentifier());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
- return Settings.Secure.putStringForUser(mContext.getContentResolver(),
- Settings.Secure.LOCATION_PROVIDERS_ALLOWED, provider, userHandle.getIdentifier());
}
/**
diff --git a/packages/SystemUI/res/layout/status_bar.xml b/packages/SystemUI/res/layout/status_bar.xml
index 9d336e2..f0138a6 100644
--- a/packages/SystemUI/res/layout/status_bar.xml
+++ b/packages/SystemUI/res/layout/status_bar.xml
@@ -60,7 +60,11 @@
<include layout="@layout/heads_up_status_bar_layout" />
+ <!-- The alpha of the left side is controlled by PhoneStatusBarTransitions, and the
+ individual views are controlled by StatusBarManager disable flags DISABLE_CLOCK and
+ DISABLE_NOTIFICATION_ICONS, respectively -->
<LinearLayout
+ android:id="@+id/status_bar_left_side"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:clipChildren="false"
@@ -76,8 +80,6 @@
android:gravity="center_vertical|start"
/>
- <!-- The alpha of this area is controlled from both PhoneStatusBarTransitions and
- PhoneStatusBar (DISABLE_NOTIFICATION_ICONS). -->
<com.android.systemui.statusbar.AlphaOptimizedFrameLayout
android:id="@+id/notification_icon_area"
android:layout_width="0dp"
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
index 1aad27f..6aa2754 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
@@ -258,9 +258,9 @@
/**
* Cancels the remote recents animation started from {@link #startRecentsActivity}.
*/
- public void cancelRecentsAnimation() {
+ public void cancelRecentsAnimation(boolean restoreHomeStackPosition) {
try {
- ActivityManager.getService().cancelRecentsAnimation();
+ ActivityManager.getService().cancelRecentsAnimation(restoreHomeStackPosition);
} catch (RemoteException e) {
Log.e(TAG, "Failed to cancel recents animation", e);
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
index 5fa6c79..80e226d 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
@@ -61,6 +61,14 @@
}
}
+ public void setSplitScreenMinimized(boolean minimized) {
+ try {
+ mAnimationController.setSplitScreenMinimized(minimized);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to set minimize dock", e);
+ }
+ }
+
public void finish(boolean toHome) {
try {
mAnimationController.finish(toHome);
diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java
index 5a2263c..ae6ee2a 100644
--- a/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java
+++ b/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java
@@ -73,7 +73,7 @@
void onAppOpChanged(int code, int uid, String packageName, boolean active);
/**
- * Gets active app ops for this user and package.
+ * Gets active app ops for this user and package
*/
@Nullable ArraySet<Integer> getAppOps(int userId, String packageName);
}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/AnglesClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/AnglesClassifier.java
index e18ac74..cdf4ba7 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/AnglesClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/AnglesClassifier.java
@@ -16,6 +16,9 @@
package com.android.systemui.classifier;
+import android.os.Build;
+import android.os.SystemProperties;
+import android.util.Log;
import android.view.MotionEvent;
import java.util.ArrayList;
@@ -49,13 +52,18 @@
public class AnglesClassifier extends StrokeClassifier {
private HashMap<Stroke, Data> mStrokeMap = new HashMap<>();
+ public static final boolean VERBOSE = SystemProperties.getBoolean("debug.falsing_log.ang",
+ Build.IS_DEBUGGABLE);
+
+ private static String TAG = "ANG";
+
public AnglesClassifier(ClassifierData classifierData) {
mClassifierData = classifierData;
}
@Override
public String getTag() {
- return "ANG";
+ return TAG;
}
@Override
@@ -170,18 +178,31 @@
public float getAnglesVariance() {
float anglesVariance = getAnglesVariance(mSumSquares, mSum, mCount);
+ if (VERBOSE) {
+ FalsingLog.i(TAG, "getAnglesVariance: (first pass) " + anglesVariance);
+ FalsingLog.i(TAG, " - mFirstLength=" + mFirstLength);
+ FalsingLog.i(TAG, " - mLength=" + mLength);
+ }
if (mFirstLength < mLength / 2f) {
anglesVariance = Math.min(anglesVariance, mFirstAngleVariance
+ getAnglesVariance(mSecondSumSquares, mSecondSum, mSecondCount));
+ if (VERBOSE) FalsingLog.i(TAG, "getAnglesVariance: (second pass) " + anglesVariance);
}
return anglesVariance;
}
public float getAnglesPercentage() {
if (mAnglesCount == 0.0f) {
+ if (VERBOSE) FalsingLog.i(TAG, "getAnglesPercentage: count==0, result=1");
return 1.0f;
}
- return (Math.max(mLeftAngles, mRightAngles) + mStraightAngles) / mAnglesCount;
+ final float result = (Math.max(mLeftAngles, mRightAngles) + mStraightAngles) / mAnglesCount;
+ if (VERBOSE) {
+ FalsingLog.i(TAG, "getAnglesPercentage: left=" + mLeftAngles + " right="
+ + mRightAngles + " straight=" + mStraightAngles + " count=" + mAnglesCount
+ + " result=" + result);
+ }
+ return result;
}
}
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/AnglesVarianceEvaluator.java b/packages/SystemUI/src/com/android/systemui/classifier/AnglesVarianceEvaluator.java
index 6883dd0..5f6c1b7 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/AnglesVarianceEvaluator.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/AnglesVarianceEvaluator.java
@@ -20,8 +20,6 @@
public static float evaluate(float value, int type) {
final boolean secureUnlock = type == Classifier.BOUNCER_UNLOCK;
float evaluation = 0.0f;
- if (value > 0.05) evaluation++;
- if (value > 0.10) evaluation++;
if (value > 0.20) evaluation++;
if (value > 0.40 && !secureUnlock) evaluation++;
if (value > 0.80 && !secureUnlock) evaluation++;
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/SpeedAnglesClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/SpeedAnglesClassifier.java
index 6df72b1..66f0cf6 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/SpeedAnglesClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/SpeedAnglesClassifier.java
@@ -16,6 +16,8 @@
package com.android.systemui.classifier;
+import android.os.Build;
+import android.os.SystemProperties;
import android.view.MotionEvent;
import java.util.ArrayList;
@@ -34,6 +36,10 @@
* should be in this interval.
*/
public class SpeedAnglesClassifier extends StrokeClassifier {
+ public static final boolean VERBOSE = SystemProperties.getBoolean("debug.falsing_log.spd_ang",
+ Build.IS_DEBUGGABLE);
+ public static final String TAG = "SPD_ANG";
+
private HashMap<Stroke, Data> mStrokeMap = new HashMap<>();
public SpeedAnglesClassifier(ClassifierData classifierData) {
@@ -42,7 +48,7 @@
@Override
public String getTag() {
- return "SPD_ANG";
+ return TAG;
}
@Override
@@ -135,14 +141,24 @@
}
public float getAnglesVariance() {
- return mSumSquares / mCount - (mSum / mCount) * (mSum / mCount);
+ final float v = mSumSquares / mCount - (mSum / mCount) * (mSum / mCount);
+ if (VERBOSE) {
+ FalsingLog.i(TAG, "getAnglesVariance: sum^2=" + mSumSquares
+ + " count=" + mCount + " result=" + v);
+ }
+ return v;
}
public float getAnglesPercentage() {
if (mAnglesCount == 0.0f) {
return 1.0f;
}
- return (mAcceleratingAngles) / mAnglesCount;
+ final float v = (mAcceleratingAngles) / mAnglesCount;
+ if (VERBOSE) {
+ FalsingLog.i(TAG, "getAnglesPercentage: angles=" + mAcceleratingAngles
+ + " count=" + mAnglesCount + " result=" + v);
+ }
+ return v;
}
}
}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
index 49b00ce..a70b358 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
@@ -229,10 +229,11 @@
// Bump the notification when the bucket dropped.
.setWhen(mWarningTriggerTimeMs)
.setShowWhen(false)
- .setContentTitle(title)
.setContentText(contentText)
+ .setContentTitle(title)
.setOnlyAlertOnce(true)
.setDeleteIntent(pendingBroadcast(ACTION_DISMISSED_WARNING))
+ .setStyle(new Notification.BigTextStyle().bigText(contentText))
.setVisibility(Notification.VISIBILITY_PUBLIC);
if (hasBatterySettings()) {
nb.setContentIntent(pendingBroadcast(ACTION_SHOW_BATTERY_SETTINGS));
@@ -483,16 +484,24 @@
d.setMessage(mContext.getString(R.string.auto_saver_enabled_text,
getLowBatteryAutoTriggerDefaultLevel()));
- // Negative == "got it". Just close the dialog. Battery saver has already been enabled.
- d.setNegativeButton(R.string.auto_saver_okay_action, null);
- d.setPositiveButton(R.string.open_saver_setting_action, (dialog, which) ->
- mContext.startActivity(actionBatterySaverSetting));
+ // "Got it". Just close the dialog. Automatic battery has been enabled already.
+ d.setPositiveButton(R.string.auto_saver_okay_action,
+ (dialog, which) -> onAutoSaverEnabledConfirmationClosed());
+
+ // "Settings" -> Opens the battery saver settings activity.
+ d.setNeutralButton(R.string.open_saver_setting_action, (dialog, which) -> {
+ mContext.startActivity(actionBatterySaverSetting);
+ onAutoSaverEnabledConfirmationClosed();
+ });
d.setShowForAllUsers(true);
- d.setOnDismissListener((dialog) -> mSaverEnabledConfirmation = null);
+ d.setOnDismissListener((dialog) -> onAutoSaverEnabledConfirmationClosed());
d.show();
mSaverEnabledConfirmation = d;
}
+ private void onAutoSaverEnabledConfirmationClosed() {
+ mSaverEnabledConfirmation = null;
+ }
private void setSaverMode(boolean mode, boolean needFirstTimeWarning) {
BatterySaverUtils.setPowerSaveMode(mContext, mode, needFirstTimeWarning);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/CustomizeTileView.java b/packages/SystemUI/src/com/android/systemui/qs/customize/CustomizeTileView.java
index eb95866..20e3cee 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/CustomizeTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/CustomizeTileView.java
@@ -44,4 +44,9 @@
public TextView getAppLabel() {
return mSecondLine;
}
+
+ @Override
+ protected boolean animationsEnabled() {
+ return false;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java
index 862a6a4..e7e756f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java
@@ -159,13 +159,13 @@
return getColorForState(getContext(), state);
}
- public static void animateGrayScale(int fromColor, int toColor, ImageView iv,
- final Runnable endRunnable) {
+ private void animateGrayScale(int fromColor, int toColor, ImageView iv,
+ final Runnable endRunnable) {
if (iv instanceof AlphaControlledSlashImageView) {
((AlphaControlledSlashImageView)iv)
.setFinalImageTintList(ColorStateList.valueOf(toColor));
}
- if (ValueAnimator.areAnimatorsEnabled()) {
+ if (mAnimationEnabled && ValueAnimator.areAnimatorsEnabled()) {
final float fromAlpha = Color.alpha(fromColor);
final float toAlpha = Color.alpha(toColor);
final float fromChannel = Color.red(fromColor);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java
index 09d928f..cc60f87 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java
@@ -179,7 +179,7 @@
protected void handleStateChanged(QSTile.State state) {
int circleColor = getCircleColor(state.state);
if (circleColor != mCircleColor) {
- if (mBg.isShown()) {
+ if (mBg.isShown() && animationsEnabled()) {
ValueAnimator animator = ValueAnimator.ofArgb(mCircleColor, circleColor)
.setDuration(QS_ANIM_LENGTH);
animator.addUpdateListener(animation -> mBg.setImageTintList(ColorStateList.valueOf(
@@ -205,6 +205,10 @@
}
}
+ protected boolean animationsEnabled() {
+ return true;
+ }
+
private int getCircleColor(int state) {
switch (state) {
case Tile.STATE_ACTIVE:
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/AppOpsListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/AppOpsListener.java
index 2ec78cf..019c680 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/AppOpsListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/AppOpsListener.java
@@ -62,7 +62,7 @@
public void onOpActiveChanged(int code, int uid, String packageName, boolean active) {
mFsc.onAppOpChanged(code, uid, packageName, active);
mPresenter.getHandler().post(() -> {
- mEntryManager.updateNotificationsForAppOps(code, uid, packageName, active);
+ mEntryManager.updateNotificationsForAppOp(code, uid, packageName, active);
});
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
index 4b6ab64..ab46b39 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
@@ -383,8 +383,6 @@
}
mGroupManager.onEntryAdded(entry);
- updateAppOps(entry);
-
updateRankingAndSort(mRankingMap);
}
@@ -403,25 +401,14 @@
updateRankingAndSort(ranking);
}
- private void updateAppOps(Entry entry) {
- final int uid = entry.notification.getUid();
- final String pkg = entry.notification.getPackageName();
- ArraySet<Integer> activeOps = mFsc.getAppOps(entry.notification.getUserId(), pkg);
- if (activeOps != null) {
- int N = activeOps.size();
- for (int i = 0; i < N; i++) {
- updateAppOp(activeOps.valueAt(i), uid, pkg, true);
- }
- }
- }
-
- public void updateAppOp(int appOp, int uid, String pkg, boolean showIcon) {
+ public void updateAppOp(int appOp, int uid, String pkg, String key, boolean showIcon) {
synchronized (mEntries) {
final int N = mEntries.size();
for (int i = 0; i < N; i++) {
Entry entry = mEntries.valueAt(i);
if (uid == entry.notification.getUid()
- && pkg.equals(entry.notification.getPackageName())) {
+ && pkg.equals(entry.notification.getPackageName())
+ && key.equals(entry.key)) {
if (showIcon) {
entry.mActiveAppOps.add(appOp);
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationEntryManager.java
index 45df450..849cfdd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationEntryManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationEntryManager.java
@@ -43,6 +43,7 @@
import android.view.View;
import android.view.ViewGroup;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.util.NotificationMessagingUtil;
@@ -665,6 +666,7 @@
}
// Add the expanded view and icon.
mNotificationData.add(entry);
+ tagForeground(entry.notification);
updateNotifications();
}
@@ -726,6 +728,19 @@
mPendingNotifications.put(key, shadeEntry);
}
+ @VisibleForTesting
+ protected void tagForeground(StatusBarNotification notification) {
+ ArraySet<Integer> activeOps = mForegroundServiceController.getAppOps(
+ notification.getUserId(), notification.getPackageName());
+ if (activeOps != null) {
+ int N = activeOps.size();
+ for (int i = 0; i < N; i++) {
+ updateNotificationsForAppOp(activeOps.valueAt(i), notification.getUid(),
+ notification.getPackageName(), true);
+ }
+ }
+ }
+
@Override
public void addNotification(StatusBarNotification notification,
NotificationListenerService.RankingMap ranking) {
@@ -736,10 +751,11 @@
}
}
- public void updateNotificationsForAppOps(int appOp, int uid, String pkg, boolean showIcon) {
- if (mForegroundServiceController.getStandardLayoutKey(
- UserHandle.getUserId(uid), pkg) != null) {
- mNotificationData.updateAppOp(appOp, uid, pkg, showIcon);
+ public void updateNotificationsForAppOp(int appOp, int uid, String pkg, boolean showIcon) {
+ String foregroundKey = mForegroundServiceController.getStandardLayoutKey(
+ UserHandle.getUserId(uid), pkg);
+ if (foregroundKey != null) {
+ mNotificationData.updateAppOp(appOp, uid, pkg, foregroundKey, showIcon);
updateNotifications();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
index 75b31c5..9fcb090 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
@@ -14,6 +14,7 @@
package com.android.systemui.statusbar.phone;
+import static android.app.StatusBarManager.DISABLE_CLOCK;
import static android.app.StatusBarManager.DISABLE_NOTIFICATION_ICONS;
import static android.app.StatusBarManager.DISABLE_SYSTEM_INFO;
@@ -96,6 +97,7 @@
mSystemIconArea = mStatusBar.findViewById(R.id.system_icon_area);
mClockView = mStatusBar.findViewById(R.id.clock);
showSystemIconArea(false);
+ showClock(false);
initEmergencyCryptkeeperText();
initOperatorName();
}
@@ -163,6 +165,13 @@
showNotificationIconArea(animate);
}
}
+ if ((diff1 & DISABLE_CLOCK) != 0) {
+ if ((state1 & DISABLE_CLOCK) != 0) {
+ hideClock(animate);
+ } else {
+ showClock(animate);
+ }
+ }
}
protected int adjustDisableFlags(int state) {
@@ -171,6 +180,7 @@
&& shouldHideNotificationIcons()) {
state |= DISABLE_NOTIFICATION_ICONS;
state |= DISABLE_SYSTEM_INFO;
+ state |= DISABLE_CLOCK;
}
if (mNetworkController != null && EncryptionHelper.IS_DATA_ENCRYPTED) {
if (mNetworkController.hasEmergencyCryptKeeperText()) {
@@ -195,11 +205,17 @@
public void hideSystemIconArea(boolean animate) {
animateHide(mSystemIconArea, animate);
- animateHide(mClockView, animate);
}
public void showSystemIconArea(boolean animate) {
animateShow(mSystemIconArea, animate);
+ }
+
+ public void hideClock(boolean animate) {
+ animateHide(mClockView, animate);
+ }
+
+ public void showClock(boolean animate) {
animateShow(mClockView, animate);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java
index 12bdfc6..a7d5aca 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java
@@ -43,10 +43,9 @@
}
public void init() {
- mLeftSide = mView.findViewById(R.id.notification_icon_area);
+ mLeftSide = mView.findViewById(R.id.status_bar_left_side);
mStatusIcons = mView.findViewById(R.id.statusIcons);
mBattery = mView.findViewById(R.id.battery);
- mClock = mView.findViewById(R.id.clock);
applyModeBackground(-1, getMode(), false /*animate*/);
applyMode(getMode(), false /*animate*/);
}
@@ -89,8 +88,7 @@
anims.playTogether(
animateTransitionTo(mLeftSide, newAlpha),
animateTransitionTo(mStatusIcons, newAlpha),
- animateTransitionTo(mBattery, newAlphaBC),
- animateTransitionTo(mClock, newAlphaBC)
+ animateTransitionTo(mBattery, newAlphaBC)
);
if (isLightsOut(mode)) {
anims.setDuration(LIGHTS_OUT_DURATION);
@@ -101,7 +99,6 @@
mLeftSide.setAlpha(newAlpha);
mStatusIcons.setAlpha(newAlpha);
mBattery.setAlpha(newAlphaBC);
- mClock.setAlpha(newAlphaBC);
}
}
}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 2c025b5..28f3162 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -807,7 +807,7 @@
@VisibleForTesting
protected WakeLock createWakeLock() {
return new DelayedWakeLock(getHandler(),
- WakeLock.createPartial(mContext, "Doze"));
+ WakeLock.createPartial(mContext, "Scrims"));
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 750d2a5..f7a97be 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -1425,11 +1425,15 @@
}
public void addQsTile(ComponentName tile) {
- mQSPanel.getHost().addTile(tile);
+ if (mQSPanel.getHost() != null) {
+ mQSPanel.getHost().addTile(tile);
+ }
}
public void remQsTile(ComponentName tile) {
- mQSPanel.getHost().removeTile(tile);
+ if (mQSPanel.getHost() != null) {
+ mQSPanel.getHost().removeTile(tile);
+ }
}
public void clickTile(ComponentName tile) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
index 378dad7..6a8d3a5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
@@ -69,6 +69,10 @@
setButton(BUTTON_NEGATIVE, mContext.getString(resId), onClick);
}
+ public void setNeutralButton(int resId, OnClickListener onClick) {
+ setButton(BUTTON_NEUTRAL, mContext.getString(resId), onClick);
+ }
+
public static void setShowForAllUsers(Dialog dialog, boolean show) {
if (show) {
dialog.getWindow().getAttributes().privateFlags |=
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
index 78dab77..2fed3fc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
@@ -52,6 +52,7 @@
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.statusbar.VibratorHelper;
+import static android.view.KeyEvent.KEYCODE_HOME;
import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK;
import static android.view.accessibility.AccessibilityNodeInfo.ACTION_LONG_CLICK;
import static com.android.systemui.shared.system.NavigationBarCompat.QUICK_SCRUB_TOUCH_SLOP_PX;
@@ -274,8 +275,12 @@
if (mCode != 0) {
if (doIt) {
// If there was a pending remote recents animation, then we need to
- // cancel the animation now before we handle the button itself
- ActivityManagerWrapper.getInstance().cancelRecentsAnimation();
+ // cancel the animation now before we handle the button itself. In the case
+ // where we are going home and the recents animation has already started,
+ // just cancel the recents animation, leaving the home stack in place
+ boolean isHomeKey = mCode == KEYCODE_HOME;
+ ActivityManagerWrapper.getInstance().cancelRecentsAnimation(!isHomeKey);
+
sendEvent(KeyEvent.ACTION_UP, 0);
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/util/wakelock/DelayedWakeLock.java b/packages/SystemUI/src/com/android/systemui/util/wakelock/DelayedWakeLock.java
index 5ec3dff..e1814098 100644
--- a/packages/SystemUI/src/com/android/systemui/util/wakelock/DelayedWakeLock.java
+++ b/packages/SystemUI/src/com/android/systemui/util/wakelock/DelayedWakeLock.java
@@ -23,7 +23,7 @@
*/
public class DelayedWakeLock implements WakeLock {
- private static final long RELEASE_DELAY_MS = 120;
+ private static final long RELEASE_DELAY_MS = 240;
private final Handler mHandler;
private final WakeLock mInner;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/AppOpsListenerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/AppOpsListenerTest.java
index 2a48c4b..dc0e2b0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/AppOpsListenerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/AppOpsListenerTest.java
@@ -86,7 +86,7 @@
mListener.onOpActiveChanged(
AppOpsManager.OP_RECORD_AUDIO, TEST_UID, TEST_PACKAGE_NAME, true);
waitForIdleSync(mHandler);
- verify(mEntryManager, times(1)).updateNotificationsForAppOps(
+ verify(mEntryManager, times(1)).updateNotificationsForAppOp(
AppOpsManager.OP_RECORD_AUDIO, TEST_UID, TEST_PACKAGE_NAME, true);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationDataTest.java
index 5e27fde..5ec77ac 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationDataTest.java
@@ -139,32 +139,7 @@
Assert.assertTrue(mRow.getEntry().channel != null);
}
- @Test
- public void testAdd_appOpsAdded() {
- ArraySet<Integer> expected = new ArraySet<>();
- expected.add(3);
- expected.add(235);
- expected.add(1);
- when(mFsc.getAppOps(mRow.getEntry().notification.getUserId(),
- mRow.getEntry().notification.getPackageName())).thenReturn(expected);
- mNotificationData.add(mRow.getEntry());
- assertEquals(expected.size(),
- mNotificationData.get(mRow.getEntry().key).mActiveAppOps.size());
- for (int op : expected) {
- assertTrue(" entry missing op " + op,
- mNotificationData.get(mRow.getEntry().key).mActiveAppOps.contains(op));
- }
- }
-
- @Test
- public void testAdd_noExistingAppOps() {
- when(mFsc.getAppOps(mRow.getEntry().notification.getUserId(),
- mRow.getEntry().notification.getPackageName())).thenReturn(null);
-
- mNotificationData.add(mRow.getEntry());
- assertEquals(0, mNotificationData.get(mRow.getEntry().key).mActiveAppOps.size());
- }
@Test
public void testAllRelevantNotisTaggedWithAppOps() throws Exception {
@@ -181,7 +156,9 @@
for (int op : expectedOps) {
mNotificationData.updateAppOp(op, NotificationTestHelper.UID,
- NotificationTestHelper.PKG, true);
+ NotificationTestHelper.PKG, mRow.getEntry().key, true);
+ mNotificationData.updateAppOp(op, NotificationTestHelper.UID,
+ NotificationTestHelper.PKG, row2.getEntry().key, true);
}
for (int op : expectedOps) {
assertTrue(mRow.getEntry().key + " doesn't have op " + op,
@@ -205,12 +182,12 @@
for (int op : expectedOps) {
mNotificationData.updateAppOp(op, NotificationTestHelper.UID,
- NotificationTestHelper.PKG, true);
+ NotificationTestHelper.PKG, row2.getEntry().key, true);
}
expectedOps.remove(OP_ACCEPT_HANDOVER);
mNotificationData.updateAppOp(OP_ACCEPT_HANDOVER, NotificationTestHelper.UID,
- NotificationTestHelper.PKG, false);
+ NotificationTestHelper.PKG, row2.getEntry().key, false);
assertTrue(mRow.getEntry().key + " doesn't have op " + OP_CAMERA,
mNotificationData.get(mRow.getEntry().key).mActiveAppOps.contains(OP_CAMERA));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationEntryManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationEntryManagerTest.java
index 3703d6a..7cfd7a3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationEntryManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationEntryManagerTest.java
@@ -37,18 +37,15 @@
import android.app.Notification;
import android.app.NotificationManager;
import android.content.Context;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.UserHandle;
import android.service.notification.NotificationListenerService;
-import android.service.notification.NotificationRankingUpdate;
import android.service.notification.StatusBarNotification;
import android.support.test.filters.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import android.util.ArraySet;
import android.widget.FrameLayout;
import com.android.internal.logging.MetricsLogger;
@@ -56,12 +53,13 @@
import com.android.systemui.ForegroundServiceController;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.UiOffloadThread;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
+import junit.framework.Assert;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -285,13 +283,12 @@
com.android.systemui.util.Assert.isNotMainThread();
when(mForegroundServiceController.getStandardLayoutKey(anyInt(), anyString()))
- .thenReturn("something");
+ .thenReturn(mEntry.key);
mEntry.row = mRow;
mEntryManager.getNotificationData().add(mEntry);
-
mHandler.post(() -> {
- mEntryManager.updateNotificationsForAppOps(
+ mEntryManager.updateNotificationsForAppOp(
AppOpsManager.OP_CAMERA, mEntry.notification.getUid(),
mEntry.notification.getPackageName(), true);
});
@@ -309,10 +306,65 @@
when(mForegroundServiceController.getStandardLayoutKey(anyInt(), anyString()))
.thenReturn(null);
mHandler.post(() -> {
- mEntryManager.updateNotificationsForAppOps(AppOpsManager.OP_CAMERA, 1000, "pkg", true);
+ mEntryManager.updateNotificationsForAppOp(AppOpsManager.OP_CAMERA, 1000, "pkg", true);
});
waitForIdleSync(mHandler);
verify(mPresenter, never()).updateNotificationViews();
}
+
+ @Test
+ public void testAddNotificationExistingAppOps() {
+ mEntry.row = mRow;
+ mEntryManager.getNotificationData().add(mEntry);
+ ArraySet<Integer> expected = new ArraySet<>();
+ expected.add(3);
+ expected.add(235);
+ expected.add(1);
+
+ when(mForegroundServiceController.getAppOps(mEntry.notification.getUserId(),
+ mEntry.notification.getPackageName())).thenReturn(expected);
+ when(mForegroundServiceController.getStandardLayoutKey(
+ mEntry.notification.getUserId(),
+ mEntry.notification.getPackageName())).thenReturn(mEntry.key);
+
+ mEntryManager.tagForeground(mEntry.notification);
+
+ Assert.assertEquals(expected.size(), mEntry.mActiveAppOps.size());
+ for (int op : expected) {
+ assertTrue("Entry missing op " + op, mEntry.mActiveAppOps.contains(op));
+ }
+ }
+
+ @Test
+ public void testAdd_noExistingAppOps() {
+ mEntry.row = mRow;
+ mEntryManager.getNotificationData().add(mEntry);
+ when(mForegroundServiceController.getStandardLayoutKey(
+ mEntry.notification.getUserId(),
+ mEntry.notification.getPackageName())).thenReturn(mEntry.key);
+ when(mForegroundServiceController.getAppOps(mEntry.notification.getUserId(),
+ mEntry.notification.getPackageName())).thenReturn(null);
+
+ mEntryManager.tagForeground(mEntry.notification);
+ Assert.assertEquals(0, mEntry.mActiveAppOps.size());
+ }
+
+ @Test
+ public void testAdd_existingAppOpsNotForegroundNoti() {
+ mEntry.row = mRow;
+ mEntryManager.getNotificationData().add(mEntry);
+ ArraySet<Integer> ops = new ArraySet<>();
+ ops.add(3);
+ ops.add(235);
+ ops.add(1);
+ when(mForegroundServiceController.getAppOps(mEntry.notification.getUserId(),
+ mEntry.notification.getPackageName())).thenReturn(ops);
+ when(mForegroundServiceController.getStandardLayoutKey(
+ mEntry.notification.getUserId(),
+ mEntry.notification.getPackageName())).thenReturn("something else");
+
+ mEntryManager.tagForeground(mEntry.notification);
+ Assert.assertEquals(0, mEntry.mActiveAppOps.size());
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java
index 2edcd01..9e8fa22 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java
@@ -89,15 +89,11 @@
assertEquals(View.INVISIBLE, mFragment.getView().findViewById(R.id.system_icon_area)
.getVisibility());
- assertEquals(View.INVISIBLE, mFragment.getView().findViewById(R.id.clock)
- .getVisibility());
fragment.disable(0, 0, false);
assertEquals(View.VISIBLE, mFragment.getView().findViewById(R.id.system_icon_area)
.getVisibility());
- assertEquals(View.VISIBLE, mFragment.getView().findViewById(R.id.clock)
- .getVisibility());
}
@Test
@@ -115,4 +111,20 @@
Mockito.verify(mNotificationAreaInner, atLeast(1)).setVisibility(eq(View.VISIBLE));
}
+
+ @Test
+ public void testDisableClock() throws Exception {
+ mFragments.dispatchResume();
+ processAllMessages();
+
+ CollapsedStatusBarFragment fragment = (CollapsedStatusBarFragment) mFragment;
+ fragment.initNotificationIconArea(mMockNotificiationAreaController);
+ fragment.disable(StatusBarManager.DISABLE_CLOCK, 0, false);
+
+ assertEquals(View.INVISIBLE, mFragment.getView().findViewById(R.id.clock).getVisibility());
+
+ fragment.disable(0, 0, false);
+
+ assertEquals(View.VISIBLE, mFragment.getView().findViewById(R.id.clock).getVisibility());
+ }
}
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 26b83f5..fb5fba0 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -1344,13 +1344,7 @@
* @param provider the name of the location provider
*/
private boolean isAllowedByCurrentUserSettingsLocked(String provider) {
- if (mEnabledProviders.contains(provider)) {
- return true;
- }
- if (mDisabledProviders.contains(provider)) {
- return false;
- }
- return isLocationProviderEnabledForUser(provider, mCurrentUserId);
+ return isAllowedByUserSettingsLockedForUser(provider, mCurrentUserId);
}
/**
@@ -1359,13 +1353,33 @@
* processes belonging to background users.
*
* @param provider the name of the location provider
- * @param uid the requestor's UID
+ * @param userId the user id to query
*/
- private boolean isAllowedByUserSettingsLocked(String provider, int uid) {
+ private boolean isAllowedByUserSettingsLockedForUser(String provider, int userId) {
+ if (mEnabledProviders.contains(provider)) {
+ return true;
+ }
+ if (mDisabledProviders.contains(provider)) {
+ return false;
+ }
+ return isLocationProviderEnabledForUser(provider, userId);
+ }
+
+
+ /**
+ * Returns "true" if access to the specified location provider is allowed by the specified
+ * user's settings. Access to all location providers is forbidden to non-location-provider
+ * processes belonging to background users.
+ *
+ * @param provider the name of the location provider
+ * @param uid the requestor's UID
+ * @param userId the user id to query
+ */
+ private boolean isAllowedByUserSettingsLocked(String provider, int uid, int userId) {
if (!isCurrentProfile(UserHandle.getUserId(uid)) && !isUidALocationProvider(uid)) {
return false;
}
- return isAllowedByCurrentUserSettingsLocked(provider);
+ return isAllowedByUserSettingsLockedForUser(provider, userId);
}
/**
@@ -1572,7 +1586,8 @@
continue;
}
if (allowedResolutionLevel >= getMinimumResolutionLevelForProviderUse(name)) {
- if (enabledOnly && !isAllowedByUserSettingsLocked(name, uid)) {
+ if (enabledOnly
+ && !isAllowedByUserSettingsLocked(name, uid, mCurrentUserId)) {
continue;
}
if (criteria != null && !LocationProvider.propertiesMeetCriteria(
@@ -2098,7 +2113,7 @@
oldRecord.disposeLocked(false);
}
- boolean isProviderEnabled = isAllowedByUserSettingsLocked(name, uid);
+ boolean isProviderEnabled = isAllowedByUserSettingsLocked(name, uid, mCurrentUserId);
if (isProviderEnabled) {
applyRequirementsLocked(name);
} else {
@@ -2219,7 +2234,7 @@
LocationProviderInterface provider = mProvidersByName.get(name);
if (provider == null) return null;
- if (!isAllowedByUserSettingsLocked(name, uid)) return null;
+ if (!isAllowedByUserSettingsLocked(name, uid, mCurrentUserId)) return null;
Location location;
if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
@@ -2540,6 +2555,173 @@
}
/**
+ * Returns the current location enabled/disabled status for a user
+ *
+ * @param userId the id of the user
+ * @return true if location is enabled
+ */
+ @Override
+ public boolean isLocationEnabledForUser(int userId) {
+ // Check INTERACT_ACROSS_USERS permission if userId is not current user id.
+ checkInteractAcrossUsersPermission(userId);
+
+ long identity = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ final String allowedProviders = Settings.Secure.getStringForUser(
+ mContext.getContentResolver(),
+ Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
+ userId);
+ if (allowedProviders == null) {
+ return false;
+ }
+ final List<String> providerList = Arrays.asList(allowedProviders.split(","));
+ for(String provider : mRealProviders.keySet()) {
+ if (provider.equals(LocationManager.PASSIVE_PROVIDER)
+ || provider.equals(LocationManager.FUSED_PROVIDER)) {
+ continue;
+ }
+ if (providerList.contains(provider)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ /**
+ * Enable or disable location for a user
+ *
+ * @param enabled true to enable location, false to disable location
+ * @param userId the id of the user
+ */
+ @Override
+ public void setLocationEnabledForUser(boolean enabled, int userId) {
+ mContext.enforceCallingPermission(
+ android.Manifest.permission.WRITE_SECURE_SETTINGS,
+ "Requires WRITE_SECURE_SETTINGS permission");
+
+ // Check INTERACT_ACROSS_USERS permission if userId is not current user id.
+ checkInteractAcrossUsersPermission(userId);
+
+ long identity = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ final Set<String> allRealProviders = mRealProviders.keySet();
+ // Update all providers on device plus gps and network provider when disabling
+ // location
+ Set<String> allProvidersSet = new ArraySet<>(allRealProviders.size() + 2);
+ allProvidersSet.addAll(allRealProviders);
+ // When disabling location, disable gps and network provider that could have been
+ // enabled by location mode api.
+ if (enabled == false) {
+ allProvidersSet.add(LocationManager.GPS_PROVIDER);
+ allProvidersSet.add(LocationManager.NETWORK_PROVIDER);
+ }
+ if (allProvidersSet.isEmpty()) {
+ return;
+ }
+ // to ensure thread safety, we write the provider name with a '+' or '-'
+ // and let the SettingsProvider handle it rather than reading and modifying
+ // the list of enabled providers.
+ final String prefix = enabled ? "+" : "-";
+ StringBuilder locationProvidersAllowed = new StringBuilder();
+ for (String provider : allProvidersSet) {
+ if (provider.equals(LocationManager.PASSIVE_PROVIDER)
+ || provider.equals(LocationManager.FUSED_PROVIDER)) {
+ continue;
+ }
+ locationProvidersAllowed.append(prefix);
+ locationProvidersAllowed.append(provider);
+ locationProvidersAllowed.append(",");
+ }
+ // Remove the trailing comma
+ locationProvidersAllowed.setLength(locationProvidersAllowed.length() - 1);
+ Settings.Secure.putStringForUser(
+ mContext.getContentResolver(),
+ Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
+ locationProvidersAllowed.toString(),
+ userId);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ /**
+ * Returns the current enabled/disabled status of a location provider and user
+ *
+ * @param provider name of the provider
+ * @param userId the id of the user
+ * @return true if the provider exists and is enabled
+ */
+ @Override
+ public boolean isProviderEnabledForUser(String provider, int userId) {
+ // Check INTERACT_ACROSS_USERS permission if userId is not current user id.
+ checkInteractAcrossUsersPermission(userId);
+
+ // Fused provider is accessed indirectly via criteria rather than the provider-based APIs,
+ // so we discourage its use
+ if (LocationManager.FUSED_PROVIDER.equals(provider)) return false;
+
+ int uid = Binder.getCallingUid();
+ synchronized (mLock) {
+ LocationProviderInterface p = mProvidersByName.get(provider);
+ return p != null
+ && isAllowedByUserSettingsLocked(provider, uid, userId);
+ }
+ }
+
+ /**
+ * Enable or disable a single location provider.
+ *
+ * @param provider name of the provider
+ * @param enabled true to enable the provider. False to disable the provider
+ * @param userId the id of the user to set
+ * @return true if the value was set, false on errors
+ */
+ @Override
+ public boolean setProviderEnabledForUser(String provider, boolean enabled, int userId) {
+ mContext.enforceCallingPermission(
+ android.Manifest.permission.WRITE_SECURE_SETTINGS,
+ "Requires WRITE_SECURE_SETTINGS permission");
+
+ // Check INTERACT_ACROSS_USERS permission if userId is not current user id.
+ checkInteractAcrossUsersPermission(userId);
+
+ // Fused provider is accessed indirectly via criteria rather than the provider-based APIs,
+ // so we discourage its use
+ if (LocationManager.FUSED_PROVIDER.equals(provider)) return false;
+
+ long identity = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ // No such provider exists
+ if (!mProvidersByName.containsKey(provider)) return false;
+
+ // If it is a test provider, do not write to Settings.Secure
+ if (mMockProviders.containsKey(provider)) {
+ setTestProviderEnabled(provider, enabled);
+ return true;
+ }
+
+ // to ensure thread safety, we write the provider name with a '+' or '-'
+ // and let the SettingsProvider handle it rather than reading and modifying
+ // the list of enabled providers.
+ String providerChange = (enabled ? "+" : "-") + provider;
+ return Settings.Secure.putStringForUser(
+ mContext.getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
+ providerChange, userId);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ /**
* Read location provider status from Settings.Secure
*
* @param provider the location provider to query
@@ -2560,6 +2742,23 @@
}
/**
+ * Method for checking INTERACT_ACROSS_USERS permission if specified user id is not the same as
+ * current user id
+ *
+ * @param userId the user id to get or set value
+ */
+ private void checkInteractAcrossUsersPermission(int userId) {
+ int uid = Binder.getCallingUid();
+ if (UserHandle.getUserId(uid) != userId) {
+ if (ActivityManager.checkComponentPermission(
+ android.Manifest.permission.INTERACT_ACROSS_USERS, uid, -1, true)
+ != PERMISSION_GRANTED) {
+ throw new SecurityException("Requires INTERACT_ACROSS_USERS permission");
+ }
+ }
+ }
+
+ /**
* Returns "true" if the UID belongs to a bound location provider.
*
* @param uid the uid
@@ -3076,7 +3275,11 @@
if (!canCallerAccessMockLocation(opPackageName)) {
return;
}
+ setTestProviderEnabled(provider, enabled);
+ }
+ /** Enable or disable a test location provider. */
+ private void setTestProviderEnabled(String provider, boolean enabled) {
synchronized (mLock) {
MockProvider mockProvider = mMockProviders.get(provider);
if (mockProvider == null) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index f97c6d6..db52b97 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -204,6 +204,8 @@
import static android.view.WindowManager.TRANSIT_TASK_IN_PLACE;
import static android.view.WindowManager.TRANSIT_TASK_OPEN;
import static android.view.WindowManager.TRANSIT_TASK_TO_FRONT;
+import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_HOME_TO_ORIGINAL_POSITION;
+import static com.android.server.wm.RecentsAnimationController.REORDER_KEEP_HOME_IN_PLACE;
import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
import static org.xmlpull.v1.XmlPullParser.START_TAG;
@@ -257,7 +259,6 @@
import android.app.WindowConfiguration.ActivityType;
import android.app.WindowConfiguration.WindowingMode;
import android.app.admin.DevicePolicyCache;
-import android.app.admin.DevicePolicyManager;
import android.app.assist.AssistContent;
import android.app.assist.AssistStructure;
import android.app.backup.IBackupManager;
@@ -5238,12 +5239,14 @@
}
@Override
- public void cancelRecentsAnimation() {
+ public void cancelRecentsAnimation(boolean restoreHomeStackPosition) {
enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "cancelRecentsAnimation()");
final long origId = Binder.clearCallingIdentity();
try {
synchronized (this) {
- mWindowManager.cancelRecentsAnimation();
+ mWindowManager.cancelRecentsAnimation(restoreHomeStackPosition
+ ? REORDER_MOVE_HOME_TO_ORIGINAL_POSITION
+ : REORDER_KEEP_HOME_IN_PLACE);
}
} finally {
Binder.restoreCallingIdentity(origId);
diff --git a/services/core/java/com/android/server/am/RecentsAnimation.java b/services/core/java/com/android/server/am/RecentsAnimation.java
index 9df321c..99337b8 100644
--- a/services/core/java/com/android/server/am/RecentsAnimation.java
+++ b/services/core/java/com/android/server/am/RecentsAnimation.java
@@ -23,6 +23,8 @@
import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
import static android.view.WindowManager.TRANSIT_NONE;
import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
+import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_HOME_TO_ORIGINAL_POSITION;
+import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_HOME_TO_TOP;
import android.app.ActivityOptions;
import android.content.ComponentName;
@@ -32,6 +34,7 @@
import android.os.Trace;
import android.util.Slog;
import android.view.IRecentsAnimationRunner;
+import com.android.server.wm.RecentsAnimationController;
import com.android.server.wm.RecentsAnimationController.RecentsAnimationCallbacks;
import com.android.server.wm.WindowManagerService;
@@ -123,7 +126,7 @@
// Fetch all the surface controls and pass them to the client to get the animation
// started
- mWindowManager.cancelRecentsAnimation();
+ mWindowManager.cancelRecentsAnimation(REORDER_MOVE_HOME_TO_ORIGINAL_POSITION);
mWindowManager.initializeRecentsAnimation(recentsAnimationRunner, this,
display.mDisplayId, mStackSupervisor.mRecentTasks.getRecentTaskIds());
@@ -140,7 +143,7 @@
}
@Override
- public void onAnimationFinished(boolean moveHomeToTop) {
+ public void onAnimationFinished(@RecentsAnimationController.ReorderMode int reorderMode) {
synchronized (mService) {
if (mWindowManager.getRecentsAnimationController() == null) return;
@@ -151,9 +154,8 @@
"RecentsAnimation#onAnimationFinished_inSurfaceTransaction");
mWindowManager.deferSurfaceLayout();
try {
- mWindowManager.cleanupRecentsAnimation(moveHomeToTop);
+ mWindowManager.cleanupRecentsAnimation(reorderMode);
- // Move the home stack to the front
final ActivityRecord homeActivity = mStackSupervisor.getHomeActivity();
if (homeActivity == null) {
return;
@@ -162,15 +164,19 @@
// Restore the launched-behind state
homeActivity.mLaunchTaskBehind = false;
- if (moveHomeToTop) {
+ if (reorderMode == REORDER_MOVE_HOME_TO_TOP) {
// Bring the home stack to the front
final ActivityStack homeStack = homeActivity.getStack();
mStackSupervisor.mNoAnimActivities.add(homeActivity);
homeStack.moveToFront("RecentsAnimation.onAnimationFinished()");
- } else {
+ } else if (reorderMode == REORDER_MOVE_HOME_TO_ORIGINAL_POSITION){
// Restore the home stack to its previous position
final ActivityDisplay display = homeActivity.getDisplay();
display.moveHomeStackBehindStack(mRestoreHomeBehindStack);
+ } else {
+ // Keep home stack in place, nothing changes, so ignore the transition logic
+ // below
+ return;
}
mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
@@ -180,6 +186,11 @@
// No reason to wait for the pausing activity in this case, as the hiding of
// surfaces needs to be done immediately.
mWindowManager.executeAppTransition();
+
+ // After reordering the stacks, reset the minimized state. At this point, either
+ // home is now top-most and we will stay minimized (if in split-screen), or we
+ // will have returned to the app, and the minimized state should be reset
+ mWindowManager.checkSplitScreenMinimizedChanged(true /* animate */);
} finally {
mWindowManager.continueSurfaceLayout();
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index c8b6b50..3e82c25 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -320,13 +320,13 @@
0, // STREAM_SYSTEM
0, // STREAM_RING
0, // STREAM_MUSIC
- 0, // STREAM_ALARM
+ 1, // STREAM_ALARM
0, // STREAM_NOTIFICATION
0, // STREAM_BLUETOOTH_SCO
0, // STREAM_SYSTEM_ENFORCED
0, // STREAM_DTMF
0, // STREAM_TTS
- 0 // STREAM_ACCESSIBILITY
+ 1 // STREAM_ACCESSIBILITY
};
/* mStreamVolumeAlias[] indicates for each stream if it uses the volume settings
@@ -1208,6 +1208,8 @@
System.VOLUME_SETTINGS_INT[a11yStreamAlias];
mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].setAllIndexes(
mStreamStates[a11yStreamAlias], caller);
+ mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].refreshRange(
+ mStreamVolumeAlias[AudioSystem.STREAM_ACCESSIBILITY]);
}
}
if (sIndependentA11yVolume) {
@@ -1389,7 +1391,15 @@
}
private int rescaleIndex(int index, int srcStream, int dstStream) {
- return (index * mStreamStates[dstStream].getMaxIndex() + mStreamStates[srcStream].getMaxIndex() / 2) / mStreamStates[srcStream].getMaxIndex();
+ final int rescaled =
+ (index * mStreamStates[dstStream].getMaxIndex()
+ + mStreamStates[srcStream].getMaxIndex() / 2)
+ / mStreamStates[srcStream].getMaxIndex();
+ if (rescaled < mStreamStates[dstStream].getMinIndex()) {
+ return mStreamStates[dstStream].getMinIndex();
+ } else {
+ return rescaled;
+ }
}
///////////////////////////////////////////////////////////////////////////
@@ -4602,8 +4612,8 @@
// 4 VolumeStreamState.class
public class VolumeStreamState {
private final int mStreamType;
- private final int mIndexMin;
- private final int mIndexMax;
+ private int mIndexMin;
+ private int mIndexMax;
private boolean mIsMuted;
private String mVolumeIndexSettingName;
@@ -4889,6 +4899,24 @@
}
/**
+ * Updates the min/max index values from another stream. Use this when changing the alias
+ * for the current stream type.
+ * @param sourceStreamType
+ */
+ // must be sync'd on mSettingsLock before VolumeStreamState.class
+ @GuardedBy("VolumeStreamState.class")
+ public void refreshRange(int sourceStreamType) {
+ mIndexMin = MIN_STREAM_VOLUME[sourceStreamType] * 10;
+ mIndexMax = MAX_STREAM_VOLUME[sourceStreamType] * 10;
+ // verify all current volumes are within bounds
+ for (int i = 0 ; i < mIndexMap.size(); i++) {
+ final int device = mIndexMap.keyAt(i);
+ final int index = mIndexMap.valueAt(i);
+ mIndexMap.put(device, getValidIndex(index));
+ }
+ }
+
+ /**
* Copies all device/index pairs from the given VolumeStreamState after initializing
* them with the volume for DEVICE_OUT_DEFAULT. No-op if the source VolumeStreamState
* has the same stream type as this instance.
diff --git a/services/core/java/com/android/server/display/BrightnessTracker.java b/services/core/java/com/android/server/display/BrightnessTracker.java
index 88df195..905c7e3 100644
--- a/services/core/java/com/android/server/display/BrightnessTracker.java
+++ b/services/core/java/com/android/server/display/BrightnessTracker.java
@@ -686,10 +686,15 @@
}
public ParceledListSlice<AmbientBrightnessDayStats> getAmbientBrightnessStats(int userId) {
- ArrayList<AmbientBrightnessDayStats> stats = mAmbientBrightnessStatsTracker.getUserStats(
- userId);
- return (stats != null) ? new ParceledListSlice<>(stats) : new ParceledListSlice<>(
- Collections.EMPTY_LIST);
+ if (mAmbientBrightnessStatsTracker != null) {
+ ArrayList<AmbientBrightnessDayStats> stats =
+ mAmbientBrightnessStatsTracker.getUserStats(
+ userId);
+ if (stats != null) {
+ return new ParceledListSlice<>(stats);
+ }
+ }
+ return ParceledListSlice.emptyList();
}
// Not allowed to keep the SensorEvent so used to copy the data we care about.
diff --git a/services/core/java/com/android/server/input/InputWindowHandle.java b/services/core/java/com/android/server/input/InputWindowHandle.java
index 3d6f7ad..720eaaa5 100644
--- a/services/core/java/com/android/server/input/InputWindowHandle.java
+++ b/services/core/java/com/android/server/input/InputWindowHandle.java
@@ -92,7 +92,7 @@
public int inputFeatures;
// Display this input is on.
- public final int displayId;
+ public int displayId;
private native void nativeDispose();
diff --git a/services/core/java/com/android/server/net/watchlist/ReportEncoder.java b/services/core/java/com/android/server/net/watchlist/ReportEncoder.java
index 2a8f4d5..a482e05 100644
--- a/services/core/java/com/android/server/net/watchlist/ReportEncoder.java
+++ b/services/core/java/com/android/server/net/watchlist/ReportEncoder.java
@@ -49,6 +49,7 @@
* Apply DP on watchlist results, and generate a serialized watchlist report ready to store
* in DropBox.
*/
+ @Nullable
static byte[] encodeWatchlistReport(WatchlistConfig config, byte[] userSecret,
List<String> appDigestList, WatchlistReportDbHelper.AggregatedResult aggregatedResult) {
Map<String, Boolean> resultMap = PrivacyUtils.createDpEncodedReportMap(
diff --git a/services/core/java/com/android/server/net/watchlist/WatchlistConfig.java b/services/core/java/com/android/server/net/watchlist/WatchlistConfig.java
index d793842..8352ca6 100644
--- a/services/core/java/com/android/server/net/watchlist/WatchlistConfig.java
+++ b/services/core/java/com/android/server/net/watchlist/WatchlistConfig.java
@@ -16,6 +16,7 @@
package com.android.server.net.watchlist;
+import android.annotation.Nullable;
import android.os.FileUtils;
import android.util.AtomicFile;
import android.util.Log;
@@ -55,9 +56,6 @@
private static final String NETWORK_WATCHLIST_DB_FOR_TEST_PATH =
"/data/misc/network_watchlist/network_watchlist_for_test.xml";
- // Hash for null / unknown config, a 32 byte array filled with content 0x00
- private static final byte[] UNKNOWN_CONFIG_HASH = new byte[32];
-
private static class XmlTags {
private static final String WATCHLIST_CONFIG = "watchlist-config";
private static final String SHA256_DOMAIN = "sha256-domain";
@@ -228,16 +226,21 @@
return mIsSecureConfig;
}
+ @Nullable
+ /**
+ * Get watchlist config SHA-256 digest.
+ * Return null if watchlist config does not exist.
+ */
public byte[] getWatchlistConfigHash() {
if (!mXmlFile.exists()) {
- return UNKNOWN_CONFIG_HASH;
+ return null;
}
try {
return DigestUtils.getSha256Hash(mXmlFile);
} catch (IOException | NoSuchAlgorithmException e) {
Log.e(TAG, "Unable to get watchlist config hash", e);
}
- return UNKNOWN_CONFIG_HASH;
+ return null;
}
/**
@@ -271,8 +274,10 @@
}
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- pw.println("Watchlist config hash: " + HexDump.toHexString(getWatchlistConfigHash()));
+ final byte[] hash = getWatchlistConfigHash();
+ pw.println("Watchlist config hash: " + (hash != null ? HexDump.toHexString(hash) : null));
pw.println("Domain CRC32 digest list:");
+ // mDomainDigests won't go from non-null to null so it's safe
if (mDomainDigests != null) {
mDomainDigests.crc32Digests.dump(fd, pw, args);
}
@@ -281,6 +286,7 @@
mDomainDigests.sha256Digests.dump(fd, pw, args);
}
pw.println("Ip CRC32 digest list:");
+ // mIpDigests won't go from non-null to null so it's safe
if (mIpDigests != null) {
mIpDigests.crc32Digests.dump(fd, pw, args);
}
diff --git a/services/core/java/com/android/server/net/watchlist/WatchlistLoggingHandler.java b/services/core/java/com/android/server/net/watchlist/WatchlistLoggingHandler.java
index b331b9c..864ce5d 100644
--- a/services/core/java/com/android/server/net/watchlist/WatchlistLoggingHandler.java
+++ b/services/core/java/com/android/server/net/watchlist/WatchlistLoggingHandler.java
@@ -346,6 +346,7 @@
* @param ipAddresses Ip address that you want to search in watchlist.
* @return Ip address that exists in watchlist, null if it does not match anything.
*/
+ @Nullable
private String searchIpInWatchlist(String[] ipAddresses) {
for (String ipAddress : ipAddresses) {
if (isIpInWatchlist(ipAddress)) {
@@ -377,6 +378,7 @@
* @param host Host that we want to search.
* @return Domain that exists in watchlist, null if it does not match anything.
*/
+ @Nullable
private String searchAllSubDomainsInWatchlist(String host) {
if (host == null) {
return null;
@@ -392,6 +394,7 @@
/** Get all sub-domains in a host */
@VisibleForTesting
+ @Nullable
static String[] getAllSubDomains(String host) {
if (host == null) {
return null;
diff --git a/services/core/java/com/android/server/net/watchlist/WatchlistReportDbHelper.java b/services/core/java/com/android/server/net/watchlist/WatchlistReportDbHelper.java
index 632ab81..c69934a 100644
--- a/services/core/java/com/android/server/net/watchlist/WatchlistReportDbHelper.java
+++ b/services/core/java/com/android/server/net/watchlist/WatchlistReportDbHelper.java
@@ -144,6 +144,7 @@
* Aggregate all records in database before input timestamp, and return a
* rappor encoded result.
*/
+ @Nullable
public AggregatedResult getAggregatedRecords(long untilTimestamp) {
final String selectStatement = WhiteListReportContract.TIMESTAMP + " < ?";
diff --git a/services/core/java/com/android/server/net/watchlist/WatchlistSettings.java b/services/core/java/com/android/server/net/watchlist/WatchlistSettings.java
index e20a510..c2f3ba0 100644
--- a/services/core/java/com/android/server/net/watchlist/WatchlistSettings.java
+++ b/services/core/java/com/android/server/net/watchlist/WatchlistSettings.java
@@ -86,7 +86,7 @@
}
}
- public void reloadSettings() {
+ private void reloadSettings() {
if (!mXmlFile.exists()) {
// No settings config
return;
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index f31ca0a..899d271 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -2286,6 +2286,12 @@
}
@Override
+ public int getBlockedChannelCount(String pkg, int uid) {
+ enforceSystemOrSystemUI("getBlockedChannelCount");
+ return mRankingHelper.getBlockedChannelCount(pkg, uid);
+ }
+
+ @Override
public ParceledListSlice<NotificationChannelGroup> getNotificationChannelGroupsForPackage(
String pkg, int uid, boolean includeDeleted) {
checkCallerIsSystem();
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index 98d5c9a..43d393a 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -15,6 +15,8 @@
*/
package com.android.server.notification;
+import static android.app.NotificationManager.IMPORTANCE_NONE;
+
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
@@ -619,7 +621,7 @@
updateConfig();
return;
}
- if (channel.getImportance() < NotificationManager.IMPORTANCE_NONE
+ if (channel.getImportance() < IMPORTANCE_NONE
|| channel.getImportance() > NotificationManager.IMPORTANCE_MAX) {
throw new IllegalArgumentException("Invalid importance level");
}
@@ -959,6 +961,23 @@
return deletedCount;
}
+ public int getBlockedChannelCount(String pkg, int uid) {
+ Preconditions.checkNotNull(pkg);
+ int blockedCount = 0;
+ Record r = getRecord(pkg, uid);
+ if (r == null) {
+ return blockedCount;
+ }
+ int N = r.channels.size();
+ for (int i = 0; i < N; i++) {
+ final NotificationChannel nc = r.channels.valueAt(i);
+ if (!nc.isDeleted() && IMPORTANCE_NONE == nc.getImportance()) {
+ blockedCount++;
+ }
+ }
+ return blockedCount;
+ }
+
/**
* Sets importance.
*/
@@ -969,12 +988,12 @@
}
public void setEnabled(String packageName, int uid, boolean enabled) {
- boolean wasEnabled = getImportance(packageName, uid) != NotificationManager.IMPORTANCE_NONE;
+ boolean wasEnabled = getImportance(packageName, uid) != IMPORTANCE_NONE;
if (wasEnabled == enabled) {
return;
}
setImportance(packageName, uid,
- enabled ? DEFAULT_IMPORTANCE : NotificationManager.IMPORTANCE_NONE);
+ enabled ? DEFAULT_IMPORTANCE : IMPORTANCE_NONE);
}
@VisibleForTesting
@@ -1199,7 +1218,7 @@
ArrayMap<Integer, String> packageBans = new ArrayMap<>(N);
for (int i = 0; i < N; i++) {
final Record r = mRecords.valueAt(i);
- if (r.importance == NotificationManager.IMPORTANCE_NONE) {
+ if (r.importance == IMPORTANCE_NONE) {
packageBans.put(r.uid, r.pkg);
}
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 2e530af..0e0bfbd 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -17,12 +17,12 @@
package com.android.server.pm;
import static android.Manifest.permission.DELETE_PACKAGES;
-import static android.Manifest.permission.MANAGE_DEVICE_ADMINS;
-import static android.Manifest.permission.SET_HARMFUL_APP_WARNINGS;
import static android.Manifest.permission.INSTALL_PACKAGES;
+import static android.Manifest.permission.MANAGE_DEVICE_ADMINS;
import static android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS;
import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
import static android.Manifest.permission.REQUEST_DELETE_PACKAGES;
+import static android.Manifest.permission.SET_HARMFUL_APP_WARNINGS;
import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
import static android.content.pm.PackageManager.CERT_INPUT_RAW_X509;
import static android.content.pm.PackageManager.CERT_INPUT_SHA256;
@@ -167,8 +167,8 @@
import android.content.pm.PackageInstaller;
import android.content.pm.PackageList;
import android.content.pm.PackageManager;
-import android.content.pm.PackageManagerInternal;
import android.content.pm.PackageManager.LegacyPackageDeleteObserver;
+import android.content.pm.PackageManagerInternal;
import android.content.pm.PackageManagerInternal.PackageListObserver;
import android.content.pm.PackageParser;
import android.content.pm.PackageParser.ActivityIntentInfo;
@@ -310,10 +310,10 @@
import com.android.server.pm.dex.PackageDexUsage;
import com.android.server.pm.permission.BasePermission;
import com.android.server.pm.permission.DefaultPermissionGrantPolicy;
-import com.android.server.pm.permission.PermissionManagerService;
-import com.android.server.pm.permission.PermissionManagerInternal;
import com.android.server.pm.permission.DefaultPermissionGrantPolicy.DefaultPermissionGrantedCallback;
+import com.android.server.pm.permission.PermissionManagerInternal;
import com.android.server.pm.permission.PermissionManagerInternal.PermissionCallback;
+import com.android.server.pm.permission.PermissionManagerService;
import com.android.server.pm.permission.PermissionsState;
import com.android.server.pm.permission.PermissionsState.PermissionState;
import com.android.server.security.VerityUtils;
@@ -8185,35 +8185,22 @@
private ProviderInfo resolveContentProviderInternal(String name, int flags, int userId) {
if (!sUserManager.exists(userId)) return null;
flags = updateFlagsForComponent(flags, userId, name);
- final String instantAppPkgName = getInstantAppPackageName(Binder.getCallingUid());
- // reader
+ final int callingUid = Binder.getCallingUid();
synchronized (mPackages) {
final PackageParser.Provider provider = mProvidersByAuthority.get(name);
PackageSetting ps = provider != null
? mSettings.mPackages.get(provider.owner.packageName)
: null;
if (ps != null) {
- final boolean isInstantApp = ps.getInstantApp(userId);
- // normal application; filter out instant application provider
- if (instantAppPkgName == null && isInstantApp) {
- return null;
- }
- // instant application; filter out other instant applications
- if (instantAppPkgName != null
- && isInstantApp
- && !provider.owner.packageName.equals(instantAppPkgName)) {
- return null;
- }
- // instant application; filter out non-exposed provider
- if (instantAppPkgName != null
- && !isInstantApp
- && (provider.info.flags & ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP) == 0) {
- return null;
- }
// provider not enabled
if (!mSettings.isEnabledAndMatchLPr(provider.info, flags, userId)) {
return null;
}
+ final ComponentName component =
+ new ComponentName(provider.info.packageName, provider.info.name);
+ if (filterAppAccessLPr(ps, callingUid, component, TYPE_PROVIDER, userId)) {
+ return null;
+ }
return PackageParser.generateProviderInfo(
provider, flags, ps.readUserState(userId), userId);
}
diff --git a/services/core/java/com/android/server/wm/BoundsAnimationController.java b/services/core/java/com/android/server/wm/BoundsAnimationController.java
index ba67ff6..112d93c 100644
--- a/services/core/java/com/android/server/wm/BoundsAnimationController.java
+++ b/services/core/java/com/android/server/wm/BoundsAnimationController.java
@@ -161,7 +161,10 @@
// Timeout callback to ensure we continue the animation if waiting for resuming or app
// windows drawn fails
- private final Runnable mResumeRunnable = () -> resume();
+ private final Runnable mResumeRunnable = () -> {
+ if (DEBUG) Slog.d(TAG, "pause: timed out waiting for windows drawn");
+ resume();
+ };
BoundsAnimator(BoundsAnimationTarget target, Rect from, Rect to,
@SchedulePipModeChangedState int schedulePipModeChangedState,
@@ -213,7 +216,7 @@
// When starting an animation from fullscreen, pause here and wait for the
// windows-drawn signal before we start the rest of the transition down into PiP.
- if (mMoveFromFullscreen) {
+ if (mMoveFromFullscreen && mTarget.shouldDeferStartOnMoveToFullscreen()) {
pause();
}
} else if (mPrevSchedulePipModeChangedState == SCHEDULE_PIP_MODE_CHANGED_ON_END &&
diff --git a/services/core/java/com/android/server/wm/BoundsAnimationTarget.java b/services/core/java/com/android/server/wm/BoundsAnimationTarget.java
index 647a2d6..68be4e8 100644
--- a/services/core/java/com/android/server/wm/BoundsAnimationTarget.java
+++ b/services/core/java/com/android/server/wm/BoundsAnimationTarget.java
@@ -34,6 +34,12 @@
void onAnimationStart(boolean schedulePipModeChangedCallback, boolean forceUpdate);
/**
+ * @return Whether the animation should be paused waiting for the windows to draw before
+ * entering PiP.
+ */
+ boolean shouldDeferStartOnMoveToFullscreen();
+
+ /**
* Sets the size of the target (without any intermediate steps, like scheduling animation)
* but freezes the bounds of any tasks in the target at taskBounds, to allow for more
* flexibility during resizing. Only works for the pinned stack at the moment. This will
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index c4f2bd4..0771b53 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -3568,7 +3568,8 @@
if (s.inSplitScreenWindowingMode() && mSplitScreenDividerAnchor != null) {
t.setLayer(mSplitScreenDividerAnchor, layer++);
}
- if (s.isAppAnimating() && state != ALWAYS_ON_TOP_STATE) {
+ if ((s.isTaskAnimating() || s.isAppAnimating())
+ && state != ALWAYS_ON_TOP_STATE) {
// Ensure the animation layer ends up above the
// highest animating stack and no higher.
layerForAnimationLayer = layer++;
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index 5e2bb10..2cd2ef1 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -666,13 +666,16 @@
}
final TaskStack topSecondaryStack = mDisplayContent.getTopStackInWindowingMode(
WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
+ final RecentsAnimationController recentsAnim = mService.getRecentsAnimationController();
+ final boolean minimizedForRecentsAnimation = recentsAnim != null &&
+ recentsAnim.isSplitScreenMinimized();
boolean homeVisible = homeTask.getTopVisibleAppToken() != null;
if (homeVisible && topSecondaryStack != null) {
// Home should only be considered visible if it is greater or equal to the top secondary
// stack in terms of z-order.
homeVisible = homeStack.compareTo(topSecondaryStack) >= 0;
}
- setMinimizedDockedStack(homeVisible, animate);
+ setMinimizedDockedStack(homeVisible || minimizedForRecentsAnimation, animate);
}
private boolean isWithinDisplay(Task task) {
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index 7274aee..c4f5197 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -29,6 +29,7 @@
import static com.android.server.wm.RemoteAnimationAdapterWrapperProto.TARGET;
import static com.android.server.wm.AnimationAdapterProto.REMOTE;
+import android.annotation.IntDef;
import android.app.ActivityManager.TaskSnapshot;
import android.app.WindowConfiguration;
import android.graphics.Point;
@@ -67,12 +68,25 @@
private static final boolean DEBUG = false;
private static final long FAILSAFE_DELAY = 1000;
+ public static final int REORDER_KEEP_HOME_IN_PLACE = 0;
+ public static final int REORDER_MOVE_HOME_TO_TOP = 1;
+ public static final int REORDER_MOVE_HOME_TO_ORIGINAL_POSITION = 2;
+
+ @IntDef(prefix = { "REORDER_MODE_" }, value = {
+ REORDER_KEEP_HOME_IN_PLACE,
+ REORDER_MOVE_HOME_TO_TOP,
+ REORDER_MOVE_HOME_TO_ORIGINAL_POSITION
+ })
+ public @interface ReorderMode {}
+
private final WindowManagerService mService;
private final IRecentsAnimationRunner mRunner;
private final RecentsAnimationCallbacks mCallbacks;
private final ArrayList<TaskAnimationAdapter> mPendingAnimations = new ArrayList<>();
private final int mDisplayId;
- private final Runnable mFailsafeRunnable = this::cancelAnimation;
+ private final Runnable mFailsafeRunnable = () -> {
+ cancelAnimation(REORDER_MOVE_HOME_TO_ORIGINAL_POSITION);
+ };
// The recents component app token that is shown behind the visibile tasks
private AppWindowToken mHomeAppToken;
@@ -84,16 +98,20 @@
private boolean mPendingStart = true;
// Set when the animation has been canceled
- private boolean mCanceled = false;
+ private boolean mCanceled;
// Whether or not the input consumer is enabled. The input consumer must be both registered and
// enabled for it to start intercepting touch events.
private boolean mInputConsumerEnabled;
+ // Whether or not the recents animation should cause the primary split-screen stack to be
+ // minimized
+ private boolean mSplitScreenMinimized;
+
private Rect mTmpRect = new Rect();
public interface RecentsAnimationCallbacks {
- void onAnimationFinished(boolean moveHomeToTop);
+ void onAnimationFinished(@ReorderMode int reorderMode);
}
private final IRecentsAnimationController mController =
@@ -102,7 +120,7 @@
@Override
public TaskSnapshot screenshotTask(int taskId) {
if (DEBUG) Log.d(TAG, "screenshotTask(" + taskId + "): mCanceled=" + mCanceled);
- long token = Binder.clearCallingIdentity();
+ final long token = Binder.clearCallingIdentity();
try {
synchronized (mService.getWindowManagerLock()) {
if (mCanceled) {
@@ -131,7 +149,7 @@
@Override
public void finish(boolean moveHomeToTop) {
if (DEBUG) Log.d(TAG, "finish(" + moveHomeToTop + "): mCanceled=" + mCanceled);
- long token = Binder.clearCallingIdentity();
+ final long token = Binder.clearCallingIdentity();
try {
synchronized (mService.getWindowManagerLock()) {
if (mCanceled) {
@@ -141,7 +159,9 @@
// Note, the callback will handle its own synchronization, do not lock on WM lock
// prior to calling the callback
- mCallbacks.onAnimationFinished(moveHomeToTop);
+ mCallbacks.onAnimationFinished(moveHomeToTop
+ ? REORDER_MOVE_HOME_TO_TOP
+ : REORDER_MOVE_HOME_TO_ORIGINAL_POSITION);
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -150,7 +170,7 @@
@Override
public void setAnimationTargetsBehindSystemBars(boolean behindSystemBars)
throws RemoteException {
- long token = Binder.clearCallingIdentity();
+ final long token = Binder.clearCallingIdentity();
try {
synchronized (mService.getWindowManagerLock()) {
for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
@@ -167,7 +187,7 @@
public void setInputConsumerEnabled(boolean enabled) {
if (DEBUG) Log.d(TAG, "setInputConsumerEnabled(" + enabled + "): mCanceled="
+ mCanceled);
- long token = Binder.clearCallingIdentity();
+ final long token = Binder.clearCallingIdentity();
try {
synchronized (mService.getWindowManagerLock()) {
if (mCanceled) {
@@ -182,6 +202,23 @@
Binder.restoreCallingIdentity(token);
}
}
+
+ @Override
+ public void setSplitScreenMinimized(boolean minimized) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ synchronized (mService.getWindowManagerLock()) {
+ if (mCanceled) {
+ return;
+ }
+
+ mSplitScreenMinimized = minimized;
+ mService.checkSplitScreenMinimizedChanged(true /* animate */);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
};
/**
@@ -222,14 +259,14 @@
// Skip the animation if there is nothing to animate
if (mPendingAnimations.isEmpty()) {
- cancelAnimation();
+ cancelAnimation(REORDER_MOVE_HOME_TO_ORIGINAL_POSITION);
return;
}
try {
mRunner.asBinder().linkToDeath(this, 0);
} catch (RemoteException e) {
- cancelAnimation();
+ cancelAnimation(REORDER_MOVE_HOME_TO_ORIGINAL_POSITION);
return;
}
@@ -299,7 +336,7 @@
reasons).sendToTarget();
}
- void cancelAnimation() {
+ void cancelAnimation(@ReorderMode int reorderMode) {
if (DEBUG) Log.d(TAG, "cancelAnimation()");
synchronized (mService.getWindowManagerLock()) {
if (mCanceled) {
@@ -314,18 +351,20 @@
Slog.e(TAG, "Failed to cancel recents animation", e);
}
}
+
// Clean up and return to the previous app
// Don't hold the WM lock here as it calls back to AM/RecentsAnimation
- mCallbacks.onAnimationFinished(false /* moveHomeToTop */);
+ mCallbacks.onAnimationFinished(reorderMode);
}
- void cleanupAnimation(boolean moveHomeToTop) {
+ void cleanupAnimation(@ReorderMode int reorderMode) {
if (DEBUG) Log.d(TAG, "cleanupAnimation(): mPendingAnimations="
+ mPendingAnimations.size());
for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
final TaskAnimationAdapter adapter = mPendingAnimations.get(i);
adapter.mTask.setCanAffectSystemUiFlags(true);
- if (moveHomeToTop) {
+ if (reorderMode == REORDER_MOVE_HOME_TO_TOP
+ || reorderMode == REORDER_KEEP_HOME_IN_PLACE) {
adapter.mTask.dontAnimateDimExit();
}
adapter.mCapturedFinishCallback.onAnimationFinished(adapter);
@@ -333,7 +372,7 @@
mPendingAnimations.clear();
mRunner.asBinder().unlinkToDeath(this, 0);
-
+ // Clear associated input consumers
mService.mInputMonitor.updateInputWindowsLw(true /*force*/);
mService.destroyInputConsumer(INPUT_CONSUMER_RECENTS_ANIMATION);
}
@@ -344,7 +383,7 @@
@Override
public void binderDied() {
- cancelAnimation();
+ cancelAnimation(REORDER_MOVE_HOME_TO_ORIGINAL_POSITION);
}
void checkAnimationReady(WallpaperController wallpaperController) {
@@ -358,6 +397,10 @@
}
}
+ boolean isSplitScreenMinimized() {
+ return mSplitScreenMinimized;
+ }
+
boolean isWallpaperVisible(WindowState w) {
return w != null && w.mAppToken != null && mHomeAppToken == w.mAppToken
&& isHomeAppOverWallpaper();
@@ -389,6 +432,15 @@
return mHomeAppToken.windowsCanBeWallpaperTarget();
}
+ boolean isAnimatingTask(Task task) {
+ for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
+ if (task == mPendingAnimations.get(i).mTask) {
+ return true;
+ }
+ }
+ return false;
+ }
+
private boolean isAnimatingApp(AppWindowToken appToken) {
for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
final Task task = mPendingAnimations.get(i).mTask;
@@ -409,18 +461,18 @@
private OnAnimationFinishedCallback mCapturedFinishCallback;
private final boolean mIsRecentTaskInvisible;
private RemoteAnimationTarget mTarget;
+ private final Point mPosition = new Point();
+ private final Rect mBounds = new Rect();
TaskAnimationAdapter(Task task, boolean isRecentTaskInvisible) {
mTask = task;
mIsRecentTaskInvisible = isRecentTaskInvisible;
+ final WindowContainer container = mTask.getParent();
+ container.getRelativePosition(mPosition);
+ container.getBounds(mBounds);
}
RemoteAnimationTarget createRemoteAnimationApp() {
- final Point position = new Point();
- final Rect bounds = new Rect();
- final WindowContainer container = mTask.getParent();
- container.getRelativePosition(position);
- container.getBounds(bounds);
final WindowState mainWindow = mTask.getTopVisibleAppMainWindow();
if (mainWindow == null) {
return null;
@@ -429,7 +481,7 @@
InsetUtils.addInsets(insets, mainWindow.mAppToken.getLetterboxInsets());
mTarget = new RemoteAnimationTarget(mTask.mTaskId, MODE_CLOSING, mCapturedLeash,
!mTask.fillsParent(), mainWindow.mWinAnimator.mLastClipRect,
- insets, mTask.getPrefixOrderIndex(), position, bounds,
+ insets, mTask.getPrefixOrderIndex(), mPosition, mBounds,
mTask.getWindowConfiguration(), mIsRecentTaskInvisible);
return mTarget;
}
@@ -452,13 +504,14 @@
@Override
public void startAnimation(SurfaceControl animationLeash, Transaction t,
OnAnimationFinishedCallback finishCallback) {
+ t.setPosition(animationLeash, mPosition.x, mPosition.y);
mCapturedLeash = animationLeash;
mCapturedFinishCallback = finishCallback;
}
@Override
public void onAnimationCancelled(SurfaceControl animationLeash) {
- cancelAnimation();
+ cancelAnimation(REORDER_MOVE_HOME_TO_ORIGINAL_POSITION);
}
@Override
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index e8d3210..95223d8 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -44,6 +44,7 @@
import android.util.proto.ProtoOutputStream;
import android.view.Surface;
+import android.view.SurfaceControl;
import com.android.internal.annotations.VisibleForTesting;
import java.io.PrintWriter;
@@ -559,6 +560,23 @@
&& !mStack.isAnimatingBoundsToFullscreen() && !mPreserveNonFloatingState;
}
+ @Override
+ public SurfaceControl getAnimationLeashParent() {
+ // Reparent to the animation layer so that we aren't clipped by the non-minimized
+ // stack bounds, currently we only animate the task for the recents animation
+ return getAppAnimationLayer(false /* boosted */);
+ }
+
+ boolean isTaskAnimating() {
+ final RecentsAnimationController recentsAnim = mService.getRecentsAnimationController();
+ if (recentsAnim != null) {
+ if (recentsAnim.isAnimatingTask(this)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
WindowState getTopVisibleAppMainWindow() {
final AppWindowToken token = getTopVisibleAppToken();
return token != null ? token.findMainWindow() : null;
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 62754ad..2175c6b 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -33,8 +33,6 @@
import static android.view.WindowManager.DOCKED_RIGHT;
import static android.view.WindowManager.DOCKED_TOP;
import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_MOVEMENT;
-import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static com.android.server.wm.StackProto.ADJUSTED_BOUNDS;
import static com.android.server.wm.StackProto.ADJUSTED_FOR_IME;
import static com.android.server.wm.StackProto.ADJUST_DIVIDER_AMOUNT;
@@ -47,6 +45,8 @@
import static com.android.server.wm.StackProto.MINIMIZE_AMOUNT;
import static com.android.server.wm.StackProto.TASKS;
import static com.android.server.wm.StackProto.WINDOW_CONTAINER;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_MOVEMENT;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import android.annotation.CallSuper;
import android.content.res.Configuration;
@@ -62,12 +62,10 @@
import android.view.DisplayInfo;
import android.view.Surface;
import android.view.SurfaceControl;
-
import com.android.internal.policy.DividerSnapAlgorithm;
import com.android.internal.policy.DividerSnapAlgorithm.SnapTarget;
import com.android.internal.policy.DockedDividerUtils;
import com.android.server.EventLogTags;
-
import java.io.PrintWriter;
public class TaskStack extends WindowContainer<Task> implements
@@ -1333,6 +1331,20 @@
return mMinimizeAmount != 0f;
}
+ /**
+ * @return {@code true} if we have a {@link Task} that is animating (currently only used for the
+ * recents animation); {@code false} otherwise.
+ */
+ boolean isTaskAnimating() {
+ for (int j = mChildren.size() - 1; j >= 0; j--) {
+ final Task task = mChildren.get(j);
+ if (task.isTaskAnimating()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
@CallSuper
@Override
public void writeToProto(ProtoOutputStream proto, long fieldId, boolean trim) {
@@ -1687,6 +1699,25 @@
}
}
+ @Override
+ public boolean shouldDeferStartOnMoveToFullscreen() {
+ // Workaround for the recents animation -- normally we need to wait for the new activity to
+ // show before starting the PiP animation, but because we start and show the home activity
+ // early for the recents animation prior to the PiP animation starting, there is no
+ // subsequent all-drawn signal. In this case, we can skip the pause when the home stack is
+ // already visible and drawn.
+ final TaskStack homeStack = mDisplayContent.getHomeStack();
+ if (homeStack == null) {
+ return true;
+ }
+ final Task homeTask = homeStack.getTopChild();
+ final AppWindowToken homeApp = homeTask.getTopVisibleAppToken();
+ if (!homeTask.isVisible() || homeApp == null) {
+ return true;
+ }
+ return !homeApp.allDrawn;
+ }
+
/**
* @return True if we are currently animating the pinned stack from fullscreen to non-fullscreen
* bounds and we have a deferred PiP mode changed callback set with the animation.
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
index c509980..6de1579 100644
--- a/services/core/java/com/android/server/wm/WallpaperController.java
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -26,6 +26,7 @@
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER;
+import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_HOME_TO_ORIGINAL_POSITION;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREENSHOT;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER;
@@ -618,7 +619,8 @@
// If there was a recents animation in progress, cancel that animation
if (mService.getRecentsAnimationController() != null) {
- mService.getRecentsAnimationController().cancelAnimation();
+ mService.getRecentsAnimationController().cancelAnimation(
+ REORDER_MOVE_HOME_TO_ORIGINAL_POSITION);
}
return true;
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index f1cd46b..28a57f5a 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2687,20 +2687,20 @@
}
}
- public void cancelRecentsAnimation() {
+ public void cancelRecentsAnimation(@RecentsAnimationController.ReorderMode int reorderMode) {
// Note: Do not hold the WM lock, this will lock appropriately in the call which also
// calls through to AM/RecentsAnimation.onAnimationFinished()
if (mRecentsAnimationController != null) {
// This call will call through to cleanupAnimation() below after the animation is
// canceled
- mRecentsAnimationController.cancelAnimation();
+ mRecentsAnimationController.cancelAnimation(reorderMode);
}
}
- public void cleanupRecentsAnimation(boolean moveHomeToTop) {
+ public void cleanupRecentsAnimation(@RecentsAnimationController.ReorderMode int reorderMode) {
synchronized (mWindowMap) {
if (mRecentsAnimationController != null) {
- mRecentsAnimationController.cleanupAnimation(moveHomeToTop);
+ mRecentsAnimationController.cleanupAnimation(reorderMode);
mRecentsAnimationController = null;
mAppTransition.updateBooster();
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 54c2e9b..f015889 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -178,6 +178,7 @@
import android.util.Slog;
import android.util.TimeUtils;
import android.util.proto.ProtoOutputStream;
+import android.view.Display;
import android.view.DisplayCutout;
import android.view.DisplayInfo;
import android.view.Gravity;
@@ -1366,6 +1367,7 @@
// Window was not laid out for this display yet, so make sure mLayoutSeq does not match.
if (dc != null) {
mLayoutSeq = dc.mLayoutSeq - 1;
+ mInputWindowHandle.displayId = dc.getDisplayId();
}
}
@@ -1378,7 +1380,7 @@
public int getDisplayId() {
final DisplayContent displayContent = getDisplayContent();
if (displayContent == null) {
- return -1;
+ return Display.INVALID_DISPLAY;
}
return displayContent.getDisplayId();
}
diff --git a/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java b/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
index 7765387..6290ff1 100644
--- a/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
@@ -649,7 +649,7 @@
assertSecurityException(expectCallable, () -> mService.cancelTaskWindowTransition(0));
assertSecurityException(expectCallable, () -> mService.startRecentsActivity(null, null,
null));
- assertSecurityException(expectCallable, () -> mService.cancelRecentsAnimation());
+ assertSecurityException(expectCallable, () -> mService.cancelRecentsAnimation(true));
}
private void testGetTasksApis(boolean expectCallable) {
diff --git a/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java b/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java
index 92cc537..45bee6e 100644
--- a/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java
@@ -30,9 +30,11 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.ParceledListSlice;
import android.database.ContentObserver;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
+import android.hardware.display.AmbientBrightnessDayStats;
import android.hardware.display.BrightnessChangeEvent;
import android.os.BatteryManager;
import android.os.Handler;
@@ -571,6 +573,19 @@
assertEquals(event.batteryLevel, event2.batteryLevel, FLOAT_DELTA);
}
+ @Test
+ public void testNonNullAmbientStats() {
+ // getAmbientBrightnessStats should return an empty list rather than null when
+ // tracker isn't started or hasn't collected any data.
+ ParceledListSlice<AmbientBrightnessDayStats> slice = mTracker.getAmbientBrightnessStats(0);
+ assertNotNull(slice);
+ assertTrue(slice.getList().isEmpty());
+ startTracker(mTracker);
+ slice = mTracker.getAmbientBrightnessStats(0);
+ assertNotNull(slice);
+ assertTrue(slice.getList().isEmpty());
+ }
+
private InputStream getInputStream(String data) {
return new ByteArrayInputStream(data.getBytes(StandardCharsets.UTF_8));
}
diff --git a/services/tests/servicestests/src/com/android/server/net/watchlist/WatchlistConfigTests.java b/services/tests/servicestests/src/com/android/server/net/watchlist/WatchlistConfigTests.java
index 654acc2..678f018 100644
--- a/services/tests/servicestests/src/com/android/server/net/watchlist/WatchlistConfigTests.java
+++ b/services/tests/servicestests/src/com/android/server/net/watchlist/WatchlistConfigTests.java
@@ -19,6 +19,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertNull;
import android.content.Context;
import android.support.test.InstrumentationRegistry;
@@ -114,13 +115,19 @@
}
@Test
- public void testWatchlistConfig_getWatchlistConfigHash() throws Exception {
+ public void testWatchlistConfig_getWatchlistConfigHash_hasConfig() throws Exception {
copyWatchlistConfigXml(mContext, TEST_XML_1, mTestXmlFile);
WatchlistConfig config = new WatchlistConfig(mTestXmlFile);
assertEquals(TEST_XML_1_HASH, HexDump.toHexString(config.getWatchlistConfigHash()));
}
@Test
+ public void testWatchlistConfig_getWatchlistConfigHash_withoutConfig() throws Exception {
+ WatchlistConfig config = new WatchlistConfig(mTestXmlFile);
+ assertNull(config.getWatchlistConfigHash());
+ }
+
+ @Test
public void testWatchlistConfig_testDumpDoesNotCrash() throws Exception {
WatchlistConfig config = new WatchlistConfig(new File("/not_exist_path.xml"));
ByteArrayOutputStream bs = new ByteArrayOutputStream(2048);
diff --git a/services/tests/servicestests/src/com/android/server/wm/BoundsAnimationControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/BoundsAnimationControllerTests.java
index 2bfe274..6019958 100644
--- a/services/tests/servicestests/src/com/android/server/wm/BoundsAnimationControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/BoundsAnimationControllerTests.java
@@ -159,6 +159,11 @@
}
@Override
+ public boolean shouldDeferStartOnMoveToFullscreen() {
+ return true;
+ }
+
+ @Override
public boolean setPinnedStackSize(Rect stackBounds, Rect taskBounds) {
// TODO: Once we break the runs apart, we should fail() here if this is called outside
// of onAnimationStart() and onAnimationEnd()
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
index 1248eae..7c928c9 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
@@ -326,6 +326,17 @@
assertThat(app.mLayoutSeq, not(is(mDisplayContent.mLayoutSeq)));
}
+ @Test
+ public void testDisplayIdUpdatedOnReparent() throws Exception {
+ final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
+ // fake a different display
+ app.mInputWindowHandle.displayId = mDisplayContent.getDisplayId() + 1;
+ app.onDisplayChanged(mDisplayContent);
+
+ assertThat(app.mInputWindowHandle.displayId, is(mDisplayContent.getDisplayId()));
+ assertThat(app.getDisplayId(), is(mDisplayContent.getDisplayId()));
+ }
+
private void testPrepareWindowToDisplayDuringRelayout(boolean wasVisible) {
reset(mPowerManagerWrapper);
final WindowState root = createWindow(null, TYPE_APPLICATION, "root");
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java
index 0815876..54ed1e6 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java
@@ -1093,7 +1093,7 @@
NotificationChannel channel2 =
new NotificationChannel("id4", "a", NotificationManager.IMPORTANCE_HIGH);
NotificationChannel channel3 =
- new NotificationChannel("id4", "a", NotificationManager.IMPORTANCE_HIGH);
+ new NotificationChannel("id5", "a", NotificationManager.IMPORTANCE_HIGH);
mHelper.createNotificationChannel(PKG, UID, channel, true, false);
mHelper.createNotificationChannel(PKG, UID, channel2, true, false);
mHelper.createNotificationChannel(PKG, UID, channel3, true, false);
@@ -1106,6 +1106,24 @@
}
@Test
+ public void testGetBlockedChannelCount() throws Exception {
+ NotificationChannel channel =
+ new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
+ NotificationChannel channel2 =
+ new NotificationChannel("id4", "a", NotificationManager.IMPORTANCE_NONE);
+ NotificationChannel channel3 =
+ new NotificationChannel("id5", "a", NotificationManager.IMPORTANCE_NONE);
+ mHelper.createNotificationChannel(PKG, UID, channel, true, false);
+ mHelper.createNotificationChannel(PKG, UID, channel2, true, false);
+ mHelper.createNotificationChannel(PKG, UID, channel3, true, false);
+
+ mHelper.deleteNotificationChannel(PKG, UID, channel3.getId());
+
+ assertEquals(1, mHelper.getBlockedChannelCount(PKG, UID));
+ assertEquals(0, mHelper.getBlockedChannelCount("pkg2", UID2));
+ }
+
+ @Test
public void testCreateDeletedChannel() throws Exception {
long[] vibration = new long[]{100, 67, 145, 156};
NotificationChannel channel =