Merge "Throw on revoked location permission - framework" into pi-dev
diff --git a/api/current.txt b/api/current.txt
index d721936..052b7f8 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -9905,6 +9905,8 @@
field public static final java.lang.String ACTION_MEDIA_UNMOUNTABLE = "android.intent.action.MEDIA_UNMOUNTABLE";
field public static final java.lang.String ACTION_MEDIA_UNMOUNTED = "android.intent.action.MEDIA_UNMOUNTED";
field public static final java.lang.String ACTION_MY_PACKAGE_REPLACED = "android.intent.action.MY_PACKAGE_REPLACED";
+ field public static final java.lang.String ACTION_MY_PACKAGE_SUSPENDED = "android.intent.action.MY_PACKAGE_SUSPENDED";
+ field public static final java.lang.String ACTION_MY_PACKAGE_UNSUSPENDED = "android.intent.action.MY_PACKAGE_UNSUSPENDED";
field public static final java.lang.String ACTION_NEW_OUTGOING_CALL = "android.intent.action.NEW_OUTGOING_CALL";
field public static final java.lang.String ACTION_OPEN_DOCUMENT = "android.intent.action.OPEN_DOCUMENT";
field public static final java.lang.String ACTION_OPEN_DOCUMENT_TREE = "android.intent.action.OPEN_DOCUMENT_TREE";
@@ -10065,6 +10067,7 @@
field public static final java.lang.String EXTRA_SPLIT_NAME = "android.intent.extra.SPLIT_NAME";
field public static final java.lang.String EXTRA_STREAM = "android.intent.extra.STREAM";
field public static final java.lang.String EXTRA_SUBJECT = "android.intent.extra.SUBJECT";
+ field public static final java.lang.String EXTRA_SUSPENDED_PACKAGE_EXTRAS = "android.intent.extra.SUSPENDED_PACKAGE_EXTRAS";
field public static final java.lang.String EXTRA_TEMPLATE = "android.intent.extra.TEMPLATE";
field public static final java.lang.String EXTRA_TEXT = "android.intent.extra.TEXT";
field public static final java.lang.String EXTRA_TITLE = "android.intent.extra.TITLE";
@@ -11178,7 +11181,7 @@
method public abstract android.content.res.Resources getResourcesForApplication(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
method public abstract android.content.pm.ServiceInfo getServiceInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
method public abstract java.util.List<android.content.pm.SharedLibraryInfo> getSharedLibraries(int);
- method public android.os.PersistableBundle getSuspendedPackageAppExtras();
+ method public android.os.Bundle getSuspendedPackageAppExtras();
method public abstract android.content.pm.FeatureInfo[] getSystemAvailableFeatures();
method public abstract java.lang.String[] getSystemSharedLibraryNames();
method public abstract java.lang.CharSequence getText(java.lang.String, int, android.content.pm.ApplicationInfo);
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index f38c80c..a68136b 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -2167,15 +2167,16 @@
@Override
public PersistableBundle getSuspendedPackageAppExtras(String packageName) {
try {
- return mPM.getPackageSuspendedAppExtras(packageName, mContext.getUserId());
+ return mPM.getSuspendedPackageAppExtras(packageName, mContext.getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
@Override
- public PersistableBundle getSuspendedPackageAppExtras() {
- return getSuspendedPackageAppExtras(mContext.getOpPackageName());
+ public Bundle getSuspendedPackageAppExtras() {
+ final PersistableBundle extras = getSuspendedPackageAppExtras(mContext.getOpPackageName());
+ return extras != null ? new Bundle(extras.deepCopy()) : null;
}
@Override
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 99efecd..3bb87a3 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -322,12 +322,14 @@
/**
* Informs ActivityManagerService that the keyguard is showing.
*
- * @param showing True if the keyguard is showing, false otherwise.
+ * @param showingKeyguard True if the keyguard is showing, false otherwise.
+ * @param showingAod True if AOD is showing, false otherwise.
* @param secondaryDisplayShowing The displayId of the secondary display on which the keyguard
* is showing, or INVALID_DISPLAY if there is no such display. Only meaningful if
* showing is true.
*/
- void setLockScreenShown(boolean showing, int secondaryDisplayShowing);
+ void setLockScreenShown(boolean showingKeyguard, boolean showingAod,
+ int secondaryDisplayShowing);
boolean finishActivityAffinity(in IBinder token);
// This is not public because you need to be very careful in how you
// manage your activity to make sure it is always the uid you expect.
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index a6e42cf..465340f 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -441,6 +441,9 @@
synchronized (this) {
mCachedWallpaper = null;
mCachedWallpaperUserId = 0;
+ if (mDefaultWallpaper != null) {
+ mDefaultWallpaper.recycle();
+ }
mDefaultWallpaper = null;
}
}
diff --git a/core/java/android/app/usage/TimeSparseArray.java b/core/java/android/app/usage/TimeSparseArray.java
index 5764fa8..9ef88e4 100644
--- a/core/java/android/app/usage/TimeSparseArray.java
+++ b/core/java/android/app/usage/TimeSparseArray.java
@@ -81,12 +81,17 @@
@Override
public void put(long key, E value) {
final long origKey = key;
- while (indexOfKey(key) >= 0) {
- key++;
- }
- if (origKey != key) {
- Slog.w(TAG, "Value " + value + " supposed to be inserted at " + origKey
- + " displaced to " + key);
+ int keyIndex = indexOfKey(key);
+ if (keyIndex >= 0) {
+ final long sz = size();
+ while (keyIndex < sz && keyAt(keyIndex) == key) {
+ key++;
+ keyIndex++;
+ }
+ if (key >= origKey + 10) {
+ Slog.w(TAG, "Value " + value + " supposed to be inserted at " + origKey
+ + " displaced to " + key);
+ }
}
super.put(key, value);
}
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index ce32278..02f0ded 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1814,6 +1814,17 @@
public static final String EXTRA_PACKAGE_NAME = "android.intent.extra.PACKAGE_NAME";
/**
+ * Intent extra: A {@link Bundle} of extras for a package being suspended. Will be sent with
+ * {@link #ACTION_MY_PACKAGE_SUSPENDED}.
+ *
+ * @see #ACTION_MY_PACKAGE_SUSPENDED
+ * @see #ACTION_MY_PACKAGE_UNSUSPENDED
+ * @see PackageManager#isPackageSuspended()
+ * @see PackageManager#getSuspendedPackageAppExtras()
+ */
+ public static final String EXTRA_SUSPENDED_PACKAGE_EXTRAS = "android.intent.extra.SUSPENDED_PACKAGE_EXTRAS";
+
+ /**
* Intent extra: An app split name.
* <p>
* Type: String
@@ -2237,6 +2248,43 @@
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_PACKAGES_UNSUSPENDED = "android.intent.action.PACKAGES_UNSUSPENDED";
+
+ /**
+ * Broadcast Action: Sent to a package that has been suspended by the system. This is sent
+ * whenever a package is put into a suspended state or any of it's app extras change while
+ * in the suspended state.
+ * <p> Optionally includes the following extras:
+ * <ul>
+ * <li> {@link #EXTRA_SUSPENDED_PACKAGE_EXTRAS} which is a {@link Bundle} which will contain
+ * useful information for the app being suspended.
+ * </ul>
+ * <p class="note">This is a protected intent that can only be sent
+ * by the system. <em>This will be delivered to {@link BroadcastReceiver} components declared in
+ * the manifest.</em>
+ *
+ * @see #ACTION_MY_PACKAGE_UNSUSPENDED
+ * @see #EXTRA_SUSPENDED_PACKAGE_EXTRAS
+ * @see PackageManager#isPackageSuspended()
+ * @see PackageManager#getSuspendedPackageAppExtras()
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_MY_PACKAGE_SUSPENDED = "android.intent.action.MY_PACKAGE_SUSPENDED";
+
+ /**
+ * Broadcast Action: Sent to a package that has been unsuspended.
+ *
+ * <p class="note">This is a protected intent that can only be sent
+ * by the system. <em>This will be delivered to {@link BroadcastReceiver} components declared in
+ * the manifest.</em>
+ *
+ * @see #ACTION_MY_PACKAGE_SUSPENDED
+ * @see #EXTRA_SUSPENDED_PACKAGE_EXTRAS
+ * @see PackageManager#isPackageSuspended()
+ * @see PackageManager#getSuspendedPackageAppExtras()
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_MY_PACKAGE_UNSUSPENDED = "android.intent.action.MY_PACKAGE_UNSUSPENDED";
+
/**
* Broadcast Action: A user ID has been removed from the system. The user
* ID number is stored in the extra data under {@link #EXTRA_UID}.
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index d43d80f..1352b5e 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -278,7 +278,7 @@
boolean isPackageSuspendedForUser(String packageName, int userId);
- PersistableBundle getPackageSuspendedAppExtras(String pacakgeName, int userId);
+ PersistableBundle getSuspendedPackageAppExtras(String packageName, int userId);
void setSuspendedPackageAppExtras(String packageName, in PersistableBundle appExtras,
int userId);
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 314eb98..491f0af 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -5513,7 +5513,7 @@
* Puts the package in a suspended state, where attempts at starting activities are denied.
*
* <p>It doesn't remove the data or the actual package file. The application's notifications
- * will be hidden, any of the it's started activities will be stopped and it will not be able to
+ * will be hidden, any of its started activities will be stopped and it will not be able to
* show toasts or dialogs or ring the device. When the user tries to launch a suspended app, a
* system dialog with the given {@code dialogMessage} will be shown instead.</p>
*
@@ -5577,11 +5577,26 @@
}
/**
- * Apps can query this to know if they have been suspended.
+ * Apps can query this to know if they have been suspended. A system app with the permission
+ * {@code android.permission.SUSPEND_APPS} can put any app on the device into a suspended state.
+ *
+ * <p>While in this state, the application's notifications will be hidden, any of its started
+ * activities will be stopped and it will not be able to show toasts or dialogs or ring the
+ * device. When the user tries to launch a suspended app, the system will, instead, show a
+ * dialog to the user informing them that they cannot use this app while it is suspended.
+ *
+ * <p>When an app is put into this state, the broadcast action
+ * {@link Intent#ACTION_MY_PACKAGE_SUSPENDED} will be delivered to any of its broadcast
+ * receivers that included this action in their intent-filters, <em>including manifest
+ * receivers.</em> Similarly, a broadcast action {@link Intent#ACTION_MY_PACKAGE_UNSUSPENDED}
+ * is delivered when a previously suspended app is taken out of this state.
+ * </p>
*
* @return {@code true} if the calling package has been suspended, {@code false} otherwise.
*
* @see #getSuspendedPackageAppExtras()
+ * @see Intent#ACTION_MY_PACKAGE_SUSPENDED
+ * @see Intent#ACTION_MY_PACKAGE_UNSUSPENDED
*/
public boolean isPackageSuspended() {
throw new UnsupportedOperationException("isPackageSuspended not implemented");
@@ -5602,7 +5617,7 @@
*/
@SystemApi
@RequiresPermission(Manifest.permission.SUSPEND_APPS)
- public PersistableBundle getSuspendedPackageAppExtras(String packageName) {
+ public @Nullable PersistableBundle getSuspendedPackageAppExtras(String packageName) {
throw new UnsupportedOperationException("getSuspendedPackageAppExtras not implemented");
}
@@ -5631,15 +5646,17 @@
* Returns any extra information supplied as {@code appExtras} to the system when the calling
* app was suspended.
*
- * <p> Note: This just returns whatever {@link PersistableBundle} was passed to the system via
- * {@code setPackagesSuspended(String[], boolean, PersistableBundle, PersistableBundle,
- * String)} when suspending the package, <em> which might be {@code null}. </em></p>
+ * <p>Note: If no extras were supplied to the system, this method will return {@code null}, even
+ * when the calling app has been suspended.</p>
*
- * @return A {@link PersistableBundle} containing the extras for the app, or {@code null} if the
+ * @return A {@link Bundle} containing the extras for the app, or {@code null} if the
* package is not currently suspended.
+ *
* @see #isPackageSuspended()
+ * @see Intent#ACTION_MY_PACKAGE_UNSUSPENDED
+ * @see Intent#ACTION_MY_PACKAGE_SUSPENDED
*/
- public @Nullable PersistableBundle getSuspendedPackageAppExtras() {
+ public @Nullable Bundle getSuspendedPackageAppExtras() {
throw new UnsupportedOperationException("getSuspendedPackageAppExtras not implemented");
}
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index d3b1e5c..df81a31 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -250,6 +250,18 @@
}
/**
+ * Destroys the HwuiContext without completely
+ * releasing the Surface.
+ * @hide
+ */
+ public void hwuiDestroy() {
+ if (mHwuiContext != null) {
+ mHwuiContext.destroy();
+ mHwuiContext = null;
+ }
+ }
+
+ /**
* Returns true if this object holds a valid surface.
*
* @return True if it holds a physical surface, so lockCanvas() will succeed.
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 7b1acb1..39755aa 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -12474,9 +12474,8 @@
+ " before=" + before + " after=" + after + ": " + buffer);
}
- if (AccessibilityManager.getInstance(mContext).isEnabled()
- && !isPasswordInputType(getInputType()) && !hasPasswordTransformationMethod()) {
- mBeforeText = buffer.toString();
+ if (AccessibilityManager.getInstance(mContext).isEnabled() && (mTransformed != null)) {
+ mBeforeText = mTransformed.toString();
}
TextView.this.sendBeforeTextChanged(buffer, start, before, after);
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 3fb52dc..1c3448b 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -89,6 +89,8 @@
<protected-broadcast android:name="android.intent.action.OVERLAY_REMOVED" />
<protected-broadcast android:name="android.intent.action.OVERLAY_PRIORITY_CHANGED" />
<protected-broadcast android:name="android.intent.action.USER_ACTIVITY_NOTIFICATION" />
+ <protected-broadcast android:name="android.intent.action.MY_PACKAGE_SUSPENDED" />
+ <protected-broadcast android:name="android.intent.action.MY_PACKAGE_UNSUSPENDED" />
<protected-broadcast android:name="android.os.action.POWER_SAVE_MODE_CHANGED" />
<protected-broadcast android:name="android.os.action.POWER_SAVE_MODE_CHANGING" />
diff --git a/libs/hwui/PathParser.cpp b/libs/hwui/PathParser.cpp
index a48fdfc..47fcca9 100644
--- a/libs/hwui/PathParser.cpp
+++ b/libs/hwui/PathParser.cpp
@@ -156,10 +156,63 @@
return;
}
-bool PathParser::isVerbValid(char verb) {
- verb = tolower(verb);
- return verb == 'a' || verb == 'c' || verb == 'h' || verb == 'l' || verb == 'm' || verb == 'q' ||
- verb == 's' || verb == 't' || verb == 'v' || verb == 'z';
+void PathParser::validateVerbAndPoints(char verb, size_t points, PathParser::ParseResult* result) {
+ size_t numberOfPointsExpected = -1;
+ switch (verb) {
+ case 'z':
+ case 'Z':
+ numberOfPointsExpected = 0;
+ break;
+ case 'm':
+ case 'l':
+ case 't':
+ case 'M':
+ case 'L':
+ case 'T':
+ numberOfPointsExpected = 2;
+ break;
+ case 'h':
+ case 'v':
+ case 'H':
+ case 'V':
+ numberOfPointsExpected = 1;
+ break;
+ case 'c':
+ case 'C':
+ numberOfPointsExpected = 6;
+ break;
+ case 's':
+ case 'q':
+ case 'S':
+ case 'Q':
+ numberOfPointsExpected = 4;
+ break;
+ case 'a':
+ case 'A':
+ numberOfPointsExpected = 7;
+ break;
+ default:
+ result->failureOccurred = true;
+ result->failureMessage += verb;
+ result->failureMessage += " is not a valid verb. ";
+ return;
+ }
+ if (numberOfPointsExpected == 0 && points == 0) {
+ return;
+ }
+ if (numberOfPointsExpected > 0 && points % numberOfPointsExpected == 0) {
+ return;
+ }
+
+ result->failureOccurred = true;
+ result->failureMessage += verb;
+ result->failureMessage += " needs to be followed by ";
+ if (numberOfPointsExpected > 0) {
+ result->failureMessage += "a multiple of ";
+ }
+ result->failureMessage += std::to_string(numberOfPointsExpected)
+ + " floats. However, " + std::to_string(points)
+ + " float(s) are found. ";
}
void PathParser::getPathDataFromAsciiString(PathData* data, ParseResult* result,
@@ -186,13 +239,11 @@
end = nextStart(pathStr, strLen, end);
std::vector<float> points;
getFloats(&points, result, pathStr, start, end);
- if (!isVerbValid(pathStr[start])) {
- result->failureOccurred = true;
- result->failureMessage = "Invalid pathData. Failure occurred at position " +
- std::to_string(start) + " of path: " + pathStr;
- }
- // If either verb or points is not valid, return immediately.
+ validateVerbAndPoints(pathStr[start], points.size(), result);
if (result->failureOccurred) {
+ // If either verb or points is not valid, return immediately.
+ result->failureMessage += "Failure occurred at position " +
+ std::to_string(start) + " of path: " + pathStr;
return;
}
data->verbs.push_back(pathStr[start]);
@@ -203,9 +254,10 @@
}
if ((end - start) == 1 && start < strLen) {
- if (!isVerbValid(pathStr[start])) {
- result->failureOccurred = true;
- result->failureMessage = "Invalid pathData. Failure occurred at position " +
+ validateVerbAndPoints(pathStr[start], 0, result);
+ if (result->failureOccurred) {
+ // If either verb or points is not valid, return immediately.
+ result->failureMessage += "Failure occurred at position " +
std::to_string(start) + " of path: " + pathStr;
return;
}
diff --git a/libs/hwui/PathParser.h b/libs/hwui/PathParser.h
index e4ec7be..474eb97 100644
--- a/libs/hwui/PathParser.h
+++ b/libs/hwui/PathParser.h
@@ -43,7 +43,7 @@
ANDROID_API static void getPathDataFromAsciiString(PathData* outData, ParseResult* result,
const char* pathStr, size_t strLength);
static void dump(const PathData& data);
- static bool isVerbValid(char verb);
+ static void validateVerbAndPoints(char verb, size_t points, ParseResult* result);
};
}; // namespace uirenderer
diff --git a/libs/hwui/tests/unit/VectorDrawableTests.cpp b/libs/hwui/tests/unit/VectorDrawableTests.cpp
index e7496f7..02f740c 100644
--- a/libs/hwui/tests/unit/VectorDrawableTests.cpp
+++ b/libs/hwui/tests/unit/VectorDrawableTests.cpp
@@ -242,7 +242,8 @@
{"\n \t z", true}, // Valid path data with leading spaces
{"1-2e34567", false}, // Not starting with a verb and ill-formatted float
{"f 4 5", false}, // Invalid verb
- {"\r ", false} // Empty string
+ {"\r ", false}, // Empty string
+ {"L1,0 L1,1 L0,1 z M1000", false} // Not enough floats following verb M.
};
static bool hasSameVerbs(const PathData& from, const PathData& to) {
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
index a59c97e..a4f8d8c 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
@@ -24,11 +24,13 @@
import android.graphics.RectF;
import android.graphics.Region.Op;
import android.os.AsyncTask;
+import android.os.Handler;
import android.os.Trace;
import android.service.wallpaper.WallpaperService;
import android.util.Log;
import android.view.Display;
import android.view.DisplayInfo;
+import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.WindowManager;
@@ -45,6 +47,7 @@
private static final String GL_LOG_TAG = "ImageWallpaperGL";
private static final boolean DEBUG = false;
private static final String PROPERTY_KERNEL_QEMU = "ro.kernel.qemu";
+ private static final long DELAY_FORGET_WALLPAPER = 5000;
private WallpaperManager mWallpaperManager;
private DrawableEngine mEngine;
@@ -69,6 +72,10 @@
}
class DrawableEngine extends Engine {
+ private final Runnable mUnloadWallpaperCallback = () -> {
+ unloadWallpaper(false /* forgetSize */);
+ };
+
Bitmap mBackground;
int mBackgroundWidth = -1, mBackgroundHeight = -1;
int mLastSurfaceWidth = -1, mLastSurfaceHeight = -1;
@@ -331,6 +338,7 @@
}
drawWallpaperWithCanvas(sh, availw, availh, xPixels, yPixels);
+ scheduleUnloadWallpaper();
} finally {
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
@@ -433,6 +441,9 @@
mBackgroundHeight = -1;
}
+ final Surface surface = getSurfaceHolder().getSurface();
+ surface.hwuiDestroy();
+
mLoader = new AsyncTask<Void, Void, Bitmap>() {
@Override
protected Bitmap doInBackground(Void... params) {
@@ -442,6 +453,12 @@
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
+ private void scheduleUnloadWallpaper() {
+ Handler handler = getMainThreadHandler();
+ handler.removeCallbacks(mUnloadWallpaperCallback);
+ handler.postDelayed(mUnloadWallpaperCallback, DELAY_FORGET_WALLPAPER);
+ }
+
@Override
protected void dump(String prefix, FileDescriptor fd, PrintWriter out, String[] args) {
super.dump(prefix, fd, out, args);
diff --git a/packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogImpl.java b/packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogImpl.java
index 4b15fbc..f2eea26 100644
--- a/packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/fingerprint/FingerprintDialogImpl.java
@@ -147,6 +147,9 @@
private void handleFingerprintAuthenticated() {
if (DEBUG) Log.d(TAG, "handleFingerprintAuthenticated");
+ mDialogView.announceForAccessibility(
+ mContext.getResources().getText(
+ com.android.internal.R.string.fingerprint_authenticated));
handleHideDialog(false /* userCanceled */);
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index a1b17e4..d6e59c7 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -27,7 +27,6 @@
import android.app.ActivityManager;
import android.app.AlarmManager;
-import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.StatusBarManager;
import android.app.trust.TrustManager;
@@ -235,6 +234,9 @@
// answer whether the input should be restricted)
private boolean mShowing;
+ // AOD is enabled and status bar is in AOD state.
+ private boolean mAodShowing;
+
// display id of the secondary display on which we have put a keyguard window
private int mSecondaryDisplayShowing = INVALID_DISPLAY;
@@ -664,7 +666,7 @@
@Override
public void onSecondaryDisplayShowingChanged(int displayId) {
synchronized (KeyguardViewMediator.this) {
- setShowingLocked(mShowing, displayId, false);
+ setShowingLocked(mShowing, mAodShowing, displayId, false);
}
}
};
@@ -707,10 +709,10 @@
setShowingLocked(!shouldWaitForProvisioning()
&& !mLockPatternUtils.isLockScreenDisabled(
KeyguardUpdateMonitor.getCurrentUser()),
- mSecondaryDisplayShowing, true /* forceCallbacks */);
+ mAodShowing, mSecondaryDisplayShowing, true /* forceCallbacks */);
} else {
// The system's keyguard is disabled or missing.
- setShowingLocked(false, mSecondaryDisplayShowing, true);
+ setShowingLocked(false, mAodShowing, mSecondaryDisplayShowing, true);
}
mStatusBarKeyguardViewManager =
@@ -1311,7 +1313,7 @@
if (mLockPatternUtils.checkVoldPassword(KeyguardUpdateMonitor.getCurrentUser())) {
if (DEBUG) Log.d(TAG, "Not showing lock screen since just decrypted");
// Without this, settings is not enabled until the lock screen first appears
- setShowingLocked(false);
+ setShowingLocked(false, mAodShowing);
hideLocked();
return;
}
@@ -1713,10 +1715,12 @@
playSound(mTrustedSoundId);
}
- private void updateActivityLockScreenState(boolean showing, int secondaryDisplayShowing) {
+ private void updateActivityLockScreenState(boolean showing, boolean aodShowing,
+ int secondaryDisplayShowing) {
mUiOffloadThread.submit(() -> {
try {
- ActivityManager.getService().setLockScreenShown(showing, secondaryDisplayShowing);
+ ActivityManager.getService().setLockScreenShown(showing, aodShowing,
+ secondaryDisplayShowing);
} catch (RemoteException e) {
}
});
@@ -1740,7 +1744,7 @@
if (DEBUG) Log.d(TAG, "handleShow");
}
- setShowingLocked(true);
+ setShowingLocked(true, mAodShowing);
mStatusBarKeyguardViewManager.show(options);
mHiding = false;
mWakeAndUnlocking = false;
@@ -1849,7 +1853,7 @@
}
mWakeAndUnlocking = false;
- setShowingLocked(false);
+ setShowingLocked(false, mAodShowing);
mDismissCallbackRegistry.notifyDismissSucceeded();
mStatusBarKeyguardViewManager.hide(startTime, fadeoutDuration);
resetKeyguardDonePendingLocked();
@@ -1909,7 +1913,7 @@
Trace.beginSection("KeyguardViewMediator#handleVerifyUnlock");
synchronized (KeyguardViewMediator.this) {
if (DEBUG) Log.d(TAG, "handleVerifyUnlock");
- setShowingLocked(true);
+ setShowingLocked(true, mAodShowing);
mStatusBarKeyguardViewManager.dismissAndCollapse();
}
Trace.endSection();
@@ -2064,6 +2068,10 @@
pw.print(" mDrawnCallback: "); pw.println(mDrawnCallback);
}
+ public void setAodShowing(boolean aodShowing) {
+ setShowingLocked(mShowing, aodShowing);
+ }
+
private static class StartKeyguardExitAnimParams {
long startTime;
@@ -2075,20 +2083,23 @@
}
}
- private void setShowingLocked(boolean showing) {
- setShowingLocked(showing, mSecondaryDisplayShowing, false /* forceCallbacks */);
+ private void setShowingLocked(boolean showing, boolean aodShowing) {
+ setShowingLocked(showing, aodShowing, mSecondaryDisplayShowing,
+ false /* forceCallbacks */);
}
- private void setShowingLocked(
- boolean showing, int secondaryDisplayShowing, boolean forceCallbacks) {
- final boolean notifyDefaultDisplayCallbacks = showing != mShowing || forceCallbacks;
+ private void setShowingLocked(boolean showing, boolean aodShowing, int secondaryDisplayShowing,
+ boolean forceCallbacks) {
+ final boolean notifyDefaultDisplayCallbacks = showing != mShowing
+ || aodShowing != mAodShowing || forceCallbacks;
if (notifyDefaultDisplayCallbacks || secondaryDisplayShowing != mSecondaryDisplayShowing) {
mShowing = showing;
+ mAodShowing = aodShowing;
mSecondaryDisplayShowing = secondaryDisplayShowing;
if (notifyDefaultDisplayCallbacks) {
notifyDefaultDisplayCallbacks(showing);
}
- updateActivityLockScreenState(showing, secondaryDisplayShowing);
+ updateActivityLockScreenState(showing, aodShowing, secondaryDisplayShowing);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index ddb67df..b8325fe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -408,6 +408,7 @@
protected NotificationEntryManager mEntryManager;
protected NotificationViewHierarchyManager mViewHierarchyManager;
protected AppOpsListener mAppOpsListener;
+ protected KeyguardViewMediator mKeyguardViewMediator;
private ZenModeController mZenController;
/**
@@ -632,6 +633,7 @@
mAppOpsListener = Dependency.get(AppOpsListener.class);
mAppOpsListener.setUpWithPresenter(this, mEntryManager);
mZenController = Dependency.get(ZenModeController.class);
+ mKeyguardViewMediator = getComponent(KeyguardViewMediator.class);
mColorExtractor = Dependency.get(SysuiColorExtractor.class);
mColorExtractor.addOnColorsChangedListener(this);
@@ -4628,6 +4630,7 @@
boolean dozing = mDozingRequested && mState == StatusBarState.KEYGUARD
|| mFingerprintUnlockController.getMode()
== FingerprintUnlockController.MODE_WAKE_AND_UNLOCK_PULSING;
+ final boolean alwaysOn = DozeParameters.getInstance(mContext).getAlwaysOn();
// When in wake-and-unlock we may not have received a change to mState
// but we still should not be dozing, manually set to false.
if (mFingerprintUnlockController.getMode() ==
@@ -4635,6 +4638,7 @@
dozing = false;
}
mDozing = dozing;
+ mKeyguardViewMediator.setAodShowing(mDozing && alwaysOn);
mStatusBarWindowManager.setDozing(mDozing);
mStatusBarKeyguardViewManager.setDozing(mDozing);
if (mAmbientIndicationContainer instanceof DozeReceiver) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
index 309a1a7..2437c51 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
@@ -143,7 +143,9 @@
final boolean scrimsOccludingWallpaper =
state.scrimsVisibility == ScrimController.VISIBILITY_FULLY_OPAQUE;
- if (state.keyguardShowing && !state.backdropShowing && !scrimsOccludingWallpaper) {
+ final boolean keyguardOrAod = state.keyguardShowing
+ || (state.dozing && mDozeParameters.getAlwaysOn());
+ if (keyguardOrAod && !state.backdropShowing && !scrimsOccludingWallpaper) {
mLpChanged.flags |= WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
} else {
mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index f81ffd8..4a66bb7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -70,6 +70,7 @@
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.assist.AssistManager;
+import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.statusbar.ActivatableNotificationView;
@@ -132,6 +133,7 @@
@Mock private NotificationViewHierarchyManager mViewHierarchyManager;
@Mock private VisualStabilityManager mVisualStabilityManager;
@Mock private NotificationListener mNotificationListener;
+ @Mock private KeyguardViewMediator mKeyguardViewMediator;
private TestableStatusBar mStatusBar;
private FakeMetricsLogger mMetricsLogger;
@@ -200,7 +202,7 @@
mPowerManager, mNotificationPanelView, mBarService, mNotificationListener,
mNotificationLogger, mVisualStabilityManager, mViewHierarchyManager,
mEntryManager, mScrimController, mFingerprintUnlockController,
- mock(ActivityLaunchAnimator.class));
+ mock(ActivityLaunchAnimator.class), mKeyguardViewMediator);
mStatusBar.mContext = mContext;
mStatusBar.mComponents = mContext.getComponents();
mEntryManager.setUpForTest(mStatusBar, mStackScroller, mStatusBar, mHeadsUpManager,
@@ -638,7 +640,7 @@
NotificationViewHierarchyManager viewHierarchyManager,
TestableNotificationEntryManager entryManager, ScrimController scrimController,
FingerprintUnlockController fingerprintUnlockController,
- ActivityLaunchAnimator launchAnimator) {
+ ActivityLaunchAnimator launchAnimator, KeyguardViewMediator keyguardViewMediator) {
mStatusBarKeyguardViewManager = man;
mUnlockMethodCache = unlock;
mKeyguardIndicationController = key;
@@ -656,6 +658,7 @@
mScrimController = scrimController;
mFingerprintUnlockController = fingerprintUnlockController;
mActivityLaunchAnimator = launchAnimator;
+ mKeyguardViewMediator = keyguardViewMediator;
mClearAllEnabled = true;
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 1037561..25d5832 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -820,7 +820,7 @@
public boolean canShowErrorDialogs() {
return mShowDialogs && !mSleeping && !mShuttingDown
- && !mKeyguardController.isKeyguardShowing(DEFAULT_DISPLAY)
+ && !mKeyguardController.isKeyguardOrAodShowing(DEFAULT_DISPLAY)
&& !mUserController.hasUserRestriction(UserManager.DISALLOW_SYSTEM_ERROR_DIALOGS,
mUserController.getCurrentUserId())
&& !(UserManager.isDeviceInDemoMode(mContext)
@@ -10605,8 +10605,8 @@
intent.addFlags(Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS);
}
}
- final ActivityInfo ainfo = AppGlobals.getPackageManager().getActivityInfo(comp, 0,
- UserHandle.getUserId(callingUid));
+ final ActivityInfo ainfo = AppGlobals.getPackageManager().getActivityInfo(comp,
+ STOCK_PM_FLAGS, UserHandle.getUserId(callingUid));
if (ainfo.applicationInfo.uid != callingUid) {
throw new SecurityException(
"Can't add task for another application: target uid="
@@ -13223,7 +13223,8 @@
}
@Override
- public void setLockScreenShown(boolean showing, int secondaryDisplayShowing) {
+ public void setLockScreenShown(boolean keyguardShowing, boolean aodShowing,
+ int secondaryDisplayShowing) {
if (checkCallingPermission(android.Manifest.permission.DEVICE_POWER)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Requires permission "
@@ -13233,13 +13234,14 @@
synchronized(this) {
long ident = Binder.clearCallingIdentity();
try {
- mKeyguardController.setKeyguardShown(showing, secondaryDisplayShowing);
+ mKeyguardController.setKeyguardShown(keyguardShowing, aodShowing,
+ secondaryDisplayShowing);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
- mHandler.obtainMessage(DISPATCH_SCREEN_KEYGUARD_MSG, showing ? 1 : 0, 0)
+ mHandler.obtainMessage(DISPATCH_SCREEN_KEYGUARD_MSG, keyguardShowing ? 1 : 0, 0)
.sendToTarget();
}
@@ -21211,7 +21213,7 @@
ApplicationInfo aInfo = null;
try {
aInfo = AppGlobals.getPackageManager()
- .getApplicationInfo(ssp, 0 /*flags*/, userId);
+ .getApplicationInfo(ssp, STOCK_PM_FLAGS, userId);
} catch (RemoteException ignore) {}
if (aInfo == null) {
Slog.w(TAG, "Dropping ACTION_PACKAGE_REPLACED for non-existent pkg:"
@@ -21236,7 +21238,7 @@
try {
ApplicationInfo ai = AppGlobals.getPackageManager().
- getApplicationInfo(ssp, 0, 0);
+ getApplicationInfo(ssp, STOCK_PM_FLAGS, 0);
mBatteryStatsService.notePackageInstalled(ssp,
ai != null ? ai.versionCode : 0);
} catch (RemoteException e) {
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index ccc17a3..1af4114 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -236,7 +236,8 @@
final IApplicationToken.Stub appToken; // window manager token
AppWindowContainerController mWindowContainerController;
final ActivityInfo info; // all about me
- final ApplicationInfo appInfo; // information about activity's app
+ // TODO: This is duplicated state already contained in info.applicationInfo - remove
+ ApplicationInfo appInfo; // information about activity's app
final int launchedFromPid; // always the pid who started the activity.
final int launchedFromUid; // always the uid who started the activity.
final String launchedFromPackage; // always the package who started the activity.
@@ -605,6 +606,11 @@
}
}
+ void updateApplicationInfo(ApplicationInfo aInfo) {
+ appInfo = aInfo;
+ info.applicationInfo = aInfo;
+ }
+
private boolean crossesHorizontalSizeThreshold(int firstDp, int secondDp) {
return crossesSizeThreshold(mHorizontalSizeConfigurations, firstDp, secondDp);
}
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index aa462ec..00ebcbd 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -1324,7 +1324,7 @@
final ActivityRecord ar = activities.get(activityNdx);
if ((userId == ar.userId) && packageName.equals(ar.packageName)) {
- ar.info.applicationInfo = aInfo;
+ ar.updateApplicationInfo(aInfo);
}
}
}
@@ -2019,8 +2019,9 @@
* @return true if {@param r} is visible taken Keyguard state into account, false otherwise
*/
boolean checkKeyguardVisibility(ActivityRecord r, boolean shouldBeVisible, boolean isTop) {
- final boolean keyguardShowing = mStackSupervisor.getKeyguardController().isKeyguardShowing(
- mDisplayId != INVALID_DISPLAY ? mDisplayId : DEFAULT_DISPLAY);
+ final int displayId = mDisplayId != INVALID_DISPLAY ? mDisplayId : DEFAULT_DISPLAY;
+ final boolean keyguardOrAodShowing = mStackSupervisor.getKeyguardController()
+ .isKeyguardOrAodShowing(displayId);
final boolean keyguardLocked = mStackSupervisor.getKeyguardController().isKeyguardLocked();
final boolean showWhenLocked = r.canShowWhenLocked();
final boolean dismissKeyguard = r.hasDismissKeyguardWindows();
@@ -2041,10 +2042,9 @@
return true;
}
}
- if (keyguardShowing) {
-
+ if (keyguardOrAodShowing) {
// If keyguard is showing, nothing is visible, except if we are able to dismiss Keyguard
- // right away.
+ // right away and AOD isn't visible.
return shouldBeVisible && mStackSupervisor.getKeyguardController()
.canShowActivityWhileKeyguardShowing(r, dismissKeyguard);
} else if (keyguardLocked) {
@@ -3987,7 +3987,8 @@
} else {
try {
ActivityInfo aInfo = AppGlobals.getPackageManager().getActivityInfo(
- destIntent.getComponent(), 0, srec.userId);
+ destIntent.getComponent(), ActivityManagerService.STOCK_PM_FLAGS,
+ srec.userId);
// TODO(b/64750076): Check if calling pid should really be -1.
final int res = mService.getActivityStartController()
.obtainStarter(destIntent, "navigateUpTo")
@@ -5139,8 +5140,9 @@
mService, taskId, info, intent, voiceSession, voiceInteractor);
// add the task to stack first, mTaskPositioner might need the stack association
addTask(task, toTop, "createTaskRecord");
+ final int displayId = mDisplayId != INVALID_DISPLAY ? mDisplayId : DEFAULT_DISPLAY;
final boolean isLockscreenShown = mService.mStackSupervisor.getKeyguardController()
- .isKeyguardShowing(mDisplayId != INVALID_DISPLAY ? mDisplayId : DEFAULT_DISPLAY);
+ .isKeyguardOrAodShowing(displayId);
if (!mStackSupervisor.getLaunchParamsController()
.layoutTask(task, info.windowLayout, activity, source, options)
&& !matchParentBounds() && task.isResizeable() && !isLockscreenShown) {
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 265e4fa..d5dfdcf 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -3382,8 +3382,8 @@
stack.goToSleepIfPossible(false /* shuttingDown */);
} else {
stack.awakeFromSleepingLocked();
- if (isFocusedStack(stack)
- && !getKeyguardController().isKeyguardShowing(display.mDisplayId)) {
+ if (isFocusedStack(stack) && !getKeyguardController().isKeyguardOrAodShowing(
+ display.mDisplayId)) {
// If the keyguard is unlocked - resume immediately.
// It is possible that the display will not be awake at the time we
// process the keyguard going away, which can happen before the sleep token
diff --git a/services/core/java/com/android/server/am/ActivityStartController.java b/services/core/java/com/android/server/am/ActivityStartController.java
index 868f90d..fb78838 100644
--- a/services/core/java/com/android/server/am/ActivityStartController.java
+++ b/services/core/java/com/android/server/am/ActivityStartController.java
@@ -198,9 +198,10 @@
// See if we should be showing the platform update setup UI.
final Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
- final List<ResolveInfo> ris = mService.mContext.getPackageManager()
- .queryIntentActivities(intent,
- PackageManager.MATCH_SYSTEM_ONLY | PackageManager.GET_META_DATA);
+ final List<ResolveInfo> ris =
+ mService.mContext.getPackageManager().queryIntentActivities(intent,
+ PackageManager.MATCH_SYSTEM_ONLY | PackageManager.GET_META_DATA
+ | ActivityManagerService.STOCK_PM_FLAGS);
if (!ris.isEmpty()) {
final ResolveInfo ri = ris.get(0);
String vers = ri.activityInfo.metaData != null
diff --git a/services/core/java/com/android/server/am/KeyguardController.java b/services/core/java/com/android/server/am/KeyguardController.java
index b67dd0d..1b7f75b 100644
--- a/services/core/java/com/android/server/am/KeyguardController.java
+++ b/services/core/java/com/android/server/am/KeyguardController.java
@@ -62,6 +62,7 @@
private final ActivityStackSupervisor mStackSupervisor;
private WindowManagerService mWindowManager;
private boolean mKeyguardShowing;
+ private boolean mAodShowing;
private boolean mKeyguardGoingAway;
private boolean mOccluded;
private boolean mDismissalRequested;
@@ -82,6 +83,15 @@
}
/**
+ * @return true if either Keyguard or AOD are showing, not going away, and not being occluded
+ * on the given display, false otherwise
+ */
+ boolean isKeyguardOrAodShowing(int displayId) {
+ return (mKeyguardShowing || mAodShowing) && !mKeyguardGoingAway &&
+ (displayId == DEFAULT_DISPLAY ? !mOccluded : displayId == mSecondaryDisplayShowing);
+ }
+
+ /**
* @return true if Keyguard is showing, not going away, and not being occluded on the given
* display, false otherwise
*/
@@ -108,17 +118,19 @@
/**
* Update the Keyguard showing state.
*/
- void setKeyguardShown(boolean showing, int secondaryDisplayShowing) {
- boolean showingChanged = showing != mKeyguardShowing;
+ void setKeyguardShown(boolean keyguardShowing, boolean aodShowing,
+ int secondaryDisplayShowing) {
+ boolean showingChanged = keyguardShowing != mKeyguardShowing || aodShowing != mAodShowing;
if (!showingChanged && secondaryDisplayShowing == mSecondaryDisplayShowing) {
return;
}
- mKeyguardShowing = showing;
+ mKeyguardShowing = keyguardShowing;
+ mAodShowing = aodShowing;
mSecondaryDisplayShowing = secondaryDisplayShowing;
if (showingChanged) {
dismissDockedStackIfNeeded();
setKeyguardGoingAway(false);
- if (showing) {
+ if (keyguardShowing) {
mDismissalRequested = false;
}
}
@@ -230,8 +242,8 @@
// Allow to show it when we are about to dismiss Keyguard. This isn't allowed if r is
// already the dismissing activity, in which case we don't allow it to repeatedly dismiss
// Keyguard.
- return dismissKeyguard && canDismissKeyguard() &&
- (mDismissalRequested || r != mDismissingKeyguardActivity);
+ return dismissKeyguard && canDismissKeyguard() && !mAodShowing
+ && (mDismissalRequested || r != mDismissingKeyguardActivity);
}
/**
@@ -369,9 +381,9 @@
}
private void updateKeyguardSleepToken() {
- if (mSleepToken == null && isKeyguardShowing(DEFAULT_DISPLAY)) {
+ if (mSleepToken == null && isKeyguardOrAodShowing(DEFAULT_DISPLAY)) {
mSleepToken = mService.acquireSleepToken("Keyguard", DEFAULT_DISPLAY);
- } else if (mSleepToken != null && !isKeyguardShowing(DEFAULT_DISPLAY)) {
+ } else if (mSleepToken != null && !isKeyguardOrAodShowing(DEFAULT_DISPLAY)) {
mSleepToken.release();
mSleepToken = null;
}
@@ -380,6 +392,7 @@
void dump(PrintWriter pw, String prefix) {
pw.println(prefix + "KeyguardController:");
pw.println(prefix + " mKeyguardShowing=" + mKeyguardShowing);
+ pw.println(prefix + " mAodShowing=" + mAodShowing);
pw.println(prefix + " mKeyguardGoingAway=" + mKeyguardGoingAway);
pw.println(prefix + " mOccluded=" + mOccluded);
pw.println(prefix + " mDismissingKeyguardActivity=" + mDismissingKeyguardActivity);
diff --git a/services/core/java/com/android/server/am/RecentTasks.java b/services/core/java/com/android/server/am/RecentTasks.java
index efd81538..fcf00ce 100644
--- a/services/core/java/com/android/server/am/RecentTasks.java
+++ b/services/core/java/com/android/server/am/RecentTasks.java
@@ -600,7 +600,8 @@
// activities that are fully runnable based on
// current system state.
ai = pm.getActivityInfo(task.realActivity,
- PackageManager.MATCH_DEBUG_TRIAGED_MISSING, userId);
+ PackageManager.MATCH_DEBUG_TRIAGED_MISSING
+ | ActivityManagerService.STOCK_PM_FLAGS, userId);
} catch (RemoteException e) {
// Will never happen.
continue;
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 9b67bbd..2ae337d 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -92,6 +92,7 @@
import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_PARENT;
import static com.android.internal.content.NativeLibraryHelper.LIB64_DIR_NAME;
import static com.android.internal.content.NativeLibraryHelper.LIB_DIR_NAME;
+import static com.android.internal.util.ArrayUtils.appendElement;
import static com.android.internal.util.ArrayUtils.appendInt;
import static com.android.server.pm.InstructionSets.getAppDexInstructionSets;
import static com.android.server.pm.InstructionSets.getDexCodeInstructionSet;
@@ -778,8 +779,14 @@
return PackageManagerService.this.hasSystemFeature(feature, 0);
}
- final List<PackageParser.Package> getStaticOverlayPackagesLocked(
+ final List<PackageParser.Package> getStaticOverlayPackages(
Collection<PackageParser.Package> allPackages, String targetPackageName) {
+ if ("android".equals(targetPackageName)) {
+ // Static RROs targeting to "android", ie framework-res.apk, are already applied by
+ // native AssetManager.
+ return null;
+ }
+
List<PackageParser.Package> overlayPackages = null;
for (PackageParser.Package p : allPackages) {
if (targetPackageName.equals(p.mOverlayTarget) && p.mOverlayIsStatic) {
@@ -800,16 +807,8 @@
return overlayPackages;
}
- @GuardedBy("mInstallLock")
- final String[] getStaticOverlayPathsLocked(Collection<PackageParser.Package> allPackages,
- String targetPackageName, String targetPath) {
- if ("android".equals(targetPackageName)) {
- // Static RROs targeting to "android", ie framework-res.apk, are already applied by
- // native AssetManager.
- return null;
- }
- List<PackageParser.Package> overlayPackages =
- getStaticOverlayPackagesLocked(allPackages, targetPackageName);
+ final String[] getStaticOverlayPaths(List<PackageParser.Package> overlayPackages,
+ String targetPath) {
if (overlayPackages == null || overlayPackages.isEmpty()) {
return null;
}
@@ -829,9 +828,11 @@
//
// OverlayManagerService will update each of them with a correct gid from its
// target package app id.
- mInstaller.idmap(targetPath, overlayPackage.baseCodePath,
- UserHandle.getSharedAppGid(
- UserHandle.getUserGid(UserHandle.USER_SYSTEM)));
+ synchronized (mInstallLock) {
+ mInstaller.idmap(targetPath, overlayPackage.baseCodePath,
+ UserHandle.getSharedAppGid(
+ UserHandle.getUserGid(UserHandle.USER_SYSTEM)));
+ }
if (overlayPathList == null) {
overlayPathList = new ArrayList<String>();
}
@@ -845,10 +846,14 @@
}
String[] getStaticOverlayPaths(String targetPackageName, String targetPath) {
+ List<PackageParser.Package> overlayPackages;
synchronized (mPackages) {
- return getStaticOverlayPathsLocked(
- mPackages.values(), targetPackageName, targetPath);
+ overlayPackages = getStaticOverlayPackages(
+ mPackages.values(), targetPackageName);
}
+ // It is safe to keep overlayPackages without holding mPackages because static overlay
+ // packages can't be uninstalled or disabled.
+ return getStaticOverlayPaths(overlayPackages, targetPath);
}
@Override public final String[] getOverlayApks(String targetPackageName) {
@@ -883,7 +888,9 @@
// can't happen while running parallel parsing.
// Moreover holding mPackages on each parsing thread causes dead-lock.
return mOverlayPackages == null ? null :
- getStaticOverlayPathsLocked(mOverlayPackages, targetPackageName, targetPath);
+ getStaticOverlayPaths(
+ getStaticOverlayPackages(mOverlayPackages, targetPackageName),
+ targetPath);
}
}
@@ -13987,18 +13994,15 @@
return packageNames;
}
- // List of package names for whom the suspended state has changed.
- final List<String> changedPackages = new ArrayList<>(packageNames.length);
- // List of package names for whom the suspended state is not set as requested in this
- // method.
+ final List<String> changedPackagesList = new ArrayList<>(packageNames.length);
final List<String> unactionedPackages = new ArrayList<>(packageNames.length);
final long callingId = Binder.clearCallingIdentity();
try {
synchronized (mPackages) {
for (int i = 0; i < packageNames.length; i++) {
final String packageName = packageNames[i];
- if (packageName == callingPackage) {
- Slog.w(TAG, "Calling package: " + callingPackage + "trying to "
+ if (callingPackage.equals(packageName)) {
+ Slog.w(TAG, "Calling package: " + callingPackage + " trying to "
+ (suspended ? "" : "un") + "suspend itself. Ignoring");
unactionedPackages.add(packageName);
continue;
@@ -14018,17 +14022,18 @@
}
pkgSetting.setSuspended(suspended, callingPackage, appExtras,
launcherExtras, userId);
- changedPackages.add(packageName);
+ changedPackagesList.add(packageName);
}
}
}
} finally {
Binder.restoreCallingIdentity(callingId);
}
- // TODO (b/75036698): Also send each package a broadcast when suspended state changed
- if (!changedPackages.isEmpty()) {
- sendPackagesSuspendedForUser(changedPackages.toArray(
- new String[changedPackages.size()]), userId, suspended);
+ if (!changedPackagesList.isEmpty()) {
+ final String[] changedPackages = changedPackagesList.toArray(
+ new String[changedPackagesList.size()]);
+ sendPackagesSuspendedForUser(changedPackages, userId, suspended);
+ sendMyPackageSuspendedOrUnsuspended(changedPackages, suspended, appExtras, userId);
synchronized (mPackages) {
scheduleWritePackageRestrictionsLocked(userId);
}
@@ -14038,7 +14043,7 @@
}
@Override
- public PersistableBundle getPackageSuspendedAppExtras(String packageName, int userId) {
+ public PersistableBundle getSuspendedPackageAppExtras(String packageName, int userId) {
final int callingUid = Binder.getCallingUid();
if (getPackageUid(packageName, 0, userId) != callingUid) {
mContext.enforceCallingOrSelfPermission(Manifest.permission.SUSPEND_APPS, null);
@@ -14049,7 +14054,10 @@
throw new IllegalArgumentException("Unknown target package: " + packageName);
}
final PackageUserState packageUserState = ps.readUserState(userId);
- return packageUserState.suspended ? packageUserState.suspendedAppExtras : null;
+ if (packageUserState.suspended) {
+ return packageUserState.suspendedAppExtras;
+ }
+ return null;
}
}
@@ -14065,12 +14073,49 @@
}
final PackageUserState packageUserState = ps.readUserState(userId);
if (packageUserState.suspended) {
- // TODO (b/75036698): Also send this package a broadcast with the new app extras
packageUserState.suspendedAppExtras = appExtras;
+ sendMyPackageSuspendedOrUnsuspended(new String[] {packageName}, true, appExtras,
+ userId);
}
}
}
+ private void sendMyPackageSuspendedOrUnsuspended(String[] affectedPackages, boolean suspended,
+ PersistableBundle appExtras, int userId) {
+ final String action;
+ final Bundle intentExtras = new Bundle();
+ if (suspended) {
+ action = Intent.ACTION_MY_PACKAGE_SUSPENDED;
+ if (appExtras != null) {
+ final Bundle bundledAppExtras = new Bundle(appExtras.deepCopy());
+ intentExtras.putBundle(Intent.EXTRA_SUSPENDED_PACKAGE_EXTRAS, bundledAppExtras);
+ }
+ } else {
+ action = Intent.ACTION_MY_PACKAGE_UNSUSPENDED;
+ }
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ final IActivityManager am = ActivityManager.getService();
+ if (am == null) {
+ Slog.wtf(TAG, "IActivityManager null. Cannot send MY_PACKAGE_ "
+ + (suspended ? "" : "UN") + "SUSPENDED broadcasts");
+ return;
+ }
+ final int[] targetUserIds = new int[] {userId};
+ for (String packageName : affectedPackages) {
+ doSendBroadcast(am, action, null, intentExtras,
+ Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND, packageName, null,
+ targetUserIds, false);
+ }
+ } catch (RemoteException ex) {
+ // Shouldn't happen as AMS is in the same process.
+ }
+ }
+ });
+ }
+
@Override
public boolean isPackageSuspendedForUser(String packageName, int userId) {
final int callingUid = Binder.getCallingUid();
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
index 062b154..81a8c55 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
@@ -213,7 +213,8 @@
// There are no longer any keyguard windows on secondary displays, so pass
// INVALID_DISPLAY. All that means is that showWhenLocked activities on
// secondary displays now get to show.
- ActivityManager.getService().setLockScreenShown(true, INVALID_DISPLAY);
+ ActivityManager.getService().setLockScreenShown(true /* keyguardShowing */,
+ false /* aodShowing */, INVALID_DISPLAY);
} catch (RemoteException e) {
// Local call.
}
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
index b452ea5..cda968a7 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
@@ -240,7 +240,7 @@
doReturn(displayShouldSleep).when(display).shouldSleep();
doReturn(displaySleeping).when(display).isSleeping();
- doReturn(keyguardShowing).when(keyguard).isKeyguardShowing(anyInt());
+ doReturn(keyguardShowing).when(keyguard).isKeyguardOrAodShowing(anyInt());
mSupervisor.mFocusedStack = isFocusedStack ? stack : null;
mSupervisor.applySleepTokensLocked(true);
diff --git a/services/tests/servicestests/src/com/android/server/pm/SuspendPackagesTest.java b/services/tests/servicestests/src/com/android/server/pm/SuspendPackagesTest.java
index d702318..ee0ad39 100644
--- a/services/tests/servicestests/src/com/android/server/pm/SuspendPackagesTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/SuspendPackagesTest.java
@@ -16,55 +16,129 @@
package com.android.server.pm;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import android.app.AppGlobals;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.os.BaseBundle;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.PersistableBundle;
+import android.os.RemoteException;
import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.MediumTest;
+import android.support.test.filters.LargeTest;
import android.support.test.runner.AndroidJUnit4;
import com.android.servicestests.apps.suspendtestapp.SuspendTestReceiver;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
@RunWith(AndroidJUnit4.class)
-@MediumTest
+@LargeTest
public class SuspendPackagesTest {
private static final String TEST_APP_PACKAGE_NAME = SuspendTestReceiver.PACKAGE_NAME;
private static final String[] PACKAGES_TO_SUSPEND = new String[]{TEST_APP_PACKAGE_NAME};
+ public static final String INSTRUMENTATION_PACKAGE = "com.android.frameworks.servicestests";
+ public static final String ACTION_REPORT_MY_PACKAGE_SUSPENDED =
+ INSTRUMENTATION_PACKAGE + ".action.REPORT_MY_PACKAGE_SUSPENDED";
+ public static final String ACTION_REPORT_MY_PACKAGE_UNSUSPENDED =
+ INSTRUMENTATION_PACKAGE + ".action.REPORT_MY_PACKAGE_UNSUSPENDED";
+
private Context mContext;
private PackageManager mPackageManager;
private Handler mReceiverHandler;
private ComponentName mTestReceiverComponent;
+ private AppCommunicationReceiver mAppCommsReceiver;
+
+ private static final class AppCommunicationReceiver extends BroadcastReceiver {
+ private Context context;
+ private boolean registered;
+ private SynchronousQueue<Intent> intentQueue = new SynchronousQueue<>();
+
+ AppCommunicationReceiver(Context context) {
+ this.context = context;
+ }
+
+ void register(Handler handler) {
+ registered = true;
+ final IntentFilter intentFilter = new IntentFilter();
+ intentFilter.addAction(ACTION_REPORT_MY_PACKAGE_SUSPENDED);
+ intentFilter.addAction(ACTION_REPORT_MY_PACKAGE_UNSUSPENDED);
+ context.registerReceiver(this, intentFilter, null, handler);
+ }
+
+ void unregister() {
+ if (registered) {
+ context.unregisterReceiver(this);
+ }
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ try {
+ intentQueue.offer(intent, 5, TimeUnit.SECONDS);
+ } catch (InterruptedException ie) {
+ throw new RuntimeException("Receiver thread interrupted", ie);
+ }
+ }
+
+ Intent receiveIntentFromApp() {
+ if (!registered) {
+ throw new IllegalStateException("Receiver not registered");
+ }
+ final Intent intent;
+ try {
+ intent = intentQueue.poll(5, TimeUnit.SECONDS);
+ } catch (InterruptedException ie) {
+ throw new RuntimeException("Interrupted while waiting for app broadcast", ie);
+ }
+ assertNotNull("No intent received from app within 5 seconds", intent);
+ return intent;
+ }
+ }
@Before
public void setUp() {
mContext = InstrumentationRegistry.getTargetContext();
mPackageManager = mContext.getPackageManager();
- mPackageManager.setPackagesSuspended(PACKAGES_TO_SUSPEND, false, null, null, null);
mReceiverHandler = new Handler(Looper.getMainLooper());
mTestReceiverComponent = new ComponentName(TEST_APP_PACKAGE_NAME,
SuspendTestReceiver.class.getCanonicalName());
+ IPackageManager ipm = AppGlobals.getPackageManager();
+ try {
+ // Otherwise implicit broadcasts will not be delivered.
+ ipm.setPackageStoppedState(TEST_APP_PACKAGE_NAME, false, mContext.getUserId());
+ } catch (RemoteException e) {
+ e.rethrowAsRuntimeException();
+ }
+ unsuspendTestPackage();
+ mAppCommsReceiver = new AppCommunicationReceiver(mContext);
}
+ /**
+ * Care should be taken when used with {@link #mAppCommsReceiver} in the same test as both use
+ * the same handler.
+ */
private Bundle requestAppAction(String action) throws InterruptedException {
final AtomicReference<Bundle> result = new AtomicReference<>();
final CountDownLatch receiverLatch = new CountDownLatch(1);
@@ -98,6 +172,24 @@
assertTrue("setPackagesSuspended returned non-empty list", unchangedPackages.length == 0);
}
+ private void unsuspendTestPackage() {
+ final String[] unchangedPackages = mPackageManager.setPackagesSuspended(
+ PACKAGES_TO_SUSPEND, false, null, null, null);
+ assertTrue("setPackagesSuspended returned non-empty list", unchangedPackages.length == 0);
+ }
+
+
+ private static void assertSameExtras(String message, BaseBundle expected, BaseBundle received) {
+ if (expected != null) {
+ expected.get(""); // hack to unparcel the bundles.
+ }
+ if (received != null) {
+ received.get("");
+ }
+ assertTrue(message + ": [expected: " + expected + "; received: " + received + "]",
+ BaseBundle.kindofEquals(expected, received));
+ }
+
@Test
public void testIsPackageSuspended() {
suspendTestPackage(null, null);
@@ -109,19 +201,73 @@
public void testSuspendedStateFromApp() throws Exception {
Bundle resultFromApp = requestAppAction(SuspendTestReceiver.ACTION_GET_SUSPENDED_STATE);
assertFalse(resultFromApp.getBoolean(SuspendTestReceiver.EXTRA_SUSPENDED, true));
- assertNull(resultFromApp.getParcelable(SuspendTestReceiver.EXTRA_SUSPENDED_APP_EXTRAS));
+ assertNull(resultFromApp.getBundle(SuspendTestReceiver.EXTRA_SUSPENDED_APP_EXTRAS));
- final PersistableBundle appExtras = getExtras("appExtras", 20, "20", 0.2);
+ final PersistableBundle appExtras = getExtras("testSuspendedStateFromApp", 20, "20", 0.2);
suspendTestPackage(appExtras, null);
resultFromApp = requestAppAction(SuspendTestReceiver.ACTION_GET_SUSPENDED_STATE);
assertTrue("resultFromApp:suspended is false",
resultFromApp.getBoolean(SuspendTestReceiver.EXTRA_SUSPENDED));
- final PersistableBundle receivedAppExtras =
- resultFromApp.getParcelable(SuspendTestReceiver.EXTRA_SUSPENDED_APP_EXTRAS);
- receivedAppExtras.get(""); // hack to unparcel the bundles
- appExtras.get("");
- assertTrue("Received app extras " + receivedAppExtras + " different to the ones supplied",
- BaseBundle.kindofEquals(appExtras, receivedAppExtras));
+ final Bundle receivedAppExtras =
+ resultFromApp.getBundle(SuspendTestReceiver.EXTRA_SUSPENDED_APP_EXTRAS);
+ assertSameExtras("Received app extras different to the ones supplied",
+ appExtras, receivedAppExtras);
+ }
+
+ @Test
+ public void testMyPackageSuspendedUnsuspended() {
+ mAppCommsReceiver.register(mReceiverHandler);
+ final PersistableBundle appExtras = getExtras("testMyPackageSuspendBroadcasts", 1, "1", .1);
+ suspendTestPackage(appExtras, null);
+ Intent intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
+ assertTrue("MY_PACKAGE_SUSPENDED delivery not reported",
+ ACTION_REPORT_MY_PACKAGE_SUSPENDED.equals(intentFromApp.getAction()));
+ assertSameExtras("Received app extras different to the ones supplied", appExtras,
+ intentFromApp.getBundleExtra(SuspendTestReceiver.EXTRA_SUSPENDED_APP_EXTRAS));
+ unsuspendTestPackage();
+ intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
+ assertTrue("MY_PACKAGE_UNSUSPENDED delivery not reported",
+ ACTION_REPORT_MY_PACKAGE_UNSUSPENDED.equals(intentFromApp.getAction()));
+ }
+
+ @Test
+ public void testUpdatingAppExtras() {
+ mAppCommsReceiver.register(mReceiverHandler);
+ final PersistableBundle extras1 = getExtras("testMyPackageSuspendedOnChangingExtras", 1,
+ "1", 0.1);
+ suspendTestPackage(extras1, null);
+ Intent intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
+ assertTrue("MY_PACKAGE_SUSPENDED delivery not reported",
+ ACTION_REPORT_MY_PACKAGE_SUSPENDED.equals(intentFromApp.getAction()));
+ assertSameExtras("Received app extras different to the ones supplied", extras1,
+ intentFromApp.getBundleExtra(SuspendTestReceiver.EXTRA_SUSPENDED_APP_EXTRAS));
+ final PersistableBundle extras2 = getExtras("testMyPackageSuspendedOnChangingExtras", 2,
+ "2", 0.2);
+ mPackageManager.setSuspendedPackageAppExtras(TEST_APP_PACKAGE_NAME, extras2);
+ intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
+ assertTrue("MY_PACKAGE_SUSPENDED delivery not reported",
+ ACTION_REPORT_MY_PACKAGE_SUSPENDED.equals(intentFromApp.getAction()));
+ assertSameExtras("Received app extras different to the updated extras", extras2,
+ intentFromApp.getBundleExtra(SuspendTestReceiver.EXTRA_SUSPENDED_APP_EXTRAS));
+ }
+
+ @Test
+ public void testCannotSuspendSelf() {
+ final String[] unchangedPkgs = mPackageManager.setPackagesSuspended(
+ new String[]{mContext.getOpPackageName()}, true, null, null, null);
+ assertTrue(unchangedPkgs.length == 1);
+ assertEquals(mContext.getOpPackageName(), unchangedPkgs[0]);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ mAppCommsReceiver.unregister();
+ Thread.sleep(250); // To prevent any race with the next registerReceiver
+ }
+
+ @FunctionalInterface
+ interface Condition {
+ boolean isTrue();
}
}
diff --git a/services/tests/servicestests/test-apps/SuspendTestApp/Android.mk b/services/tests/servicestests/test-apps/SuspendTestApp/Android.mk
index 40a34b9..afdde72 100644
--- a/services/tests/servicestests/test-apps/SuspendTestApp/Android.mk
+++ b/services/tests/servicestests/test-apps/SuspendTestApp/Android.mk
@@ -17,14 +17,18 @@
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := tests
-LOCAL_SDK_VERSION := current
LOCAL_COMPATIBILITY_SUITE := device-tests
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+
LOCAL_SRC_FILES := $(call all-subdir-java-files)
+LOCAL_SRC_FILES += ../../src/com/android/server/pm/SuspendPackagesTest.java
LOCAL_PACKAGE_NAME := SuspendTestApp
LOCAL_DEX_PREOPT := false
LOCAL_PROGUARD_ENABLED := disabled
+LOCAL_PRIVATE_PLATFORM_APIS := true
+
include $(BUILD_PACKAGE)
\ No newline at end of file
diff --git a/services/tests/servicestests/test-apps/SuspendTestApp/AndroidManifest.xml b/services/tests/servicestests/test-apps/SuspendTestApp/AndroidManifest.xml
index 70a1fd0..ce6a27a 100644
--- a/services/tests/servicestests/test-apps/SuspendTestApp/AndroidManifest.xml
+++ b/services/tests/servicestests/test-apps/SuspendTestApp/AndroidManifest.xml
@@ -21,7 +21,12 @@
<activity android:name=".SuspendTestActivity"
android:exported="true" />
<receiver android:name=".SuspendTestReceiver"
- android:exported="true" />
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MY_PACKAGE_SUSPENDED" />
+ <action android:name="android.intent.action.MY_PACKAGE_UNSUSPENDED" />
+ </intent-filter>
+ </receiver>
</application>
</manifest>
\ No newline at end of file
diff --git a/services/tests/servicestests/test-apps/SuspendTestApp/src/com/android/servicestests/apps/suspendtestapp/SuspendTestReceiver.java b/services/tests/servicestests/test-apps/SuspendTestApp/src/com/android/servicestests/apps/suspendtestapp/SuspendTestReceiver.java
index 6f353a0..90a9f01 100644
--- a/services/tests/servicestests/test-apps/SuspendTestApp/src/com/android/servicestests/apps/suspendtestapp/SuspendTestReceiver.java
+++ b/services/tests/servicestests/test-apps/SuspendTestApp/src/com/android/servicestests/apps/suspendtestapp/SuspendTestReceiver.java
@@ -16,12 +16,15 @@
package com.android.servicestests.apps.suspendtestapp;
+import static com.android.server.pm.SuspendPackagesTest.ACTION_REPORT_MY_PACKAGE_SUSPENDED;
+import static com.android.server.pm.SuspendPackagesTest.ACTION_REPORT_MY_PACKAGE_UNSUSPENDED;
+import static com.android.server.pm.SuspendPackagesTest.INSTRUMENTATION_PACKAGE;
+
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
-import android.os.PersistableBundle;
import android.util.Log;
public class SuspendTestReceiver extends BroadcastReceiver {
@@ -34,21 +37,33 @@
public static final String EXTRA_SUSPENDED_APP_EXTRAS =
PACKAGE_NAME + ".extra.SUSPENDED_APP_EXTRAS";
- private PackageManager mPm;
-
@Override
public void onReceive(Context context, Intent intent) {
- mPm = context.getPackageManager();
- Log.d(TAG, "Received request action " + intent.getAction());
+ final PackageManager packageManager = context.getPackageManager();
+ Log.d(TAG, "Received action " + intent.getAction());
+ final Bundle appExtras;
switch (intent.getAction()) {
case ACTION_GET_SUSPENDED_STATE:
final Bundle result = new Bundle();
- final boolean suspended = mPm.isPackageSuspended();
- final PersistableBundle appExtras = mPm.getSuspendedPackageAppExtras();
+ final boolean suspended = packageManager.isPackageSuspended();
+ appExtras = packageManager.getSuspendedPackageAppExtras();
result.putBoolean(EXTRA_SUSPENDED, suspended);
- result.putParcelable(EXTRA_SUSPENDED_APP_EXTRAS, appExtras);
+ result.putBundle(EXTRA_SUSPENDED_APP_EXTRAS, appExtras);
setResult(0, null, result);
break;
+ case Intent.ACTION_MY_PACKAGE_SUSPENDED:
+ appExtras = intent.getBundleExtra(Intent.EXTRA_SUSPENDED_PACKAGE_EXTRAS);
+ final Intent reportSuspendIntent = new Intent(ACTION_REPORT_MY_PACKAGE_SUSPENDED)
+ .putExtra(EXTRA_SUSPENDED_APP_EXTRAS, appExtras)
+ .setPackage(INSTRUMENTATION_PACKAGE);
+ context.sendBroadcast(reportSuspendIntent);
+ break;
+ case Intent.ACTION_MY_PACKAGE_UNSUSPENDED:
+ final Intent reportUnsuspendIntent =
+ new Intent(ACTION_REPORT_MY_PACKAGE_UNSUSPENDED)
+ .setPackage(INSTRUMENTATION_PACKAGE);
+ context.sendBroadcast(reportUnsuspendIntent);
+ break;
default:
Log.e(TAG, "Unknown action: " + intent.getAction());
}