Merge "Update documentation for WindowManager.LayoutParams#preferredRefreshRate" into udc-dev
diff --git a/core/api/current.txt b/core/api/current.txt
index 79123c7..771d56c 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -6623,6 +6623,7 @@
ctor public Notification.MediaStyle();
ctor @Deprecated public Notification.MediaStyle(android.app.Notification.Builder);
method public android.app.Notification.MediaStyle setMediaSession(android.media.session.MediaSession.Token);
+ method @NonNull @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public android.app.Notification.MediaStyle setRemotePlaybackInfo(@NonNull CharSequence, @DrawableRes int, @Nullable android.app.PendingIntent);
method public android.app.Notification.MediaStyle setShowActionsInCompactView(int...);
}
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 0a893f0..ce5723b 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -968,10 +968,6 @@
field public static final int SEMANTIC_ACTION_MARK_CONVERSATION_AS_PRIORITY = 11; // 0xb
}
- public static class Notification.MediaStyle extends android.app.Notification.Style {
- method @NonNull @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public android.app.Notification.MediaStyle setRemotePlaybackInfo(@NonNull CharSequence, @DrawableRes int, @Nullable android.app.PendingIntent);
- }
-
public static final class Notification.TvExtender implements android.app.Notification.Extender {
ctor public Notification.TvExtender();
ctor public Notification.TvExtender(android.app.Notification);
@@ -9984,6 +9980,7 @@
public final class HotspotNetwork implements android.os.Parcelable {
method public int describeContents();
method public long getDeviceId();
+ method @NonNull public android.os.Bundle getExtras();
method public int getHostNetworkType();
method @Nullable public String getHotspotBssid();
method @NonNull public java.util.Set<java.lang.Integer> getHotspotSecurityTypes();
@@ -10003,6 +10000,7 @@
method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetwork.Builder addHotspotSecurityType(int);
method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetwork build();
method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetwork.Builder setDeviceId(long);
+ method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetwork.Builder setExtras(@NonNull android.os.Bundle);
method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetwork.Builder setHostNetworkType(int);
method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetwork.Builder setHotspotBssid(@NonNull String);
method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetwork.Builder setHotspotSsid(@NonNull String);
@@ -10039,6 +10037,7 @@
public final class KnownNetwork implements android.os.Parcelable {
method public int describeContents();
+ method @NonNull public android.os.Bundle getExtras();
method @Nullable public android.net.wifi.sharedconnectivity.app.NetworkProviderInfo getNetworkProviderInfo();
method public int getNetworkSource();
method @NonNull public java.util.Set<java.lang.Integer> getSecurityTypes();
@@ -10054,6 +10053,7 @@
ctor public KnownNetwork.Builder();
method @NonNull public android.net.wifi.sharedconnectivity.app.KnownNetwork.Builder addSecurityType(int);
method @NonNull public android.net.wifi.sharedconnectivity.app.KnownNetwork build();
+ method @NonNull public android.net.wifi.sharedconnectivity.app.KnownNetwork.Builder setExtras(@NonNull android.os.Bundle);
method @NonNull public android.net.wifi.sharedconnectivity.app.KnownNetwork.Builder setNetworkProviderInfo(@Nullable android.net.wifi.sharedconnectivity.app.NetworkProviderInfo);
method @NonNull public android.net.wifi.sharedconnectivity.app.KnownNetwork.Builder setNetworkSource(int);
method @NonNull public android.net.wifi.sharedconnectivity.app.KnownNetwork.Builder setSsid(@NonNull String);
@@ -10085,6 +10085,7 @@
method @IntRange(from=0, to=3) public int getConnectionStrength();
method @NonNull public String getDeviceName();
method public int getDeviceType();
+ method @NonNull public android.os.Bundle getExtras();
method @NonNull public String getModelName();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.sharedconnectivity.app.NetworkProviderInfo> CREATOR;
@@ -10103,6 +10104,7 @@
method @NonNull public android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.Builder setConnectionStrength(@IntRange(from=0, to=3) int);
method @NonNull public android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.Builder setDeviceName(@NonNull String);
method @NonNull public android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.Builder setDeviceType(int);
+ method @NonNull public android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.Builder setExtras(@NonNull android.os.Bundle);
method @NonNull public android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.Builder setModelName(@NonNull String);
}
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 445b957..6bfaa35 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -516,6 +516,10 @@
package android.app.admin {
+ public final class AccountTypePolicyKey extends android.app.admin.PolicyKey {
+ ctor public AccountTypePolicyKey(@NonNull String, @NonNull String);
+ }
+
public final class DeviceAdminAuthority extends android.app.admin.Authority {
field @NonNull public static final android.app.admin.DeviceAdminAuthority DEVICE_ADMIN_AUTHORITY;
}
@@ -612,6 +616,10 @@
field @NonNull public static final android.app.admin.FlagUnion FLAG_UNION;
}
+ public final class IntentFilterPolicyKey extends android.app.admin.PolicyKey {
+ ctor public IntentFilterPolicyKey(@NonNull String, @NonNull android.content.IntentFilter);
+ }
+
public final class MostRecent<V> extends android.app.admin.ResolutionMechanism<V> {
ctor public MostRecent();
method public int describeContents();
@@ -627,6 +635,14 @@
field @NonNull public static final android.os.Parcelable.Creator<android.app.admin.MostRestrictive<?>> CREATOR;
}
+ public final class PackagePermissionPolicyKey extends android.app.admin.PolicyKey {
+ ctor public PackagePermissionPolicyKey(@NonNull String, @NonNull String, @NonNull String);
+ }
+
+ public final class PackagePolicyKey extends android.app.admin.PolicyKey {
+ ctor public PackagePolicyKey(@NonNull String, @NonNull String);
+ }
+
public final class PolicyState<V> implements android.os.Parcelable {
method @NonNull public android.app.admin.ResolutionMechanism<V> getResolutionMechanism();
}
@@ -676,6 +692,10 @@
method public int getOperation();
}
+ public final class UserRestrictionPolicyKey extends android.app.admin.PolicyKey {
+ ctor public UserRestrictionPolicyKey(@NonNull String, @NonNull String);
+ }
+
}
package android.app.assist {
diff --git a/core/java/android/animation/Animator.java b/core/java/android/animation/Animator.java
index a81ef18..d0ce701 100644
--- a/core/java/android/animation/Animator.java
+++ b/core/java/android/animation/Animator.java
@@ -69,7 +69,7 @@
* backing field for backgroundPauseDelay property. This could be simply a hardcoded
* value in AnimationHandler, but it is useful to be able to change the value in tests.
*/
- private static long sBackgroundPauseDelay = 10000;
+ private static long sBackgroundPauseDelay = 1000;
/**
* Sets the duration for delaying pausing animators when apps go into the background.
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 0e89f57..502ef0d 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -9163,10 +9163,7 @@
* {@code null}, in which case the output switcher will be disabled.
* This intent should open an Activity or it will be ignored.
* @return MediaStyle
- *
- * @hide
*/
- @SystemApi
@RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL)
@NonNull
public MediaStyle setRemotePlaybackInfo(@NonNull CharSequence deviceName,
diff --git a/core/java/android/app/admin/AccountTypePolicyKey.java b/core/java/android/app/admin/AccountTypePolicyKey.java
index 6417cd4..9e376a7 100644
--- a/core/java/android/app/admin/AccountTypePolicyKey.java
+++ b/core/java/android/app/admin/AccountTypePolicyKey.java
@@ -23,6 +23,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.os.Bundle;
import android.os.Parcel;
@@ -49,6 +50,7 @@
/**
* @hide
*/
+ @TestApi
public AccountTypePolicyKey(@NonNull String key, @NonNull String accountType) {
super(key);
mAccountType = Objects.requireNonNull((accountType));
diff --git a/core/java/android/app/admin/IntentFilterPolicyKey.java b/core/java/android/app/admin/IntentFilterPolicyKey.java
index b0af4cd..30aad96 100644
--- a/core/java/android/app/admin/IntentFilterPolicyKey.java
+++ b/core/java/android/app/admin/IntentFilterPolicyKey.java
@@ -23,6 +23,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Parcel;
@@ -49,6 +50,7 @@
/**
* @hide
*/
+ @TestApi
public IntentFilterPolicyKey(@NonNull String identifier, @NonNull IntentFilter filter) {
super(identifier);
mFilter = Objects.requireNonNull(filter);
diff --git a/core/java/android/app/admin/PackagePermissionPolicyKey.java b/core/java/android/app/admin/PackagePermissionPolicyKey.java
index 08c4224..7fd514c 100644
--- a/core/java/android/app/admin/PackagePermissionPolicyKey.java
+++ b/core/java/android/app/admin/PackagePermissionPolicyKey.java
@@ -24,6 +24,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@@ -53,6 +54,7 @@
/**
* @hide
*/
+ @TestApi
public PackagePermissionPolicyKey(@NonNull String identifier, @NonNull String packageName,
@NonNull String permissionName) {
super(identifier);
diff --git a/core/java/android/app/admin/PackagePolicyKey.java b/core/java/android/app/admin/PackagePolicyKey.java
index b2a8d5d..2ab00bc 100644
--- a/core/java/android/app/admin/PackagePolicyKey.java
+++ b/core/java/android/app/admin/PackagePolicyKey.java
@@ -23,6 +23,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@@ -50,6 +51,7 @@
/**
* @hide
*/
+ @TestApi
public PackagePolicyKey(@NonNull String key, @NonNull String packageName) {
super(key);
mPackageName = Objects.requireNonNull((packageName));
diff --git a/core/java/android/app/admin/UserRestrictionPolicyKey.java b/core/java/android/app/admin/UserRestrictionPolicyKey.java
index 880b58b..aeb2380 100644
--- a/core/java/android/app/admin/UserRestrictionPolicyKey.java
+++ b/core/java/android/app/admin/UserRestrictionPolicyKey.java
@@ -20,6 +20,7 @@
import android.annotation.NonNull;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.os.Bundle;
import android.os.Parcel;
@@ -40,6 +41,7 @@
/**
* @hide
*/
+ @TestApi
public UserRestrictionPolicyKey(@NonNull String identifier, @NonNull String restriction) {
super(identifier);
mRestriction = Objects.requireNonNull(restriction);
diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java
index fe10b7f..27f6a26 100644
--- a/core/java/android/appwidget/AppWidgetHostView.java
+++ b/core/java/android/appwidget/AppWidgetHostView.java
@@ -31,6 +31,7 @@
import android.content.pm.LauncherApps;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
+import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.PointF;
import android.graphics.Rect;
@@ -311,20 +312,27 @@
super.onLayout(changed, left, top, right, bottom);
} catch (final RuntimeException e) {
Log.e(TAG, "Remote provider threw runtime exception, using error view instead.", e);
- removeViewInLayout(mView);
- View child = getErrorView();
- prepareView(child);
- addViewInLayout(child, 0, child.getLayoutParams());
- measureChild(child, MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.EXACTLY),
- MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.EXACTLY));
- child.layout(0, 0, child.getMeasuredWidth() + mPaddingLeft + mPaddingRight,
- child.getMeasuredHeight() + mPaddingTop + mPaddingBottom);
- mView = child;
- mViewMode = VIEW_MODE_ERROR;
+ handleViewError();
}
}
/**
+ * Remove bad view and replace with error message view
+ */
+ private void handleViewError() {
+ removeViewInLayout(mView);
+ View child = getErrorView();
+ prepareView(child);
+ addViewInLayout(child, 0, child.getLayoutParams());
+ measureChild(child, MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.EXACTLY),
+ MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.EXACTLY));
+ child.layout(0, 0, child.getMeasuredWidth() + mPaddingLeft + mPaddingRight,
+ child.getMeasuredHeight() + mPaddingTop + mPaddingBottom);
+ mView = child;
+ mViewMode = VIEW_MODE_ERROR;
+ }
+
+ /**
* Provide guidance about the size of this widget to the AppWidgetManager. The widths and
* heights should correspond to the full area the AppWidgetHostView is given. Padding added by
* the framework will be accounted for automatically. This information gets embedded into the
@@ -953,4 +961,15 @@
reapplyLastRemoteViews();
}
}
+
+ @Override
+ protected void dispatchDraw(@NonNull Canvas canvas) {
+ try {
+ super.dispatchDraw(canvas);
+ } catch (Exception e) {
+ // Catch draw exceptions that may be caused by RemoteViews
+ Log.e(TAG, "Drawing view failed: " + e);
+ post(this::handleViewError);
+ }
+ }
}
diff --git a/core/java/android/hardware/input/InputDeviceLightsManager.java b/core/java/android/hardware/input/InputDeviceLightsManager.java
index 802e6dd..f4ee9a2 100644
--- a/core/java/android/hardware/input/InputDeviceLightsManager.java
+++ b/core/java/android/hardware/input/InputDeviceLightsManager.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.app.ActivityThread;
+import android.content.Context;
import android.hardware.lights.Light;
import android.hardware.lights.LightState;
import android.hardware.lights.LightsManager;
@@ -30,22 +31,22 @@
import java.util.List;
/**
- * LightsManager manages an input device's lights {@link android.hardware.input.Light}.
+ * LightsManager manages an input device's lights {@link android.hardware.lights.Light}
*/
class InputDeviceLightsManager extends LightsManager {
private static final String TAG = "InputDeviceLightsManager";
private static final boolean DEBUG = false;
- private final InputManager mInputManager;
+ private final InputManagerGlobal mGlobal;
// The input device ID.
private final int mDeviceId;
// Package name
private final String mPackageName;
- InputDeviceLightsManager(InputManager inputManager, int deviceId) {
- super(ActivityThread.currentActivityThread().getSystemContext());
- mInputManager = inputManager;
+ InputDeviceLightsManager(Context context, int deviceId) {
+ super(context);
+ mGlobal = InputManagerGlobal.getInstance();
mDeviceId = deviceId;
mPackageName = ActivityThread.currentPackageName();
}
@@ -57,7 +58,7 @@
*/
@Override
public @NonNull List<Light> getLights() {
- return mInputManager.getLights(mDeviceId);
+ return mGlobal.getLights(mDeviceId);
}
/**
@@ -68,7 +69,7 @@
@Override
public @NonNull LightState getLightState(@NonNull Light light) {
Preconditions.checkNotNull(light);
- return mInputManager.getLightState(mDeviceId, light);
+ return mGlobal.getLightState(mDeviceId, light);
}
/**
@@ -77,7 +78,7 @@
@Override
public @NonNull LightsSession openSession() {
final LightsSession session = new InputDeviceLightsSession();
- mInputManager.openLightSession(mDeviceId, mPackageName, session.getToken());
+ mGlobal.openLightSession(mDeviceId, mPackageName, session.getToken());
return session;
}
@@ -113,7 +114,7 @@
Preconditions.checkNotNull(request);
Preconditions.checkArgument(!mClosed);
- mInputManager.requestLights(mDeviceId, request, getToken());
+ mGlobal.requestLights(mDeviceId, request, getToken());
}
/**
@@ -122,7 +123,7 @@
@Override
public void close() {
if (!mClosed) {
- mInputManager.closeLightSession(mDeviceId, getToken());
+ mGlobal.closeLightSession(mDeviceId, getToken());
mClosed = true;
mCloseGuard.close();
}
diff --git a/core/java/android/hardware/input/InputDeviceVibrator.java b/core/java/android/hardware/input/InputDeviceVibrator.java
index ce6b523..9c18260 100644
--- a/core/java/android/hardware/input/InputDeviceVibrator.java
+++ b/core/java/android/hardware/input/InputDeviceVibrator.java
@@ -45,14 +45,14 @@
private final int mDeviceId;
private final VibratorInfo mVibratorInfo;
private final Binder mToken;
- private final InputManager mInputManager;
+ private final InputManagerGlobal mGlobal;
@GuardedBy("mDelegates")
private final ArrayMap<OnVibratorStateChangedListener,
OnVibratorStateChangedListenerDelegate> mDelegates = new ArrayMap<>();
- InputDeviceVibrator(InputManager inputManager, int deviceId, int vibratorId) {
- mInputManager = inputManager;
+ InputDeviceVibrator(int deviceId, int vibratorId) {
+ mGlobal = InputManagerGlobal.getInstance();
mDeviceId = deviceId;
mVibratorInfo = new VibratorInfo.Builder(vibratorId)
.setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL)
@@ -93,7 +93,7 @@
@Override
public boolean isVibrating() {
- return mInputManager.isVibrating(mDeviceId);
+ return mGlobal.isVibrating(mDeviceId);
}
/**
@@ -132,7 +132,7 @@
final OnVibratorStateChangedListenerDelegate delegate =
new OnVibratorStateChangedListenerDelegate(listener, executor);
- if (!mInputManager.registerVibratorStateListener(mDeviceId, delegate)) {
+ if (!mGlobal.registerVibratorStateListener(mDeviceId, delegate)) {
Log.w(TAG, "Failed to register vibrate state listener");
return;
}
@@ -156,7 +156,7 @@
if (mDelegates.containsKey(listener)) {
final OnVibratorStateChangedListenerDelegate delegate = mDelegates.get(listener);
- if (!mInputManager.unregisterVibratorStateListener(mDeviceId, delegate)) {
+ if (!mGlobal.unregisterVibratorStateListener(mDeviceId, delegate)) {
Log.w(TAG, "Failed to unregister vibrate state listener");
return;
}
@@ -176,12 +176,12 @@
@Override
public void vibrate(int uid, String opPkg, @NonNull VibrationEffect effect, String reason,
@NonNull VibrationAttributes attributes) {
- mInputManager.vibrate(mDeviceId, effect, mToken);
+ mGlobal.vibrate(mDeviceId, effect, mToken);
}
@Override
public void cancel() {
- mInputManager.cancelVibrate(mDeviceId, mToken);
+ mGlobal.cancelVibrate(mDeviceId, mToken);
}
@Override
diff --git a/core/java/android/hardware/input/InputDeviceVibratorManager.java b/core/java/android/hardware/input/InputDeviceVibratorManager.java
index d77f9c3..64b56677 100644
--- a/core/java/android/hardware/input/InputDeviceVibratorManager.java
+++ b/core/java/android/hardware/input/InputDeviceVibratorManager.java
@@ -40,7 +40,7 @@
private static final boolean DEBUG = false;
private final Binder mToken;
- private final InputManager mInputManager;
+ private final InputManagerGlobal mGlobal;
// The input device Id.
private final int mDeviceId;
@@ -48,8 +48,8 @@
@GuardedBy("mVibrators")
private final SparseArray<Vibrator> mVibrators = new SparseArray<>();
- public InputDeviceVibratorManager(InputManager inputManager, int deviceId) {
- mInputManager = inputManager;
+ public InputDeviceVibratorManager(int deviceId) {
+ mGlobal = InputManagerGlobal.getInstance();
mDeviceId = deviceId;
mToken = new Binder();
@@ -61,10 +61,10 @@
mVibrators.clear();
InputDevice inputDevice = InputDevice.getDevice(mDeviceId);
final int[] vibratorIds =
- mInputManager.getVibratorIds(mDeviceId);
+ mGlobal.getVibratorIds(mDeviceId);
for (int i = 0; i < vibratorIds.length; i++) {
mVibrators.put(vibratorIds[i],
- new InputDeviceVibrator(mInputManager, mDeviceId, vibratorIds[i]));
+ new InputDeviceVibrator(mDeviceId, vibratorIds[i]));
}
}
}
@@ -127,12 +127,12 @@
@Override
public void vibrate(int uid, String opPkg, @NonNull CombinedVibration effect,
String reason, @Nullable VibrationAttributes attributes) {
- mInputManager.vibrate(mDeviceId, effect, mToken);
+ mGlobal.vibrate(mDeviceId, effect, mToken);
}
@Override
public void cancel() {
- mInputManager.cancelVibrate(mDeviceId, mToken);
+ mGlobal.cancelVibrate(mDeviceId, mToken);
}
@Override
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index 054ae21..5dc3825 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -33,21 +33,15 @@
import android.content.Context;
import android.hardware.BatteryState;
import android.hardware.SensorManager;
-import android.hardware.lights.Light;
-import android.hardware.lights.LightState;
import android.hardware.lights.LightsManager;
-import android.hardware.lights.LightsRequest;
import android.os.Binder;
import android.os.Build;
-import android.os.CombinedVibration;
import android.os.Handler;
import android.os.IBinder;
-import android.os.IVibratorStateListener;
import android.os.InputEventInjectionSync;
import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
-import android.os.VibrationEffect;
import android.os.Vibrator;
import android.os.VibratorManager;
import android.util.Log;
@@ -1380,7 +1374,7 @@
* @hide
*/
public Vibrator getInputDeviceVibrator(int deviceId, int vibratorId) {
- return new InputDeviceVibrator(this, deviceId, vibratorId);
+ return new InputDeviceVibrator(deviceId, vibratorId);
}
/**
@@ -1391,85 +1385,7 @@
*/
@NonNull
public VibratorManager getInputDeviceVibratorManager(int deviceId) {
- return new InputDeviceVibratorManager(InputManager.this, deviceId);
- }
-
- /*
- * Get the list of device vibrators
- * @return The list of vibrators IDs
- */
- int[] getVibratorIds(int deviceId) {
- try {
- return mIm.getVibratorIds(deviceId);
- } catch (RemoteException ex) {
- throw ex.rethrowFromSystemServer();
- }
- }
-
- /*
- * Perform vibration effect
- */
- void vibrate(int deviceId, VibrationEffect effect, IBinder token) {
- try {
- mIm.vibrate(deviceId, effect, token);
- } catch (RemoteException ex) {
- throw ex.rethrowFromSystemServer();
- }
- }
-
- /*
- * Perform combined vibration effect
- */
- void vibrate(int deviceId, CombinedVibration effect, IBinder token) {
- try {
- mIm.vibrateCombined(deviceId, effect, token);
- } catch (RemoteException ex) {
- throw ex.rethrowFromSystemServer();
- }
- }
-
- /*
- * Cancel an ongoing vibration
- */
- void cancelVibrate(int deviceId, IBinder token) {
- try {
- mIm.cancelVibrate(deviceId, token);
- } catch (RemoteException ex) {
- throw ex.rethrowFromSystemServer();
- }
- }
-
- /*
- * Check if input device is vibrating
- */
- boolean isVibrating(int deviceId) {
- try {
- return mIm.isVibrating(deviceId);
- } catch (RemoteException ex) {
- throw ex.rethrowFromSystemServer();
- }
- }
-
- /**
- * Register input device vibrator state listener
- */
- boolean registerVibratorStateListener(int deviceId, IVibratorStateListener listener) {
- try {
- return mIm.registerVibratorStateListener(deviceId, listener);
- } catch (RemoteException ex) {
- throw ex.rethrowFromSystemServer();
- }
- }
-
- /**
- * Unregister input device vibrator state listener
- */
- boolean unregisterVibratorStateListener(int deviceId, IVibratorStateListener listener) {
- try {
- return mIm.unregisterVibratorStateListener(deviceId, listener);
- } catch (RemoteException ex) {
- throw ex.rethrowFromSystemServer();
- }
+ return new InputDeviceVibratorManager(deviceId);
}
/**
@@ -1499,77 +1415,7 @@
*/
@NonNull
public LightsManager getInputDeviceLightsManager(int deviceId) {
- return new InputDeviceLightsManager(InputManager.this, deviceId);
- }
-
- /**
- * Gets a list of light objects associated with an input device.
- * @return The list of lights, never null.
- */
- @NonNull List<Light> getLights(int deviceId) {
- try {
- return mIm.getLights(deviceId);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Returns the state of an input device light.
- * @return the light state
- */
- @NonNull LightState getLightState(int deviceId, @NonNull Light light) {
- try {
- return mIm.getLightState(deviceId, light.getId());
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Request to modify the states of multiple lights.
- *
- * @param request the settings for lights that should change
- */
- void requestLights(int deviceId, @NonNull LightsRequest request, IBinder token) {
- try {
- List<Integer> lightIdList = request.getLights();
- int[] lightIds = new int[lightIdList.size()];
- for (int i = 0; i < lightIds.length; i++) {
- lightIds[i] = lightIdList.get(i);
- }
- List<LightState> lightStateList = request.getLightStates();
- mIm.setLightStates(deviceId, lightIds,
- lightStateList.toArray(new LightState[0]),
- token);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Open light session for input device manager
- *
- * @param token The token for the light session
- */
- void openLightSession(int deviceId, String opPkg, @NonNull IBinder token) {
- try {
- mIm.openLightSession(deviceId, opPkg, token);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Close light session
- *
- */
- void closeLightSession(int deviceId, @NonNull IBinder token) {
- try {
- mIm.closeLightSession(deviceId, token);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return new InputDeviceLightsManager(getContext(), deviceId);
}
/**
diff --git a/core/java/android/hardware/input/InputManagerGlobal.java b/core/java/android/hardware/input/InputManagerGlobal.java
index 524d820..08d81bd 100644
--- a/core/java/android/hardware/input/InputManagerGlobal.java
+++ b/core/java/android/hardware/input/InputManagerGlobal.java
@@ -27,12 +27,18 @@
import android.hardware.input.InputManager.InputDeviceListener;
import android.hardware.input.InputManager.KeyboardBacklightListener;
import android.hardware.input.InputManager.OnTabletModeChangedListener;
+import android.hardware.lights.Light;
+import android.hardware.lights.LightState;
+import android.hardware.lights.LightsRequest;
+import android.os.CombinedVibration;
import android.os.Handler;
import android.os.IBinder;
+import android.os.IVibratorStateListener;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.VibrationEffect;
import android.util.Log;
import android.util.SparseArray;
import android.view.Display;
@@ -903,4 +909,152 @@
throw ex.rethrowFromSystemServer();
}
}
+
+ /**
+ * Gets a list of light objects associated with an input device.
+ * @return The list of lights, never null.
+ */
+ @NonNull List<Light> getLights(int deviceId) {
+ try {
+ return mIm.getLights(deviceId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Returns the state of an input device light.
+ * @return the light state
+ */
+ @NonNull LightState getLightState(int deviceId, @NonNull Light light) {
+ try {
+ return mIm.getLightState(deviceId, light.getId());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Request to modify the states of multiple lights.
+ *
+ * @param request the settings for lights that should change
+ */
+ void requestLights(int deviceId, @NonNull LightsRequest request, IBinder token) {
+ try {
+ List<Integer> lightIdList = request.getLights();
+ int[] lightIds = new int[lightIdList.size()];
+ for (int i = 0; i < lightIds.length; i++) {
+ lightIds[i] = lightIdList.get(i);
+ }
+ List<LightState> lightStateList = request.getLightStates();
+ mIm.setLightStates(deviceId, lightIds,
+ lightStateList.toArray(new LightState[0]),
+ token);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Open light session for input device manager
+ *
+ * @param token The token for the light session
+ */
+ void openLightSession(int deviceId, String opPkg, @NonNull IBinder token) {
+ try {
+ mIm.openLightSession(deviceId, opPkg, token);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Close light session
+ *
+ */
+ void closeLightSession(int deviceId, @NonNull IBinder token) {
+ try {
+ mIm.closeLightSession(deviceId, token);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /*
+ * Get the list of device vibrators
+ * @return The list of vibrators IDs
+ */
+ int[] getVibratorIds(int deviceId) {
+ try {
+ return mIm.getVibratorIds(deviceId);
+ } catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
+ }
+ }
+
+ /*
+ * Perform vibration effect
+ */
+ void vibrate(int deviceId, VibrationEffect effect, IBinder token) {
+ try {
+ mIm.vibrate(deviceId, effect, token);
+ } catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
+ }
+ }
+
+ /*
+ * Perform combined vibration effect
+ */
+ void vibrate(int deviceId, CombinedVibration effect, IBinder token) {
+ try {
+ mIm.vibrateCombined(deviceId, effect, token);
+ } catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
+ }
+ }
+
+ /*
+ * Cancel an ongoing vibration
+ */
+ void cancelVibrate(int deviceId, IBinder token) {
+ try {
+ mIm.cancelVibrate(deviceId, token);
+ } catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
+ }
+ }
+
+ /*
+ * Check if input device is vibrating
+ */
+ boolean isVibrating(int deviceId) {
+ try {
+ return mIm.isVibrating(deviceId);
+ } catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Register input device vibrator state listener
+ */
+ boolean registerVibratorStateListener(int deviceId, IVibratorStateListener listener) {
+ try {
+ return mIm.registerVibratorStateListener(deviceId, listener);
+ } catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Unregister input device vibrator state listener
+ */
+ boolean unregisterVibratorStateListener(int deviceId, IVibratorStateListener listener) {
+ try {
+ return mIm.unregisterVibratorStateListener(deviceId, listener);
+ } catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
+ }
+ }
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 127c7a0..05b6da4 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -11433,21 +11433,46 @@
public @interface DeviceStateRotationLockSetting {
}
+ /** @hide */
+ public static final int DEVICE_STATE_ROTATION_KEY_UNKNOWN = -1;
+ /** @hide */
+ public static final int DEVICE_STATE_ROTATION_KEY_FOLDED = 0;
+ /** @hide */
+ public static final int DEVICE_STATE_ROTATION_KEY_HALF_FOLDED = 1;
+ /** @hide */
+ public static final int DEVICE_STATE_ROTATION_KEY_UNFOLDED = 2;
+
+ /**
+ * The different postures that can be used as keys with
+ * {@link #DEVICE_STATE_ROTATION_LOCK}.
+ * @hide
+ */
+ @IntDef(prefix = {"DEVICE_STATE_ROTATION_KEY_"}, value = {
+ DEVICE_STATE_ROTATION_KEY_UNKNOWN,
+ DEVICE_STATE_ROTATION_KEY_FOLDED,
+ DEVICE_STATE_ROTATION_KEY_HALF_FOLDED,
+ DEVICE_STATE_ROTATION_KEY_UNFOLDED,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface DeviceStateRotationLockKey {
+ }
+
/**
* Rotation lock setting keyed on device state.
*
- * This holds a serialized map using int keys that represent Device States and value of
+ * This holds a serialized map using int keys that represent postures in
+ * {@link DeviceStateRotationLockKey} and value of
* {@link DeviceStateRotationLockSetting} representing the rotation lock setting for that
- * device state.
+ * posture.
*
* Serialized as key0:value0:key1:value1:...:keyN:valueN.
*
* Example: "0:1:1:2:2:1"
* This example represents a map of:
* <ul>
- * <li>0 -> DEVICE_STATE_ROTATION_LOCK_LOCKED</li>
- * <li>1 -> DEVICE_STATE_ROTATION_LOCK_UNLOCKED</li>
- * <li>2 -> DEVICE_STATE_ROTATION_LOCK_IGNORED</li>
+ * <li>DEVICE_STATE_ROTATION_KEY_FOLDED -> DEVICE_STATE_ROTATION_LOCK_LOCKED</li>
+ * <li>DEVICE_STATE_ROTATION_KEY_HALF_FOLDED -> DEVICE_STATE_ROTATION_LOCK_UNLOCKED</li>
+ * <li>DEVICE_STATE_ROTATION_KEY_UNFOLDED -> DEVICE_STATE_ROTATION_LOCK_IGNORED</li>
* </ul>
*
* @hide
diff --git a/core/java/android/security/net/config/SystemCertificateSource.java b/core/java/android/security/net/config/SystemCertificateSource.java
index 13f7e5d..3a254c1 100644
--- a/core/java/android/security/net/config/SystemCertificateSource.java
+++ b/core/java/android/security/net/config/SystemCertificateSource.java
@@ -39,9 +39,13 @@
}
private static File getDirectory() {
- // TODO(miguelaranda): figure out correct code path.
+ if ((System.getProperty("system.certs.enabled") != null)
+ && (System.getProperty("system.certs.enabled")).equals("true")) {
+ return new File(System.getenv("ANDROID_ROOT") + "/etc/security/cacerts");
+ }
File updatable_dir = new File("/apex/com.android.conscrypt/cacerts");
- if (updatable_dir.exists() && !(updatable_dir.list().length == 0)) {
+ if (updatable_dir.exists()
+ && !(updatable_dir.list().length == 0)) {
return updatable_dir;
}
return new File(System.getenv("ANDROID_ROOT") + "/etc/security/cacerts");
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index 48b112d..83de2a0 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -294,7 +294,7 @@
* an input channel where the client can receive input.
*/
void grantInputChannel(int displayId, in SurfaceControl surface, in IWindow window,
- in IBinder hostInputToken, int flags, int privateFlags, int type,
+ in IBinder hostInputToken, int flags, int privateFlags, int inputFeatures, int type,
in IBinder windowToken, in IBinder focusGrantToken, String inputHandleName,
out InputChannel outInputChannel);
@@ -302,7 +302,8 @@
* Update the flags on an input channel associated with a particular surface.
*/
oneway void updateInputChannel(in IBinder channelToken, int displayId,
- in SurfaceControl surface, int flags, int privateFlags, in Region region);
+ in SurfaceControl surface, int flags, int privateFlags, int inputFeatures,
+ in Region region);
/**
* Transfer window focus to an embedded window if the calling window has focus.
diff --git a/core/java/android/view/WindowlessWindowManager.java b/core/java/android/view/WindowlessWindowManager.java
index b77b7a6..0560caf 100644
--- a/core/java/android/view/WindowlessWindowManager.java
+++ b/core/java/android/view/WindowlessWindowManager.java
@@ -139,7 +139,7 @@
try {
mRealWm.updateInputChannel(state.mInputChannelToken, state.mDisplayId,
state.mSurfaceControl, state.mParams.flags, state.mParams.privateFlags,
- state.mInputRegion);
+ state.mParams.inputFeatures, state.mInputRegion);
} catch (RemoteException e) {
Log.e(TAG, "Failed to update surface input channel: ", e);
}
@@ -189,12 +189,13 @@
mRealWm.grantInputChannel(displayId,
new SurfaceControl(sc, "WindowlessWindowManager.addToDisplay"),
window, mHostInputToken,
- attrs.flags, attrs.privateFlags, attrs.type, attrs.token,
- mFocusGrantToken, attrs.getTitle().toString(), outInputChannel);
+ attrs.flags, attrs.privateFlags, attrs.inputFeatures, attrs.type,
+ attrs.token, mFocusGrantToken, attrs.getTitle().toString(),
+ outInputChannel);
} else {
mRealWm.grantInputChannel(displayId, sc, window, mHostInputToken, attrs.flags,
- attrs.privateFlags, attrs.type, attrs.token, mFocusGrantToken,
- attrs.getTitle().toString(), outInputChannel);
+ attrs.privateFlags, attrs.inputFeatures, attrs.type, attrs.token,
+ mFocusGrantToken, attrs.getTitle().toString(), outInputChannel);
}
} catch (RemoteException e) {
Log.e(TAG, "Failed to grant input to surface: ", e);
@@ -381,16 +382,19 @@
outMergedConfiguration.setConfiguration(mConfiguration, mConfiguration);
}
- if ((attrChanges & WindowManager.LayoutParams.FLAGS_CHANGED) != 0
- && state.mInputChannelToken != null) {
+ final int inputChangeMask = WindowManager.LayoutParams.FLAGS_CHANGED
+ | WindowManager.LayoutParams.INPUT_FEATURES_CHANGED;
+ if ((attrChanges & inputChangeMask) != 0 && state.mInputChannelToken != null) {
try {
- if(mRealWm instanceof IWindowSession.Stub) {
+ if (mRealWm instanceof IWindowSession.Stub) {
mRealWm.updateInputChannel(state.mInputChannelToken, state.mDisplayId,
new SurfaceControl(sc, "WindowlessWindowManager.relayout"),
- attrs.flags, attrs.privateFlags, state.mInputRegion);
+ attrs.flags, attrs.privateFlags, attrs.inputFeatures,
+ state.mInputRegion);
} else {
mRealWm.updateInputChannel(state.mInputChannelToken, state.mDisplayId, sc,
- attrs.flags, attrs.privateFlags, state.mInputRegion);
+ attrs.flags, attrs.privateFlags, attrs.inputFeatures,
+ state.mInputRegion);
}
} catch (RemoteException e) {
Log.e(TAG, "Failed to update surface input channel: ", e);
@@ -560,14 +564,14 @@
@Override
public void grantInputChannel(int displayId, SurfaceControl surface, IWindow window,
- IBinder hostInputToken, int flags, int privateFlags, int type,
+ IBinder hostInputToken, int flags, int privateFlags, int inputFeatures, int type,
IBinder windowToken, IBinder focusGrantToken, String inputHandleName,
InputChannel outInputChannel) {
}
@Override
public void updateInputChannel(IBinder channelToken, int displayId, SurfaceControl surface,
- int flags, int privateFlags, Region region) {
+ int flags, int privateFlags, int inputFeatures, Region region) {
}
@Override
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 2ed1817..220a193 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -720,14 +720,13 @@
display is powered on at the same time. -->
<bool name="config_supportsConcurrentInternalDisplays">true</bool>
- <!-- Map of DeviceState to rotation lock setting. Each entry must be in the format
- "key:value", for example: "0:1".
- The keys are device states, and the values are one of
- Settings.Secure.DeviceStateRotationLockSetting.
- Any device state that doesn't have a default set here will be treated as
- DEVICE_STATE_ROTATION_LOCK_IGNORED meaning it will not have its own rotation lock setting.
- If this map is missing, the feature is disabled and only one global rotation lock setting
- will apply, regardless of device state. -->
+ <!-- Map of device posture to rotation lock setting. Each entry must be in the format
+ "key:value", or "key:value:fallback_key" for example: "0:1" or "2:0:1". The keys are one of
+ Settings.Secure.DeviceStateRotationLockKey, and the values are one of
+ Settings.Secure.DeviceStateRotationLockSetting.
+ The fallback is a key to a device posture that can be specified when the value is
+ Settings.Secure.DEVICE_STATE_ROTATION_LOCK_IGNORED.
+ -->
<string-array name="config_perDeviceStateRotationLockDefaults" />
<!-- Dock behavior -->
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
index e5a4362..9ccd6eb 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
@@ -229,6 +229,7 @@
options.setLaunchedFromBubble(true);
options.setPendingIntentBackgroundActivityStartMode(
MODE_BACKGROUND_ACTIVITY_START_ALLOWED);
+ options.setPendingIntentBackgroundActivityLaunchAllowedByPermission(true);
Intent fillInIntent = new Intent();
// Apply flags to make behaviour match documentLaunchMode=always.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java
index 0a9c331..8cb575c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java
@@ -103,6 +103,7 @@
null /* hostInputToken */,
FLAG_NOT_FOCUSABLE,
PRIVATE_FLAG_TRUSTED_OVERLAY,
+ 0 /* inputFeatures */,
TYPE_APPLICATION,
null /* windowToken */,
mFocusGrantToken,
@@ -208,6 +209,7 @@
mDecorationSurface,
FLAG_NOT_FOCUSABLE,
PRIVATE_FLAG_TRUSTED_OVERLAY,
+ 0 /* inputFeatures */,
touchRegion);
} catch (RemoteException e) {
e.rethrowFromSystemServer();
diff --git a/packages/SettingsLib/DeviceStateRotationLock/Android.bp b/packages/SettingsLib/DeviceStateRotationLock/Android.bp
index c642bd1..103309a 100644
--- a/packages/SettingsLib/DeviceStateRotationLock/Android.bp
+++ b/packages/SettingsLib/DeviceStateRotationLock/Android.bp
@@ -10,7 +10,10 @@
android_library {
name: "SettingsLibDeviceStateRotationLock",
- srcs: ["src/**/*.java"],
+ srcs: [
+ "src/**/*.java",
+ "src/**/*.kt",
+ ],
min_sdk_version: "21",
}
diff --git a/packages/SettingsLib/DeviceStateRotationLock/src/com.android.settingslib.devicestate/DeviceStateRotationLockSettingsManager.java b/packages/SettingsLib/DeviceStateRotationLock/src/com.android.settingslib.devicestate/DeviceStateRotationLockSettingsManager.java
index 10b004e..76e1df1 100644
--- a/packages/SettingsLib/DeviceStateRotationLock/src/com.android.settingslib.devicestate/DeviceStateRotationLockSettingsManager.java
+++ b/packages/SettingsLib/DeviceStateRotationLock/src/com.android.settingslib.devicestate/DeviceStateRotationLockSettingsManager.java
@@ -57,17 +57,19 @@
private final Handler mMainHandler = new Handler(Looper.getMainLooper());
private final Set<DeviceStateRotationLockSettingsListener> mListeners = new HashSet<>();
private final SecureSettings mSecureSettings;
- private String[] mDeviceStateRotationLockDefaults;
- private SparseIntArray mDeviceStateRotationLockSettings;
- private SparseIntArray mDeviceStateDefaultRotationLockSettings;
- private SparseIntArray mDeviceStateRotationLockFallbackSettings;
+ private final PosturesHelper mPosturesHelper;
+ private String[] mPostureRotationLockDefaults;
+ private SparseIntArray mPostureRotationLockSettings;
+ private SparseIntArray mPostureDefaultRotationLockSettings;
+ private SparseIntArray mPostureRotationLockFallbackSettings;
private String mLastSettingValue;
private List<SettableDeviceState> mSettableDeviceStates;
@VisibleForTesting
DeviceStateRotationLockSettingsManager(Context context, SecureSettings secureSettings) {
- this.mSecureSettings = secureSettings;
- mDeviceStateRotationLockDefaults =
+ mSecureSettings = secureSettings;
+ mPosturesHelper = new PosturesHelper(context);
+ mPostureRotationLockDefaults =
context.getResources()
.getStringArray(R.array.config_perDeviceStateRotationLockDefaults);
loadDefaults();
@@ -134,13 +136,14 @@
/** Updates the rotation lock setting for a specified device state. */
public void updateSetting(int deviceState, boolean rotationLocked) {
- if (mDeviceStateRotationLockFallbackSettings.indexOfKey(deviceState) >= 0) {
- // The setting for this device state is IGNORED, and has a fallback device state.
- // The setting for that fallback device state should be the changed in this case.
- deviceState = mDeviceStateRotationLockFallbackSettings.get(deviceState);
+ int posture = mPosturesHelper.deviceStateToPosture(deviceState);
+ if (mPostureRotationLockFallbackSettings.indexOfKey(posture) >= 0) {
+ // The setting for this device posture is IGNORED, and has a fallback posture.
+ // The setting for that fallback posture should be the changed in this case.
+ posture = mPostureRotationLockFallbackSettings.get(posture);
}
- mDeviceStateRotationLockSettings.put(
- deviceState,
+ mPostureRotationLockSettings.put(
+ posture,
rotationLocked
? DEVICE_STATE_ROTATION_LOCK_LOCKED
: DEVICE_STATE_ROTATION_LOCK_UNLOCKED);
@@ -159,22 +162,23 @@
*/
@Settings.Secure.DeviceStateRotationLockSetting
public int getRotationLockSetting(int deviceState) {
- int rotationLockSetting = mDeviceStateRotationLockSettings.get(
- deviceState, /* valueIfKeyNotFound= */ DEVICE_STATE_ROTATION_LOCK_IGNORED);
+ int devicePosture = mPosturesHelper.deviceStateToPosture(deviceState);
+ int rotationLockSetting = mPostureRotationLockSettings.get(
+ devicePosture, /* valueIfKeyNotFound= */ DEVICE_STATE_ROTATION_LOCK_IGNORED);
if (rotationLockSetting == DEVICE_STATE_ROTATION_LOCK_IGNORED) {
- rotationLockSetting = getFallbackRotationLockSetting(deviceState);
+ rotationLockSetting = getFallbackRotationLockSetting(devicePosture);
}
return rotationLockSetting;
}
- private int getFallbackRotationLockSetting(int deviceState) {
- int indexOfFallbackState = mDeviceStateRotationLockFallbackSettings.indexOfKey(deviceState);
- if (indexOfFallbackState < 0) {
+ private int getFallbackRotationLockSetting(int devicePosture) {
+ int indexOfFallback = mPostureRotationLockFallbackSettings.indexOfKey(devicePosture);
+ if (indexOfFallback < 0) {
Log.w(TAG, "Setting is ignored, but no fallback was specified.");
return DEVICE_STATE_ROTATION_LOCK_IGNORED;
}
- int fallbackState = mDeviceStateRotationLockFallbackSettings.valueAt(indexOfFallbackState);
- return mDeviceStateRotationLockSettings.get(fallbackState,
+ int fallbackPosture = mPostureRotationLockFallbackSettings.valueAt(indexOfFallback);
+ return mPostureRotationLockSettings.get(fallbackPosture,
/* valueIfKeyNotFound= */ DEVICE_STATE_ROTATION_LOCK_IGNORED);
}
@@ -189,8 +193,8 @@
* DEVICE_STATE_ROTATION_LOCK_UNLOCKED}.
*/
public boolean isRotationLockedForAllStates() {
- for (int i = 0; i < mDeviceStateRotationLockSettings.size(); i++) {
- if (mDeviceStateRotationLockSettings.valueAt(i)
+ for (int i = 0; i < mPostureRotationLockSettings.size(); i++) {
+ if (mPostureRotationLockSettings.valueAt(i)
== DEVICE_STATE_ROTATION_LOCK_UNLOCKED) {
return false;
}
@@ -221,7 +225,7 @@
fallbackOnDefaults();
return;
}
- mDeviceStateRotationLockSettings = new SparseIntArray(values.length / 2);
+ mPostureRotationLockSettings = new SparseIntArray(values.length / 2);
int key;
int value;
@@ -230,7 +234,7 @@
key = Integer.parseInt(values[i++]);
value = Integer.parseInt(values[i++]);
boolean isPersistedValueIgnored = value == DEVICE_STATE_ROTATION_LOCK_IGNORED;
- boolean isDefaultValueIgnored = mDeviceStateDefaultRotationLockSettings.get(key)
+ boolean isDefaultValueIgnored = mPostureDefaultRotationLockSettings.get(key)
== DEVICE_STATE_ROTATION_LOCK_IGNORED;
if (isPersistedValueIgnored != isDefaultValueIgnored) {
Log.w(TAG, "Conflict for ignored device state " + key
@@ -238,7 +242,7 @@
fallbackOnDefaults();
return;
}
- mDeviceStateRotationLockSettings.put(key, value);
+ mPostureRotationLockSettings.put(key, value);
} catch (NumberFormatException e) {
Log.wtf(TAG, "Error deserializing one of the saved settings", e);
fallbackOnDefaults();
@@ -253,7 +257,7 @@
*/
@VisibleForTesting
public void resetStateForTesting(Resources resources) {
- mDeviceStateRotationLockDefaults =
+ mPostureRotationLockDefaults =
resources.getStringArray(R.array.config_perDeviceStateRotationLockDefaults);
fallbackOnDefaults();
}
@@ -264,23 +268,23 @@
}
private void persistSettings() {
- if (mDeviceStateRotationLockSettings.size() == 0) {
+ if (mPostureRotationLockSettings.size() == 0) {
persistSettingIfChanged(/* newSettingValue= */ "");
return;
}
StringBuilder stringBuilder = new StringBuilder();
stringBuilder
- .append(mDeviceStateRotationLockSettings.keyAt(0))
+ .append(mPostureRotationLockSettings.keyAt(0))
.append(SEPARATOR_REGEX)
- .append(mDeviceStateRotationLockSettings.valueAt(0));
+ .append(mPostureRotationLockSettings.valueAt(0));
- for (int i = 1; i < mDeviceStateRotationLockSettings.size(); i++) {
+ for (int i = 1; i < mPostureRotationLockSettings.size(); i++) {
stringBuilder
.append(SEPARATOR_REGEX)
- .append(mDeviceStateRotationLockSettings.keyAt(i))
+ .append(mPostureRotationLockSettings.keyAt(i))
.append(SEPARATOR_REGEX)
- .append(mDeviceStateRotationLockSettings.valueAt(i));
+ .append(mPostureRotationLockSettings.valueAt(i));
}
persistSettingIfChanged(stringBuilder.toString());
}
@@ -300,22 +304,20 @@
}
private void loadDefaults() {
- mSettableDeviceStates = new ArrayList<>(mDeviceStateRotationLockDefaults.length);
- mDeviceStateDefaultRotationLockSettings = new SparseIntArray(
- mDeviceStateRotationLockDefaults.length);
- mDeviceStateRotationLockSettings = new SparseIntArray(
- mDeviceStateRotationLockDefaults.length);
- mDeviceStateRotationLockFallbackSettings = new SparseIntArray(1);
- for (String entry : mDeviceStateRotationLockDefaults) {
+ mSettableDeviceStates = new ArrayList<>(mPostureRotationLockDefaults.length);
+ mPostureDefaultRotationLockSettings = new SparseIntArray(
+ mPostureRotationLockDefaults.length);
+ mPostureRotationLockSettings = new SparseIntArray(mPostureRotationLockDefaults.length);
+ mPostureRotationLockFallbackSettings = new SparseIntArray(1);
+ for (String entry : mPostureRotationLockDefaults) {
String[] values = entry.split(SEPARATOR_REGEX);
try {
- int deviceState = Integer.parseInt(values[0]);
+ int posture = Integer.parseInt(values[0]);
int rotationLockSetting = Integer.parseInt(values[1]);
if (rotationLockSetting == DEVICE_STATE_ROTATION_LOCK_IGNORED) {
if (values.length == 3) {
- int fallbackDeviceState = Integer.parseInt(values[2]);
- mDeviceStateRotationLockFallbackSettings.put(deviceState,
- fallbackDeviceState);
+ int fallbackPosture = Integer.parseInt(values[2]);
+ mPostureRotationLockFallbackSettings.put(posture, fallbackPosture);
} else {
Log.w(TAG,
"Rotation lock setting is IGNORED, but values have unexpected "
@@ -324,9 +326,14 @@
}
}
boolean isSettable = rotationLockSetting != DEVICE_STATE_ROTATION_LOCK_IGNORED;
- mSettableDeviceStates.add(new SettableDeviceState(deviceState, isSettable));
- mDeviceStateRotationLockSettings.put(deviceState, rotationLockSetting);
- mDeviceStateDefaultRotationLockSettings.put(deviceState, rotationLockSetting);
+ Integer deviceState = mPosturesHelper.postureToDeviceState(posture);
+ if (deviceState != null) {
+ mSettableDeviceStates.add(new SettableDeviceState(deviceState, isSettable));
+ } else {
+ Log.wtf(TAG, "No matching device state for posture: " + posture);
+ }
+ mPostureRotationLockSettings.put(posture, rotationLockSetting);
+ mPostureDefaultRotationLockSettings.put(posture, rotationLockSetting);
} catch (NumberFormatException e) {
Log.wtf(TAG, "Error parsing settings entry. Entry was: " + entry, e);
return;
@@ -338,13 +345,11 @@
public void dump(IndentingPrintWriter pw) {
pw.println("DeviceStateRotationLockSettingsManager");
pw.increaseIndent();
- pw.println("mDeviceStateRotationLockDefaults: " + Arrays.toString(
- mDeviceStateRotationLockDefaults));
- pw.println("mDeviceStateDefaultRotationLockSettings: "
- + mDeviceStateDefaultRotationLockSettings);
- pw.println("mDeviceStateRotationLockSettings: " + mDeviceStateRotationLockSettings);
- pw.println("mDeviceStateRotationLockFallbackSettings: "
- + mDeviceStateRotationLockFallbackSettings);
+ pw.println("mPostureRotationLockDefaults: "
+ + Arrays.toString(mPostureRotationLockDefaults));
+ pw.println("mPostureDefaultRotationLockSettings: " + mPostureDefaultRotationLockSettings);
+ pw.println("mDeviceStateRotationLockSettings: " + mPostureRotationLockSettings);
+ pw.println("mPostureRotationLockFallbackSettings: " + mPostureRotationLockFallbackSettings);
pw.println("mSettableDeviceStates: " + mSettableDeviceStates);
pw.println("mLastSettingValue: " + mLastSettingValue);
pw.decreaseIndent();
diff --git a/packages/SettingsLib/DeviceStateRotationLock/src/com.android.settingslib.devicestate/PosturesHelper.kt b/packages/SettingsLib/DeviceStateRotationLock/src/com.android.settingslib.devicestate/PosturesHelper.kt
new file mode 100644
index 0000000..9c70be9
--- /dev/null
+++ b/packages/SettingsLib/DeviceStateRotationLock/src/com.android.settingslib.devicestate/PosturesHelper.kt
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.devicestate
+
+import android.content.Context
+import android.provider.Settings.Secure.DEVICE_STATE_ROTATION_KEY_FOLDED
+import android.provider.Settings.Secure.DEVICE_STATE_ROTATION_KEY_HALF_FOLDED
+import android.provider.Settings.Secure.DEVICE_STATE_ROTATION_KEY_UNFOLDED
+import android.provider.Settings.Secure.DEVICE_STATE_ROTATION_KEY_UNKNOWN
+import android.provider.Settings.Secure.DeviceStateRotationLockKey
+import com.android.internal.R
+
+/** Helps to convert between device state and posture. */
+class PosturesHelper(context: Context) {
+
+ private val foldedDeviceStates =
+ context.resources.getIntArray(R.array.config_foldedDeviceStates)
+ private val halfFoldedDeviceStates =
+ context.resources.getIntArray(R.array.config_halfFoldedDeviceStates)
+ private val unfoldedDeviceStates =
+ context.resources.getIntArray(R.array.config_openDeviceStates)
+
+ @DeviceStateRotationLockKey
+ fun deviceStateToPosture(deviceState: Int): Int {
+ return when (deviceState) {
+ in foldedDeviceStates -> DEVICE_STATE_ROTATION_KEY_FOLDED
+ in halfFoldedDeviceStates -> DEVICE_STATE_ROTATION_KEY_HALF_FOLDED
+ in unfoldedDeviceStates -> DEVICE_STATE_ROTATION_KEY_UNFOLDED
+ else -> DEVICE_STATE_ROTATION_KEY_UNKNOWN
+ }
+ }
+
+ fun postureToDeviceState(@DeviceStateRotationLockKey posture: Int): Int? {
+ return when (posture) {
+ DEVICE_STATE_ROTATION_KEY_FOLDED -> foldedDeviceStates.firstOrNull()
+ DEVICE_STATE_ROTATION_KEY_HALF_FOLDED -> halfFoldedDeviceStates.firstOrNull()
+ DEVICE_STATE_ROTATION_KEY_UNFOLDED -> unfoldedDeviceStates.firstOrNull()
+ else -> null
+ }
+ }
+}
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/devicestate/DeviceStateRotationLockSettingsManagerTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/devicestate/DeviceStateRotationLockSettingsManagerTest.java
index 0fa15eb..fdefcde 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/devicestate/DeviceStateRotationLockSettingsManagerTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/devicestate/DeviceStateRotationLockSettingsManagerTest.java
@@ -70,12 +70,20 @@
when(mMockContext.getApplicationContext()).thenReturn(mMockContext);
when(mMockContext.getResources()).thenReturn(mMockResources);
when(mMockContext.getContentResolver()).thenReturn(context.getContentResolver());
+ when(mMockResources.getStringArray(R.array.config_perDeviceStateRotationLockDefaults))
+ .thenReturn(new String[]{"0:1", "1:0:2", "2:2"});
+ when(mMockResources.getIntArray(R.array.config_foldedDeviceStates))
+ .thenReturn(new int[]{0});
+ when(mMockResources.getIntArray(R.array.config_halfFoldedDeviceStates))
+ .thenReturn(new int[]{1});
+ when(mMockResources.getIntArray(R.array.config_openDeviceStates))
+ .thenReturn(new int[]{2});
mFakeSecureSettings.registerContentObserver(
Settings.Secure.DEVICE_STATE_ROTATION_LOCK,
/* notifyForDescendents= */ false, //NOTYPO
mContentObserver,
UserHandle.USER_CURRENT);
- mManager = new DeviceStateRotationLockSettingsManager(context, mFakeSecureSettings);
+ mManager = new DeviceStateRotationLockSettingsManager(mMockContext, mFakeSecureSettings);
}
@Test
@@ -109,7 +117,7 @@
public void getSettableDeviceStates_returnsExpectedValuesInOriginalOrder() {
when(mMockResources.getStringArray(
R.array.config_perDeviceStateRotationLockDefaults)).thenReturn(
- new String[]{"2:2", "4:0", "1:1", "0:0"});
+ new String[]{"2:1", "1:0:1", "0:2"});
List<SettableDeviceState> settableDeviceStates =
DeviceStateRotationLockSettingsManager.getInstance(
@@ -117,9 +125,8 @@
assertThat(settableDeviceStates).containsExactly(
new SettableDeviceState(/* deviceState= */ 2, /* isSettable= */ true),
- new SettableDeviceState(/* deviceState= */ 4, /* isSettable= */ false),
- new SettableDeviceState(/* deviceState= */ 1, /* isSettable= */ true),
- new SettableDeviceState(/* deviceState= */ 0, /* isSettable= */ false)
+ new SettableDeviceState(/* deviceState= */ 1, /* isSettable= */ false),
+ new SettableDeviceState(/* deviceState= */ 0, /* isSettable= */ true)
).inOrder();
}
diff --git a/packages/SystemUI/res/layout/notification_conversation_info.xml b/packages/SystemUI/res/layout/notification_conversation_info.xml
index 9b2f0ac..79948da 100644
--- a/packages/SystemUI/res/layout/notification_conversation_info.xml
+++ b/packages/SystemUI/res/layout/notification_conversation_info.xml
@@ -311,7 +311,7 @@
android:clickable="false"
android:focusable="false"
android:ellipsize="end"
- android:maxLines="3"
+ android:maxLines="4"
android:textAppearance="@style/TextAppearance.NotificationImportanceDetail"/>
</com.android.systemui.statusbar.notification.row.ButtonLinearLayout>
@@ -364,7 +364,7 @@
android:clickable="false"
android:focusable="false"
android:ellipsize="end"
- android:maxLines="3"
+ android:maxLines="4"
android:textAppearance="@style/TextAppearance.NotificationImportanceDetail"/>
</com.android.systemui.statusbar.notification.row.ButtonLinearLayout>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index ebf0f8e..2aa912c 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -2877,7 +2877,7 @@
<string name="manage_users">Manage users</string>
<!-- Toast shown when a notification does not support dragging to split [CHAR LIMIT=NONE] -->
- <string name="drag_split_not_supported">This notification does not support dragging to Splitscreen.</string>
+ <string name="drag_split_not_supported">This notification does not support dragging to split screen</string>
<!-- Content description for the Wi-Fi off icon in the dream overlay status bar [CHAR LIMIT=NONE] -->
<string name="dream_overlay_status_bar_wifi_off">Wi\u2011Fi unavailable</string>
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index c0e1133..a80d28d 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -236,12 +236,21 @@
// TODO(b/270223352): Tracking Bug
@JvmField
- val HIDE_SMARTSPACE_ON_DREAM_OVERLAY = unreleasedFlag(404, "hide_smartspace_on_dream_overlay")
+ val HIDE_SMARTSPACE_ON_DREAM_OVERLAY =
+ unreleasedFlag(
+ 404,
+ "hide_smartspace_on_dream_overlay",
+ teamfood = true
+ )
// TODO(b/271460958): Tracking Bug
@JvmField
- val SHOW_WEATHER_COMPLICATION_ON_DREAM_OVERLAY = unreleasedFlag(405,
- "show_weather_complication_on_dream_overlay")
+ val SHOW_WEATHER_COMPLICATION_ON_DREAM_OVERLAY =
+ unreleasedFlag(
+ 405,
+ "show_weather_complication_on_dream_overlay",
+ teamfood = true
+ )
// 500 - quick settings
@@ -661,8 +670,7 @@
// 2600 - keyboard
// TODO(b/259352579): Tracking Bug
- @JvmField val SHORTCUT_LIST_SEARCH_LAYOUT =
- unreleasedFlag(2600, "shortcut_list_search_layout", teamfood = true)
+ @JvmField val SHORTCUT_LIST_SEARCH_LAYOUT = releasedFlag(2600, "shortcut_list_search_layout")
// TODO(b/259428678): Tracking Bug
@JvmField
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSHost.java
index a71e6dd..9ece72d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSHost.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSHost.java
@@ -26,6 +26,7 @@
import com.android.systemui.plugins.qs.QSFactory;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.qs.QSTileView;
+import com.android.systemui.qs.pipeline.domain.interactor.PanelInteractor;
import com.android.systemui.util.leak.GarbageMonitor;
import java.util.ArrayList;
@@ -33,7 +34,7 @@
import java.util.Collection;
import java.util.List;
-public interface QSHost {
+public interface QSHost extends PanelInteractor {
String TILES_SETTING = Settings.Secure.QS_TILES;
int POSITION_AT_END = -1;
@@ -57,9 +58,6 @@
}
void warn(String message, Throwable t);
- void collapsePanels();
- void forceCollapsePanels();
- void openPanels();
Context getContext();
Context getUserContext();
int getUserId();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSHostModule.kt b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSHostModule.kt
new file mode 100644
index 0000000..958fa71
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSHostModule.kt
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.qs.dagger
+
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
+import com.android.systemui.qs.QSHost
+import com.android.systemui.qs.QSTileHost
+import com.android.systemui.qs.pipeline.domain.interactor.PanelInteractor
+import com.android.systemui.qs.pipeline.domain.interactor.PanelInteractorImpl
+import dagger.Binds
+import dagger.Module
+import dagger.Provides
+
+@Module
+interface QSHostModule {
+
+ @Binds fun provideQsHost(controllerImpl: QSTileHost): QSHost
+
+ @Module
+ companion object {
+ @Provides
+ @JvmStatic
+ fun providePanelInteractor(
+ featureFlags: FeatureFlags,
+ qsHost: QSHost,
+ panelInteractorImpl: PanelInteractorImpl
+ ): PanelInteractor {
+ return if (featureFlags.isEnabled(Flags.QS_PIPELINE_NEW_HOST)) {
+ panelInteractorImpl
+ } else {
+ qsHost
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java
index 431d6e8..cfe9313 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java
@@ -27,7 +27,6 @@
import com.android.systemui.media.dagger.MediaModule;
import com.android.systemui.qs.AutoAddTracker;
import com.android.systemui.qs.QSHost;
-import com.android.systemui.qs.QSTileHost;
import com.android.systemui.qs.ReduceBrightColorsController;
import com.android.systemui.qs.external.QSExternalModule;
import com.android.systemui.qs.tileimpl.QSTileImpl;
@@ -45,7 +44,6 @@
import javax.inject.Named;
-import dagger.Binds;
import dagger.Module;
import dagger.Provides;
import dagger.multibindings.Multibinds;
@@ -54,7 +52,13 @@
* Module for QS dependencies
*/
@Module(subcomponents = {QSFragmentComponent.class},
- includes = {MediaModule.class, QSExternalModule.class, QSFlagsModule.class})
+ includes = {
+ MediaModule.class,
+ QSExternalModule.class,
+ QSFlagsModule.class,
+ QSHostModule.class
+ }
+)
public interface QSModule {
/** A map of internal QS tiles. Ensures that this can be injected even if
@@ -100,8 +104,4 @@
manager.init();
return manager;
}
-
- /** */
- @Binds
- QSHost provideQsHost(QSTileHost controllerImpl);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
index adc7165..2083cc7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
@@ -40,6 +40,7 @@
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.qs.QSHost;
+import com.android.systemui.qs.pipeline.domain.interactor.PanelInteractor;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.phone.StatusBarIconController;
@@ -74,6 +75,7 @@
private final CommandQueue mCommandQueue;
private final UserTracker mUserTracker;
private final StatusBarIconController mStatusBarIconController;
+ private final PanelInteractor mPanelInteractor;
private int mMaxBound = DEFAULT_MAX_BOUND;
@@ -85,7 +87,8 @@
UserTracker userTracker,
KeyguardStateController keyguardStateController,
CommandQueue commandQueue,
- StatusBarIconController statusBarIconController) {
+ StatusBarIconController statusBarIconController,
+ PanelInteractor panelInteractor) {
mHost = host;
mKeyguardStateController = keyguardStateController;
mContext = mHost.getContext();
@@ -96,6 +99,7 @@
mCommandQueue = commandQueue;
mStatusBarIconController = statusBarIconController;
mCommandQueue.addCallback(mRequestListeningCallback);
+ mPanelInteractor = panelInteractor;
}
public Context getContext() {
@@ -255,7 +259,7 @@
if (customTile != null) {
verifyCaller(customTile);
customTile.onDialogShown();
- mHost.forceCollapsePanels();
+ mPanelInteractor.forceCollapsePanels();
Objects.requireNonNull(mServices.get(customTile)).setShowingDialog(true);
}
}
@@ -275,7 +279,7 @@
CustomTile customTile = getTileForToken(token);
if (customTile != null) {
verifyCaller(customTile);
- mHost.forceCollapsePanels();
+ mPanelInteractor.forceCollapsePanels();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/interactor/PanelInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/interactor/PanelInteractor.kt
new file mode 100644
index 0000000..260caa7
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/interactor/PanelInteractor.kt
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+package com.android.systemui.qs.pipeline.domain.interactor
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.statusbar.phone.CentralSurfaces
+import java.util.Optional
+import javax.inject.Inject
+
+/** Encapsulates business logic for interacting with the QS panel. */
+interface PanelInteractor {
+
+ /** Collapse the shade */
+ fun collapsePanels()
+
+ /** Collapse the shade forcefully, skipping some animations. */
+ fun forceCollapsePanels()
+
+ /** Open the Quick Settings panel */
+ fun openPanels()
+}
+
+@SysUISingleton
+class PanelInteractorImpl
+@Inject
+constructor(
+ private val centralSurfaces: Optional<CentralSurfaces>,
+) : PanelInteractor {
+ override fun collapsePanels() {
+ centralSurfaces.ifPresent { it.postAnimateCollapsePanels() }
+ }
+
+ override fun forceCollapsePanels() {
+ centralSurfaces.ifPresent { it.postAnimateForceCollapsePanels() }
+ }
+
+ override fun openPanels() {
+ centralSurfaces.ifPresent { it.postAnimateOpenPanels() }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
index 89d402a3..27f5826 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
@@ -38,6 +38,7 @@
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.logging.QSLogger;
+import com.android.systemui.qs.pipeline.domain.interactor.PanelInteractor;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.LocationController;
@@ -52,6 +53,7 @@
private final LocationController mController;
private final KeyguardStateController mKeyguard;
+ private final PanelInteractor mPanelInteractor;
private final Callback mCallback = new Callback();
@Inject
@@ -65,12 +67,14 @@
ActivityStarter activityStarter,
QSLogger qsLogger,
LocationController locationController,
- KeyguardStateController keyguardStateController
+ KeyguardStateController keyguardStateController,
+ PanelInteractor panelInteractor
) {
super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger,
statusBarStateController, activityStarter, qsLogger);
mController = locationController;
mKeyguard = keyguardStateController;
+ mPanelInteractor = panelInteractor;
mController.observe(this, mCallback);
mKeyguard.observe(this, mCallback);
}
@@ -90,7 +94,7 @@
if (mKeyguard.isMethodSecure() && mKeyguard.isShowing()) {
mActivityStarter.postQSRunnableDismissingKeyguard(() -> {
final boolean wasEnabled = mState.value;
- mHost.openPanels();
+ mPanelInteractor.openPanels();
mController.setLocationEnabled(!wasEnabled);
});
return;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java
index 07b50c9..65592a7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java
@@ -42,6 +42,7 @@
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.logging.QSLogger;
+import com.android.systemui.qs.pipeline.domain.interactor.PanelInteractor;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.screenrecord.RecordingController;
import com.android.systemui.statusbar.phone.KeyguardDismissUtil;
@@ -66,6 +67,7 @@
private final Callback mCallback = new Callback();
private final DialogLaunchAnimator mDialogLaunchAnimator;
private final FeatureFlags mFlags;
+ private final PanelInteractor mPanelInteractor;
private long mMillisUntilFinished = 0;
@@ -83,7 +85,8 @@
RecordingController controller,
KeyguardDismissUtil keyguardDismissUtil,
KeyguardStateController keyguardStateController,
- DialogLaunchAnimator dialogLaunchAnimator
+ DialogLaunchAnimator dialogLaunchAnimator,
+ PanelInteractor panelInteractor
) {
super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger,
statusBarStateController, activityStarter, qsLogger);
@@ -93,6 +96,7 @@
mKeyguardDismissUtil = keyguardDismissUtil;
mKeyguardStateController = keyguardStateController;
mDialogLaunchAnimator = dialogLaunchAnimator;
+ mPanelInteractor = panelInteractor;
}
@Override
@@ -171,7 +175,7 @@
// disable the exit animation which looks weird when it happens at the same time as the
// shade collapsing.
mDialogLaunchAnimator.disableAllCurrentDialogsExitAnimations();
- getHost().collapsePanels();
+ mPanelInteractor.collapsePanels();
};
final Dialog dialog = mController.createScreenRecordDialog(mContext, mFlags,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index 33cbf06..a529da5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -68,6 +68,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.util.ContrastColorUtil;
import com.android.internal.widget.CachingIconView;
import com.android.internal.widget.CallLayout;
@@ -1671,7 +1672,8 @@
MetricsLogger metricsLogger,
SmartReplyConstants smartReplyConstants,
SmartReplyController smartReplyController,
- FeatureFlags featureFlags) {
+ FeatureFlags featureFlags,
+ IStatusBarService statusBarService) {
mEntry = entry;
mAppName = appName;
if (mMenuRow == null) {
@@ -1699,7 +1701,8 @@
mPeopleNotificationIdentifier,
rivSubcomponentFactory,
smartReplyConstants,
- smartReplyController);
+ smartReplyController,
+ statusBarService);
}
mOnUserInteractionCallback = onUserInteractionCallback;
mBubblesManagerOptional = bubblesManagerOptional;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java
index e2a3111..5ca0866 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java
@@ -29,6 +29,7 @@
import androidx.annotation.Nullable;
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.statusbar.IStatusBarService;
import com.android.systemui.classifier.FalsingCollector;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
@@ -100,6 +101,7 @@
private final SmartReplyController mSmartReplyController;
private final ExpandableNotificationRowDragController mDragController;
private final NotificationDismissibilityProvider mDismissibilityProvider;
+ private final IStatusBarService mStatusBarService;
private final ExpandableNotificationRow.ExpandableNotificationRowLogger mLoggerCallback =
new ExpandableNotificationRow.ExpandableNotificationRowLogger() {
@Override
@@ -157,7 +159,8 @@
PeopleNotificationIdentifier peopleNotificationIdentifier,
Optional<BubblesManager> bubblesManagerOptional,
ExpandableNotificationRowDragController dragController,
- NotificationDismissibilityProvider dismissibilityProvider) {
+ NotificationDismissibilityProvider dismissibilityProvider,
+ IStatusBarService statusBarService) {
mView = view;
mListContainer = listContainer;
mRemoteInputViewSubcomponentFactory = rivSubcomponentFactory;
@@ -189,6 +192,7 @@
mSmartReplyConstants = smartReplyConstants;
mSmartReplyController = smartReplyController;
mDismissibilityProvider = dismissibilityProvider;
+ mStatusBarService = statusBarService;
}
/**
@@ -220,7 +224,8 @@
mMetricsLogger,
mSmartReplyConstants,
mSmartReplyController,
- mFeatureFlags
+ mFeatureFlags,
+ mStatusBarService
);
mView.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
if (mAllowLongPress) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
index 5834dcb..78392f7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
@@ -21,10 +21,13 @@
import android.app.Notification;
import android.app.PendingIntent;
import android.content.Context;
+import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Build;
+import android.os.RemoteException;
import android.provider.Settings;
+import android.service.notification.StatusBarNotification;
import android.util.ArrayMap;
import android.util.AttributeSet;
import android.util.IndentingPrintWriter;
@@ -39,6 +42,7 @@
import android.widget.LinearLayout;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.statusbar.IStatusBarService;
import com.android.systemui.R;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.statusbar.RemoteInputController;
@@ -129,6 +133,7 @@
private Runnable mExpandedVisibleListener;
private PeopleNotificationIdentifier mPeopleIdentifier;
private RemoteInputViewSubcomponent.Factory mRemoteInputSubcomponentFactory;
+ private IStatusBarService mStatusBarService;
/**
* List of listeners for when content views become inactive (i.e. not the showing view).
@@ -196,11 +201,13 @@
PeopleNotificationIdentifier peopleNotificationIdentifier,
RemoteInputViewSubcomponent.Factory rivSubcomponentFactory,
SmartReplyConstants smartReplyConstants,
- SmartReplyController smartReplyController) {
+ SmartReplyController smartReplyController,
+ IStatusBarService statusBarService) {
mPeopleIdentifier = peopleNotificationIdentifier;
mRemoteInputSubcomponentFactory = rivSubcomponentFactory;
mSmartReplyConstants = smartReplyConstants;
mSmartReplyController = smartReplyController;
+ mStatusBarService = statusBarService;
}
public void reinflate() {
@@ -2193,4 +2200,36 @@
protected void setHeadsUpWrapper(NotificationViewWrapper headsUpWrapper) {
mHeadsUpWrapper = headsUpWrapper;
}
+
+ @Override
+ protected void dispatchDraw(Canvas canvas) {
+ try {
+ super.dispatchDraw(canvas);
+ } catch (Exception e) {
+ // Catch draw exceptions that may be caused by RemoteViews
+ Log.e(TAG, "Drawing view failed: " + e);
+ cancelNotification(e);
+ }
+ }
+
+ private void cancelNotification(Exception exception) {
+ try {
+ setVisibility(GONE);
+ final StatusBarNotification sbn = mNotificationEntry.getSbn();
+ if (mStatusBarService != null) {
+ // report notification inflation errors back up
+ // to notification delegates
+ mStatusBarService.onNotificationError(
+ sbn.getPackageName(),
+ sbn.getTag(),
+ sbn.getId(),
+ sbn.getUid(),
+ sbn.getInitialPid(),
+ exception.getMessage(),
+ sbn.getUser().getIdentifier());
+ }
+ } catch (RemoteException ex) {
+ Log.e(TAG, "cancelNotification failed: " + ex);
+ }
+ }
}
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 0bded73..46603df 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -809,6 +809,11 @@
public void setOccludeAnimationPlaying(boolean occludeAnimationPlaying) {
mOccludeAnimationPlaying = occludeAnimationPlaying;
+
+ for (ScrimState state : ScrimState.values()) {
+ state.setOccludeAnimationPlaying(occludeAnimationPlaying);
+ }
+
applyAndDispatchState();
}
@@ -853,7 +858,6 @@
if (mState == ScrimState.UNLOCKED || mState == ScrimState.DREAMING) {
final boolean occluding =
mOccludeAnimationPlaying || mState.mLaunchingAffordanceWithPreview;
-
// Darken scrim as it's pulled down while unlocked. If we're unlocked but playing the
// screen off/occlusion animations, ignore expansion changes while those animations
// play.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
index 0e9d3ce..7b20283 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
@@ -243,7 +243,12 @@
: CentralSurfaces.FADE_KEYGUARD_DURATION;
boolean fromAod = previousState == AOD || previousState == PULSING;
- mAnimateChange = !mLaunchingAffordanceWithPreview && !fromAod;
+ // If launch/occlude animations were playing, they already animated the scrim
+ // alpha to 0f as part of the animation. If we animate it now, we'll set it back
+ // to 1f and animate it back to 0f, causing an unwanted scrim flash.
+ mAnimateChange = !mLaunchingAffordanceWithPreview
+ && !mOccludeAnimationPlaying
+ && !fromAod;
mFrontTint = Color.TRANSPARENT;
mBehindTint = Color.BLACK;
@@ -308,6 +313,7 @@
boolean mWallpaperSupportsAmbientMode;
boolean mHasBackdrop;
boolean mLaunchingAffordanceWithPreview;
+ boolean mOccludeAnimationPlaying;
boolean mWakeLockScreenSensorActive;
boolean mKeyguardFadingAway;
long mKeyguardFadingAwayDuration;
@@ -411,6 +417,10 @@
mLaunchingAffordanceWithPreview = launchingAffordanceWithPreview;
}
+ public void setOccludeAnimationPlaying(boolean occludeAnimationPlaying) {
+ mOccludeAnimationPlaying = occludeAnimationPlaying;
+ }
+
public boolean isLowPowerState() {
return false;
}
diff --git a/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java b/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java
index a0a0372..209ea41 100644
--- a/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java
@@ -59,6 +59,7 @@
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.logging.QSLogger;
+import com.android.systemui.qs.pipeline.domain.interactor.PanelInteractor;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.util.concurrency.DelayableExecutor;
import com.android.systemui.util.concurrency.MessageRouter;
@@ -412,6 +413,7 @@
private final GarbageMonitor gm;
private ProcessMemInfo pmi;
private boolean dumpInProgress;
+ private final PanelInteractor mPanelInteractor;
@Inject
public MemoryTile(
@@ -423,11 +425,13 @@
StatusBarStateController statusBarStateController,
ActivityStarter activityStarter,
QSLogger qsLogger,
- GarbageMonitor monitor
+ GarbageMonitor monitor,
+ PanelInteractor panelInteractor
) {
super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger,
statusBarStateController, activityStarter, qsLogger);
gm = monitor;
+ mPanelInteractor = panelInteractor;
}
@Override
@@ -457,7 +461,7 @@
mHandler.post(() -> {
dumpInProgress = false;
refreshState();
- getHost().collapsePanels();
+ mPanelInteractor.collapsePanels();
mActivityStarter.postStartActivityDismissingKeyguard(shareIntent, 0);
});
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java
index 64e9a3e..7e052bf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java
@@ -29,6 +29,7 @@
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Intent;
+import android.os.Binder;
import android.os.Handler;
import android.os.RemoteException;
import android.os.UserHandle;
@@ -41,6 +42,7 @@
import com.android.systemui.SysuiTestCase;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.qs.QSHost;
+import com.android.systemui.qs.pipeline.domain.interactor.PanelInteractor;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.phone.StatusBarIconController;
@@ -91,6 +93,8 @@
private TileLifecycleManager mTileLifecycleManager;
@Mock
private QSHost mQSHost;
+ @Mock
+ private PanelInteractor mPanelInteractor;
@Before
public void setUp() throws Exception {
@@ -107,7 +111,8 @@
Provider<Handler> provider = () -> new Handler(mTestableLooper.getLooper());
mTileService = new TestTileServices(mQSHost, provider, mBroadcastDispatcher,
- mUserTracker, mKeyguardStateController, mCommandQueue, mStatusBarIconController);
+ mUserTracker, mKeyguardStateController, mCommandQueue, mStatusBarIconController,
+ mPanelInteractor);
}
@After
@@ -222,13 +227,37 @@
verify(tile, never()).startActivityAndCollapse(pi);
}
+ @Test
+ public void testOnStartActivityCollapsesPanel() {
+ CustomTile tile = mock(CustomTile.class);
+ ComponentName componentName = mock(ComponentName.class);
+ when(tile.getComponent()).thenReturn(componentName);
+ when(componentName.getPackageName()).thenReturn(this.getContext().getPackageName());
+ TileServiceManager manager = mTileService.getTileWrapper(tile);
+
+ mTileService.onStartActivity(manager.getToken());
+ verify(mPanelInteractor).forceCollapsePanels();
+ }
+
+ @Test
+ public void testOnShowDialogCollapsesPanel() {
+ CustomTile tile = mock(CustomTile.class);
+ ComponentName componentName = mock(ComponentName.class);
+ when(tile.getComponent()).thenReturn(componentName);
+ when(componentName.getPackageName()).thenReturn(this.getContext().getPackageName());
+ TileServiceManager manager = mTileService.getTileWrapper(tile);
+
+ mTileService.onShowDialog(manager.getToken());
+ verify(mPanelInteractor).forceCollapsePanels();
+ }
+
private class TestTileServices extends TileServices {
TestTileServices(QSHost host, Provider<Handler> handlerProvider,
BroadcastDispatcher broadcastDispatcher, UserTracker userTracker,
KeyguardStateController keyguardStateController, CommandQueue commandQueue,
- StatusBarIconController statusBarIconController) {
+ StatusBarIconController statusBarIconController, PanelInteractor panelInteractor) {
super(host, handlerProvider, broadcastDispatcher, userTracker, keyguardStateController,
- commandQueue, statusBarIconController);
+ commandQueue, statusBarIconController, panelInteractor);
}
@Override
@@ -237,6 +266,8 @@
TileServiceManager manager = mock(TileServiceManager.class);
mManagers.add(manager);
when(manager.isLifecycleStarted()).thenReturn(true);
+ Binder b = new Binder();
+ when(manager.getToken()).thenReturn(b);
return manager;
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/interactor/PanelInteractorImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/interactor/PanelInteractorImplTest.kt
new file mode 100644
index 0000000..45783ab
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/pipeline/domain/interactor/PanelInteractorImplTest.kt
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+package com.android.systemui.qs.pipeline.domain.interactor
+
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.statusbar.phone.CentralSurfaces
+import java.util.Optional
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@RunWith(AndroidTestingRunner::class)
+@SmallTest
+class PanelInteractorImplTest : SysuiTestCase() {
+
+ @Mock private lateinit var centralSurfaces: CentralSurfaces
+
+ @Before
+ fun setup() {
+ MockitoAnnotations.initMocks(this)
+ }
+
+ @Test
+ fun openPanels_callsCentralSurfaces() {
+ val underTest = PanelInteractorImpl(Optional.of(centralSurfaces))
+
+ underTest.openPanels()
+
+ verify(centralSurfaces).postAnimateOpenPanels()
+ }
+
+ @Test
+ fun collapsePanels_callsCentralSurfaces() {
+ val underTest = PanelInteractorImpl(Optional.of(centralSurfaces))
+
+ underTest.collapsePanels()
+
+ verify(centralSurfaces).postAnimateCollapsePanels()
+ }
+
+ @Test
+ fun forceCollapsePanels_callsCentralSurfaces() {
+ val underTest = PanelInteractorImpl(Optional.of(centralSurfaces))
+
+ underTest.forceCollapsePanels()
+
+ verify(centralSurfaces).postAnimateForceCollapsePanels()
+ }
+
+ @Test
+ fun whenOptionalEmpty_doesnThrow() {
+ val underTest = PanelInteractorImpl(Optional.empty())
+
+ underTest.openPanels()
+ underTest.collapsePanels()
+ underTest.forceCollapsePanels()
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/LocationTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/LocationTileTest.kt
index 33921c7..3642e87 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/LocationTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/LocationTileTest.kt
@@ -31,9 +31,12 @@
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.qs.QSHost
import com.android.systemui.qs.logging.QSLogger
+import com.android.systemui.qs.pipeline.domain.interactor.PanelInteractor
import com.android.systemui.qs.tileimpl.QSTileImpl
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.statusbar.policy.LocationController
+import com.android.systemui.util.mockito.argumentCaptor
+import com.android.systemui.util.mockito.capture
import com.google.common.truth.Truth.assertThat
import org.junit.After
import org.junit.Before
@@ -41,6 +44,7 @@
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.Mockito.`when`
+import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
@RunWith(AndroidTestingRunner::class)
@@ -65,6 +69,8 @@
private lateinit var locationController: LocationController
@Mock
private lateinit var keyguardStateController: KeyguardStateController
+ @Mock
+ private lateinit var panelInteractor: PanelInteractor
private val uiEventLogger = UiEventLoggerFake()
private lateinit var testableLooper: TestableLooper
@@ -86,7 +92,9 @@
activityStarter,
qsLogger,
locationController,
- keyguardStateController)
+ keyguardStateController,
+ panelInteractor,
+ )
}
@After
@@ -116,4 +124,18 @@
assertThat(state.icon)
.isEqualTo(QSTileImpl.ResourceIcon.get(R.drawable.qs_location_icon_on))
}
+
+ @Test
+ fun testClickWhenLockedWillCallOpenPanels() {
+ `when`(keyguardStateController.isMethodSecure).thenReturn(true)
+ `when`(keyguardStateController.isShowing).thenReturn(true)
+
+ tile.handleClick(null)
+
+ val captor = argumentCaptor<Runnable>()
+ verify(activityStarter).postQSRunnableDismissingKeyguard(capture(captor))
+ captor.value.run()
+
+ verify(panelInteractor).openPanels()
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java
index 5aef758..d9ed1a2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java
@@ -45,6 +45,7 @@
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.logging.QSLogger;
+import com.android.systemui.qs.pipeline.domain.interactor.PanelInteractor;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.screenrecord.RecordingController;
import com.android.systemui.statusbar.phone.KeyguardDismissUtil;
@@ -83,6 +84,8 @@
private KeyguardStateController mKeyguardStateController;
@Mock
private DialogLaunchAnimator mDialogLaunchAnimator;
+ @Mock
+ private PanelInteractor mPanelInteractor;
private TestableLooper mTestableLooper;
private ScreenRecordTile mTile;
@@ -108,7 +111,8 @@
mController,
mKeyguardDismissUtil,
mKeyguardStateController,
- mDialogLaunchAnimator
+ mDialogLaunchAnimator,
+ mPanelInteractor
);
mTile.initialize();
@@ -146,7 +150,7 @@
assertNotNull(onStartRecordingClicked.getValue());
onStartRecordingClicked.getValue().run();
verify(mDialogLaunchAnimator).disableAllCurrentDialogsExitAnimations();
- verify(mHost).collapsePanels();
+ verify(mPanelInteractor).collapsePanels();
}
// Test that the tile is active and labeled correctly when the controller is starting
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowControllerTest.kt
index c92134b..60bc3a4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowControllerTest.kt
@@ -21,6 +21,7 @@
import android.testing.TestableLooper
import androidx.test.filters.SmallTest
import com.android.internal.logging.MetricsLogger
+import com.android.internal.statusbar.IStatusBarService
import com.android.systemui.SysuiTestCase
import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.flags.FeatureFlags
@@ -93,6 +94,7 @@
private val bubblesManager: BubblesManager = mock()
private val dragController: ExpandableNotificationRowDragController = mock()
private val dismissibilityProvider: NotificationDismissibilityProvider = mock()
+ private val statusBarService: IStatusBarService = mock()
private lateinit var controller: ExpandableNotificationRowController
@@ -130,7 +132,8 @@
peopleNotificationIdentifier,
Optional.of(bubblesManager),
dragController,
- dismissibilityProvider
+ dismissibilityProvider,
+ statusBarService
)
whenever(view.childrenContainer).thenReturn(childrenContainer)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.kt
index 7b2051d..0b90ebe 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.kt
@@ -74,7 +74,7 @@
doReturn(10).whenever(spyRow).intrinsicHeight
with(view) {
- initialize(mPeopleNotificationIdentifier, mock(), mock(), mock())
+ initialize(mPeopleNotificationIdentifier, mock(), mock(), mock(), mock())
setContainingNotification(spyRow)
setHeights(/* smallHeight= */ 10, /* headsUpMaxHeight= */ 20, /* maxHeight= */ 30)
contractedChild = createViewWithHeight(10)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
index f8a8e50..813bae8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
@@ -49,6 +49,7 @@
import android.widget.RemoteViews;
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.statusbar.IStatusBarService;
import com.android.systemui.TestableDependency;
import com.android.systemui.classifier.FalsingCollectorFake;
import com.android.systemui.classifier.FalsingManagerFake;
@@ -582,7 +583,8 @@
mock(MetricsLogger.class),
mock(SmartReplyConstants.class),
mock(SmartReplyController.class),
- mFeatureFlags);
+ mFeatureFlags,
+ mock(IStatusBarService.class));
row.setAboveShelfChangedListener(aboveShelf -> { });
mBindStage.getStageParams(entry).requireContentViews(extraInflationFlags);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
index 7a1270f..a9ed175 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
@@ -25,6 +25,7 @@
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -1163,8 +1164,8 @@
@Test
public void testScrimFocus() {
mScrimController.transitionTo(ScrimState.AOD);
- Assert.assertFalse("Should not be focusable on AOD", mScrimBehind.isFocusable());
- Assert.assertFalse("Should not be focusable on AOD", mScrimInFront.isFocusable());
+ assertFalse("Should not be focusable on AOD", mScrimBehind.isFocusable());
+ assertFalse("Should not be focusable on AOD", mScrimInFront.isFocusable());
mScrimController.transitionTo(ScrimState.KEYGUARD);
Assert.assertTrue("Should be focusable on keyguard", mScrimBehind.isFocusable());
@@ -1224,7 +1225,7 @@
public void testAnimatesTransitionToAod() {
when(mDozeParameters.shouldControlScreenOff()).thenReturn(false);
ScrimState.AOD.prepare(ScrimState.KEYGUARD);
- Assert.assertFalse("No animation when ColorFade kicks in",
+ assertFalse("No animation when ColorFade kicks in",
ScrimState.AOD.getAnimateChange());
reset(mDozeParameters);
@@ -1236,9 +1237,9 @@
@Test
public void testViewsDontHaveFocusHighlight() {
- Assert.assertFalse("Scrim shouldn't have focus highlight",
+ assertFalse("Scrim shouldn't have focus highlight",
mScrimInFront.getDefaultFocusHighlightEnabled());
- Assert.assertFalse("Scrim shouldn't have focus highlight",
+ assertFalse("Scrim shouldn't have focus highlight",
mScrimBehind.getDefaultFocusHighlightEnabled());
}
@@ -1738,7 +1739,7 @@
@Test
public void aodStateSetsFrontScrimToNotBlend() {
mScrimController.transitionTo(ScrimState.AOD);
- Assert.assertFalse("Front scrim should not blend with main color",
+ assertFalse("Front scrim should not blend with main color",
mScrimInFront.shouldBlendWithMainColor());
}
@@ -1773,6 +1774,14 @@
verify(mStatusBarKeyguardViewManager).onKeyguardFadedAway();
}
+ @Test
+ public void testDoNotAnimateChangeIfOccludeAnimationPlaying() {
+ mScrimController.setOccludeAnimationPlaying(true);
+ mScrimController.transitionTo(ScrimState.UNLOCKED);
+
+ assertFalse(ScrimState.UNLOCKED.mAnimateChange);
+ }
+
private void assertAlphaAfterExpansion(ScrimView scrim, float expectedAlpha, float expansion) {
mScrimController.setRawPanelExpansionFraction(expansion);
finishAnimationsImmediately();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingControllerTest.java
index 481d453..c8f28bc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingControllerTest.java
@@ -55,6 +55,9 @@
public class DeviceStateRotationLockSettingControllerTest extends SysuiTestCase {
private static final String[] DEFAULT_SETTINGS = new String[]{"0:1", "2:0:1", "1:2"};
+ private static final int[] DEFAULT_FOLDED_STATES = new int[]{0};
+ private static final int[] DEFAULT_HALF_FOLDED_STATES = new int[]{2};
+ private static final int[] DEFAULT_UNFOLDED_STATES = new int[]{1};
@Mock private DeviceStateManager mDeviceStateManager;
@Mock private DeviceStateRotationLockSettingControllerLogger mLogger;
@@ -73,6 +76,9 @@
MockitoAnnotations.initMocks(/* testClass= */ this);
TestableResources resources = mContext.getOrCreateTestableResources();
resources.addOverride(R.array.config_perDeviceStateRotationLockDefaults, DEFAULT_SETTINGS);
+ resources.addOverride(R.array.config_foldedDeviceStates, DEFAULT_FOLDED_STATES);
+ resources.addOverride(R.array.config_halfFoldedDeviceStates, DEFAULT_HALF_FOLDED_STATES);
+ resources.addOverride(R.array.config_openDeviceStates, DEFAULT_UNFOLDED_STATES);
ArgumentCaptor<DeviceStateManager.DeviceStateCallback> deviceStateCallbackArgumentCaptor =
ArgumentCaptor.forClass(DeviceStateManager.DeviceStateCallback.class);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 7550196..b4e75e1 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -9351,7 +9351,9 @@
String logcatSetting = Settings.Global.ERROR_LOGCAT_PREFIX + dropboxTag;
String maxBytesSetting = Settings.Global.MAX_ERROR_BYTES_PREFIX + dropboxTag;
- int lines = Settings.Global.getInt(mContext.getContentResolver(), logcatSetting, 0);
+ int lines = Build.IS_USER
+ ? 0
+ : Settings.Global.getInt(mContext.getContentResolver(), logcatSetting, 0);
int dropboxMaxSize = Settings.Global.getInt(
mContext.getContentResolver(), maxBytesSetting, DROPBOX_DEFAULT_MAX_SIZE);
int maxDataFileSize = dropboxMaxSize - sb.length()
diff --git a/services/core/java/com/android/server/location/gnss/GnssConfiguration.java b/services/core/java/com/android/server/location/gnss/GnssConfiguration.java
index 77cd673..a081dff 100644
--- a/services/core/java/com/android/server/location/gnss/GnssConfiguration.java
+++ b/services/core/java/com/android/server/location/gnss/GnssConfiguration.java
@@ -92,6 +92,8 @@
// Represents an HAL interface version. Instances of this class are created in the JNI layer
// and returned through native methods.
static class HalInterfaceVersion {
+ // mMajor being this value denotes AIDL HAL. In this case, mMinor denotes the AIDL version.
+ static final int AIDL_INTERFACE = 3;
final int mMajor;
final int mMinor;
diff --git a/services/core/java/com/android/server/location/gnss/GnssMeasurementsProvider.java b/services/core/java/com/android/server/location/gnss/GnssMeasurementsProvider.java
index 6c4c829..041f11d 100644
--- a/services/core/java/com/android/server/location/gnss/GnssMeasurementsProvider.java
+++ b/services/core/java/com/android/server/location/gnss/GnssMeasurementsProvider.java
@@ -21,6 +21,7 @@
import static com.android.server.location.gnss.GnssManagerService.D;
import static com.android.server.location.gnss.GnssManagerService.TAG;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.AppOpsManager;
import android.location.GnssMeasurementRequest;
@@ -31,6 +32,7 @@
import android.stats.location.LocationStatsEnums;
import android.util.Log;
+import com.android.server.location.gnss.GnssConfiguration.HalInterfaceVersion;
import com.android.server.location.gnss.hal.GnssNative;
import com.android.server.location.injector.AppOpsHelper;
import com.android.server.location.injector.Injector;
@@ -115,16 +117,6 @@
if (request.getIntervalMillis() == GnssMeasurementRequest.PASSIVE_INTERVAL) {
return true;
}
- // The HAL doc does not specify if consecutive start() calls will be allowed.
- // Some vendors may ignore the 2nd start() call if stop() is not called.
- // Thus, here we always call stop() before calling start() to avoid being ignored.
- if (mGnssNative.stopMeasurementCollection()) {
- if (D) {
- Log.d(TAG, "stopping gnss measurements");
- }
- } else {
- Log.e(TAG, "error stopping gnss measurements");
- }
if (mGnssNative.startMeasurementCollection(request.isFullTracking(),
request.isCorrelationVectorOutputsEnabled(),
request.getIntervalMillis())) {
@@ -139,6 +131,28 @@
}
@Override
+ protected boolean reregisterWithService(GnssMeasurementRequest old,
+ GnssMeasurementRequest request,
+ @NonNull Collection<GnssListenerRegistration> registrations) {
+ if (request.getIntervalMillis() == GnssMeasurementRequest.PASSIVE_INTERVAL) {
+ unregisterWithService();
+ return true;
+ }
+ HalInterfaceVersion halInterfaceVersion =
+ mGnssNative.getConfiguration().getHalInterfaceVersion();
+ boolean aidlV3Plus = halInterfaceVersion.mMajor == HalInterfaceVersion.AIDL_INTERFACE
+ && halInterfaceVersion.mMinor >= 3;
+ if (!aidlV3Plus) {
+ // The HAL doc does not specify if consecutive start() calls will be allowed.
+ // Some vendors may ignore the 2nd start() call if stop() is not called.
+ // Thus, here we always call stop() before calling start() to avoid being ignored.
+ // AIDL v3+ is free from this issue.
+ unregisterWithService();
+ }
+ return registerWithService(request, registrations);
+ }
+
+ @Override
protected void unregisterWithService() {
if (mGnssNative.stopMeasurementCollection()) {
if (D) {
diff --git a/services/core/java/com/android/server/pm/ReconcilePackageUtils.java b/services/core/java/com/android/server/pm/ReconcilePackageUtils.java
index d160740..5312ae6 100644
--- a/services/core/java/com/android/server/pm/ReconcilePackageUtils.java
+++ b/services/core/java/com/android/server/pm/ReconcilePackageUtils.java
@@ -69,7 +69,6 @@
for (InstallRequest installRequest : installRequests) {
installRequest.onReconcileStarted();
- final String installPackageName = installRequest.getParsedPackage().getPackageName();
// add / replace existing with incoming packages
combinedPackages.put(installRequest.getScannedPackageSetting().getPackageName(),
@@ -84,12 +83,17 @@
incomingSharedLibraries, info)) {
throw ReconcileFailure.ofInternalError(
"Shared Library " + info.getName()
- + " is being installed twice in this set!",
+ + " is being installed twice in this set!",
PackageManagerException.INTERNAL_ERROR_SHARED_LIB_INSTALLED_TWICE);
}
}
}
+ }
+ for (InstallRequest installRequest : installRequests) {
+ final String installPackageName = installRequest.getParsedPackage().getPackageName();
+ final List<SharedLibraryInfo> allowedSharedLibInfos =
+ sharedLibraries.getAllowedSharedLibInfos(installRequest);
final DeletePackageAction deletePackageAction;
// we only want to try to delete for non system apps
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index b1ca72b..78ee6f9 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -857,7 +857,7 @@
@Override
public void grantInputChannel(int displayId, SurfaceControl surface,
IWindow window, IBinder hostInputToken, int flags, int privateFlags, int type,
- IBinder windowToken, IBinder focusGrantToken, String inputHandleName,
+ int inputFeatures, IBinder windowToken, IBinder focusGrantToken, String inputHandleName,
InputChannel outInputChannel) {
if (hostInputToken == null && !mCanAddInternalSystemWindow) {
// Callers without INTERNAL_SYSTEM_WINDOW permission cannot grant input channel to
@@ -869,7 +869,7 @@
try {
mService.grantInputChannel(this, mUid, mPid, displayId, surface, window, hostInputToken,
flags, mCanAddInternalSystemWindow ? privateFlags : 0,
- type, windowToken, focusGrantToken, inputHandleName,
+ type, inputFeatures, windowToken, focusGrantToken, inputHandleName,
outInputChannel);
} finally {
Binder.restoreCallingIdentity(identity);
@@ -878,11 +878,11 @@
@Override
public void updateInputChannel(IBinder channelToken, int displayId, SurfaceControl surface,
- int flags, int privateFlags, Region region) {
+ int flags, int privateFlags, int inputFeatures, Region region) {
final long identity = Binder.clearCallingIdentity();
try {
mService.updateInputChannel(channelToken, displayId, surface, flags,
- mCanAddInternalSystemWindow ? privateFlags : 0, region);
+ mCanAddInternalSystemWindow ? privateFlags : 0, inputFeatures, region);
} finally {
Binder.restoreCallingIdentity(identity);
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 8582356..be42f36 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -8571,8 +8571,8 @@
*/
void grantInputChannel(Session session, int callingUid, int callingPid, int displayId,
SurfaceControl surface, IWindow window, IBinder hostInputToken,
- int flags, int privateFlags, int type, IBinder windowToken, IBinder focusGrantToken,
- String inputHandleName, InputChannel outInputChannel) {
+ int flags, int privateFlags, int inputFeatures, int type, IBinder windowToken,
+ IBinder focusGrantToken, String inputHandleName, InputChannel outInputChannel) {
final int sanitizedType = sanitizeWindowType(session, displayId, windowToken, type);
final InputApplicationHandle applicationHandle;
final String name;
@@ -8589,7 +8589,7 @@
}
updateInputChannel(clientChannel.getToken(), callingUid, callingPid, displayId, surface,
- name, applicationHandle, flags, privateFlags, sanitizedType,
+ name, applicationHandle, flags, privateFlags, inputFeatures, sanitizedType,
null /* region */, window);
clientChannel.copyTo(outInputChannel);
@@ -8630,13 +8630,14 @@
private void updateInputChannel(IBinder channelToken, int callingUid, int callingPid,
int displayId, SurfaceControl surface, String name,
InputApplicationHandle applicationHandle, int flags,
- int privateFlags, int type, Region region, IWindow window) {
+ int privateFlags, int inputFeatures, int type, Region region, IWindow window) {
final InputWindowHandle h = new InputWindowHandle(applicationHandle, displayId);
h.token = channelToken;
h.setWindowToken(window);
h.name = name;
flags = sanitizeFlagSlippery(flags, name, callingUid, callingPid);
+ inputFeatures = sanitizeSpyWindow(inputFeatures, name, callingUid, callingPid);
final int sanitizedLpFlags =
(flags & (FLAG_NOT_TOUCHABLE | FLAG_SLIPPERY | LayoutParams.FLAG_NOT_FOCUSABLE))
@@ -8646,7 +8647,7 @@
// Do not allow any input features to be set without sanitizing them first.
h.inputConfig = InputConfigAdapter.getInputConfigFromWindowParams(
- type, sanitizedLpFlags, 0 /*inputFeatures*/);
+ type, sanitizedLpFlags, inputFeatures);
if ((flags & LayoutParams.FLAG_NOT_FOCUSABLE) != 0) {
@@ -8683,7 +8684,7 @@
* is undefined.
*/
void updateInputChannel(IBinder channelToken, int displayId, SurfaceControl surface,
- int flags, int privateFlags, Region region) {
+ int flags, int privateFlags, int inputFeatures, Region region) {
final InputApplicationHandle applicationHandle;
final String name;
final EmbeddedWindowController.EmbeddedWindow win;
@@ -8698,7 +8699,8 @@
}
updateInputChannel(channelToken, win.mOwnerUid, win.mOwnerPid, displayId, surface, name,
- applicationHandle, flags, privateFlags, win.mWindowType, region, win.mClient);
+ applicationHandle, flags, privateFlags, inputFeatures, win.mWindowType, region,
+ win.mClient);
}
/** Return whether layer tracing is enabled */
diff --git a/services/core/jni/gnss/GnssConfiguration.cpp b/services/core/jni/gnss/GnssConfiguration.cpp
index 3677641..b57e451 100644
--- a/services/core/jni/gnss/GnssConfiguration.cpp
+++ b/services/core/jni/gnss/GnssConfiguration.cpp
@@ -67,7 +67,7 @@
: mIGnssConfiguration(iGnssConfiguration) {}
jobject GnssConfiguration::getVersion(JNIEnv* env) {
- return createHalInterfaceVersionJavaObject(env, 3, 0);
+ return createHalInterfaceVersionJavaObject(env, 3, mIGnssConfiguration->getInterfaceVersion());
}
jboolean GnssConfiguration::setEmergencySuplPdn(jint enable) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 720533f..321924c 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -21882,7 +21882,9 @@
}
if (!isProfileOwnerOfOrganizationOwnedDevice(
admin.info.getComponent(), user.getIdentifier())
- && !isDeviceOwner(admin)) {
+ && !isDeviceOwner(admin)
+ && !(isProfileOwner(admin.info.getComponent(), user.getIdentifier())
+ && admin.getUserHandle().isSystem())) {
continue;
}
// Don't send the broadcast twice if the DPC is the same package as the
diff --git a/services/tests/mockingservicestests/src/com/android/server/location/gnss/GnssMeasurementsProviderTest.java b/services/tests/mockingservicestests/src/com/android/server/location/gnss/GnssMeasurementsProviderTest.java
new file mode 100644
index 0000000..fd9dfe8
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/location/gnss/GnssMeasurementsProviderTest.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.location.gnss;
+
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.content.Context;
+import android.location.GnssMeasurementRequest;
+import android.location.IGnssMeasurementsListener;
+import android.location.LocationManager;
+import android.location.LocationManagerInternal;
+import android.location.util.identity.CallerIdentity;
+import android.os.IBinder;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.server.LocalServices;
+import com.android.server.location.gnss.hal.FakeGnssHal;
+import com.android.server.location.gnss.hal.GnssNative;
+import com.android.server.location.injector.FakeUserInfoHelper;
+import com.android.server.location.injector.Injector;
+import com.android.server.location.injector.TestInjector;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Objects;
+
+@Presubmit
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class GnssMeasurementsProviderTest {
+ private static final int CURRENT_USER = FakeUserInfoHelper.DEFAULT_USERID;
+ private static final CallerIdentity IDENTITY = CallerIdentity.forTest(CURRENT_USER, 1000,
+ "mypackage", "attribution", "listener");
+ private static final GnssConfiguration.HalInterfaceVersion HIDL_V2_1 =
+ new GnssConfiguration.HalInterfaceVersion(
+ 2, 1);
+ private static final GnssConfiguration.HalInterfaceVersion AIDL_V3 =
+ new GnssConfiguration.HalInterfaceVersion(
+ GnssConfiguration.HalInterfaceVersion.AIDL_INTERFACE, 3);
+ private static final GnssMeasurementRequest ACTIVE_REQUEST =
+ new GnssMeasurementRequest.Builder().build();
+ private static final GnssMeasurementRequest PASSIVE_REQUEST =
+ new GnssMeasurementRequest.Builder().setIntervalMillis(
+ GnssMeasurementRequest.PASSIVE_INTERVAL).build();
+ private @Mock Context mContext;
+ private @Mock LocationManagerInternal mInternal;
+ private @Mock GnssConfiguration mMockConfiguration;
+ private @Mock GnssNative.GeofenceCallbacks mGeofenceCallbacks;
+ private @Mock IGnssMeasurementsListener mListener1;
+ private @Mock IGnssMeasurementsListener mListener2;
+ private @Mock IBinder mBinder1;
+ private @Mock IBinder mBinder2;
+
+ private GnssNative mGnssNative;
+
+ private GnssMeasurementsProvider mTestProvider;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ doReturn(mBinder1).when(mListener1).asBinder();
+ doReturn(mBinder2).when(mListener2).asBinder();
+ doReturn(true).when(mInternal).isProviderEnabledForUser(eq(LocationManager.GPS_PROVIDER),
+ anyInt());
+ LocalServices.addService(LocationManagerInternal.class, mInternal);
+ FakeGnssHal fakeGnssHal = new FakeGnssHal();
+ GnssNative.setGnssHalForTest(fakeGnssHal);
+ Injector injector = new TestInjector(mContext);
+ mGnssNative = spy(Objects.requireNonNull(
+ GnssNative.create(injector, mMockConfiguration)));
+ mGnssNative.setGeofenceCallbacks(mGeofenceCallbacks);
+ mTestProvider = new GnssMeasurementsProvider(injector, mGnssNative);
+ mGnssNative.register();
+ }
+
+ @After
+ public void tearDown() {
+ LocalServices.removeServiceForTest(LocationManagerInternal.class);
+ }
+
+ @Test
+ public void testAddListener_active() {
+ // add the active request
+ mTestProvider.addListener(ACTIVE_REQUEST, IDENTITY, mListener1);
+ verify(mGnssNative, times(1)).startMeasurementCollection(
+ eq(ACTIVE_REQUEST.isFullTracking()),
+ eq(ACTIVE_REQUEST.isCorrelationVectorOutputsEnabled()),
+ eq(ACTIVE_REQUEST.getIntervalMillis()));
+
+ // remove the active request
+ mTestProvider.removeListener(mListener1);
+ verify(mGnssNative, times(1)).stopMeasurementCollection();
+ }
+
+ @Test
+ public void testAddListener_passive() {
+ // add the passive request
+ mTestProvider.addListener(PASSIVE_REQUEST, IDENTITY, mListener1);
+ verify(mGnssNative, never()).startMeasurementCollection(anyBoolean(), anyBoolean(),
+ anyInt());
+
+ // remove the passive request
+ mTestProvider.removeListener(mListener1);
+ verify(mGnssNative, times(1)).stopMeasurementCollection();
+ }
+
+ @Test
+ public void testReregister_aidlV3Plus() {
+ doReturn(AIDL_V3).when(mMockConfiguration).getHalInterfaceVersion();
+
+ // add the passive request
+ mTestProvider.addListener(PASSIVE_REQUEST, IDENTITY, mListener1);
+ verify(mGnssNative, never()).startMeasurementCollection(anyBoolean(), anyBoolean(),
+ anyInt());
+
+ // add the active request, reregister with the active request
+ mTestProvider.addListener(ACTIVE_REQUEST, IDENTITY, mListener2);
+ verify(mGnssNative, never()).stopMeasurementCollection();
+ verify(mGnssNative, times(1)).startMeasurementCollection(
+ eq(ACTIVE_REQUEST.isFullTracking()),
+ eq(ACTIVE_REQUEST.isCorrelationVectorOutputsEnabled()),
+ eq(ACTIVE_REQUEST.getIntervalMillis()));
+
+ // remove the active request, reregister with the passive request
+ mTestProvider.removeListener(mListener2);
+ verify(mGnssNative, times(1)).stopMeasurementCollection();
+
+ // remove the passive request
+ mTestProvider.removeListener(mListener1);
+ verify(mGnssNative, times(2)).stopMeasurementCollection();
+ }
+
+ @Test
+ public void testReregister_preAidlV3() {
+ doReturn(HIDL_V2_1).when(mMockConfiguration).getHalInterfaceVersion();
+
+ // add the passive request
+ mTestProvider.addListener(PASSIVE_REQUEST, IDENTITY, mListener1);
+ verify(mGnssNative, never()).startMeasurementCollection(anyBoolean(), anyBoolean(),
+ anyInt());
+
+ // add the active request, reregister with the active request
+ mTestProvider.addListener(ACTIVE_REQUEST, IDENTITY, mListener2);
+ verify(mGnssNative, times(1)).stopMeasurementCollection();
+ verify(mGnssNative, times(1)).startMeasurementCollection(
+ eq(ACTIVE_REQUEST.isFullTracking()),
+ eq(ACTIVE_REQUEST.isCorrelationVectorOutputsEnabled()),
+ eq(ACTIVE_REQUEST.getIntervalMillis()));
+
+ // remove the active request, reregister with the passive request
+ mTestProvider.removeListener(mListener2);
+ verify(mGnssNative, times(2)).stopMeasurementCollection();
+
+ // remove the passive request
+ mTestProvider.removeListener(mListener1);
+ verify(mGnssNative, times(3)).stopMeasurementCollection();
+ }
+}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
index 7d6cf4a..677ec46 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
@@ -26,7 +26,10 @@
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_TRUSTED;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.FLAG_OWN_FOCUS;
+import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_SPY;
import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
@@ -49,11 +52,13 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
@@ -67,12 +72,16 @@
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
+import android.os.InputConfig;
+import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
import android.platform.test.annotations.Presubmit;
import android.util.DisplayMetrics;
import android.util.MergedConfiguration;
+import android.view.IWindow;
import android.view.IWindowSessionCallback;
+import android.view.InputChannel;
import android.view.InsetsSourceControl;
import android.view.InsetsState;
import android.view.Surface;
@@ -690,6 +699,102 @@
assertEquals(validRect, resultingArgs.mSourceCrop);
}
+ @Test
+ public void testGrantInputChannel_sanitizeSpyWindowForApplications() {
+ final Session session = mock(Session.class);
+ final int callingUid = Process.FIRST_APPLICATION_UID;
+ final int callingPid = 1234;
+ final SurfaceControl surfaceControl = mock(SurfaceControl.class);
+ final IWindow window = mock(IWindow.class);
+ final IBinder windowToken = mock(IBinder.class);
+ when(window.asBinder()).thenReturn(windowToken);
+ final IBinder focusGrantToken = mock(IBinder.class);
+
+ final InputChannel inputChannel = new InputChannel();
+ assertThrows(IllegalArgumentException.class, () ->
+ mWm.grantInputChannel(session, callingUid, callingPid, DEFAULT_DISPLAY,
+ surfaceControl, window, null /* hostInputToken */, FLAG_NOT_FOCUSABLE,
+ PRIVATE_FLAG_TRUSTED_OVERLAY, INPUT_FEATURE_SPY, TYPE_APPLICATION,
+ null /* windowToken */, focusGrantToken, "TestInputChannel",
+ inputChannel));
+ }
+
+ @Test
+ public void testGrantInputChannel_allowSpyWindowForInputMonitorPermission() {
+ final Session session = mock(Session.class);
+ final int callingUid = Process.SYSTEM_UID;
+ final int callingPid = 1234;
+ final SurfaceControl surfaceControl = mock(SurfaceControl.class);
+ final IWindow window = mock(IWindow.class);
+ final IBinder windowToken = mock(IBinder.class);
+ when(window.asBinder()).thenReturn(windowToken);
+ final IBinder focusGrantToken = mock(IBinder.class);
+
+ final InputChannel inputChannel = new InputChannel();
+ mWm.grantInputChannel(session, callingUid, callingPid, DEFAULT_DISPLAY, surfaceControl,
+ window, null /* hostInputToken */, FLAG_NOT_FOCUSABLE, PRIVATE_FLAG_TRUSTED_OVERLAY,
+ INPUT_FEATURE_SPY, TYPE_APPLICATION, null /* windowToken */, focusGrantToken,
+ "TestInputChannel", inputChannel);
+
+ verify(mTransaction).setInputWindowInfo(
+ eq(surfaceControl),
+ argThat(h -> (h.inputConfig & InputConfig.SPY) == InputConfig.SPY));
+ }
+
+ @Test
+ public void testUpdateInputChannel_sanitizeSpyWindowForApplications() {
+ final Session session = mock(Session.class);
+ final int callingUid = Process.FIRST_APPLICATION_UID;
+ final int callingPid = 1234;
+ final SurfaceControl surfaceControl = mock(SurfaceControl.class);
+ final IWindow window = mock(IWindow.class);
+ final IBinder windowToken = mock(IBinder.class);
+ when(window.asBinder()).thenReturn(windowToken);
+ final IBinder focusGrantToken = mock(IBinder.class);
+
+ final InputChannel inputChannel = new InputChannel();
+ mWm.grantInputChannel(session, callingUid, callingPid, DEFAULT_DISPLAY, surfaceControl,
+ window, null /* hostInputToken */, FLAG_NOT_FOCUSABLE, PRIVATE_FLAG_TRUSTED_OVERLAY,
+ 0 /* inputFeatures */, TYPE_APPLICATION, null /* windowToken */, focusGrantToken,
+ "TestInputChannel", inputChannel);
+ verify(mTransaction).setInputWindowInfo(
+ eq(surfaceControl),
+ argThat(h -> (h.inputConfig & InputConfig.SPY) == 0));
+
+ assertThrows(IllegalArgumentException.class, () ->
+ mWm.updateInputChannel(inputChannel.getToken(), DEFAULT_DISPLAY, surfaceControl,
+ FLAG_NOT_FOCUSABLE, PRIVATE_FLAG_TRUSTED_OVERLAY, INPUT_FEATURE_SPY,
+ null /* region */));
+ }
+
+ @Test
+ public void testUpdateInputChannel_allowSpyWindowForInputMonitorPermission() {
+ final Session session = mock(Session.class);
+ final int callingUid = Process.SYSTEM_UID;
+ final int callingPid = 1234;
+ final SurfaceControl surfaceControl = mock(SurfaceControl.class);
+ final IWindow window = mock(IWindow.class);
+ final IBinder windowToken = mock(IBinder.class);
+ when(window.asBinder()).thenReturn(windowToken);
+ final IBinder focusGrantToken = mock(IBinder.class);
+
+ final InputChannel inputChannel = new InputChannel();
+ mWm.grantInputChannel(session, callingUid, callingPid, DEFAULT_DISPLAY, surfaceControl,
+ window, null /* hostInputToken */, FLAG_NOT_FOCUSABLE, PRIVATE_FLAG_TRUSTED_OVERLAY,
+ 0 /* inputFeatures */, TYPE_APPLICATION, null /* windowToken */, focusGrantToken,
+ "TestInputChannel", inputChannel);
+ verify(mTransaction).setInputWindowInfo(
+ eq(surfaceControl),
+ argThat(h -> (h.inputConfig & InputConfig.SPY) == 0));
+
+ mWm.updateInputChannel(inputChannel.getToken(), DEFAULT_DISPLAY, surfaceControl,
+ FLAG_NOT_FOCUSABLE, PRIVATE_FLAG_TRUSTED_OVERLAY, INPUT_FEATURE_SPY,
+ null /* region */);
+ verify(mTransaction).setInputWindowInfo(
+ eq(surfaceControl),
+ argThat(h -> (h.inputConfig & InputConfig.SPY) == InputConfig.SPY));
+ }
+
private void setupActivityWithLaunchCookie(IBinder launchCookie, WindowContainerToken wct) {
final WindowContainer.RemoteToken remoteToken = mock(WindowContainer.RemoteToken.class);
when(remoteToken.toWindowContainerToken()).thenReturn(wct);
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 212dc41..7aa1334 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -8654,6 +8654,16 @@
public static final String KEY_EPDG_ADDRESS_PRIORITY_INT_ARRAY =
KEY_PREFIX + "epdg_address_priority_int_array";
+ /**
+ * A priority list of PLMN to be used in EPDG_ADDRESS_PLMN. Possible values are {@link
+ * #EPDG_PLMN_RPLMN}, {@link #EPDG_PLMN_HPLMN}, {@link #EPDG_PLMN_EHPLMN_ALL}, {@link
+ * #EPDG_PLMN_EHPLMN_FIRST}
+ *
+ * @hide
+ */
+ public static final String KEY_EPDG_PLMN_PRIORITY_INT_ARRAY =
+ KEY_PREFIX + "epdg_plmn_priority_int_array";
+
/** Epdg static IP address or FQDN */
public static final String KEY_EPDG_STATIC_ADDRESS_STRING =
KEY_PREFIX + "epdg_static_address_string";
@@ -8854,6 +8864,36 @@
public static final int EPDG_ADDRESS_VISITED_COUNTRY = 4;
/** @hide */
+ @IntDef({
+ EPDG_PLMN_RPLMN,
+ EPDG_PLMN_HPLMN,
+ EPDG_PLMN_EHPLMN_ALL,
+ EPDG_PLMN_EHPLMN_FIRST
+ })
+ public @interface EpdgAddressPlmnType {}
+
+ /**
+ * Use the Registered PLMN
+ * @hide
+ */
+ public static final int EPDG_PLMN_RPLMN = 0;
+ /**
+ * Use the PLMN derived from IMSI
+ * @hide
+ */
+ public static final int EPDG_PLMN_HPLMN = 1;
+ /**
+ * Use all EHPLMN from SIM EF files
+ * @hide
+ */
+ public static final int EPDG_PLMN_EHPLMN_ALL = 2;
+ /**
+ * Use the first EHPLMN from SIM EF files
+ * @hide
+ */
+ public static final int EPDG_PLMN_EHPLMN_FIRST = 3;
+
+ /** @hide */
@IntDef({ID_TYPE_FQDN, ID_TYPE_RFC822_ADDR, ID_TYPE_KEY_ID})
public @interface IkeIdType {}
@@ -8988,6 +9028,12 @@
defaults.putIntArray(
KEY_EPDG_ADDRESS_PRIORITY_INT_ARRAY,
new int[] {EPDG_ADDRESS_PLMN, EPDG_ADDRESS_STATIC});
+ defaults.putIntArray(
+ KEY_EPDG_PLMN_PRIORITY_INT_ARRAY,
+ new int[]{
+ EPDG_PLMN_RPLMN,
+ EPDG_PLMN_HPLMN,
+ EPDG_PLMN_EHPLMN_ALL});
defaults.putStringArray(KEY_MCC_MNCS_STRING_ARRAY, new String[0]);
defaults.putInt(KEY_IKE_LOCAL_ID_TYPE_INT, ID_TYPE_RFC822_ADDR);
defaults.putInt(KEY_IKE_REMOTE_ID_TYPE_INT, ID_TYPE_FQDN);
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/HotspotNetwork.java b/wifi/java/src/android/net/wifi/sharedconnectivity/app/HotspotNetwork.java
index 9bfeb63..fe397d9 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/HotspotNetwork.java
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/HotspotNetwork.java
@@ -23,6 +23,7 @@
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.net.wifi.sharedconnectivity.service.SharedConnectivityService;
+import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.ArraySet;
@@ -86,6 +87,7 @@
@Nullable
@SecurityType
private final ArraySet<Integer> mHotspotSecurityTypes;
+ private final Bundle mExtras;
/**
* Builder class for {@link HotspotNetwork}.
@@ -102,8 +104,8 @@
private String mHotspotBssid;
@Nullable
@SecurityType
- private final ArraySet<Integer> mHotspotSecurityTypes =
- new ArraySet<>();
+ private final ArraySet<Integer> mHotspotSecurityTypes = new ArraySet<>();
+ private Bundle mExtras = Bundle.EMPTY;
/**
* Set the remote device ID.
@@ -190,6 +192,17 @@
}
/**
+ * Sets the extras bundle
+ *
+ * @return Returns the Builder object.
+ */
+ @NonNull
+ public Builder setExtras(@NonNull Bundle extras) {
+ mExtras = extras;
+ return this;
+ }
+
+ /**
* Builds the {@link HotspotNetwork} object.
*
* @return Returns the built {@link HotspotNetwork} object.
@@ -203,7 +216,8 @@
mNetworkName,
mHotspotSsid,
mHotspotBssid,
- mHotspotSecurityTypes);
+ mHotspotSecurityTypes,
+ mExtras);
}
}
@@ -231,7 +245,8 @@
@NonNull String networkName,
@Nullable String hotspotSsid,
@Nullable String hotspotBssid,
- @Nullable @SecurityType ArraySet<Integer> hotspotSecurityTypes) {
+ @Nullable @SecurityType ArraySet<Integer> hotspotSecurityTypes,
+ @NonNull Bundle extras) {
validate(deviceId,
networkType,
networkName,
@@ -243,6 +258,7 @@
mHotspotSsid = hotspotSsid;
mHotspotBssid = hotspotBssid;
mHotspotSecurityTypes = new ArraySet<>(hotspotSecurityTypes);
+ mExtras = extras;
}
/**
@@ -315,6 +331,16 @@
return mHotspotSecurityTypes;
}
+ /**
+ * Gets the extras Bundle.
+ *
+ * @return Returns a Bundle object.
+ */
+ @NonNull
+ public Bundle getExtras() {
+ return mExtras;
+ }
+
@Override
public boolean equals(Object obj) {
if (!(obj instanceof HotspotNetwork)) return false;
@@ -348,6 +374,7 @@
dest.writeString(mHotspotSsid);
dest.writeString(mHotspotBssid);
dest.writeArraySet(mHotspotSecurityTypes);
+ dest.writeBundle(mExtras);
}
/**
@@ -359,7 +386,7 @@
public static HotspotNetwork readFromParcel(@NonNull Parcel in) {
return new HotspotNetwork(in.readLong(), NetworkProviderInfo.readFromParcel(in),
in.readInt(), in.readString(), in.readString(), in.readString(),
- (ArraySet<Integer>) in.readArraySet(null));
+ (ArraySet<Integer>) in.readArraySet(null), in.readBundle());
}
@NonNull
@@ -385,6 +412,7 @@
.append(", hotspotSsid=").append(mHotspotSsid)
.append(", hotspotBssid=").append(mHotspotBssid)
.append(", hotspotSecurityTypes=").append(mHotspotSecurityTypes.toString())
+ .append(", extras=").append(mExtras.toString())
.append("]").toString();
}
}
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkConnectionStatus.java b/wifi/java/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkConnectionStatus.java
index 69767f3..72acf2c 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkConnectionStatus.java
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkConnectionStatus.java
@@ -117,7 +117,7 @@
@ConnectionStatus
private int mStatus;
private HotspotNetwork mHotspotNetwork;
- private Bundle mExtras;
+ private Bundle mExtras = Bundle.EMPTY;
/**
* Sets the status of the connection
@@ -179,7 +179,7 @@
}
private HotspotNetworkConnectionStatus(@ConnectionStatus int status,
- HotspotNetwork hotspotNetwork, Bundle extras) {
+ HotspotNetwork hotspotNetwork, @NonNull Bundle extras) {
validate(status);
mStatus = status;
mHotspotNetwork = hotspotNetwork;
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/KnownNetwork.java b/wifi/java/src/android/net/wifi/sharedconnectivity/app/KnownNetwork.java
index 64412bc..c390e42 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/KnownNetwork.java
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/KnownNetwork.java
@@ -22,6 +22,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
+import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
@@ -73,6 +74,7 @@
@SecurityType
private final ArraySet<Integer> mSecurityTypes;
private final NetworkProviderInfo mNetworkProviderInfo;
+ private final Bundle mExtras;
/**
* Builder class for {@link KnownNetwork}.
@@ -84,6 +86,7 @@
@SecurityType
private final ArraySet<Integer> mSecurityTypes = new ArraySet<>();
private NetworkProviderInfo mNetworkProviderInfo;
+ private Bundle mExtras = Bundle.EMPTY;
/**
* Sets the indicated source of the known network.
@@ -135,6 +138,17 @@
}
/**
+ * Sets the extras bundle
+ *
+ * @return Returns the Builder object.
+ */
+ @NonNull
+ public Builder setExtras(@NonNull Bundle extras) {
+ mExtras = extras;
+ return this;
+ }
+
+ /**
* Builds the {@link KnownNetwork} object.
*
* @return Returns the built {@link KnownNetwork} object.
@@ -145,7 +159,8 @@
mNetworkSource,
mSsid,
mSecurityTypes,
- mNetworkProviderInfo);
+ mNetworkProviderInfo,
+ mExtras);
}
}
@@ -173,12 +188,14 @@
@NetworkSource int networkSource,
@NonNull String ssid,
@NonNull @SecurityType ArraySet<Integer> securityTypes,
- @Nullable NetworkProviderInfo networkProviderInfo) {
+ @Nullable NetworkProviderInfo networkProviderInfo,
+ @NonNull Bundle extras) {
validate(networkSource, ssid, securityTypes, networkProviderInfo);
mNetworkSource = networkSource;
mSsid = ssid;
mSecurityTypes = new ArraySet<>(securityTypes);
mNetworkProviderInfo = networkProviderInfo;
+ mExtras = extras;
}
/**
@@ -223,6 +240,16 @@
return mNetworkProviderInfo;
}
+ /**
+ * Gets the extras Bundle.
+ *
+ * @return Returns a Bundle object.
+ */
+ @NonNull
+ public Bundle getExtras() {
+ return mExtras;
+ }
+
@Override
public boolean equals(Object obj) {
if (!(obj instanceof KnownNetwork)) return false;
@@ -249,6 +276,7 @@
dest.writeString(mSsid);
dest.writeArraySet(mSecurityTypes);
mNetworkProviderInfo.writeToParcel(dest, flags);
+ dest.writeBundle(mExtras);
}
/**
@@ -260,7 +288,7 @@
public static KnownNetwork readFromParcel(@NonNull Parcel in) {
return new KnownNetwork(in.readInt(), in.readString(),
(ArraySet<Integer>) in.readArraySet(null),
- NetworkProviderInfo.readFromParcel(in));
+ NetworkProviderInfo.readFromParcel(in), in.readBundle());
}
@NonNull
@@ -283,6 +311,7 @@
.append(", ssid=").append(mSsid)
.append(", securityTypes=").append(mSecurityTypes.toString())
.append(", networkProviderInfo=").append(mNetworkProviderInfo.toString())
+ .append(", extras=").append(mExtras.toString())
.append("]").toString();
}
}
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/KnownNetworkConnectionStatus.java b/wifi/java/src/android/net/wifi/sharedconnectivity/app/KnownNetworkConnectionStatus.java
index 6bd0a5e..b30dc3f 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/KnownNetworkConnectionStatus.java
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/KnownNetworkConnectionStatus.java
@@ -72,7 +72,7 @@
public static final class Builder {
@ConnectionStatus private int mStatus;
private KnownNetwork mKnownNetwork;
- private Bundle mExtras;
+ private Bundle mExtras = Bundle.EMPTY;
public Builder() {}
@@ -128,7 +128,7 @@
}
private KnownNetworkConnectionStatus(@ConnectionStatus int status, KnownNetwork knownNetwork,
- Bundle extras) {
+ @NonNull Bundle extras) {
validate(status);
mStatus = status;
mKnownNetwork = knownNetwork;
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfo.java b/wifi/java/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfo.java
index ed4d699..25fbabc 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfo.java
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfo.java
@@ -21,6 +21,7 @@
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.net.wifi.sharedconnectivity.service.SharedConnectivityService;
+import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@@ -89,6 +90,7 @@
private final String mModelName;
private final int mBatteryPercentage;
private final int mConnectionStrength;
+ private final Bundle mExtras;
/**
* Builder class for {@link NetworkProviderInfo}.
@@ -99,6 +101,7 @@
private String mModelName;
private int mBatteryPercentage;
private int mConnectionStrength;
+ private Bundle mExtras = Bundle.EMPTY;
public Builder(@NonNull String deviceName, @NonNull String modelName) {
Objects.requireNonNull(deviceName);
@@ -170,6 +173,17 @@
}
/**
+ * Sets the extras bundle
+ *
+ * @return Returns the Builder object.
+ */
+ @NonNull
+ public Builder setExtras(@NonNull Bundle extras) {
+ mExtras = extras;
+ return this;
+ }
+
+ /**
* Builds the {@link NetworkProviderInfo} object.
*
* @return Returns the built {@link NetworkProviderInfo} object.
@@ -177,7 +191,7 @@
@NonNull
public NetworkProviderInfo build() {
return new NetworkProviderInfo(mDeviceType, mDeviceName, mModelName, mBatteryPercentage,
- mConnectionStrength);
+ mConnectionStrength, mExtras);
}
}
@@ -197,13 +211,15 @@
}
private NetworkProviderInfo(@DeviceType int deviceType, @NonNull String deviceName,
- @NonNull String modelName, int batteryPercentage, int connectionStrength) {
+ @NonNull String modelName, int batteryPercentage, int connectionStrength,
+ @NonNull Bundle extras) {
validate(deviceType, deviceName, modelName, batteryPercentage, connectionStrength);
mDeviceType = deviceType;
mDeviceName = deviceName;
mModelName = modelName;
mBatteryPercentage = batteryPercentage;
mConnectionStrength = connectionStrength;
+ mExtras = extras;
}
/**
@@ -256,6 +272,16 @@
return mConnectionStrength;
}
+ /**
+ * Gets the extras Bundle.
+ *
+ * @return Returns a Bundle object.
+ */
+ @NonNull
+ public Bundle getExtras() {
+ return mExtras;
+ }
+
@Override
public boolean equals(Object obj) {
if (!(obj instanceof NetworkProviderInfo)) return false;
@@ -280,6 +306,7 @@
dest.writeString(mModelName);
dest.writeInt(mBatteryPercentage);
dest.writeInt(mConnectionStrength);
+ dest.writeBundle(mExtras);
}
@Override
@@ -295,7 +322,7 @@
@NonNull
public static NetworkProviderInfo readFromParcel(@NonNull Parcel in) {
return new NetworkProviderInfo(in.readInt(), in.readString(), in.readString(), in.readInt(),
- in.readInt());
+ in.readInt(), in.readBundle());
}
@NonNull
@@ -319,6 +346,7 @@
.append(", modelName=").append(mModelName)
.append(", batteryPercentage=").append(mBatteryPercentage)
.append(", connectionStrength=").append(mConnectionStrength)
+ .append(", extras=").append(mExtras.toString())
.append("]").toString();
}
}
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivitySettingsState.java b/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivitySettingsState.java
index 63e471b..30bb989 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivitySettingsState.java
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivitySettingsState.java
@@ -51,7 +51,7 @@
private boolean mInstantTetherEnabled;
private Intent mInstantTetherSettingsIntent;
private final Context mContext;
- private Bundle mExtras;
+ private Bundle mExtras = Bundle.EMPTY;
public Builder(@NonNull Context context) {
mContext = context;
@@ -112,8 +112,7 @@
}
private SharedConnectivitySettingsState(boolean instantTetherEnabled,
- PendingIntent pendingIntent, Bundle extras) {
-
+ PendingIntent pendingIntent, @NonNull Bundle extras) {
mInstantTetherEnabled = instantTetherEnabled;
mInstantTetherSettingsPendingIntent = pendingIntent;
mExtras = extras;
diff --git a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkTest.java
index 8302094..0827ffa 100644
--- a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkTest.java
+++ b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkTest.java
@@ -28,6 +28,7 @@
import static org.junit.Assert.assertThrows;
+import android.os.Bundle;
import android.os.Parcel;
import android.util.ArraySet;
@@ -55,6 +56,8 @@
private static final String HOTSPOT_SSID = "TEST_SSID";
private static final String HOTSPOT_BSSID = "TEST _BSSID";
private static final int[] HOTSPOT_SECURITY_TYPES = {SECURITY_TYPE_WEP, SECURITY_TYPE_EAP};
+ private static final String BUNDLE_KEY = "INT-KEY";
+ private static final int BUNDLE_VALUE = 1;
private static final long DEVICE_ID_1 = 111L;
private static final NetworkProviderInfo NETWORK_PROVIDER_INFO1 =
@@ -138,6 +141,7 @@
assertThat(network.getHotspotSsid()).isEqualTo(HOTSPOT_SSID);
assertThat(network.getHotspotBssid()).isEqualTo(HOTSPOT_BSSID);
assertThat(network.getHotspotSecurityTypes()).containsExactlyElementsIn(securityTypes);
+ assertThat(network.getExtras().getInt(BUNDLE_KEY)).isEqualTo(BUNDLE_VALUE);
}
@Test
@@ -161,11 +165,18 @@
.setHostNetworkType(NETWORK_TYPE)
.setNetworkName(NETWORK_NAME)
.setHotspotSsid(HOTSPOT_SSID)
- .setHotspotBssid(HOTSPOT_BSSID);
+ .setHotspotBssid(HOTSPOT_BSSID)
+ .setExtras(buildBundle());
Arrays.stream(HOTSPOT_SECURITY_TYPES).forEach(builder::addHotspotSecurityType);
if (withNetworkProviderInfo) {
builder.setNetworkProviderInfo(NETWORK_PROVIDER_INFO);
}
return builder;
}
+
+ private Bundle buildBundle() {
+ Bundle bundle = new Bundle();
+ bundle.putInt(BUNDLE_KEY, BUNDLE_VALUE);
+ return bundle;
+ }
}
diff --git a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/KnownNetworkTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/KnownNetworkTest.java
index 1ecba76..81d7b44 100644
--- a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/KnownNetworkTest.java
+++ b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/KnownNetworkTest.java
@@ -25,6 +25,7 @@
import static com.google.common.truth.Truth.assertThat;
+import android.os.Bundle;
import android.os.Parcel;
import android.util.ArraySet;
@@ -47,6 +48,9 @@
new NetworkProviderInfo.Builder("TEST_NAME", "TEST_MODEL")
.setDeviceType(DEVICE_TYPE_TABLET).setConnectionStrength(2)
.setBatteryPercentage(50).build();
+ private static final String BUNDLE_KEY = "INT-KEY";
+ private static final int BUNDLE_VALUE = 1;
+
private static final int NETWORK_SOURCE_1 = NETWORK_SOURCE_CLOUD_SELF;
private static final String SSID_1 = "TEST_SSID1";
private static final int[] SECURITY_TYPES_1 = {SECURITY_TYPE_PSK};
@@ -113,6 +117,7 @@
assertThat(network.getSsid()).isEqualTo(SSID);
assertThat(network.getSecurityTypes()).containsExactlyElementsIn(securityTypes);
assertThat(network.getNetworkProviderInfo()).isEqualTo(NETWORK_PROVIDER_INFO);
+ assertThat(network.getExtras().getInt(BUNDLE_KEY)).isEqualTo(BUNDLE_VALUE);
}
@Test
@@ -125,8 +130,15 @@
private KnownNetwork.Builder buildKnownNetworkBuilder() {
KnownNetwork.Builder builder = new KnownNetwork.Builder().setNetworkSource(NETWORK_SOURCE)
- .setSsid(SSID).setNetworkProviderInfo(NETWORK_PROVIDER_INFO);
+ .setSsid(SSID).setNetworkProviderInfo(NETWORK_PROVIDER_INFO)
+ .setExtras(buildBundle());
Arrays.stream(SECURITY_TYPES).forEach(builder::addSecurityType);
return builder;
}
+
+ private Bundle buildBundle() {
+ Bundle bundle = new Bundle();
+ bundle.putInt(BUNDLE_KEY, BUNDLE_VALUE);
+ return bundle;
+ }
}
diff --git a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfoTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfoTest.java
index 8f35d8d..4aa9ca6 100644
--- a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfoTest.java
+++ b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfoTest.java
@@ -21,6 +21,7 @@
import static com.google.common.truth.Truth.assertThat;
+import android.os.Bundle;
import android.os.Parcel;
import androidx.test.filters.SmallTest;
@@ -38,6 +39,8 @@
private static final String DEVICE_MODEL = "TEST_MODEL";
private static final int BATTERY_PERCENTAGE = 50;
private static final int CONNECTION_STRENGTH = 2;
+ private static final String BUNDLE_KEY = "INT-KEY";
+ private static final int BUNDLE_VALUE = 1;
private static final int DEVICE_TYPE_1 = DEVICE_TYPE_LAPTOP;
private static final String DEVICE_NAME_1 = "TEST_NAME1";
@@ -105,6 +108,7 @@
assertThat(info.getModelName()).isEqualTo(DEVICE_MODEL);
assertThat(info.getBatteryPercentage()).isEqualTo(BATTERY_PERCENTAGE);
assertThat(info.getConnectionStrength()).isEqualTo(CONNECTION_STRENGTH);
+ assertThat(info.getExtras().getInt(BUNDLE_KEY)).isEqualTo(BUNDLE_VALUE);
}
@Test
@@ -118,6 +122,13 @@
private NetworkProviderInfo.Builder buildNetworkProviderInfoBuilder() {
return new NetworkProviderInfo.Builder(DEVICE_NAME, DEVICE_MODEL).setDeviceType(DEVICE_TYPE)
.setBatteryPercentage(BATTERY_PERCENTAGE)
- .setConnectionStrength(CONNECTION_STRENGTH);
+ .setConnectionStrength(CONNECTION_STRENGTH)
+ .setExtras(buildBundle());
+ }
+
+ private Bundle buildBundle() {
+ Bundle bundle = new Bundle();
+ bundle.putInt(BUNDLE_KEY, BUNDLE_VALUE);
+ return bundle;
}
}