Merge "OP_REQUEST_INSTALL_PACKAGES denied by default" into qt-dev
diff --git a/api/current.txt b/api/current.txt
index bc634c6..535fbbcf 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -44381,9 +44381,9 @@
method public int getCid();
method public int getLac();
method @Deprecated public int getMcc();
- method public String getMccString();
+ method @Nullable public String getMccString();
method @Deprecated public int getMnc();
- method public String getMncString();
+ method @Nullable public String getMncString();
method @Nullable public String getMobileNetworkOperator();
method @Deprecated public int getPsc();
method public void writeToParcel(android.os.Parcel, int);
@@ -44395,9 +44395,9 @@
method public int getCi();
method public int getEarfcn();
method @Deprecated public int getMcc();
- method public String getMccString();
+ method @Nullable public String getMccString();
method @Deprecated public int getMnc();
- method public String getMncString();
+ method @Nullable public String getMncString();
method @Nullable public String getMobileNetworkOperator();
method public int getPci();
method public int getTac();
@@ -44420,8 +44420,8 @@
method public int getCid();
method public int getCpid();
method public int getLac();
- method public String getMccString();
- method public String getMncString();
+ method @Nullable public String getMccString();
+ method @Nullable public String getMncString();
method @Nullable public String getMobileNetworkOperator();
method public int getUarfcn();
method public void writeToParcel(android.os.Parcel, int);
@@ -44432,9 +44432,9 @@
method public int getCid();
method public int getLac();
method @Deprecated public int getMcc();
- method public String getMccString();
+ method @Nullable public String getMccString();
method @Deprecated public int getMnc();
- method public String getMncString();
+ method @Nullable public String getMncString();
method @Nullable public String getMobileNetworkOperator();
method public int getPsc();
method public int getUarfcn();
@@ -44457,22 +44457,22 @@
}
public final class CellInfoCdma extends android.telephony.CellInfo implements android.os.Parcelable {
- method public android.telephony.CellIdentityCdma getCellIdentity();
- method public android.telephony.CellSignalStrengthCdma getCellSignalStrength();
+ method @NonNull public android.telephony.CellIdentityCdma getCellIdentity();
+ method @NonNull public android.telephony.CellSignalStrengthCdma getCellSignalStrength();
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CellInfoCdma> CREATOR;
}
public final class CellInfoGsm extends android.telephony.CellInfo implements android.os.Parcelable {
- method public android.telephony.CellIdentityGsm getCellIdentity();
- method public android.telephony.CellSignalStrengthGsm getCellSignalStrength();
+ method @NonNull public android.telephony.CellIdentityGsm getCellIdentity();
+ method @NonNull public android.telephony.CellSignalStrengthGsm getCellSignalStrength();
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CellInfoGsm> CREATOR;
}
public final class CellInfoLte extends android.telephony.CellInfo implements android.os.Parcelable {
- method public android.telephony.CellIdentityLte getCellIdentity();
- method public android.telephony.CellSignalStrengthLte getCellSignalStrength();
+ method @NonNull public android.telephony.CellIdentityLte getCellIdentity();
+ method @NonNull public android.telephony.CellSignalStrengthLte getCellSignalStrength();
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CellInfoLte> CREATOR;
}
@@ -44508,7 +44508,7 @@
method public abstract boolean equals(Object);
method public abstract int getAsuLevel();
method public abstract int getDbm();
- method public abstract int getLevel();
+ method @IntRange(from=android.telephony.CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN, to=android.telephony.CellSignalStrength.SIGNAL_STRENGTH_GREAT) public abstract int getLevel();
method public abstract int hashCode();
field public static final int SIGNAL_STRENGTH_GOOD = 3; // 0x3
field public static final int SIGNAL_STRENGTH_GREAT = 4; // 0x4
@@ -44528,7 +44528,7 @@
method public int getEvdoEcio();
method public int getEvdoLevel();
method public int getEvdoSnr();
- method public int getLevel();
+ method @IntRange(from=android.telephony.CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN, to=android.telephony.CellSignalStrength.SIGNAL_STRENGTH_GREAT) public int getLevel();
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CellSignalStrengthCdma> CREATOR;
}
@@ -44538,7 +44538,7 @@
method public int getAsuLevel();
method public int getBitErrorRate();
method public int getDbm();
- method public int getLevel();
+ method @IntRange(from=android.telephony.CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN, to=android.telephony.CellSignalStrength.SIGNAL_STRENGTH_GREAT) public int getLevel();
method public int getTimingAdvance();
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CellSignalStrengthGsm> CREATOR;
@@ -44549,7 +44549,7 @@
method public int getAsuLevel();
method public int getCqi();
method public int getDbm();
- method public int getLevel();
+ method @IntRange(from=android.telephony.CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN, to=android.telephony.CellSignalStrength.SIGNAL_STRENGTH_GREAT) public int getLevel();
method public int getRsrp();
method public int getRsrq();
method public int getRssi();
@@ -44566,7 +44566,7 @@
method public int getCsiRsrq();
method public int getCsiSinr();
method public int getDbm();
- method public int getLevel();
+ method @IntRange(from=android.telephony.CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN, to=android.telephony.CellSignalStrength.SIGNAL_STRENGTH_GREAT) public int getLevel();
method public int getSsRsrp();
method public int getSsRsrq();
method public int getSsSinr();
@@ -44578,7 +44578,7 @@
method public int describeContents();
method public int getAsuLevel();
method public int getDbm();
- method public int getLevel();
+ method @IntRange(from=0, to=4) public int getLevel();
method public int getRscp();
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CellSignalStrengthTdscdma> CREATOR;
@@ -44588,7 +44588,7 @@
method public int describeContents();
method public int getAsuLevel();
method public int getDbm();
- method public int getLevel();
+ method @IntRange(from=android.telephony.CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN, to=android.telephony.CellSignalStrength.SIGNAL_STRENGTH_GREAT) public int getLevel();
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CellSignalStrengthWcdma> CREATOR;
}
diff --git a/core/java/android/view/IRecentsAnimationController.aidl b/core/java/android/view/IRecentsAnimationController.aidl
index 597b34bf..956161a 100644
--- a/core/java/android/view/IRecentsAnimationController.aidl
+++ b/core/java/android/view/IRecentsAnimationController.aidl
@@ -41,9 +41,11 @@
* with remote animation targets should be relinquished. If {@param moveHomeToTop} is true, then
* the home activity should be moved to the top. Otherwise, the home activity is hidden and the
* user is returned to the app.
+ * @param sendUserLeaveHint If set to true, {@link Activity#onUserLeaving} will be sent to the
+ * top resumed app, false otherwise.
*/
@UnsupportedAppUsage
- void finish(boolean moveHomeToTop);
+ void finish(boolean moveHomeToTop, boolean sendUserLeaveHint);
/**
* Called by the handler to indicate that the recents animation input consumer should be
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
index d4d0519..e02709e 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
@@ -83,17 +83,18 @@
* as needed.
*/
public class ApplicationsState {
- static final String TAG = "ApplicationsState";
- static final boolean DEBUG = false;
- static final boolean DEBUG_LOCKING = false;
+ private static final String TAG = "ApplicationsState";
public static final int SIZE_UNKNOWN = -1;
public static final int SIZE_INVALID = -2;
- static final Pattern REMOVE_DIACRITICALS_PATTERN
+ private static final boolean DEBUG = false;
+ private static final boolean DEBUG_LOCKING = false;
+ private static final Object sLock = new Object();
+ private static final Pattern REMOVE_DIACRITICALS_PATTERN
= Pattern.compile("\\p{InCombiningDiacriticalMarks}+");
- static final Object sLock = new Object();
+ @VisibleForTesting
static ApplicationsState sInstance;
public static ApplicationsState getInstance(Application app) {
@@ -126,13 +127,12 @@
// Information about all applications. Synchronize on mEntriesMap
// to protect access to these.
- final ArrayList<Session> mSessions = new ArrayList<Session>();
- final ArrayList<Session> mRebuildingSessions = new ArrayList<Session>();
+ final ArrayList<Session> mSessions = new ArrayList<>();
+ final ArrayList<Session> mRebuildingSessions = new ArrayList<>();
private InterestingConfigChanges mInterestingConfigChanges = new InterestingConfigChanges();
// Map: userid => (Map: package name => AppEntry)
- final SparseArray<HashMap<String, AppEntry>> mEntriesMap =
- new SparseArray<HashMap<String, AppEntry>>();
- final ArrayList<AppEntry> mAppEntries = new ArrayList<AppEntry>();
+ final SparseArray<HashMap<String, AppEntry>> mEntriesMap = new SparseArray<>();
+ final ArrayList<AppEntry> mAppEntries = new ArrayList<>();
List<ApplicationInfo> mApplications = new ArrayList<>();
long mCurId = 1;
UUID mCurComputingSizeUuid;
@@ -182,9 +182,10 @@
mInterestingConfigChanges = interestingConfigChanges;
}
- public static final @SessionFlags int DEFAULT_SESSION_FLAGS =
+ @SessionFlags
+ public static final int DEFAULT_SESSION_FLAGS =
FLAG_SESSION_REQUEST_HOME_APP | FLAG_SESSION_REQUEST_ICONS |
- FLAG_SESSION_REQUEST_SIZES | FLAG_SESSION_REQUEST_LAUNCHER;
+ FLAG_SESSION_REQUEST_SIZES | FLAG_SESSION_REQUEST_LAUNCHER;
private ApplicationsState(Application app, IPackageManager iPackageManager) {
mContext = app;
@@ -194,7 +195,7 @@
mUm = mContext.getSystemService(UserManager.class);
mStats = mContext.getSystemService(StorageStatsManager.class);
for (int userId : mUm.getProfileIdsWithDisabled(UserHandle.myUserId())) {
- mEntriesMap.put(userId, new HashMap<String, AppEntry>());
+ mEntriesMap.put(userId, new HashMap<>());
}
mThread = new HandlerThread("ApplicationsState.Loader",
@@ -683,9 +684,16 @@
private AppEntry getEntryLocked(ApplicationInfo info) {
int userId = UserHandle.getUserId(info.uid);
AppEntry entry = mEntriesMap.get(userId).get(info.packageName);
- if (DEBUG) Log.i(TAG, "Looking up entry of pkg " + info.packageName + ": " + entry);
+ if (DEBUG) {
+ Log.i(TAG, "Looking up entry of pkg " + info.packageName + ": " + entry);
+ }
if (entry == null) {
- if (DEBUG) Log.i(TAG, "Creating AppEntry for " + info.packageName);
+ if (mHiddenModules.contains(info.packageName)) {
+ return null;
+ }
+ if (DEBUG) {
+ Log.i(TAG, "Creating AppEntry for " + info.packageName);
+ }
entry = new AppEntry(mContext, info, mCurId++);
mEntriesMap.get(userId).put(info.packageName, entry);
mAppEntries.add(entry);
@@ -759,7 +767,8 @@
boolean mRebuildForeground;
private final boolean mHasLifecycle;
- @SessionFlags private int mFlags = DEFAULT_SESSION_FLAGS;
+ @SessionFlags
+ private int mFlags = DEFAULT_SESSION_FLAGS;
Session(Callbacks callbacks, Lifecycle lifecycle) {
mCallbacks = callbacks;
@@ -771,7 +780,8 @@
}
}
- public @SessionFlags int getSessionFlags() {
+ @SessionFlags
+ public int getSessionFlags() {
return mFlags;
}
@@ -863,25 +873,32 @@
filter.init(mContext);
}
- List<AppEntry> apps;
+ final List<AppEntry> apps;
synchronized (mEntriesMap) {
apps = new ArrayList<>(mAppEntries);
}
- ArrayList<AppEntry> filteredApps = new ArrayList<AppEntry>();
- if (DEBUG) Log.i(TAG, "Rebuilding...");
- for (int i = 0; i < apps.size(); i++) {
- AppEntry entry = apps.get(i);
+ ArrayList<AppEntry> filteredApps = new ArrayList<>();
+ if (DEBUG) {
+ Log.i(TAG, "Rebuilding...");
+ }
+ for (AppEntry entry : apps) {
if (entry != null && (filter == null || filter.filterApp(entry))) {
synchronized (mEntriesMap) {
- if (DEBUG_LOCKING) Log.v(TAG, "rebuild acquired lock");
+ if (DEBUG_LOCKING) {
+ Log.v(TAG, "rebuild acquired lock");
+ }
if (comparator != null) {
// Only need the label if we are going to be sorting.
entry.ensureLabel(mContext);
}
- if (DEBUG) Log.i(TAG, "Using " + entry.info.packageName + ": " + entry);
+ if (DEBUG) {
+ Log.i(TAG, "Using " + entry.info.packageName + ": " + entry);
+ }
filteredApps.add(entry);
- if (DEBUG_LOCKING) Log.v(TAG, "rebuild releasing lock");
+ if (DEBUG_LOCKING) {
+ Log.v(TAG, "rebuild releasing lock");
+ }
}
}
}
@@ -1290,7 +1307,8 @@
}
}
- private @SessionFlags int getCombinedSessionFlags(List<Session> sessions) {
+ @SessionFlags
+ private int getCombinedSessionFlags(List<Session> sessions) {
synchronized (mEntriesMap) {
int flags = 0;
for (Session session : sessions) {
@@ -1601,7 +1619,7 @@
}
if (object1.info != null && object2.info != null) {
compareResult =
- sCollator.compare(object1.info.packageName, object2.info.packageName);
+ sCollator.compare(object1.info.packageName, object2.info.packageName);
if (compareResult != 0) {
return compareResult;
}
diff --git a/packages/SystemUI/res/drawable/ic_sysbar_back.xml b/packages/SystemUI/res/drawable/ic_sysbar_back.xml
index 1448843..ee40262 100644
--- a/packages/SystemUI/res/drawable/ic_sysbar_back.xml
+++ b/packages/SystemUI/res/drawable/ic_sysbar_back.xml
@@ -17,6 +17,7 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="28dp"
android:height="28dp"
+ android:autoMirrored="true"
android:viewportWidth="28"
android:viewportHeight="28">
diff --git a/packages/SystemUI/res/drawable/ic_sysbar_back_quick_step.xml b/packages/SystemUI/res/drawable/ic_sysbar_back_quick_step.xml
index 93b2f9c8..442fafc 100644
--- a/packages/SystemUI/res/drawable/ic_sysbar_back_quick_step.xml
+++ b/packages/SystemUI/res/drawable/ic_sysbar_back_quick_step.xml
@@ -17,6 +17,7 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="28dp"
android:height="28dp"
+ android:autoMirrored="true"
android:viewportWidth="28"
android:viewportHeight="28">
<path
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
index 1d9105c..d2fe5cd 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
@@ -77,9 +77,15 @@
}
}
- public void finish(boolean toHome) {
+ /**
+ * Finish the current recents animation.
+ * @param toHome Going to home or back to the previous app.
+ * @param sendUserLeaveHint determines whether userLeaveHint will be set true to the previous
+ * app.
+ */
+ public void finish(boolean toHome, boolean sendUserLeaveHint) {
try {
- mAnimationController.finish(toHome);
+ mAnimationController.finish(toHome, sendUserLeaveHint);
} catch (RemoteException e) {
Log.e(TAG, "Failed to finish recents animation", e);
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
index 34f3c60..33a2acf 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
@@ -64,6 +64,7 @@
import com.android.systemui.R;
import com.android.systemui.shared.recents.IOverviewProxy;
import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.shared.system.TaskStackChangeListener;
import java.io.PrintWriter;
@@ -339,7 +340,7 @@
}
public void onConnectedToLauncher() {
- if (!ONBOARDING_ENABLED) {
+ if (!ONBOARDING_ENABLED || QuickStepContract.isGesturalMode(mContext)) {
return;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
index 1d87a8b..443cc43 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
@@ -98,8 +98,10 @@
// Short-circuiting from UserManager. Needs to be extracted because of SystemUI boolean flag
// qs_show_user_switcher_for_single_user
+ // The default in UserManager is to show the switcher. We want to not show it unless the
+ // user explicitly requests it in Settings
final boolean userSwitcherEnabled = Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.USER_SWITCHER_ENABLED, 1) != 0;
+ Settings.Global.USER_SWITCHER_ENABLED, 0) != 0;
if (!UserManager.supportsMultipleUsers()
|| mUserManager.hasUserRestriction(UserManager.DISALLOW_USER_SWITCH)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index e2a63cc..544bb95 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -507,9 +507,7 @@
final boolean useAltBack =
(mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0;
final boolean isRtl = mConfiguration.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
- float degrees = useAltBack
- ? (isRtl ? 270 : -90)
- : (isRtl ? 180 : 0);
+ float degrees = useAltBack ? (isRtl ? 90 : -90) : 0;
if (drawable.getRotation() == degrees) {
return;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonDrawable.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonDrawable.java
index 03c89c6..dd0c344 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonDrawable.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonDrawable.java
@@ -37,6 +37,7 @@
import android.graphics.drawable.Drawable;
import android.util.FloatProperty;
import android.view.ContextThemeWrapper;
+import android.view.View;
import com.android.settingslib.Utils;
import com.android.systemui.R;
@@ -79,9 +80,10 @@
private final ShadowDrawableState mState;
private AnimatedVectorDrawable mAnimatedDrawable;
- public KeyButtonDrawable(Drawable d, @ColorInt int lightColor, @ColorInt int darkColor) {
+ public KeyButtonDrawable(Drawable d, @ColorInt int lightColor, @ColorInt int darkColor,
+ boolean horizontalFlip) {
this(d, new ShadowDrawableState(lightColor, darkColor,
- d instanceof AnimatedVectorDrawable));
+ d instanceof AnimatedVectorDrawable, horizontalFlip));
}
private KeyButtonDrawable(Drawable d, ShadowDrawableState state) {
@@ -282,7 +284,12 @@
// Call mutate, so that the pixel allocation by the underlying vector drawable is cleared.
final Drawable d = mState.mChildState.newDrawable().mutate();
setDrawableBounds(d);
+ canvas.save();
+ if (mState.mHorizontalFlip) {
+ canvas.scale(-1f, 1f, width * 0.5f, height * 0.5f);
+ }
d.draw(canvas);
+ canvas.restore();
if (mState.mIsHardwareBitmap) {
bitmap = bitmap.copy(Bitmap.Config.HARDWARE, false);
@@ -305,7 +312,12 @@
// Call mutate, so that the pixel allocation by the underlying vector drawable is cleared.
final Drawable d = mState.mChildState.newDrawable().mutate();
setDrawableBounds(d);
+ canvas.save();
+ if (mState.mHorizontalFlip) {
+ canvas.scale(-1f, 1f, width * 0.5f, height * 0.5f);
+ }
d.draw(canvas);
+ canvas.restore();
// Draws the shadow from original drawable
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
@@ -357,6 +369,7 @@
int mShadowColor;
float mDarkIntensity;
int mAlpha;
+ boolean mHorizontalFlip;
boolean mIsHardwareBitmap;
Bitmap mLastDrawnIcon;
@@ -368,11 +381,12 @@
final boolean mSupportsAnimation;
public ShadowDrawableState(@ColorInt int lightColor, @ColorInt int darkColor,
- boolean animated) {
+ boolean animated, boolean horizontalFlip) {
mLightColor = lightColor;
mDarkColor = darkColor;
mSupportsAnimation = animated;
mAlpha = 255;
+ mHorizontalFlip = horizontalFlip;
}
@Override
@@ -400,7 +414,7 @@
* @return KeyButtonDrawable
*/
public static KeyButtonDrawable create(@NonNull Context ctx, @DrawableRes int icon,
- boolean hasShadow) {
+ boolean hasShadow) {
final int dualToneDarkTheme = Utils.getThemeAttr(ctx, R.attr.darkIconTheme);
final int dualToneLightTheme = Utils.getThemeAttr(ctx, R.attr.lightIconTheme);
Context lightContext = new ContextThemeWrapper(ctx, dualToneLightTheme);
@@ -409,7 +423,7 @@
}
public static KeyButtonDrawable create(Context lightContext, Context darkContext,
- @DrawableRes int iconResId, boolean hasShadow) {
+ @DrawableRes int iconResId, boolean hasShadow) {
return create(lightContext,
Utils.getColorAttrDefaultColor(lightContext, R.attr.singleToneColor),
Utils.getColorAttrDefaultColor(darkContext, R.attr.singleToneColor),
@@ -418,10 +432,12 @@
public static KeyButtonDrawable create(Context context, @ColorInt int lightColor,
@ColorInt int darkColor, @DrawableRes int iconResId, boolean hasShadow) {
- final KeyButtonDrawable drawable = new KeyButtonDrawable(context.getDrawable(iconResId),
- lightColor, darkColor);
+ final Resources res = context.getResources();
+ boolean isRtl = res.getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
+ Drawable d = context.getDrawable(iconResId);
+ final KeyButtonDrawable drawable = new KeyButtonDrawable(d, lightColor, darkColor,
+ isRtl && d.isAutoMirrored());
if (hasShadow) {
- final Resources res = context.getResources();
int offsetX = res.getDimensionPixelSize(R.dimen.nav_key_button_shadow_offset_x);
int offsetY = res.getDimensionPixelSize(R.dimen.nav_key_button_shadow_offset_y);
int radius = res.getDimensionPixelSize(R.dimen.nav_key_button_shadow_radius);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarContextTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarContextTest.java
index e3c081e..c837c9c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarContextTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarContextTest.java
@@ -179,8 +179,10 @@
final int unusedColor = 0;
final Drawable d = mock(Drawable.class);
final ContextualButton button = spy(mBtn0);
- final KeyButtonDrawable kbd1 = spy(new KeyButtonDrawable(d, unusedColor, unusedColor));
- final KeyButtonDrawable kbd2 = spy(new KeyButtonDrawable(d, unusedColor, unusedColor));
+ final KeyButtonDrawable kbd1 = spy(new KeyButtonDrawable(d, unusedColor, unusedColor,
+ false /* horizontalFlip */));
+ final KeyButtonDrawable kbd2 = spy(new KeyButtonDrawable(d, unusedColor, unusedColor,
+ false /* horizontalFlip */));
kbd1.setDarkIntensity(TEST_DARK_INTENSITY);
kbd2.setDarkIntensity(0f);
diff --git a/services/core/java/com/android/server/wm/BoundsAnimationController.java b/services/core/java/com/android/server/wm/BoundsAnimationController.java
index f9980be..c1d872f 100644
--- a/services/core/java/com/android/server/wm/BoundsAnimationController.java
+++ b/services/core/java/com/android/server/wm/BoundsAnimationController.java
@@ -73,6 +73,13 @@
/** Schedule a PiP mode changed callback when this animation ends. */
public static final int SCHEDULE_PIP_MODE_CHANGED_ON_END = 2;
+ public static final int BOUNDS = 0;
+ public static final int FADE_IN = 1;
+
+ @IntDef({BOUNDS, FADE_IN}) public @interface AnimationType {}
+
+ private static final int FADE_IN_DURATION = 500;
+
// Only accessed on UI thread.
private ArrayMap<BoundsAnimationTarget, BoundsAnimator> mRunningAnimations = new ArrayMap<>();
@@ -115,6 +122,7 @@
private boolean mFinishAnimationAfterTransition = false;
private final AnimationHandler mAnimationHandler;
private Choreographer mChoreographer;
+ private @AnimationType int mAnimationType;
private static final int WAIT_FOR_DRAW_TIMEOUT_MS = 3000;
@@ -140,6 +148,7 @@
implements ValueAnimator.AnimatorUpdateListener, ValueAnimator.AnimatorListener {
private final BoundsAnimationTarget mTarget;
+ private final @AnimationType int mAnimationType;
private final Rect mFrom = new Rect();
private final Rect mTo = new Rect();
private final Rect mTmpRect = new Rect();
@@ -166,8 +175,8 @@
// Depending on whether we are animating from
// a smaller to a larger size
- private final int mFrozenTaskWidth;
- private final int mFrozenTaskHeight;
+ private int mFrozenTaskWidth;
+ private int mFrozenTaskHeight;
// Timeout callback to ensure we continue the animation if waiting for resuming or app
// windows drawn fails
@@ -176,12 +185,13 @@
resume();
};
- BoundsAnimator(BoundsAnimationTarget target, Rect from, Rect to,
- @SchedulePipModeChangedState int schedulePipModeChangedState,
+ BoundsAnimator(BoundsAnimationTarget target, @AnimationType int animationType, Rect from,
+ Rect to, @SchedulePipModeChangedState int schedulePipModeChangedState,
@SchedulePipModeChangedState int prevShedulePipModeChangedState,
boolean moveFromFullscreen, boolean moveToFullscreen, Rect frozenTask) {
super();
mTarget = target;
+ mAnimationType = animationType;
mFrom.set(from);
mTo.set(to);
mSchedulePipModeChangedState = schedulePipModeChangedState;
@@ -195,12 +205,14 @@
// to their final size immediately so we can use scaling to make the window
// larger. Likewise if we are going from bigger to smaller, we want to wait until
// the end so we don't have to upscale from the smaller finished size.
- if (animatingToLargerSize()) {
- mFrozenTaskWidth = mTo.width();
- mFrozenTaskHeight = mTo.height();
- } else {
- mFrozenTaskWidth = frozenTask.isEmpty() ? mFrom.width() : frozenTask.width();
- mFrozenTaskHeight = frozenTask.isEmpty() ? mFrom.height() : frozenTask.height();
+ if (mAnimationType == BOUNDS) {
+ if (animatingToLargerSize()) {
+ mFrozenTaskWidth = mTo.width();
+ mFrozenTaskHeight = mTo.height();
+ } else {
+ mFrozenTaskWidth = frozenTask.isEmpty() ? mFrom.width() : frozenTask.width();
+ mFrozenTaskHeight = frozenTask.isEmpty() ? mFrom.height() : frozenTask.height();
+ }
}
}
@@ -222,8 +234,9 @@
// otherwise.
boolean continueAnimation;
if (mPrevSchedulePipModeChangedState == NO_PIP_MODE_CHANGED_CALLBACKS) {
- continueAnimation = mTarget.onAnimationStart(mSchedulePipModeChangedState ==
- SCHEDULE_PIP_MODE_CHANGED_ON_START, false /* forceUpdate */);
+ continueAnimation = mTarget.onAnimationStart(
+ mSchedulePipModeChangedState == SCHEDULE_PIP_MODE_CHANGED_ON_START,
+ false /* forceUpdate */, mAnimationType);
// When starting an animation from fullscreen, pause here and wait for the
// windows-drawn signal before we start the rest of the transition down into PiP.
@@ -238,7 +251,8 @@
// However, we still need to report to them that they are leaving PiP, so this will
// force an update via a mode changed callback.
continueAnimation = mTarget.onAnimationStart(
- true /* schedulePipModeChangedCallback */, true /* forceUpdate */);
+ true /* schedulePipModeChangedCallback */, true /* forceUpdate */,
+ mAnimationType);
} else {
// The animation is already running, but we should check that the TaskStack is still
// valid before continuing with the animation
@@ -285,6 +299,13 @@
@Override
public void onAnimationUpdate(ValueAnimator animation) {
final float value = (Float) animation.getAnimatedValue();
+ if (mAnimationType == FADE_IN) {
+ if (!mTarget.setPinnedStackAlpha(value)) {
+ cancelAndCallAnimationEnd();
+ }
+ return;
+ }
+
final float remains = 1 - value;
mTmpRect.left = (int) (mFrom.left * remains + mTo.left * value + 0.5f);
mTmpRect.top = (int) (mFrom.top * remains + mTo.top * value + 0.5f);
@@ -408,16 +429,29 @@
public void animateBounds(final BoundsAnimationTarget target, Rect from, Rect to,
int animationDuration, @SchedulePipModeChangedState int schedulePipModeChangedState,
- boolean moveFromFullscreen, boolean moveToFullscreen) {
+ boolean moveFromFullscreen, boolean moveToFullscreen,
+ @AnimationType int animationType) {
animateBoundsImpl(target, from, to, animationDuration, schedulePipModeChangedState,
- moveFromFullscreen, moveToFullscreen);
+ moveFromFullscreen, moveToFullscreen, animationType);
}
@VisibleForTesting
BoundsAnimator animateBoundsImpl(final BoundsAnimationTarget target, Rect from, Rect to,
int animationDuration, @SchedulePipModeChangedState int schedulePipModeChangedState,
- boolean moveFromFullscreen, boolean moveToFullscreen) {
+ boolean moveFromFullscreen, boolean moveToFullscreen,
+ @AnimationType int animationType) {
final BoundsAnimator existing = mRunningAnimations.get(target);
+ // animateBoundsImpl gets called twice for each animation. The second time we get the final
+ // to rect that respects the shelf, which is when we want to resize. Our signal for fade in
+ // comes in from how to enter into pip, but we also need to use the to and from rect to
+ // decide which animation we want to run finally.
+ boolean shouldResize = false;
+ if (isRunningFadeInAnimation(target)) {
+ shouldResize = true;
+ if (from.contains(to)) {
+ animationType = FADE_IN;
+ }
+ }
final boolean replacing = existing != null;
@SchedulePipModeChangedState int prevSchedulePipModeChangedState =
NO_PIP_MODE_CHANGED_CALLBACKS;
@@ -477,18 +511,34 @@
// Since we are replacing, we skip both animation start and end callbacks
existing.cancel();
}
- final BoundsAnimator animator = new BoundsAnimator(target, from, to,
+ if (shouldResize) {
+ target.setPinnedStackSize(to, null);
+ }
+ final BoundsAnimator animator = new BoundsAnimator(target, animationType, from, to,
schedulePipModeChangedState, prevSchedulePipModeChangedState,
moveFromFullscreen, moveToFullscreen, frozenTask);
mRunningAnimations.put(target, animator);
animator.setFloatValues(0f, 1f);
- animator.setDuration((animationDuration != -1 ? animationDuration
- : DEFAULT_TRANSITION_DURATION) * DEBUG_ANIMATION_SLOW_DOWN_FACTOR);
+ animator.setDuration(animationType == FADE_IN ? FADE_IN_DURATION
+ : (animationDuration != -1 ? animationDuration : DEFAULT_TRANSITION_DURATION)
+ * DEBUG_ANIMATION_SLOW_DOWN_FACTOR);
animator.setInterpolator(mFastOutSlowInInterpolator);
animator.start();
return animator;
}
+ public void setAnimationType(@AnimationType int animationType) {
+ mAnimationType = animationType;
+ }
+
+ /** return the current animation type. */
+ public @AnimationType int getAnimationType() {
+ @AnimationType int animationType = mAnimationType;
+ // Default to BOUNDS.
+ mAnimationType = BOUNDS;
+ return animationType;
+ }
+
public Handler getHandler() {
return mHandler;
}
@@ -498,6 +548,11 @@
mHandler.post(this::resume);
}
+ private boolean isRunningFadeInAnimation(final BoundsAnimationTarget target) {
+ final BoundsAnimator existing = mRunningAnimations.get(target);
+ return existing != null && existing.mAnimationType == FADE_IN && existing.isStarted();
+ }
+
private void resume() {
for (int i = 0; i < mRunningAnimations.size(); i++) {
final BoundsAnimator b = mRunningAnimations.valueAt(i);
diff --git a/services/core/java/com/android/server/wm/BoundsAnimationTarget.java b/services/core/java/com/android/server/wm/BoundsAnimationTarget.java
index 5cb80de..9f54e49e0 100644
--- a/services/core/java/com/android/server/wm/BoundsAnimationTarget.java
+++ b/services/core/java/com/android/server/wm/BoundsAnimationTarget.java
@@ -32,7 +32,8 @@
* callbacks
* @return whether to continue the animation
*/
- boolean onAnimationStart(boolean schedulePipModeChangedCallback, boolean forceUpdate);
+ boolean onAnimationStart(boolean schedulePipModeChangedCallback, boolean forceUpdate,
+ @BoundsAnimationController.AnimationType int animationType);
/**
* @return Whether the animation should be paused waiting for the windows to draw before
@@ -53,6 +54,9 @@
*/
boolean setPinnedStackSize(Rect stackBounds, Rect taskBounds);
+ /** Sets the alpha of the animation target */
+ boolean setPinnedStackAlpha(float alpha);
+
/**
* Callback for the target to inform it that the animation has ended, so it can do some
* necessary cleanup.
diff --git a/services/core/java/com/android/server/wm/RecentsAnimation.java b/services/core/java/com/android/server/wm/RecentsAnimation.java
index 144efb4..07d3fb9 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimation.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimation.java
@@ -26,6 +26,8 @@
import static android.view.WindowManager.TRANSIT_NONE;
import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
+import static com.android.server.wm.BoundsAnimationController.BOUNDS;
+import static com.android.server.wm.BoundsAnimationController.FADE_IN;
import static com.android.server.wm.RecentsAnimationController.REORDER_KEEP_IN_PLACE;
import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_TO_ORIGINAL_POSITION;
import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_TO_TOP;
@@ -201,7 +203,8 @@
}
}
- private void finishAnimation(@RecentsAnimationController.ReorderMode int reorderMode) {
+ private void finishAnimation(@RecentsAnimationController.ReorderMode int reorderMode,
+ boolean sendUserLeaveHint) {
synchronized (mService.mGlobalLock) {
if (DEBUG) Slog.d(TAG, "onAnimationFinished(): controller="
+ mWindowManager.getRecentsAnimationController()
@@ -246,7 +249,18 @@
if (reorderMode == REORDER_MOVE_TO_TOP) {
// Bring the target stack to the front
mStackSupervisor.mNoAnimActivities.add(targetActivity);
- targetStack.moveToFront("RecentsAnimation.onAnimationFinished()");
+
+ if (sendUserLeaveHint) {
+ // Setting this allows the previous app to PiP.
+ mStackSupervisor.mUserLeaving = true;
+ targetStack.moveTaskToFrontLocked(targetActivity.getTaskRecord(),
+ true /* noAnimation */, null /* activityOptions */,
+ targetActivity.appTimeTracker,
+ "RecentsAnimation.onAnimationFinished()");
+ } else {
+ targetStack.moveToFront("RecentsAnimation.onAnimationFinished()");
+ }
+
if (DEBUG) {
final ActivityStack topStack = getTopNonAlwaysOnTopStack();
if (topStack != targetStack) {
@@ -300,11 +314,11 @@
@Override
public void onAnimationFinished(@RecentsAnimationController.ReorderMode int reorderMode,
- boolean runSychronously) {
+ boolean runSychronously, boolean sendUserLeaveHint) {
if (runSychronously) {
- finishAnimation(reorderMode);
+ finishAnimation(reorderMode, sendUserLeaveHint);
} else {
- mService.mH.post(() -> finishAnimation(reorderMode));
+ mService.mH.post(() -> finishAnimation(reorderMode, sendUserLeaveHint));
}
}
@@ -317,6 +331,10 @@
}
final RecentsAnimationController controller =
mWindowManager.getRecentsAnimationController();
+ final DisplayContent dc =
+ mService.mRootActivityContainer.getDefaultDisplay().mDisplayContent;
+ dc.mBoundsAnimationController.setAnimationType(
+ controller.shouldCancelWithDeferredScreenshot() ? FADE_IN : BOUNDS);
// Cancel running recents animation and screenshot previous task when the next
// transition starts in below cases:
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index 3813669..d2c510f 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -27,6 +27,7 @@
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_RECENTS_ANIM;
import static com.android.server.wm.AnimationAdapterProto.REMOTE;
+import static com.android.server.wm.BoundsAnimationController.FADE_IN;
import static com.android.server.wm.RemoteAnimationAdapterWrapperProto.TARGET;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_RECENTS_ANIMATIONS;
import static com.android.server.wm.WindowManagerInternal.AppTransitionListener;
@@ -142,7 +143,9 @@
};
public interface RecentsAnimationCallbacks {
- void onAnimationFinished(@ReorderMode int reorderMode, boolean runSychronously);
+ /** Callback when recents animation is finished. */
+ void onAnimationFinished(@ReorderMode int reorderMode, boolean runSychronously,
+ boolean sendUserLeaveHint);
}
private final IRecentsAnimationController mController =
@@ -179,7 +182,7 @@
}
@Override
- public void finish(boolean moveHomeToTop) {
+ public void finish(boolean moveHomeToTop, boolean sendUserLeaveHint) {
if (DEBUG_RECENTS_ANIMATIONS) Slog.d(TAG, "finish(" + moveHomeToTop + "):"
+ " mCanceled=" + mCanceled);
final long token = Binder.clearCallingIdentity();
@@ -195,7 +198,9 @@
mCallbacks.onAnimationFinished(moveHomeToTop
? REORDER_MOVE_TO_TOP
: REORDER_MOVE_TO_ORIGINAL_POSITION,
- true /* runSynchronously */);
+ true /* runSynchronously */, sendUserLeaveHint);
+ final DisplayContent dc = mService.mRoot.getDisplayContent(mDisplayId);
+ dc.mBoundsAnimationController.setAnimationType(FADE_IN);
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -497,7 +502,8 @@
Slog.e(TAG, "Failed to cancel recents animation", e);
}
// Clean up and return to the previous app
- mCallbacks.onAnimationFinished(reorderMode, runSynchronously);
+ mCallbacks.onAnimationFinished(reorderMode, runSynchronously,
+ false /* sendUserLeaveHint */);
}
}
@@ -542,7 +548,8 @@
if (DEBUG_RECENTS_ANIMATIONS) {
Slog.d(TAG, "mRecentScreenshotAnimator finish");
}
- mCallbacks.onAnimationFinished(reorderMode, runSynchronously);
+ mCallbacks.onAnimationFinished(reorderMode, runSynchronously,
+ false /* sendUserLeaveHint */);
}, mService);
mRecentScreenshotAnimator.transferAnimation(task.mSurfaceAnimator);
}
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 09baf8c..bdb4d04 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -34,6 +34,7 @@
import static android.view.WindowManager.DOCKED_RIGHT;
import static android.view.WindowManager.DOCKED_TOP;
+import static com.android.server.wm.BoundsAnimationController.FADE_IN;
import static com.android.server.wm.BoundsAnimationController.NO_PIP_MODE_CHANGED_CALLBACKS;
import static com.android.server.wm.BoundsAnimationController.SCHEDULE_PIP_MODE_CHANGED_ON_END;
import static com.android.server.wm.BoundsAnimationController.SCHEDULE_PIP_MODE_CHANGED_ON_START;
@@ -148,6 +149,7 @@
private boolean mCancelCurrentBoundsAnimation = false;
private Rect mBoundsAnimationTarget = new Rect();
private Rect mBoundsAnimationSourceHintBounds = new Rect();
+ private @BoundsAnimationController.AnimationType int mAnimationType;
Rect mPreAnimationBounds = new Rect();
@@ -1572,7 +1574,8 @@
}
@Override // AnimatesBounds
- public boolean onAnimationStart(boolean schedulePipModeChangedCallback, boolean forceUpdate) {
+ public boolean onAnimationStart(boolean schedulePipModeChangedCallback, boolean forceUpdate,
+ @BoundsAnimationController.AnimationType int animationType) {
// Hold the lock since this is called from the BoundsAnimator running on the UiThread
synchronized (mWmService.mGlobalLock) {
if (!isAttached()) {
@@ -1583,6 +1586,7 @@
mBoundsAnimatingRequested = false;
mBoundsAnimating = true;
mCancelCurrentBoundsAnimation = false;
+ mAnimationType = animationType;
// If we are changing UI mode, as in the PiP to fullscreen
// transition, then we need to wait for the window to draw.
@@ -1599,7 +1603,8 @@
// I don't believe you...
}
- if (schedulePipModeChangedCallback && mActivityStack != null) {
+ if ((schedulePipModeChangedCallback || animationType == FADE_IN)
+ && mActivityStack != null) {
// We need to schedule the PiP mode change before the animation up. It is possible
// in this case for the animation down to not have been completed, so always
// force-schedule and update to the client to ensure that it is notified that it
@@ -1614,6 +1619,21 @@
@Override // AnimatesBounds
public void onAnimationEnd(boolean schedulePipModeChangedCallback, Rect finalStackSize,
boolean moveToFullscreen) {
+ if (mAnimationType == BoundsAnimationController.FADE_IN) {
+ setPinnedStackAlpha(1f);
+ try {
+ mWmService.mActivityTaskManager.notifyPinnedStackAnimationEnded();
+ } catch (RemoteException e) {
+ // I don't believe you...
+ }
+ return;
+ }
+
+ onBoundAnimationEnd(schedulePipModeChangedCallback, finalStackSize, moveToFullscreen);
+ }
+
+ private void onBoundAnimationEnd(boolean schedulePipModeChangedCallback, Rect finalStackSize,
+ boolean moveToFullscreen) {
if (inPinnedWindowingMode()) {
// Update to the final bounds if requested. This is done here instead of in the bounds
// animator to allow us to coordinate this after we notify the PiP mode changed
@@ -1725,10 +1745,23 @@
final @SchedulePipModeChangedState int finalSchedulePipModeChangedState =
schedulePipModeChangedState;
final DisplayContent displayContent = getDisplayContent();
+ @BoundsAnimationController.AnimationType int intendedAnimationType =
+ displayContent.mBoundsAnimationController.getAnimationType();
+ if (intendedAnimationType == FADE_IN) {
+ if (fromFullscreen) {
+ setPinnedStackAlpha(0f);
+ }
+ if (toBounds.width() == fromBounds.width()
+ && toBounds.height() == fromBounds.height()) {
+ intendedAnimationType = BoundsAnimationController.BOUNDS;
+ }
+ }
+
+ final @BoundsAnimationController.AnimationType int animationType = intendedAnimationType;
displayContent.mBoundsAnimationController.getHandler().post(() -> {
displayContent.mBoundsAnimationController.animateBounds(this, fromBounds,
finalToBounds, animationDuration, finalSchedulePipModeChangedState,
- fromFullscreen, toFullscreen);
+ fromFullscreen, toFullscreen, animationType);
});
}
@@ -1905,6 +1938,20 @@
}
}
+ @Override
+ public boolean setPinnedStackAlpha(float alpha) {
+ // Hold the lock since this is called from the BoundsAnimator running on the UiThread
+ synchronized (mWmService.mGlobalLock) {
+ if (mCancelCurrentBoundsAnimation) {
+ return false;
+ }
+ getPendingTransaction().setAlpha(getSurfaceControl(), alpha);
+ scheduleAnimation();
+ }
+
+ return true;
+ }
+
public DisplayInfo getDisplayInfo() {
return mDisplayContent.getDisplayInfo();
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/BoundsAnimationControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/BoundsAnimationControllerTests.java
index 9ce5795..beec1a8 100644
--- a/services/tests/wmtests/src/com/android/server/wm/BoundsAnimationControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/BoundsAnimationControllerTests.java
@@ -18,6 +18,8 @@
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+import static com.android.server.wm.BoundsAnimationController.BOUNDS;
+import static com.android.server.wm.BoundsAnimationController.FADE_IN;
import static com.android.server.wm.BoundsAnimationController.NO_PIP_MODE_CHANGED_CALLBACKS;
import static com.android.server.wm.BoundsAnimationController.SCHEDULE_PIP_MODE_CHANGED_ON_END;
import static com.android.server.wm.BoundsAnimationController.SCHEDULE_PIP_MODE_CHANGED_ON_START;
@@ -131,6 +133,8 @@
boolean mCancelRequested;
Rect mStackBounds;
Rect mTaskBounds;
+ float mAlpha;
+ @BoundsAnimationController.AnimationType int mAnimationType;
void initialize(Rect from) {
mAwaitingAnimationStart = true;
@@ -148,11 +152,12 @@
@Override
public boolean onAnimationStart(boolean schedulePipModeChangedCallback,
- boolean forceUpdate) {
+ boolean forceUpdate, @BoundsAnimationController.AnimationType int animationType) {
mAwaitingAnimationStart = false;
mAnimationStarted = true;
mSchedulePipModeChangedOnStart = schedulePipModeChangedCallback;
mForcePipModeChangedCallback = forceUpdate;
+ mAnimationType = animationType;
return true;
}
@@ -185,6 +190,12 @@
mMovedToFullscreen = moveToFullscreen;
mTaskBounds = null;
}
+
+ @Override
+ public boolean setPinnedStackAlpha(float alpha) {
+ mAlpha = alpha;
+ return true;
+ }
}
/**
@@ -201,6 +212,7 @@
private Rect mTo;
private Rect mLargerBounds;
private Rect mExpectedFinalBounds;
+ private @BoundsAnimationController.AnimationType int mAnimationType;
BoundsAnimationDriver(BoundsAnimationController controller,
TestBoundsAnimationTarget target, MockValueAnimator mockValueAnimator) {
@@ -209,7 +221,8 @@
mMockAnimator = mockValueAnimator;
}
- BoundsAnimationDriver start(Rect from, Rect to) {
+ BoundsAnimationDriver start(Rect from, Rect to,
+ @BoundsAnimationController.AnimationType int animationType) {
if (mAnimator != null) {
throw new IllegalArgumentException("Call restart() to restart an animation");
}
@@ -223,7 +236,7 @@
assertTrue(mTarget.mAwaitingAnimationStart);
assertFalse(mTarget.mAnimationStarted);
- startImpl(from, to);
+ startImpl(from, to, animationType);
// Ensure that the animator is paused for the all windows drawn signal when animating
// to/from fullscreen
@@ -253,7 +266,7 @@
mTarget.mAnimationStarted = false;
// Start animation
- startImpl(mTarget.mStackBounds, to);
+ startImpl(mTarget.mStackBounds, to, BOUNDS);
if (toSameBounds) {
// Same animator if same final bounds
@@ -273,13 +286,15 @@
return this;
}
- private BoundsAnimationDriver startImpl(Rect from, Rect to) {
+ private BoundsAnimationDriver startImpl(Rect from, Rect to,
+ @BoundsAnimationController.AnimationType int animationType) {
boolean fromFullscreen = from.equals(BOUNDS_FULL);
boolean toFullscreen = to.equals(BOUNDS_FULL);
mFrom = new Rect(from);
mTo = new Rect(to);
mExpectedFinalBounds = new Rect(to);
mLargerBounds = getLargerBounds(mFrom, mTo);
+ mAnimationType = animationType;
// Start animation
final @SchedulePipModeChangedState int schedulePipModeChangedState = toFullscreen
@@ -288,17 +303,19 @@
? SCHEDULE_PIP_MODE_CHANGED_ON_END
: NO_PIP_MODE_CHANGED_CALLBACKS;
mAnimator = mController.animateBoundsImpl(mTarget, from, to, DURATION,
- schedulePipModeChangedState, fromFullscreen, toFullscreen);
+ schedulePipModeChangedState, fromFullscreen, toFullscreen, animationType);
- // Original stack bounds, frozen task bounds
- assertEquals(mFrom, mTarget.mStackBounds);
- assertEqualSizeAtOffset(mLargerBounds, mTarget.mTaskBounds);
+ if (animationType == BOUNDS) {
+ // Original stack bounds, frozen task bounds
+ assertEquals(mFrom, mTarget.mStackBounds);
+ assertEqualSizeAtOffset(mLargerBounds, mTarget.mTaskBounds);
- // Animating to larger size
- if (mFrom.equals(mLargerBounds)) {
- assertFalse(mAnimator.animatingToLargerSize());
- } else if (mTo.equals(mLargerBounds)) {
- assertTrue(mAnimator.animatingToLargerSize());
+ // Animating to larger size
+ if (mFrom.equals(mLargerBounds)) {
+ assertFalse(mAnimator.animatingToLargerSize());
+ } else if (mTo.equals(mLargerBounds)) {
+ assertTrue(mAnimator.animatingToLargerSize());
+ }
}
return this;
@@ -315,16 +332,20 @@
BoundsAnimationDriver update(float t) {
mAnimator.onAnimationUpdate(mMockAnimator.getWithValue(t));
- // Temporary stack bounds, frozen task bounds
- if (t == 0f) {
- assertEquals(mFrom, mTarget.mStackBounds);
- } else if (t == 1f) {
- assertEquals(mTo, mTarget.mStackBounds);
+ if (mAnimationType == BOUNDS) {
+ // Temporary stack bounds, frozen task bounds
+ if (t == 0f) {
+ assertEquals(mFrom, mTarget.mStackBounds);
+ } else if (t == 1f) {
+ assertEquals(mTo, mTarget.mStackBounds);
+ } else {
+ assertNotEquals(mFrom, mTarget.mStackBounds);
+ assertNotEquals(mTo, mTarget.mStackBounds);
+ }
+ assertEqualSizeAtOffset(mLargerBounds, mTarget.mTaskBounds);
} else {
- assertNotEquals(mFrom, mTarget.mStackBounds);
- assertNotEquals(mTo, mTarget.mStackBounds);
+ assertEquals((float) mMockAnimator.getAnimatedValue(), mTarget.mAlpha, 0.01f);
}
- assertEqualSizeAtOffset(mLargerBounds, mTarget.mTaskBounds);
return this;
}
@@ -353,10 +374,14 @@
BoundsAnimationDriver end() {
mAnimator.end();
- // Final stack bounds
- assertEquals(mTo, mTarget.mStackBounds);
- assertEquals(mExpectedFinalBounds, mTarget.mAnimationEndFinalStackBounds);
- assertNull(mTarget.mTaskBounds);
+ if (mAnimationType == BOUNDS) {
+ // Final stack bounds
+ assertEquals(mTo, mTarget.mStackBounds);
+ assertEquals(mExpectedFinalBounds, mTarget.mAnimationEndFinalStackBounds);
+ assertNull(mTarget.mTaskBounds);
+ } else {
+ assertEquals(mTarget.mAlpha, 1f, 0.01f);
+ }
return this;
}
@@ -413,7 +438,7 @@
@UiThreadTest
@Test
public void testFullscreenToFloatingTransition() {
- mDriver.start(BOUNDS_FULL, BOUNDS_FLOATING)
+ mDriver.start(BOUNDS_FULL, BOUNDS_FLOATING, BOUNDS)
.expectStarted(!SCHEDULE_PIP_MODE_CHANGED)
.update(0f)
.update(0.5f)
@@ -425,7 +450,7 @@
@UiThreadTest
@Test
public void testFloatingToFullscreenTransition() {
- mDriver.start(BOUNDS_FLOATING, BOUNDS_FULL)
+ mDriver.start(BOUNDS_FLOATING, BOUNDS_FULL, BOUNDS)
.expectStarted(SCHEDULE_PIP_MODE_CHANGED)
.update(0f)
.update(0.5f)
@@ -437,7 +462,7 @@
@UiThreadTest
@Test
public void testFloatingToSmallerFloatingTransition() {
- mDriver.start(BOUNDS_FLOATING, BOUNDS_SMALLER_FLOATING)
+ mDriver.start(BOUNDS_FLOATING, BOUNDS_SMALLER_FLOATING, BOUNDS)
.expectStarted(!SCHEDULE_PIP_MODE_CHANGED)
.update(0f)
.update(0.5f)
@@ -449,7 +474,7 @@
@UiThreadTest
@Test
public void testFloatingToLargerFloatingTransition() {
- mDriver.start(BOUNDS_SMALLER_FLOATING, BOUNDS_FLOATING)
+ mDriver.start(BOUNDS_SMALLER_FLOATING, BOUNDS_FLOATING, BOUNDS)
.expectStarted(!SCHEDULE_PIP_MODE_CHANGED)
.update(0f)
.update(0.5f)
@@ -463,7 +488,7 @@
@UiThreadTest
@Test
public void testFullscreenToFloatingCancelFromTarget() {
- mDriver.start(BOUNDS_FULL, BOUNDS_FLOATING)
+ mDriver.start(BOUNDS_FULL, BOUNDS_FLOATING, BOUNDS)
.expectStarted(!SCHEDULE_PIP_MODE_CHANGED)
.update(0.25f)
.cancel()
@@ -473,7 +498,7 @@
@UiThreadTest
@Test
public void testFullscreenToFloatingCancelFromAnimationToSameBounds() {
- mDriver.start(BOUNDS_FULL, BOUNDS_FLOATING)
+ mDriver.start(BOUNDS_FULL, BOUNDS_FLOATING, BOUNDS)
.expectStarted(!SCHEDULE_PIP_MODE_CHANGED)
.update(0.25f)
.restart(BOUNDS_FLOATING, false /* expectStartedAndPipModeChangedCallback */)
@@ -484,7 +509,7 @@
@UiThreadTest
@Test
public void testFullscreenToFloatingCancelFromAnimationToFloatingBounds() {
- mDriver.start(BOUNDS_FULL, BOUNDS_FLOATING)
+ mDriver.start(BOUNDS_FULL, BOUNDS_FLOATING, BOUNDS)
.expectStarted(!SCHEDULE_PIP_MODE_CHANGED)
.update(0.25f)
.restart(BOUNDS_SMALLER_FLOATING,
@@ -498,7 +523,7 @@
public void testFullscreenToFloatingCancelFromAnimationToFullscreenBounds() {
// When animating from fullscreen and the animation is interruped, we expect the animation
// start callback to be made, with a forced pip mode change callback
- mDriver.start(BOUNDS_FULL, BOUNDS_FLOATING)
+ mDriver.start(BOUNDS_FULL, BOUNDS_FLOATING, BOUNDS)
.expectStarted(!SCHEDULE_PIP_MODE_CHANGED)
.update(0.25f)
.restart(BOUNDS_FULL, true /* expectStartedAndPipModeChangedCallback */)
@@ -511,7 +536,7 @@
@UiThreadTest
@Test
public void testFloatingToFullscreenCancelFromTarget() {
- mDriver.start(BOUNDS_FLOATING, BOUNDS_FULL)
+ mDriver.start(BOUNDS_FLOATING, BOUNDS_FULL, BOUNDS)
.expectStarted(SCHEDULE_PIP_MODE_CHANGED)
.update(0.25f)
.cancel()
@@ -521,7 +546,7 @@
@UiThreadTest
@Test
public void testFloatingToFullscreenCancelFromAnimationToSameBounds() {
- mDriver.start(BOUNDS_FLOATING, BOUNDS_FULL)
+ mDriver.start(BOUNDS_FLOATING, BOUNDS_FULL, BOUNDS)
.expectStarted(SCHEDULE_PIP_MODE_CHANGED)
.update(0.25f)
.restart(BOUNDS_FULL, false /* expectStartedAndPipModeChangedCallback */)
@@ -532,7 +557,7 @@
@UiThreadTest
@Test
public void testFloatingToFullscreenCancelFromAnimationToFloatingBounds() {
- mDriver.start(BOUNDS_FLOATING, BOUNDS_FULL)
+ mDriver.start(BOUNDS_FLOATING, BOUNDS_FULL, BOUNDS)
.expectStarted(SCHEDULE_PIP_MODE_CHANGED)
.update(0.25f)
.restart(BOUNDS_SMALLER_FLOATING,
@@ -546,7 +571,7 @@
@UiThreadTest
@Test
public void testFloatingToSmallerFloatingCancelFromTarget() {
- mDriver.start(BOUNDS_FLOATING, BOUNDS_SMALLER_FLOATING)
+ mDriver.start(BOUNDS_FLOATING, BOUNDS_SMALLER_FLOATING, BOUNDS)
.expectStarted(!SCHEDULE_PIP_MODE_CHANGED)
.update(0.25f)
.cancel()
@@ -556,13 +581,25 @@
@UiThreadTest
@Test
public void testFloatingToLargerFloatingCancelFromTarget() {
- mDriver.start(BOUNDS_SMALLER_FLOATING, BOUNDS_FLOATING)
+ mDriver.start(BOUNDS_SMALLER_FLOATING, BOUNDS_FLOATING, BOUNDS)
.expectStarted(!SCHEDULE_PIP_MODE_CHANGED)
.update(0.25f)
.cancel()
.expectEnded(!SCHEDULE_PIP_MODE_CHANGED, !MOVE_TO_FULLSCREEN);
}
+ @UiThreadTest
+ @Test
+ public void testFadeIn() {
+ mDriver.start(BOUNDS_FULL, BOUNDS_FLOATING, FADE_IN)
+ .expectStarted(!SCHEDULE_PIP_MODE_CHANGED)
+ .update(0f)
+ .update(0.5f)
+ .update(1f)
+ .end()
+ .expectEnded(SCHEDULE_PIP_MODE_CHANGED, !MOVE_TO_FULLSCREEN);
+ }
+
/** MISC **/
@UiThreadTest
@@ -570,7 +607,7 @@
public void testBoundsAreCopied() {
Rect from = new Rect(0, 0, 100, 100);
Rect to = new Rect(25, 25, 75, 75);
- mDriver.start(from, to)
+ mDriver.start(from, to, BOUNDS)
.update(0.25f)
.end();
assertEquals(new Rect(0, 0, 100, 100), from);
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
index e392353..0c2ce61 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
@@ -163,7 +163,7 @@
// Assume IRecentsAnimationController#cleanupScreenshot called to finish screenshot
// animation.
mController.mRecentScreenshotAnimator.cancelAnimation();
- verify(mAnimationCallbacks).onAnimationFinished(REORDER_KEEP_IN_PLACE, true);
+ verify(mAnimationCallbacks).onAnimationFinished(REORDER_KEEP_IN_PLACE, true, false);
}
private static void verifyNoMoreInteractionsExceptAsBinder(IInterface binder) {
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
index 5625ea4..f615823 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
@@ -71,6 +71,7 @@
@Test
public void testCancelAnimationOnVisibleStackOrderChange() {
ActivityDisplay display = mService.mRootActivityContainer.getDefaultDisplay();
+ display.mDisplayContent.mBoundsAnimationController = mock(BoundsAnimationController.class);
ActivityStack fullscreenStack = display.createStack(WINDOWING_MODE_FULLSCREEN,
ACTIVITY_TYPE_STANDARD, true /* onTop */);
new ActivityBuilder(mService)
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 0f8f873..970bbf8 100755
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -2803,6 +2803,19 @@
public static final String KEY_IS_OPPORTUNISTIC_SUBSCRIPTION_BOOL =
"key_is_opportunistic_subscription_bool";
+ /**
+ * A list of 4 GSM RSSI thresholds above which a signal level is considered POOR,
+ * MODERATE, GOOD, or EXCELLENT, to be used in SignalStrength reporting.
+ *
+ * Note that the min and max thresholds are fixed at -113 and -51, as set in 3GPP TS 27.007
+ * section 8.5.
+ * <p>
+ * See CellSignalStrengthGsm#GSM_RSSI_MAX and CellSignalStrengthGsm#GSM_RSSI_MIN. Any signal
+ * level outside these boundaries is considered invalid.
+ * @hide
+ */
+ public static final String KEY_GSM_RSSI_THRESHOLDS_INT_ARRAY =
+ "gsm_rssi_thresholds_int_array";
/** The default value for every variable. */
private final static PersistableBundle sDefaults;
@@ -3204,6 +3217,13 @@
false);
sDefaults.putString(KEY_SUBSCRIPTION_GROUP_UUID_STRING, "");
sDefaults.putBoolean(KEY_IS_OPPORTUNISTIC_SUBSCRIPTION_BOOL, false);
+ sDefaults.putIntArray(KEY_GSM_RSSI_THRESHOLDS_INT_ARRAY,
+ new int[] {
+ -107, /* SIGNAL_STRENGTH_POOR */
+ -103, /* SIGNAL_STRENGTH_MODERATE */
+ -97, /* SIGNAL_STRENGTH_GOOD */
+ -89, /* SIGNAL_STRENGTH_GREAT */
+ });
}
/**
diff --git a/telephony/java/android/telephony/CellIdentityGsm.java b/telephony/java/android/telephony/CellIdentityGsm.java
index 5e44bf2..864540d 100644
--- a/telephony/java/android/telephony/CellIdentityGsm.java
+++ b/telephony/java/android/telephony/CellIdentityGsm.java
@@ -166,6 +166,7 @@
/**
* @return Mobile Country Code in string format, null if unavailable.
*/
+ @Nullable
public String getMccString() {
return mMccStr;
}
@@ -173,6 +174,7 @@
/**
* @return Mobile Network Code in string format, null if unavailable.
*/
+ @Nullable
public String getMncString() {
return mMncStr;
}
diff --git a/telephony/java/android/telephony/CellIdentityLte.java b/telephony/java/android/telephony/CellIdentityLte.java
index 2dd72d6..14503c7 100644
--- a/telephony/java/android/telephony/CellIdentityLte.java
+++ b/telephony/java/android/telephony/CellIdentityLte.java
@@ -187,6 +187,7 @@
/**
* @return Mobile Country Code in string format, null if unavailable.
*/
+ @Nullable
public String getMccString() {
return mMccStr;
}
@@ -194,6 +195,7 @@
/**
* @return Mobile Network Code in string format, null if unavailable.
*/
+ @Nullable
public String getMncString() {
return mMncStr;
}
diff --git a/telephony/java/android/telephony/CellIdentityTdscdma.java b/telephony/java/android/telephony/CellIdentityTdscdma.java
index a591bd1..937de70 100644
--- a/telephony/java/android/telephony/CellIdentityTdscdma.java
+++ b/telephony/java/android/telephony/CellIdentityTdscdma.java
@@ -104,6 +104,7 @@
* Get Mobile Country Code in string format
* @return Mobile Country Code in string format, null if unknown
*/
+ @Nullable
public String getMccString() {
return mMccStr;
}
@@ -112,6 +113,7 @@
* Get Mobile Network Code in string format
* @return Mobile Network Code in string format, null if unknown
*/
+ @Nullable
public String getMncString() {
return mMncStr;
}
diff --git a/telephony/java/android/telephony/CellIdentityWcdma.java b/telephony/java/android/telephony/CellIdentityWcdma.java
index 674c40c..b4a2ead 100644
--- a/telephony/java/android/telephony/CellIdentityWcdma.java
+++ b/telephony/java/android/telephony/CellIdentityWcdma.java
@@ -150,6 +150,7 @@
/**
* @return Mobile Country Code in string version, null if unavailable.
*/
+ @Nullable
public String getMccString() {
return mMccStr;
}
@@ -157,6 +158,7 @@
/**
* @return Mobile Network Code in string version, null if unavailable.
*/
+ @Nullable
public String getMncString() {
return mMncStr;
}
diff --git a/telephony/java/android/telephony/CellInfoCdma.java b/telephony/java/android/telephony/CellInfoCdma.java
index a4570e4..30b131f 100644
--- a/telephony/java/android/telephony/CellInfoCdma.java
+++ b/telephony/java/android/telephony/CellInfoCdma.java
@@ -16,6 +16,7 @@
package android.telephony;
+import android.annotation.NonNull;
import android.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
@@ -76,18 +77,25 @@
new CellSignalStrengthCdma(cic.signalStrengthCdma, cic.signalStrengthEvdo);
}
+ /**
+ * @return a {@link CellIdentityCdma} instance.
+ */
@Override
- public CellIdentityCdma getCellIdentity() {
+ public @NonNull CellIdentityCdma getCellIdentity() {
return mCellIdentityCdma;
}
+
/** @hide */
@UnsupportedAppUsage
public void setCellIdentity(CellIdentityCdma cid) {
mCellIdentityCdma = cid;
}
+ /**
+ * @return a {@link CellSignalStrengthCdma} instance.
+ */
@Override
- public CellSignalStrengthCdma getCellSignalStrength() {
+ public @NonNull CellSignalStrengthCdma getCellSignalStrength() {
return mCellSignalStrengthCdma;
}
diff --git a/telephony/java/android/telephony/CellInfoGsm.java b/telephony/java/android/telephony/CellInfoGsm.java
index ce32bc1..137f97e 100644
--- a/telephony/java/android/telephony/CellInfoGsm.java
+++ b/telephony/java/android/telephony/CellInfoGsm.java
@@ -16,6 +16,7 @@
package android.telephony;
+import android.annotation.NonNull;
import android.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
@@ -71,17 +72,24 @@
mCellSignalStrengthGsm = new CellSignalStrengthGsm(cig.signalStrengthGsm);
}
+ /**
+ * @return a {@link CellIdentityGsm} instance.
+ */
@Override
- public CellIdentityGsm getCellIdentity() {
+ public @NonNull CellIdentityGsm getCellIdentity() {
return mCellIdentityGsm;
}
+
/** @hide */
public void setCellIdentity(CellIdentityGsm cid) {
mCellIdentityGsm = cid;
}
+ /**
+ * @return a {@link CellSignalStrengthGsm} instance.
+ */
@Override
- public CellSignalStrengthGsm getCellSignalStrength() {
+ public @NonNull CellSignalStrengthGsm getCellSignalStrength() {
return mCellSignalStrengthGsm;
}
diff --git a/telephony/java/android/telephony/CellInfoLte.java b/telephony/java/android/telephony/CellInfoLte.java
index 01ee20a..da7b7ab 100644
--- a/telephony/java/android/telephony/CellInfoLte.java
+++ b/telephony/java/android/telephony/CellInfoLte.java
@@ -16,6 +16,7 @@
package android.telephony;
+import android.annotation.NonNull;
import android.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
@@ -79,11 +80,15 @@
mCellConfig = new CellConfigLte(cil.cellConfig);
}
+ /**
+ * @return a {@link CellIdentityLte} instance.
+ */
@Override
- public CellIdentityLte getCellIdentity() {
+ public @NonNull CellIdentityLte getCellIdentity() {
if (DBG) log("getCellIdentity: " + mCellIdentityLte);
return mCellIdentityLte;
}
+
/** @hide */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
public void setCellIdentity(CellIdentityLte cid) {
@@ -91,8 +96,11 @@
mCellIdentityLte = cid;
}
+ /**
+ * @return a {@link CellSignalStrengthLte} instance.
+ */
@Override
- public CellSignalStrengthLte getCellSignalStrength() {
+ public @NonNull CellSignalStrengthLte getCellSignalStrength() {
if (DBG) log("getCellSignalStrength: " + mCellSignalStrengthLte);
return mCellSignalStrengthLte;
}
diff --git a/telephony/java/android/telephony/CellInfoNr.java b/telephony/java/android/telephony/CellInfoNr.java
index ba4a907..9775abd 100644
--- a/telephony/java/android/telephony/CellInfoNr.java
+++ b/telephony/java/android/telephony/CellInfoNr.java
@@ -43,12 +43,18 @@
mCellSignalStrength = other.mCellSignalStrength;
}
+ /**
+ * @return a {@link CellIdentityNr} instance.
+ */
@Override
@NonNull
public CellIdentity getCellIdentity() {
return mCellIdentity;
}
+ /**
+ * @return a {@link CellSignalStrengthNr} instance.
+ */
@Override
@NonNull
public CellSignalStrength getCellSignalStrength() {
diff --git a/telephony/java/android/telephony/CellInfoTdscdma.java b/telephony/java/android/telephony/CellInfoTdscdma.java
index ccafda6..f1305f5 100644
--- a/telephony/java/android/telephony/CellInfoTdscdma.java
+++ b/telephony/java/android/telephony/CellInfoTdscdma.java
@@ -75,6 +75,9 @@
mCellSignalStrengthTdscdma = new CellSignalStrengthTdscdma(cit.signalStrengthTdscdma);
}
+ /**
+ * @return a {@link CellIdentityTdscdma} instance.
+ */
@Override
public @NonNull CellIdentityTdscdma getCellIdentity() {
return mCellIdentityTdscdma;
@@ -85,6 +88,9 @@
mCellIdentityTdscdma = cid;
}
+ /**
+ * @return a {@link CellSignalStrengthTdscdma} instance.
+ */
@Override
public @NonNull CellSignalStrengthTdscdma getCellSignalStrength() {
return mCellSignalStrengthTdscdma;
diff --git a/telephony/java/android/telephony/CellInfoWcdma.java b/telephony/java/android/telephony/CellInfoWcdma.java
index 1b32178..ee5fec8 100644
--- a/telephony/java/android/telephony/CellInfoWcdma.java
+++ b/telephony/java/android/telephony/CellInfoWcdma.java
@@ -71,15 +71,22 @@
mCellSignalStrengthWcdma = new CellSignalStrengthWcdma(ciw.signalStrengthWcdma);
}
+ /**
+ * @return a {@link CellIdentityWcdma} instance.
+ */
@Override
public CellIdentityWcdma getCellIdentity() {
return mCellIdentityWcdma;
}
+
/** @hide */
public void setCellIdentity(CellIdentityWcdma cid) {
mCellIdentityWcdma = cid;
}
+ /**
+ * @return a {@link CellSignalStrengthWcdma} instance.
+ */
@Override
public CellSignalStrengthWcdma getCellSignalStrength() {
return mCellSignalStrengthWcdma;
diff --git a/telephony/java/android/telephony/CellSignalStrength.java b/telephony/java/android/telephony/CellSignalStrength.java
index 740b970..e65b048ec 100644
--- a/telephony/java/android/telephony/CellSignalStrength.java
+++ b/telephony/java/android/telephony/CellSignalStrength.java
@@ -16,6 +16,7 @@
package android.telephony;
+import android.annotation.IntRange;
import android.os.PersistableBundle;
/**
@@ -57,23 +58,24 @@
public abstract void setDefaultValues();
/**
- * Get signal level as an int from 0..4
- * <p>
- * @see #SIGNAL_STRENGTH_NONE_OR_UNKNOWN
- * @see #SIGNAL_STRENGTH_POOR
- * @see #SIGNAL_STRENGTH_MODERATE
- * @see #SIGNAL_STRENGTH_GOOD
- * @see #SIGNAL_STRENGTH_GREAT
+ * Retrieve an abstract level value for the overall signal quality.
+ *
+ * @return a single integer from 0 to 4 representing the general signal quality.
+ * 0 represents very poor or unknown signal quality while 4 represents excellent
+ * signal quality.
*/
+ @IntRange(from = SIGNAL_STRENGTH_NONE_OR_UNKNOWN, to = SIGNAL_STRENGTH_GREAT)
public abstract int getLevel();
/**
- * Get the signal level as an asu value between 0..31, 99 is unknown
+ * Get the technology-specific signal strength in Arbitrary Strength Units, calculated from the
+ * strength of the pilot signal or equivalent.
*/
public abstract int getAsuLevel();
/**
- * Get the signal strength as dBm
+ * Get the technology-specific signal strength in dBm, which is the signal strength of the
+ * pilot signal or equivalent.
*/
public abstract int getDbm();
diff --git a/telephony/java/android/telephony/CellSignalStrengthCdma.java b/telephony/java/android/telephony/CellSignalStrengthCdma.java
index 5b19599..1998439 100644
--- a/telephony/java/android/telephony/CellSignalStrengthCdma.java
+++ b/telephony/java/android/telephony/CellSignalStrengthCdma.java
@@ -16,6 +16,7 @@
package android.telephony;
+import android.annotation.IntRange;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.PersistableBundle;
@@ -114,13 +115,9 @@
mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
}
- /**
- * Retrieve an abstract level value for the overall signal strength.
- *
- * @return a single integer from 0 to 4 representing the general signal quality.
- * 0 represents very poor signal strength while 4 represents a very strong signal strength.
- */
+ /** {@inheritDoc} */
@Override
+ @IntRange(from = SIGNAL_STRENGTH_NONE_OR_UNKNOWN, to = SIGNAL_STRENGTH_GREAT)
public int getLevel() {
return mLevel;
}
diff --git a/telephony/java/android/telephony/CellSignalStrengthGsm.java b/telephony/java/android/telephony/CellSignalStrengthGsm.java
index 0aeb0f6..14ae689 100644
--- a/telephony/java/android/telephony/CellSignalStrengthGsm.java
+++ b/telephony/java/android/telephony/CellSignalStrengthGsm.java
@@ -16,6 +16,7 @@
package android.telephony;
+import android.annotation.IntRange;
import android.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
@@ -37,6 +38,10 @@
private static final int GSM_RSSI_GOOD = -97;
private static final int GSM_RSSI_MODERATE = -103;
private static final int GSM_RSSI_POOR = -107;
+ private static final int GSM_RSSI_MIN = -113;
+
+ private static final int[] sRssiThresholds = new int[] {
+ GSM_RSSI_POOR, GSM_RSSI_MODERATE, GSM_RSSI_GOOD, GSM_RSSI_GREAT};
private int mRssi; // in dBm [-113, -51] or UNAVAILABLE
@UnsupportedAppUsage
@@ -53,7 +58,7 @@
/** @hide */
public CellSignalStrengthGsm(int rssi, int ber, int ta) {
- mRssi = inRangeOrUnavailable(rssi, -113, -51);
+ mRssi = inRangeOrUnavailable(rssi, GSM_RSSI_MIN, GSM_RSSI_MAX);
mBitErrorRate = inRangeOrUnavailable(ber, 0, 7, 99);
mTimingAdvance = inRangeOrUnavailable(ta, 0, 219);
updateLevel(null, null);
@@ -97,13 +102,9 @@
mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
}
- /**
- * Retrieve an abstract level value for the overall signal strength.
- *
- * @return a single integer from 0 to 4 representing the general signal quality.
- * 0 represents very poor signal strength while 4 represents a very strong signal strength.
- */
+ /** {@inheritDoc} */
@Override
+ @IntRange(from = SIGNAL_STRENGTH_NONE_OR_UNKNOWN, to = SIGNAL_STRENGTH_GREAT)
public int getLevel() {
return mLevel;
}
@@ -111,12 +112,22 @@
/** @hide */
@Override
public void updateLevel(PersistableBundle cc, ServiceState ss) {
- if (mRssi > GSM_RSSI_MAX) mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
- else if (mRssi >= GSM_RSSI_GREAT) mLevel = SIGNAL_STRENGTH_GREAT;
- else if (mRssi >= GSM_RSSI_GOOD) mLevel = SIGNAL_STRENGTH_GOOD;
- else if (mRssi >= GSM_RSSI_MODERATE) mLevel = SIGNAL_STRENGTH_MODERATE;
- else if (mRssi >= GSM_RSSI_POOR) mLevel = SIGNAL_STRENGTH_POOR;
- else mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+ int[] rssiThresholds;
+ if (cc == null) {
+ rssiThresholds = sRssiThresholds;
+ } else {
+ rssiThresholds = cc.getIntArray(CarrierConfigManager.KEY_GSM_RSSI_THRESHOLDS_INT_ARRAY);
+ if (rssiThresholds == null || rssiThresholds.length != NUM_SIGNAL_STRENGTH_THRESHOLDS) {
+ rssiThresholds = sRssiThresholds;
+ }
+ }
+ int level = NUM_SIGNAL_STRENGTH_THRESHOLDS;
+ if (mRssi < GSM_RSSI_MIN || mRssi > GSM_RSSI_MAX) {
+ mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+ return;
+ }
+ while (level > 0 && mRssi < rssiThresholds[level - 1]) level--;
+ mLevel = level;
}
/**
@@ -141,7 +152,7 @@
/**
* Get the RSSI in ASU.
*
- * Asu is calculated based on 3GPP RSRP. Refer to 3GPP 27.007 (Ver 10.3.0) Sec 8.69
+ * Asu is calculated based on 3GPP RSSI. Refer to 3GPP 27.007 (Ver 10.3.0) Sec 8.69
*
* @return RSSI in ASU 0..31, 99, or UNAVAILABLE
*/
diff --git a/telephony/java/android/telephony/CellSignalStrengthLte.java b/telephony/java/android/telephony/CellSignalStrengthLte.java
index 5687ada..2272dc9 100644
--- a/telephony/java/android/telephony/CellSignalStrengthLte.java
+++ b/telephony/java/android/telephony/CellSignalStrengthLte.java
@@ -16,6 +16,7 @@
package android.telephony;
+import android.annotation.IntRange;
import android.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
@@ -145,13 +146,9 @@
mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
}
- /**
- * Retrieve an abstract level value for the overall signal strength.
- *
- * @return a single integer from 0 to 4 representing the general signal quality.
- * 0 represents very poor signal strength while 4 represents a very strong signal strength.
- */
+ /** {@inheritDoc} */
@Override
+ @IntRange(from = SIGNAL_STRENGTH_NONE_OR_UNKNOWN, to = SIGNAL_STRENGTH_GREAT)
public int getLevel() {
return mLevel;
}
diff --git a/telephony/java/android/telephony/CellSignalStrengthNr.java b/telephony/java/android/telephony/CellSignalStrengthNr.java
index fff3adf..1912c60 100644
--- a/telephony/java/android/telephony/CellSignalStrengthNr.java
+++ b/telephony/java/android/telephony/CellSignalStrengthNr.java
@@ -16,6 +16,7 @@
package android.telephony;
+import android.annotation.IntRange;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.PersistableBundle;
@@ -183,7 +184,9 @@
mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
}
+ /** {@inheritDoc} */
@Override
+ @IntRange(from = SIGNAL_STRENGTH_NONE_OR_UNKNOWN, to = SIGNAL_STRENGTH_GREAT)
public int getLevel() {
return mLevel;
}
@@ -227,6 +230,9 @@
return asuLevel;
}
+ /**
+ * Get the CSI-RSRP as dBm value -140..-44dBm or {@link CellInfo#UNAVAILABLE UNAVAILABLE}.
+ */
@Override
public int getDbm() {
return mCsiRsrp;
diff --git a/telephony/java/android/telephony/CellSignalStrengthTdscdma.java b/telephony/java/android/telephony/CellSignalStrengthTdscdma.java
index b562f32..f4a3dbb 100644
--- a/telephony/java/android/telephony/CellSignalStrengthTdscdma.java
+++ b/telephony/java/android/telephony/CellSignalStrengthTdscdma.java
@@ -16,6 +16,7 @@
package android.telephony;
+import android.annotation.IntRange;
import android.annotation.NonNull;
import android.os.Parcel;
import android.os.Parcelable;
@@ -121,13 +122,10 @@
mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
}
- /**
- * Retrieve an abstract level value for the overall signal strength.
- *
- * @return a single integer from 0 to 4 representing the general signal quality.
- * 0 represents very poor signal strength while 4 represents a very strong signal strength.
- */
+
+ /** {@inheritDoc} */
@Override
+ @IntRange(from = 0, to = 4)
public int getLevel() {
return mLevel;
}
@@ -144,7 +142,7 @@
}
/**
- * Get the signal strength as dBm
+ * Get the RSCP as dBm value -120..-24dBm or {@link CellInfo#UNAVAILABLE UNAVAILABLE}.
*/
@Override
public int getDbm() {
diff --git a/telephony/java/android/telephony/CellSignalStrengthWcdma.java b/telephony/java/android/telephony/CellSignalStrengthWcdma.java
index 8efc0f2..1693252 100644
--- a/telephony/java/android/telephony/CellSignalStrengthWcdma.java
+++ b/telephony/java/android/telephony/CellSignalStrengthWcdma.java
@@ -16,6 +16,7 @@
package android.telephony;
+import android.annotation.IntRange;
import android.annotation.StringDef;
import android.os.Parcel;
import android.os.Parcelable;
@@ -143,13 +144,9 @@
mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
}
- /**
- * Retrieve an abstract level value for the overall signal strength.
- *
- * @return a single integer from 0 to 4 representing the general signal quality.
- * 0 represents very poor signal strength while 4 represents a very strong signal strength.
- */
+ /** {@inheritDoc} */
@Override
+ @IntRange(from = SIGNAL_STRENGTH_NONE_OR_UNKNOWN, to = SIGNAL_STRENGTH_GREAT)
public int getLevel() {
return mLevel;
}
@@ -202,7 +199,7 @@
}
/**
- * Get the signal strength as dBm
+ * Get the RSCP as dBm value -120..-24dBm or {@link CellInfo#UNAVAILABLE UNAVAILABLE}.
*/
@Override
public int getDbm() {