Merge "Show snoozed conversations in conversation header" into rvc-dev
diff --git a/apex/statsd/aidl/Android.bp b/apex/statsd/aidl/Android.bp
index 487c8e1..404c632 100644
--- a/apex/statsd/aidl/Android.bp
+++ b/apex/statsd/aidl/Android.bp
@@ -31,7 +31,7 @@
],
backend: {
java: {
- enabled: false, // the platform uses statsd_java_aidl
+ enabled: false, // framework-statsd and service-statsd use framework-statsd-aidl-sources
},
cpp: {
enabled: false,
diff --git a/apex/statsd/tests/libstatspull/Android.bp b/apex/statsd/tests/libstatspull/Android.bp
index e813964..2d64f19 100644
--- a/apex/statsd/tests/libstatspull/Android.bp
+++ b/apex/statsd/tests/libstatspull/Android.bp
@@ -48,9 +48,13 @@
"-Werror",
],
shared_libs: [
- "libbinder",
- "libutils",
- "libstatspull",
- "libstatssocket",
+ "libbinder_ndk",
+ "statsd-aidl-ndk_platform",
],
-}
\ No newline at end of file
+ static_libs: [
+ "libstatspull_private",
+ "libstatssocket_private",
+ "libutils",
+ "libcutils",
+ ],
+}
diff --git a/apex/statsd/tests/libstatspull/jni/stats_pull_helper.cpp b/apex/statsd/tests/libstatspull/jni/stats_pull_helper.cpp
index 22daa8e..eb97f65 100644
--- a/apex/statsd/tests/libstatspull/jni/stats_pull_helper.cpp
+++ b/apex/statsd/tests/libstatspull/jni/stats_pull_helper.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include <binder/ProcessState.h>
+#include <android/binder_process.h>
#include <jni.h>
#include <log/log.h>
#include <stats_event.h>
@@ -24,7 +24,6 @@
#include <thread>
using std::this_thread::sleep_for;
-using namespace android;
namespace {
static int32_t sAtomTag;
@@ -39,10 +38,8 @@
if (!initialized) {
initialized = true;
// Set up the binder
- sp<ProcessState> ps(ProcessState::self());
- ps->setThreadPoolMaxThreadCount(9);
- ps->startThreadPool();
- ps->giveThreadPoolName();
+ ABinderProcess_setThreadPoolMaxThreadCount(9);
+ ABinderProcess_startThreadPool();
}
}
diff --git a/api/current.txt b/api/current.txt
index 2ec3bcc..ca19c39 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -27059,7 +27059,7 @@
method public void unregisterTransferCallback(@NonNull android.media.MediaRouter2.TransferCallback);
}
- public static class MediaRouter2.ControllerCallback {
+ public abstract static class MediaRouter2.ControllerCallback {
ctor public MediaRouter2.ControllerCallback();
method public void onControllerUpdated(@NonNull android.media.MediaRouter2.RoutingController);
}
@@ -27068,7 +27068,7 @@
method @Nullable public android.os.Bundle onGetControllerHints(@NonNull android.media.MediaRoute2Info);
}
- public static class MediaRouter2.RouteCallback {
+ public abstract static class MediaRouter2.RouteCallback {
ctor public MediaRouter2.RouteCallback();
method public void onRoutesAdded(@NonNull java.util.List<android.media.MediaRoute2Info>);
method public void onRoutesChanged(@NonNull java.util.List<android.media.MediaRoute2Info>);
@@ -27091,7 +27091,7 @@
method public void setVolume(int);
}
- public static class MediaRouter2.TransferCallback {
+ public abstract static class MediaRouter2.TransferCallback {
ctor public MediaRouter2.TransferCallback();
method public void onTransferFailed(@NonNull android.media.MediaRoute2Info);
method public void onTransferred(@NonNull android.media.MediaRouter2.RoutingController, @Nullable android.media.MediaRouter2.RoutingController);
diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp
index 73a8f66..0c3a49a 100644
--- a/cmds/statsd/Android.bp
+++ b/cmds/statsd/Android.bp
@@ -302,11 +302,7 @@
static_libs: [
"libgmock",
"libplatformprotos",
-
- // TODO(b/149842105): Make libstatssocket shared and remove libcutils once statsd_test is
- // moved to the apex.
- "libstatssocket",
- "libcutils",
+ "libstatssocket_private",
],
proto: {
diff --git a/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java b/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java
index e7d91c2..115d6c4 100644
--- a/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java
+++ b/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java
@@ -40,11 +40,6 @@
import android.content.pm.ServiceInfo;
import android.content.pm.Signature;
import android.content.pm.SigningInfo;
-import android.content.pm.parsing.ParsingPackage;
-import android.os.Environment;
-import android.os.UserHandle;
-
-import com.android.internal.util.ArrayUtils;
import android.content.pm.parsing.component.ComponentParseUtils;
import android.content.pm.parsing.component.ParsedActivity;
import android.content.pm.parsing.component.ParsedComponent;
@@ -54,6 +49,10 @@
import android.content.pm.parsing.component.ParsedPermissionGroup;
import android.content.pm.parsing.component.ParsedProvider;
import android.content.pm.parsing.component.ParsedService;
+import android.os.Environment;
+import android.os.UserHandle;
+
+import com.android.internal.util.ArrayUtils;
import libcore.util.EmptyArray;
@@ -186,6 +185,22 @@
return null;
}
+ return generateWithoutComponentsUnchecked(pkg, gids, flags, firstInstallTime,
+ lastUpdateTime, grantedPermissions, state, userId, apexInfo, applicationInfo);
+ }
+
+ /**
+ * This bypasses critical checks that are necessary for usage with data passed outside of
+ * system server.
+ *
+ * Prefer {@link #generateWithoutComponents(ParsingPackageRead, int[], int, long, long, Set,
+ * PackageUserState, int, ApexInfo, ApplicationInfo)}.
+ */
+ @NonNull
+ public static PackageInfo generateWithoutComponentsUnchecked(ParsingPackageRead pkg, int[] gids,
+ @PackageManager.PackageInfoFlags int flags, long firstInstallTime, long lastUpdateTime,
+ Set<String> grantedPermissions, PackageUserState state, int userId,
+ @Nullable ApexInfo apexInfo, @NonNull ApplicationInfo applicationInfo) {
PackageInfo pi = new PackageInfo();
pi.packageName = pkg.getPackageName();
pi.splitNames = pkg.getSplitNames();
@@ -317,6 +332,18 @@
return null;
}
+ return generateApplicationInfoUnchecked(pkg, flags, state, userId);
+ }
+
+ /**
+ * This bypasses critical checks that are necessary for usage with data passed outside of
+ * system server.
+ *
+ * Prefer {@link #generateApplicationInfo(ParsingPackageRead, int, PackageUserState, int)}.
+ */
+ @NonNull
+ public static ApplicationInfo generateApplicationInfoUnchecked(@NonNull ParsingPackageRead pkg,
+ @PackageManager.ApplicationInfoFlags int flags, PackageUserState state, int userId) {
// Make shallow copy so we can store the metadata/libraries safely
ApplicationInfo ai = pkg.toAppInfoWithoutState();
// Init handles data directories
@@ -378,6 +405,23 @@
if (applicationInfo == null) {
applicationInfo = generateApplicationInfo(pkg, flags, state, userId);
}
+ if (applicationInfo == null) {
+ return null;
+ }
+
+ return generateActivityInfoUnchecked(a, applicationInfo);
+ }
+
+ /**
+ * This bypasses critical checks that are necessary for usage with data passed outside of
+ * system server.
+ *
+ * Prefer {@link #generateActivityInfo(ParsingPackageRead, ParsedActivity, int,
+ * PackageUserState, ApplicationInfo, int)}.
+ */
+ @NonNull
+ public static ActivityInfo generateActivityInfoUnchecked(@NonNull ParsedActivity a,
+ @NonNull ApplicationInfo applicationInfo) {
// Make shallow copies so we can store the metadata safely
ActivityInfo ai = new ActivityInfo();
assignSharedFieldsForComponentInfo(ai, a);
@@ -431,6 +475,23 @@
if (applicationInfo == null) {
applicationInfo = generateApplicationInfo(pkg, flags, state, userId);
}
+ if (applicationInfo == null) {
+ return null;
+ }
+
+ return generateServiceInfoUnchecked(s, applicationInfo);
+ }
+
+ /**
+ * This bypasses critical checks that are necessary for usage with data passed outside of
+ * system server.
+ *
+ * Prefer {@link #generateServiceInfo(ParsingPackageRead, ParsedService, int, PackageUserState,
+ * ApplicationInfo, int)}.
+ */
+ @NonNull
+ public static ServiceInfo generateServiceInfoUnchecked(@NonNull ParsedService s,
+ @NonNull ApplicationInfo applicationInfo) {
// Make shallow copies so we can store the metadata safely
ServiceInfo si = new ServiceInfo();
assignSharedFieldsForComponentInfo(si, s);
@@ -461,6 +522,24 @@
if (applicationInfo == null) {
applicationInfo = generateApplicationInfo(pkg, flags, state, userId);
}
+ if (applicationInfo == null) {
+ return null;
+ }
+
+ return generateProviderInfoUnchecked(p, flags, applicationInfo);
+ }
+
+ /**
+ * This bypasses critical checks that are necessary for usage with data passed outside of
+ * system server.
+ *
+ * Prefer {@link #generateProviderInfo(ParsingPackageRead, ParsedProvider, int,
+ * PackageUserState, ApplicationInfo, int)}.
+ */
+ @NonNull
+ public static ProviderInfo generateProviderInfoUnchecked(@NonNull ParsedProvider p,
+ @PackageManager.ComponentInfoFlags int flags,
+ @NonNull ApplicationInfo applicationInfo) {
// Make shallow copies so we can store the metadata safely
ProviderInfo pi = new ProviderInfo();
assignSharedFieldsForComponentInfo(pi, p);
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index f2d415a..fa2b014 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -53,7 +53,9 @@
import android.net.ConnectivityManager;
import android.net.NetworkScoreManager;
import android.net.Uri;
+import android.net.wifi.SoftApConfiguration;
import android.net.wifi.WifiManager;
+import android.net.wifi.p2p.WifiP2pManager;
import android.os.BatteryManager;
import android.os.Binder;
import android.os.Build.VERSION_CODES;
@@ -10272,7 +10274,8 @@
/**
* Setting to allow scans to be enabled even wifi is turned off for connectivity.
* @hide
- * @deprecated To be removed.
+ * @deprecated To be removed. Use {@link WifiManager#setScanAlwaysAvailable(boolean)} for
+ * setting the value and {@link WifiManager#isScanAlwaysAvailable()} for query.
*/
public static final String WIFI_SCAN_ALWAYS_AVAILABLE =
"wifi_scan_always_enabled";
@@ -10292,7 +10295,9 @@
*
* Type: int (0 for false, 1 for true)
* @hide
- * @deprecated To be removed.
+ * @deprecated To be removed. Use {@link SoftApConfiguration.Builder#
+ * setAutoShutdownEnabled(boolean)} for setting the value and {@link SoftApConfiguration#
+ * isAutoShutdownEnabled()} for query.
*/
public static final String SOFT_AP_TIMEOUT_ENABLED = "soft_ap_timeout_enabled";
@@ -10301,7 +10306,8 @@
*
* Type: int (0 for false, 1 for true)
* @hide
- * @deprecated Use {@link WifiManager#isAutoWakeupEnabled()} instead.
+ * @deprecated Use {@link WifiManager#setAutoWakeupEnabled(boolean)} for setting the value
+ * and {@link WifiManager#isAutoWakeupEnabled()} for query.
*/
@Deprecated
@SystemApi
@@ -10381,7 +10387,8 @@
*
* Type: int (0 for false, 1 for true)
* @hide
- * @deprecated To be removed.
+ * @deprecated Use {@link WifiManager#setScanThrottleEnabled(boolean)} for setting the value
+ * and {@link WifiManager#isScanThrottleEnabled()} for query.
*/
public static final String WIFI_SCAN_THROTTLE_ENABLED = "wifi_scan_throttle_enabled";
@@ -10484,7 +10491,8 @@
* Setting to enable verbose logging in Wi-Fi; disabled by default, and setting to 1
* will enable it. In the future, additional values may be supported.
* @hide
- * @deprecated To be removed.
+ * @deprecated Use {@link WifiManager#setVerboseLoggingEnabled(boolean)} for setting the
+ * value and {@link WifiManager#isVerboseLoggingEnabled()} for query.
*/
public static final String WIFI_VERBOSE_LOGGING_ENABLED =
"wifi_verbose_logging_enabled";
@@ -10553,7 +10561,9 @@
/**
* The Wi-Fi peer-to-peer device name
* @hide
- * @deprecated To be removed.
+ * @deprecated Use {@link WifiP2pManager#setDeviceName(WifiP2pManager.Channel, String,
+ * WifiP2pManager.ActionListener)} for setting the value and
+ * {@link android.net.wifi.p2p.WifiP2pDevice#deviceName} for query.
*/
public static final String WIFI_P2P_DEVICE_NAME = "wifi_p2p_device_name";
diff --git a/media/java/android/media/MediaRouter2.java b/media/java/android/media/MediaRouter2.java
index 3410919..68df7d2 100644
--- a/media/java/android/media/MediaRouter2.java
+++ b/media/java/android/media/MediaRouter2.java
@@ -749,7 +749,7 @@
/**
* Callback for receiving events about media route discovery.
*/
- public static class RouteCallback {
+ public abstract static class RouteCallback {
/**
* Called when routes are added. Whenever you registers a callback, this will
* be invoked with known routes.
@@ -777,7 +777,7 @@
/**
* Callback for receiving events on media transfer.
*/
- public static class TransferCallback {
+ public abstract static class TransferCallback {
/**
* Called when a media is transferred between two different routing controllers.
* This can happen by calling {@link #transferTo(MediaRoute2Info)} or
@@ -826,7 +826,7 @@
/**
* Callback for receiving {@link RoutingController} updates.
*/
- public static class ControllerCallback {
+ public abstract static class ControllerCallback {
/**
* Called when a controller is updated. (e.g., the selected routes of the
* controller is changed or the volume of the controller is changed.)
diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2ManagerTest.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2ManagerTest.java
index bcff6a1..4e12859 100644
--- a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2ManagerTest.java
+++ b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2ManagerTest.java
@@ -123,7 +123,7 @@
@Test
public void testOnRoutesRemovedAndAdded() throws Exception {
- RouteCallback routeCallback = new RouteCallback();
+ RouteCallback routeCallback = new RouteCallback() {};
mRouteCallbacks.add(routeCallback);
mRouter2.registerRouteCallback(mExecutor, routeCallback,
new RouteDiscoveryPreference.Builder(FEATURES_ALL, true).build());
@@ -201,7 +201,7 @@
addManagerCallback(new MediaRouter2Manager.Callback());
//TODO: remove this when it's not necessary.
- addRouterCallback(new MediaRouter2.RouteCallback());
+ addRouterCallback(new MediaRouter2.RouteCallback() {});
addTransferCallback(new MediaRouter2.TransferCallback() {
@Override
public void onTransferred(MediaRouter2.RoutingController oldController,
@@ -228,7 +228,7 @@
CountDownLatch latch = new CountDownLatch(1);
Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(FEATURES_ALL);
- addRouterCallback(new RouteCallback());
+ addRouterCallback(new RouteCallback() {});
addManagerCallback(new MediaRouter2Manager.Callback() {
@Override
public void onSessionCreated(MediaRouter2Manager.RoutingController controller) {
@@ -263,7 +263,7 @@
@Test
public void testSelectAndTransferAndRelease() throws Exception {
Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(FEATURES_ALL);
- addRouterCallback(new RouteCallback());
+ addRouterCallback(new RouteCallback() {});
CountDownLatch onSessionCreatedLatch = new CountDownLatch(1);
@@ -346,7 +346,7 @@
@Test
public void testSetSessionVolume() throws Exception {
Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(FEATURES_ALL);
- addRouterCallback(new RouteCallback());
+ addRouterCallback(new RouteCallback() {});
CountDownLatch onSessionCreatedLatch = new CountDownLatch(1);
CountDownLatch volumeChangedLatch = new CountDownLatch(2);
@@ -471,7 +471,7 @@
CountDownLatch featuresLatch = new CountDownLatch(1);
// A dummy callback is required to send route feature info.
- RouteCallback routeCallback = new RouteCallback();
+ RouteCallback routeCallback = new RouteCallback() {};
MediaRouter2Manager.Callback managerCallback = new MediaRouter2Manager.Callback() {
@Override
public void onRoutesAdded(List<MediaRoute2Info> routes) {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index ba8a1a9..3cf07d1 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -19,7 +19,9 @@
import static android.view.ViewRootImpl.sNewInsetsMode;
import static android.view.WindowInsets.Type.ime;
import static android.view.WindowInsets.Type.systemBars;
+
import static com.android.systemui.DejankUtils.whitelistIpcs;
+
import static java.lang.Integer.max;
import android.app.Activity;
@@ -28,7 +30,6 @@
import android.content.Context;
import android.content.Intent;
import android.content.res.ColorStateList;
-import android.graphics.Rect;
import android.metrics.LogMaker;
import android.os.Handler;
import android.os.Looper;
@@ -511,6 +512,8 @@
boolean finish = false;
boolean strongAuth = false;
int eventSubtype = -1;
+ mCurrentSecuritySelection = whitelistIpcs(() ->
+ mSecurityModel.getSecurityMode(targetUserId));
if (mUpdateMonitor.getUserHasTrust(targetUserId)) {
finish = true;
eventSubtype = BOUNCER_DISMISS_EXTENDED_ACCESS;
@@ -518,13 +521,8 @@
finish = true;
eventSubtype = BOUNCER_DISMISS_BIOMETRIC;
} else if (SecurityMode.None == mCurrentSecuritySelection) {
- SecurityMode securityMode = mSecurityModel.getSecurityMode(targetUserId);
- if (SecurityMode.None == securityMode) {
- finish = true; // no security required
- eventSubtype = BOUNCER_DISMISS_NONE_SECURITY;
- } else {
- showSecurityScreen(securityMode); // switch to the alternate security view
- }
+ finish = true; // no security required
+ eventSubtype = BOUNCER_DISMISS_NONE_SECURITY;
} else if (authenticated) {
switch (mCurrentSecuritySelection) {
case Pattern:
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java
index b3561c2..8ee2f50 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java
@@ -16,6 +16,8 @@
package com.android.systemui.statusbar.notification.stack;
+import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_GENTLE;
+
import static java.lang.annotation.RetentionPolicy.SOURCE;
import android.annotation.IntDef;
@@ -100,14 +102,11 @@
private boolean mInitialized = false;
private SectionHeaderView mGentleHeader;
- private boolean mGentleHeaderVisible;
@Nullable private View.OnClickListener mOnClearGentleNotifsClickListener;
private SectionHeaderView mAlertingHeader;
- private boolean mAlertingHeaderVisible;
private PeopleHubView mPeopleHubView;
- private boolean mPeopleHeaderVisible;
private boolean mPeopleHubVisible = false;
@Nullable private Subscription mPeopleHubSubscription;
@@ -231,88 +230,135 @@
return;
}
+ // The overall strategy here is to iterate over the current children of mParent, looking
+ // for where the sections headers are currently positioned, and where each section begins.
+ // Then, once we find the start of a new section, we track that position as the "target" for
+ // the section header, adjusted for the case where existing headers are in front of that
+ // target, but won't be once they are moved / removed after the pass has completed.
+
final boolean showHeaders = mStatusBarStateController.getState() != StatusBarState.KEYGUARD;
final boolean usingPeopleFiltering = mSectionsFeatureManager.isFilteringEnabled();
boolean peopleNotifsPresent = false;
+
+ int currentPeopleHeaderIdx = -1;
int peopleHeaderTarget = -1;
+ int currentAlertingHeaderIdx = -1;
int alertingHeaderTarget = -1;
+ int currentGentleHeaderIdx = -1;
int gentleHeaderTarget = -1;
- int viewCount = 0;
+ int lastNotifIndex = 0;
- if (showHeaders) {
- final int childCount = mParent.getChildCount();
- for (int i = 0; i < childCount; i++) {
- View child = mParent.getChildAt(i);
- if (child.getVisibility() == View.GONE
- || !(child instanceof ExpandableNotificationRow)) {
- continue;
- }
- ExpandableNotificationRow row = (ExpandableNotificationRow) child;
- switch (row.getEntry().getBucket()) {
- case BUCKET_PEOPLE:
- if (peopleHeaderTarget == -1) {
- peopleNotifsPresent = true;
- peopleHeaderTarget = viewCount;
- viewCount++;
- }
- break;
- case BUCKET_ALERTING:
- if (usingPeopleFiltering && alertingHeaderTarget == -1) {
- alertingHeaderTarget = viewCount;
- viewCount++;
- }
- break;
- case BUCKET_SILENT:
- if (gentleHeaderTarget == -1) {
- gentleHeaderTarget = viewCount;
- viewCount++;
- }
- break;
- }
- viewCount++;
+ final int childCount = mParent.getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ View child = mParent.getChildAt(i);
+
+ // Track the existing positions of the headers
+ if (child == mPeopleHubView) {
+ currentPeopleHeaderIdx = i;
+ continue;
}
- if (usingPeopleFiltering && mPeopleHubVisible && peopleHeaderTarget == -1) {
- // Insert the people header even if there are no people visible, in order to show
- // the hub. Put it directly above the next header.
- if (alertingHeaderTarget != -1) {
- peopleHeaderTarget = alertingHeaderTarget;
- alertingHeaderTarget++;
- gentleHeaderTarget++;
- } else if (gentleHeaderTarget != -1) {
- peopleHeaderTarget = gentleHeaderTarget;
- gentleHeaderTarget++;
- } else {
- // Put it at the end of the list.
- peopleHeaderTarget = viewCount;
- }
+ if (child == mAlertingHeader) {
+ currentAlertingHeaderIdx = i;
+ continue;
+ }
+ if (child == mGentleHeader) {
+ currentGentleHeaderIdx = i;
+ continue;
+ }
+
+ if (!(child instanceof ExpandableNotificationRow)) {
+ continue;
+ }
+ lastNotifIndex = i;
+ ExpandableNotificationRow row = (ExpandableNotificationRow) child;
+ // Once we enter a new section, calculate the target position for the header.
+ switch (row.getEntry().getBucket()) {
+ case BUCKET_HEADS_UP:
+ break;
+ case BUCKET_PEOPLE:
+ peopleNotifsPresent = true;
+ if (showHeaders && peopleHeaderTarget == -1) {
+ peopleHeaderTarget = i;
+ // Offset the target if there are other headers before this that will be
+ // moved.
+ if (currentPeopleHeaderIdx != -1) {
+ peopleHeaderTarget--;
+ }
+ if (currentAlertingHeaderIdx != -1) {
+ peopleHeaderTarget--;
+ }
+ if (currentGentleHeaderIdx != -1) {
+ peopleHeaderTarget--;
+ }
+ }
+ break;
+ case BUCKET_ALERTING:
+ if (showHeaders && usingPeopleFiltering && alertingHeaderTarget == -1) {
+ alertingHeaderTarget = i;
+ // Offset the target if there are other headers before this that will be
+ // moved.
+ if (currentAlertingHeaderIdx != -1) {
+ alertingHeaderTarget--;
+ }
+ if (currentGentleHeaderIdx != -1) {
+ alertingHeaderTarget--;
+ }
+ }
+ break;
+ case BUCKET_SILENT:
+ if (showHeaders && gentleHeaderTarget == -1) {
+ gentleHeaderTarget = i;
+ // Offset the target if there are other headers before this that will be
+ // moved.
+ if (currentGentleHeaderIdx != -1) {
+ gentleHeaderTarget--;
+ }
+ }
+ break;
+ default:
+ throw new IllegalStateException("Cannot find section bucket for view");
+ }
+ }
+ if (showHeaders && usingPeopleFiltering && mPeopleHubVisible && peopleHeaderTarget == -1) {
+ // Insert the people header even if there are no people visible, in order to show
+ // the hub. Put it directly above the next header.
+ if (alertingHeaderTarget != -1) {
+ peopleHeaderTarget = alertingHeaderTarget;
+ } else if (gentleHeaderTarget != -1) {
+ peopleHeaderTarget = gentleHeaderTarget;
+ } else {
+ // Put it at the end of the list.
+ peopleHeaderTarget = lastNotifIndex;
}
}
- // Allow swiping the people header if the section is empty
- mPeopleHubView.setCanSwipe(mPeopleHubVisible && !peopleNotifsPresent);
+ // Add headers in reverse order to preserve indices
+ adjustHeaderVisibilityAndPosition(
+ gentleHeaderTarget, mGentleHeader, currentGentleHeaderIdx);
+ adjustHeaderVisibilityAndPosition(
+ alertingHeaderTarget, mAlertingHeader, currentAlertingHeaderIdx);
+ adjustHeaderVisibilityAndPosition(
+ peopleHeaderTarget, mPeopleHubView, currentPeopleHeaderIdx);
- mPeopleHeaderVisible = adjustHeaderVisibilityAndPosition(
- peopleHeaderTarget, mPeopleHubView, mPeopleHeaderVisible);
- mAlertingHeaderVisible = adjustHeaderVisibilityAndPosition(
- alertingHeaderTarget, mAlertingHeader, mAlertingHeaderVisible);
- mGentleHeaderVisible = adjustHeaderVisibilityAndPosition(
- gentleHeaderTarget, mGentleHeader, mGentleHeaderVisible);
+ // Update headers to reflect state of section contents
+ mGentleHeader.setAreThereDismissableGentleNotifs(
+ mParent.hasActiveClearableNotifications(ROWS_GENTLE));
+ mPeopleHubView.setCanSwipe(showHeaders && mPeopleHubVisible && !peopleNotifsPresent);
+ if (peopleHeaderTarget != currentPeopleHeaderIdx) {
+ mPeopleHubView.resetTranslation();
+ }
}
- private boolean adjustHeaderVisibilityAndPosition(
- int targetIndex, StackScrollerDecorView header, boolean isCurrentlyVisible) {
- if (targetIndex == -1) {
- if (isCurrentlyVisible) {
+ private void adjustHeaderVisibilityAndPosition(
+ int targetPosition, StackScrollerDecorView header, int currentPosition) {
+ if (targetPosition == -1) {
+ if (currentPosition != -1) {
mParent.removeView(header);
}
- return false;
} else {
- if (header instanceof SwipeableView) {
- ((SwipeableView) header).resetTranslation();
- }
- if (!isCurrentlyVisible) {
+ if (currentPosition == -1) {
// If the header is animating away, it will still have a parent, so detach it first
// TODO: We should really cancel the active animations here. This will happen
// automatically when the view's intro animation starts, but it's a fragile link.
@@ -321,11 +367,10 @@
header.setTransientContainer(null);
}
header.setContentVisible(true);
- mParent.addView(header, targetIndex);
- } else if (mParent.indexOfChild(header) != targetIndex) {
- mParent.changeViewPosition(header, targetIndex);
+ mParent.addView(header, targetPosition);
+ } else {
+ mParent.changeViewPosition(header, targetPosition);
}
- return true;
}
}
@@ -400,10 +445,20 @@
@VisibleForTesting
- SectionHeaderView getGentleHeaderView() {
+ ExpandableView getGentleHeaderView() {
return mGentleHeader;
}
+ @VisibleForTesting
+ ExpandableView getAlertingHeaderView() {
+ return mAlertingHeader;
+ }
+
+ @VisibleForTesting
+ ExpandableView getPeopleHeaderView() {
+ return mPeopleHubView;
+ }
+
private final ConfigurationListener mConfigurationListener = new ConfigurationListener() {
@Override
public void onLocaleListChanged() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java
index abfbcd9..c64dd09 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java
@@ -19,6 +19,8 @@
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_ALERTING;
+import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_HEADS_UP;
+import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_PEOPLE;
import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_SILENT;
import static org.mockito.ArgumentMatchers.any;
@@ -107,7 +109,7 @@
@Test
public void testInsertHeader() {
// GIVEN a stack with HI and LO rows but no section headers
- setStackState(ChildType.HIPRI, ChildType.HIPRI, ChildType.HIPRI, ChildType.LOPRI);
+ setStackState(ChildType.ALERTING, ChildType.ALERTING, ChildType.ALERTING, ChildType.GENTLE);
// WHEN we update the section headers
mSectionsManager.updateSectionBoundaries();
@@ -119,11 +121,15 @@
@Test
public void testRemoveHeader() {
// GIVEN a stack that originally had a header between the HI and LO sections
- setStackState(ChildType.HIPRI, ChildType.HIPRI, ChildType.LOPRI);
+ setStackState(ChildType.ALERTING, ChildType.ALERTING, ChildType.GENTLE);
mSectionsManager.updateSectionBoundaries();
// WHEN the last LO row is replaced with a HI row
- setStackState(ChildType.HIPRI, ChildType.HIPRI, ChildType.HEADER, ChildType.HIPRI);
+ setStackState(
+ ChildType.ALERTING,
+ ChildType.ALERTING,
+ ChildType.GENTLE_HEADER,
+ ChildType.ALERTING);
clearInvocations(mNssl);
mSectionsManager.updateSectionBoundaries();
@@ -134,7 +140,7 @@
@Test
public void testDoNothingIfHeaderAlreadyRemoved() {
// GIVEN a stack with only HI rows
- setStackState(ChildType.HIPRI, ChildType.HIPRI, ChildType.HIPRI);
+ setStackState(ChildType.ALERTING, ChildType.ALERTING, ChildType.ALERTING);
// WHEN we update the sections headers
mSectionsManager.updateSectionBoundaries();
@@ -147,19 +153,19 @@
public void testMoveHeaderForward() {
// GIVEN a stack that originally had a header between the HI and LO sections
setStackState(
- ChildType.HIPRI,
- ChildType.HIPRI,
- ChildType.HIPRI,
- ChildType.LOPRI);
+ ChildType.ALERTING,
+ ChildType.ALERTING,
+ ChildType.ALERTING,
+ ChildType.GENTLE);
mSectionsManager.updateSectionBoundaries();
// WHEN the LO section moves forward
setStackState(
- ChildType.HIPRI,
- ChildType.HIPRI,
- ChildType.LOPRI,
- ChildType.HEADER,
- ChildType.LOPRI);
+ ChildType.ALERTING,
+ ChildType.ALERTING,
+ ChildType.GENTLE,
+ ChildType.GENTLE_HEADER,
+ ChildType.GENTLE);
mSectionsManager.updateSectionBoundaries();
// THEN the LO section header is also moved forward
@@ -170,19 +176,19 @@
public void testMoveHeaderBackward() {
// GIVEN a stack that originally had a header between the HI and LO sections
setStackState(
- ChildType.HIPRI,
- ChildType.LOPRI,
- ChildType.LOPRI,
- ChildType.LOPRI);
+ ChildType.ALERTING,
+ ChildType.GENTLE,
+ ChildType.GENTLE,
+ ChildType.GENTLE);
mSectionsManager.updateSectionBoundaries();
// WHEN the LO section moves backward
setStackState(
- ChildType.HIPRI,
- ChildType.HEADER,
- ChildType.HIPRI,
- ChildType.HIPRI,
- ChildType.LOPRI);
+ ChildType.ALERTING,
+ ChildType.GENTLE_HEADER,
+ ChildType.ALERTING,
+ ChildType.ALERTING,
+ ChildType.GENTLE);
mSectionsManager.updateSectionBoundaries();
// THEN the LO section header is also moved backward (with appropriate index shifting)
@@ -193,14 +199,14 @@
public void testHeaderRemovedFromTransientParent() {
// GIVEN a stack where the header is animating away
setStackState(
- ChildType.HIPRI,
- ChildType.LOPRI,
- ChildType.LOPRI,
- ChildType.LOPRI);
+ ChildType.ALERTING,
+ ChildType.GENTLE,
+ ChildType.GENTLE,
+ ChildType.GENTLE);
mSectionsManager.updateSectionBoundaries();
setStackState(
- ChildType.HIPRI,
- ChildType.HEADER);
+ ChildType.ALERTING,
+ ChildType.GENTLE_HEADER);
mSectionsManager.updateSectionBoundaries();
clearInvocations(mNssl);
@@ -209,8 +215,8 @@
// WHEN the LO section reappears
setStackState(
- ChildType.HIPRI,
- ChildType.LOPRI);
+ ChildType.ALERTING,
+ ChildType.GENTLE);
mSectionsManager.updateSectionBoundaries();
// THEN the header is first removed from the transient parent before being added to the
@@ -223,7 +229,7 @@
public void testHeaderNotShownOnLockscreen() {
// GIVEN a stack of HI and LO notifs on the lockscreen
when(mStatusBarStateController.getState()).thenReturn(StatusBarState.KEYGUARD);
- setStackState(ChildType.HIPRI, ChildType.HIPRI, ChildType.HIPRI, ChildType.LOPRI);
+ setStackState(ChildType.ALERTING, ChildType.ALERTING, ChildType.ALERTING, ChildType.GENTLE);
// WHEN we update the section headers
mSectionsManager.updateSectionBoundaries();
@@ -236,7 +242,7 @@
public void testHeaderShownWhenEnterLockscreen() {
// GIVEN a stack of HI and LO notifs on the lockscreen
when(mStatusBarStateController.getState()).thenReturn(StatusBarState.KEYGUARD);
- setStackState(ChildType.HIPRI, ChildType.HIPRI, ChildType.HIPRI, ChildType.LOPRI);
+ setStackState(ChildType.ALERTING, ChildType.ALERTING, ChildType.ALERTING, ChildType.GENTLE);
mSectionsManager.updateSectionBoundaries();
// WHEN we unlock
@@ -250,37 +256,104 @@
@Test
public void testHeaderHiddenWhenEnterLockscreen() {
// GIVEN a stack of HI and LO notifs on the shade
- when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE_LOCKED);
- setStackState(ChildType.HIPRI, ChildType.HIPRI, ChildType.HIPRI, ChildType.LOPRI);
- mSectionsManager.updateSectionBoundaries();
+ setStackState(ChildType.ALERTING, ChildType.GENTLE_HEADER, ChildType.GENTLE);
// WHEN we go back to the keyguard
when(mStatusBarStateController.getState()).thenReturn(StatusBarState.KEYGUARD);
mSectionsManager.updateSectionBoundaries();
// Then the section header is removed
- verify(mNssl).removeView(eq(mSectionsManager.getGentleHeaderView()));
+ verify(mNssl).removeView(mSectionsManager.getGentleHeaderView());
}
- private enum ChildType { HEADER, HIPRI, LOPRI }
+ @Test
+ public void testPeopleFiltering_addHeadersFromShowingOnlyGentle() {
+ enablePeopleFiltering();
+
+ setStackState(
+ ChildType.GENTLE_HEADER,
+ ChildType.PERSON,
+ ChildType.ALERTING,
+ ChildType.GENTLE);
+ mSectionsManager.updateSectionBoundaries();
+
+ verify(mNssl).changeViewPosition(mSectionsManager.getGentleHeaderView(), 2);
+ verify(mNssl).addView(mSectionsManager.getAlertingHeaderView(), 1);
+ verify(mNssl).addView(mSectionsManager.getPeopleHeaderView(), 0);
+ }
+
+ @Test
+ public void testPeopleFiltering_addAllHeaders() {
+ enablePeopleFiltering();
+
+ setStackState(
+ ChildType.PERSON,
+ ChildType.ALERTING,
+ ChildType.GENTLE);
+ mSectionsManager.updateSectionBoundaries();
+
+ verify(mNssl).addView(mSectionsManager.getGentleHeaderView(), 2);
+ verify(mNssl).addView(mSectionsManager.getAlertingHeaderView(), 1);
+ verify(mNssl).addView(mSectionsManager.getPeopleHeaderView(), 0);
+ }
+
+ @Test
+ public void testPeopleFiltering_moveAllHeaders() {
+ enablePeopleFiltering();
+
+ setStackState(
+ ChildType.PEOPLE_HEADER,
+ ChildType.ALERTING_HEADER,
+ ChildType.GENTLE_HEADER,
+ ChildType.PERSON,
+ ChildType.ALERTING,
+ ChildType.GENTLE);
+ mSectionsManager.updateSectionBoundaries();
+
+ verify(mNssl).changeViewPosition(mSectionsManager.getGentleHeaderView(), 4);
+ verify(mNssl).changeViewPosition(mSectionsManager.getAlertingHeaderView(), 2);
+ verify(mNssl).changeViewPosition(mSectionsManager.getPeopleHeaderView(), 0);
+ }
+
+ private void enablePeopleFiltering() {
+ when(mSectionsFeatureManager.isFilteringEnabled()).thenReturn(true);
+ when(mSectionsFeatureManager.getNumberOfBuckets()).thenReturn(4);
+ }
+
+ private enum ChildType {
+ PEOPLE_HEADER, ALERTING_HEADER, GENTLE_HEADER, HEADS_UP, PERSON, ALERTING, GENTLE, OTHER
+ }
private void setStackState(ChildType... children) {
when(mNssl.getChildCount()).thenReturn(children.length);
for (int i = 0; i < children.length; i++) {
View child;
switch (children[i]) {
- case HEADER:
+ case PEOPLE_HEADER:
+ child = mSectionsManager.getPeopleHeaderView();
+ break;
+ case ALERTING_HEADER:
+ child = mSectionsManager.getAlertingHeaderView();
+ break;
+ case GENTLE_HEADER:
child = mSectionsManager.getGentleHeaderView();
break;
- case HIPRI:
- case LOPRI:
- ExpandableNotificationRow notifRow = mock(ExpandableNotificationRow.class,
- RETURNS_DEEP_STUBS);
- when(notifRow.getVisibility()).thenReturn(View.VISIBLE);
- when(notifRow.getEntry().getBucket()).thenReturn(
- children[i] == ChildType.HIPRI ? BUCKET_ALERTING : BUCKET_SILENT);
- when(notifRow.getParent()).thenReturn(mNssl);
- child = notifRow;
+ case HEADS_UP:
+ child = mockNotification(BUCKET_HEADS_UP);
+ break;
+ case PERSON:
+ child = mockNotification(BUCKET_PEOPLE);
+ break;
+ case ALERTING:
+ child = mockNotification(BUCKET_ALERTING);
+ break;
+ case GENTLE:
+ child = mockNotification(BUCKET_SILENT);
+ break;
+ case OTHER:
+ child = mock(View.class);
+ when(child.getVisibility()).thenReturn(View.VISIBLE);
+ when(child.getParent()).thenReturn(mNssl);
break;
default:
throw new RuntimeException("Unknown ChildType: " + children[i]);
@@ -289,4 +362,13 @@
when(mNssl.indexOfChild(child)).thenReturn(i);
}
}
+
+ private View mockNotification(int bucket) {
+ ExpandableNotificationRow notifRow = mock(ExpandableNotificationRow.class,
+ RETURNS_DEEP_STUBS);
+ when(notifRow.getVisibility()).thenReturn(View.VISIBLE);
+ when(notifRow.getEntry().getBucket()).thenReturn(bucket);
+ when(notifRow.getParent()).thenReturn(mNssl);
+ return notifRow;
+ }
}
diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java
index 1b1e06a..485127a 100644
--- a/services/core/java/android/content/pm/PackageManagerInternal.java
+++ b/services/core/java/android/content/pm/PackageManagerInternal.java
@@ -845,18 +845,11 @@
"android.content.pm.extra.ENABLE_ROLLBACK_TOKEN";
/**
- * Extra field name for the installFlags of a request to enable rollback
+ * Extra field name for the session id of a request to enable rollback
* for a package.
*/
- public static final String EXTRA_ENABLE_ROLLBACK_INSTALL_FLAGS =
- "android.content.pm.extra.ENABLE_ROLLBACK_INSTALL_FLAGS";
-
- /**
- * Extra field name for the user id an install is associated with when
- * enabling rollback.
- */
- public static final String EXTRA_ENABLE_ROLLBACK_USER =
- "android.content.pm.extra.ENABLE_ROLLBACK_USER";
+ public static final String EXTRA_ENABLE_ROLLBACK_SESSION_ID =
+ "android.content.pm.extra.ENABLE_ROLLBACK_SESSION_ID";
/**
* Used as the {@code enableRollbackCode} argument for
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 3441a5f..7840b19 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -1670,6 +1670,7 @@
Intent intent = new Intent(Intent.ACTION_TIMEZONE_CHANGED);
intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
| Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND
+ | Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
| Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
intent.putExtra("time-zone", zone.getID());
getContext().sendBroadcastAsUser(intent, UserHandle.ALL);
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index f2bc1fe..5d1b0e3 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -2334,6 +2334,19 @@
if (sb == null) sb = new StringBuilder();
sb.append("seq=" + app.startSeq + ",expected=" + expectedStartSeq + ";");
}
+ try {
+ AppGlobals.getPackageManager().checkPackageStartable(app.info.packageName, app.userId);
+ } catch (RemoteException e) {
+ // unexpected; ignore
+ } catch (SecurityException e) {
+ if (mService.mConstants.FLAG_PROCESS_START_ASYNC) {
+ if (sb == null) sb = new StringBuilder();
+ sb.append("Package is frozen;");
+ } else {
+ // we're not being started async and so should throw to the caller.
+ throw e;
+ }
+ }
return sb == null ? null : sb.toString();
}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 41988d6..5cc5059 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -1689,8 +1689,8 @@
}
mRelinquished = true;
- return new PackageManagerService.ActiveInstallSession(mPackageName, stageDir,
- localObserver, params, mInstallerUid, mInstallSource, user, mSigningDetails);
+ return new PackageManagerService.ActiveInstallSession(mPackageName, stageDir, localObserver,
+ sessionId, params, mInstallerUid, mInstallSource, user, mSigningDetails);
}
private static void maybeRenameFile(File from, File to) throws PackageManagerException {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 74cb93d..36843d4 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -1967,6 +1967,7 @@
}
case ENABLE_ROLLBACK_TIMEOUT: {
final int enableRollbackToken = msg.arg1;
+ final int sessionId = msg.arg2;
final InstallParams params = mPendingEnableRollback.get(enableRollbackToken);
if (params != null) {
final InstallArgs args = params.mArgs;
@@ -1982,8 +1983,8 @@
Intent rollbackTimeoutIntent = new Intent(
Intent.ACTION_CANCEL_ENABLE_ROLLBACK);
rollbackTimeoutIntent.putExtra(
- PackageManagerInternal.EXTRA_ENABLE_ROLLBACK_TOKEN,
- enableRollbackToken);
+ PackageManagerInternal.EXTRA_ENABLE_ROLLBACK_SESSION_ID,
+ sessionId);
rollbackTimeoutIntent.addFlags(
Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
mContext.sendBroadcastAsUser(rollbackTimeoutIntent, UserHandle.SYSTEM,
@@ -14260,6 +14261,7 @@
final long requiredInstalledVersionCode;
final boolean forceQueryableOverride;
final int mDataLoaderType;
+ final int mSessionId;
InstallParams(OriginInfo origin, MoveInfo move, IPackageInstallObserver2 observer,
int installFlags, InstallSource installSource, String volumeUuid,
@@ -14283,6 +14285,7 @@
this.requiredInstalledVersionCode = requiredInstalledVersionCode;
this.forceQueryableOverride = false;
this.mDataLoaderType = dataLoaderType;
+ this.mSessionId = -1;
}
InstallParams(ActiveInstallSession activeInstallSession) {
@@ -14318,6 +14321,7 @@
forceQueryableOverride = sessionParams.forceQueryableOverride;
mDataLoaderType = (sessionParams.dataLoaderParams != null)
? sessionParams.dataLoaderParams.getType() : DataLoaderType.NONE;
+ mSessionId = activeInstallSession.getSessionId();
}
@Override
@@ -14549,13 +14553,9 @@
PackageManagerInternal.EXTRA_ENABLE_ROLLBACK_TOKEN,
enableRollbackToken);
enableRollbackIntent.putExtra(
- PackageManagerInternal.EXTRA_ENABLE_ROLLBACK_INSTALL_FLAGS,
- installFlags);
- enableRollbackIntent.putExtra(
- PackageManagerInternal.EXTRA_ENABLE_ROLLBACK_USER,
- getRollbackUser().getIdentifier());
- enableRollbackIntent.setDataAndType(Uri.fromFile(new File(origin.resolvedPath)),
- PACKAGE_MIME_TYPE);
+ PackageManagerInternal.EXTRA_ENABLE_ROLLBACK_SESSION_ID,
+ mSessionId);
+ enableRollbackIntent.setType(PACKAGE_MIME_TYPE);
enableRollbackIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
// Allow the broadcast to be sent before boot complete.
@@ -14581,6 +14581,7 @@
final Message msg = mHandler.obtainMessage(
ENABLE_ROLLBACK_TIMEOUT);
msg.arg1 = enableRollbackToken;
+ msg.arg2 = mSessionId;
mHandler.sendMessageDelayed(msg, rollbackTimeout);
}
}, null, 0, null, null);
@@ -24590,6 +24591,7 @@
private final String mPackageName;
private final File mStagedDir;
private final IPackageInstallObserver2 mObserver;
+ private final int mSessionId;
private final PackageInstaller.SessionParams mSessionParams;
private final int mInstallerUid;
@NonNull private final InstallSource mInstallSource;
@@ -24597,11 +24599,12 @@
private final SigningDetails mSigningDetails;
ActiveInstallSession(String packageName, File stagedDir, IPackageInstallObserver2 observer,
- PackageInstaller.SessionParams sessionParams, int installerUid,
+ int sessionId, PackageInstaller.SessionParams sessionParams, int installerUid,
InstallSource installSource, UserHandle user, SigningDetails signingDetails) {
mPackageName = packageName;
mStagedDir = stagedDir;
mObserver = observer;
+ mSessionId = sessionId;
mSessionParams = sessionParams;
mInstallerUid = installerUid;
mInstallSource = Preconditions.checkNotNull(installSource);
@@ -24621,6 +24624,10 @@
return mObserver;
}
+ public int getSessionId() {
+ return mSessionId;
+ }
+
public PackageInstaller.SessionParams getSessionParams() {
return mSessionParams;
}
diff --git a/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java b/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
index 4ab1f396..d3f668c 100644
--- a/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
+++ b/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
@@ -61,7 +61,6 @@
import java.util.Collections;
import java.util.List;
import java.util.Map;
-import java.util.Objects;
import java.util.Set;
@@ -110,12 +109,9 @@
return null;
}
- PackageInfo info = PackageInfoWithoutStateUtils.generateWithoutComponents(pkg, gids, flags,
- firstInstallTime, lastUpdateTime, grantedPermissions, state, userId, apexInfo,
- applicationInfo);
- if (info == null) {
- return null;
- }
+ PackageInfo info = PackageInfoWithoutStateUtils.generateWithoutComponentsUnchecked(pkg,
+ gids, flags, firstInstallTime, lastUpdateTime, grantedPermissions, state, userId,
+ apexInfo, applicationInfo);
info.isStub = pkg.isStub();
info.coreApp = pkg.isCoreApp();
@@ -220,11 +216,8 @@
return null;
}
- ApplicationInfo info = PackageInfoWithoutStateUtils.generateApplicationInfo(pkg, flags,
- state, userId);
- if (info == null) {
- return null;
- }
+ ApplicationInfo info = PackageInfoWithoutStateUtils.generateApplicationInfoUnchecked(pkg,
+ flags, state, userId);
if (pkgSetting != null) {
// TODO(b/135203078): Remove PackageParser1/toAppInfoWithoutState and clean all this up
@@ -267,12 +260,13 @@
if (applicationInfo == null) {
applicationInfo = generateApplicationInfo(pkg, flags, state, userId, pkgSetting);
}
- ActivityInfo info = PackageInfoWithoutStateUtils.generateActivityInfo(pkg, a, flags, state,
- applicationInfo, userId);
- if (info == null) {
+
+ if (applicationInfo == null) {
return null;
}
+ ActivityInfo info =
+ PackageInfoWithoutStateUtils.generateActivityInfoUnchecked(a, applicationInfo);
assignSharedFieldsForComponentInfo(info, a, pkgSetting);
return info;
}
@@ -302,12 +296,12 @@
if (applicationInfo == null) {
applicationInfo = generateApplicationInfo(pkg, flags, state, userId, pkgSetting);
}
- ServiceInfo info = PackageInfoWithoutStateUtils.generateServiceInfo(pkg, s, flags, state,
- applicationInfo, userId);
- if (info == null) {
+ if (applicationInfo == null) {
return null;
}
+ ServiceInfo info =
+ PackageInfoWithoutStateUtils.generateServiceInfoUnchecked(s, applicationInfo);
assignSharedFieldsForComponentInfo(info, s, pkgSetting);
return info;
}
@@ -321,21 +315,20 @@
@NonNull ApplicationInfo applicationInfo, int userId,
@Nullable PackageSetting pkgSetting) {
if (p == null) return null;
+ if (!checkUseInstalledOrHidden(pkg, pkgSetting, state, flags)) {
+ return null;
+ }
if (applicationInfo == null || !pkg.getPackageName().equals(applicationInfo.packageName)) {
Slog.wtf(TAG, "AppInfo's package name is different. Expected=" + pkg.getPackageName()
+ " actual=" + (applicationInfo == null ? "(null AppInfo)"
: applicationInfo.packageName));
applicationInfo = generateApplicationInfo(pkg, flags, state, userId, pkgSetting);
}
- if (!checkUseInstalledOrHidden(pkg, pkgSetting, state, flags)) {
+ if (applicationInfo == null) {
return null;
}
- ProviderInfo info = PackageInfoWithoutStateUtils.generateProviderInfo(pkg, p, flags, state,
- applicationInfo, userId);
- if (info == null) {
- return null;
- }
-
+ ProviderInfo info = PackageInfoWithoutStateUtils.generateProviderInfoUnchecked(p, flags,
+ applicationInfo);
assignSharedFieldsForComponentInfo(info, p, pkgSetting);
return info;
}
diff --git a/services/core/java/com/android/server/rollback/Rollback.java b/services/core/java/com/android/server/rollback/Rollback.java
index 7b96777..885f561 100644
--- a/services/core/java/com/android/server/rollback/Rollback.java
+++ b/services/core/java/com/android/server/rollback/Rollback.java
@@ -159,13 +159,6 @@
@Nullable public final String mInstallerPackageName;
/**
- * This array holds all of the rollback tokens associated with package sessions included in
- * this rollback.
- */
- @GuardedBy("mLock")
- private final IntArray mTokens = new IntArray();
-
- /**
* Session ids for all packages in the install. For multi-package sessions, this is the list
* of child session ids. For normal sessions, this list is a single element with the normal
* session id.
@@ -769,26 +762,6 @@
}
/**
- * Adds a rollback token to be associated with this rollback. This may be used to
- * identify which rollback should be removed in case {@link PackageManager} sends an
- * {@link Intent#ACTION_CANCEL_ENABLE_ROLLBACK} intent.
- */
- void addToken(int token) {
- synchronized (mLock) {
- mTokens.add(token);
- }
- }
-
- /**
- * Returns true if this rollback is associated with the provided {@code token}.
- */
- boolean hasToken(int token) {
- synchronized (mLock) {
- return mTokens.indexOf(token) != -1;
- }
- }
-
- /**
* Returns true if this rollback contains the provided {@code packageSessionId}.
*/
boolean containsSessionId(int packageSessionId) {
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index f9981d0..42fada1 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -20,7 +20,6 @@
import android.annotation.AnyThread;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UserIdInt;
import android.annotation.WorkerThread;
import android.app.AppOpsManager;
import android.content.BroadcastReceiver;
@@ -201,18 +200,13 @@
if (Intent.ACTION_PACKAGE_ENABLE_ROLLBACK.equals(intent.getAction())) {
int token = intent.getIntExtra(
PackageManagerInternal.EXTRA_ENABLE_ROLLBACK_TOKEN, -1);
- int installFlags = intent.getIntExtra(
- PackageManagerInternal.EXTRA_ENABLE_ROLLBACK_INSTALL_FLAGS, 0);
- int user = intent.getIntExtra(
- PackageManagerInternal.EXTRA_ENABLE_ROLLBACK_USER, 0);
-
- File newPackageCodePath = new File(intent.getData().getPath());
+ int sessionId = intent.getIntExtra(
+ PackageManagerInternal.EXTRA_ENABLE_ROLLBACK_SESSION_ID, -1);
queueSleepIfNeeded();
getHandler().post(() -> {
- boolean success =
- enableRollback(installFlags, newPackageCodePath, user, token);
+ boolean success = enableRollback(sessionId);
int ret = PackageManagerInternal.ENABLE_ROLLBACK_SUCCEEDED;
if (!success) {
ret = PackageManagerInternal.ENABLE_ROLLBACK_FAILED;
@@ -238,19 +232,16 @@
@Override
public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_CANCEL_ENABLE_ROLLBACK.equals(intent.getAction())) {
- int token = intent.getIntExtra(
- PackageManagerInternal.EXTRA_ENABLE_ROLLBACK_TOKEN, -1);
+ int sessionId = intent.getIntExtra(
+ PackageManagerInternal.EXTRA_ENABLE_ROLLBACK_SESSION_ID, -1);
if (LOCAL_LOGV) {
- Slog.v(TAG, "broadcast=ACTION_CANCEL_ENABLE_ROLLBACK token=" + token);
+ Slog.v(TAG, "broadcast=ACTION_CANCEL_ENABLE_ROLLBACK id=" + sessionId);
}
synchronized (mLock) {
- for (int i = 0; i < mRollbacks.size(); ++i) {
- Rollback rollback = mRollbacks.get(i);
- if (rollback.hasToken(token) && rollback.isEnabling()) {
- mRollbacks.remove(i);
- rollback.delete(mAppDataRollbackHelper);
- break;
- }
+ Rollback rollback = getRollbackForSessionLocked(sessionId);
+ if (rollback != null && rollback.isEnabling()) {
+ mRollbacks.remove(rollback);
+ rollback.delete(mAppDataRollbackHelper);
}
}
}
@@ -684,24 +675,6 @@
return mHandlerThread.getThreadHandler();
}
- // Returns true if <code>session</code> has installFlags and code path
- // matching the installFlags and new package code path given to
- // enableRollback.
- @WorkerThread
- private boolean sessionMatchesForEnableRollback(PackageInstaller.SessionInfo session,
- int installFlags, File newPackageCodePath) {
- if (session == null || session.resolvedBaseCodePath == null) {
- return false;
- }
-
- File packageCodePath = new File(session.resolvedBaseCodePath).getParentFile();
- if (newPackageCodePath.equals(packageCodePath) && installFlags == session.installFlags) {
- return true;
- }
-
- return false;
- }
-
@AnyThread
private Context getContextAsUser(UserHandle user) {
try {
@@ -716,58 +689,26 @@
* staged for install with rollback enabled. Called before the package has
* been installed.
*
- * @param installFlags information about what is being installed.
- * @param newPackageCodePath path to the package about to be installed.
- * @param user the user that owns the install session to enable rollback on.
- * @param token the distinct rollback token sent by package manager.
+ * @param sessionId the id of the install session
* @return true if enabling the rollback succeeds, false otherwise.
*/
@WorkerThread
- private boolean enableRollback(
- int installFlags, File newPackageCodePath, @UserIdInt int user, int token) {
+ private boolean enableRollback(int sessionId) {
if (LOCAL_LOGV) {
- Slog.v(TAG, "enableRollback user=" + user + " token=" + token
- + " path=" + newPackageCodePath.getAbsolutePath());
+ Slog.v(TAG, "enableRollback sessionId=" + sessionId);
}
- // Find the session id associated with this install.
- // TODO: It would be nice if package manager or package installer told
- // us the session directly, rather than have to search for it
- // ourselves.
-
- // getAllSessions only returns sessions for the associated user.
- // Create a context with the right user so we can find the matching
- // session.
- final Context context = getContextAsUser(UserHandle.of(user));
- if (context == null) {
- Slog.e(TAG, "Unable to create context for install session user.");
+ PackageInstaller installer = mContext.getPackageManager().getPackageInstaller();
+ PackageInstaller.SessionInfo packageSession = installer.getSessionInfo(sessionId);
+ if (packageSession == null) {
+ Slog.e(TAG, "Unable to find session for enabled rollback.");
return false;
}
- PackageInstaller.SessionInfo parentSession = null;
- PackageInstaller.SessionInfo packageSession = null;
- PackageInstaller installer = context.getPackageManager().getPackageInstaller();
- for (PackageInstaller.SessionInfo info : installer.getAllSessions()) {
- if (info.isMultiPackage()) {
- for (int childId : info.getChildSessionIds()) {
- PackageInstaller.SessionInfo child = installer.getSessionInfo(childId);
- if (sessionMatchesForEnableRollback(child, installFlags, newPackageCodePath)) {
- // TODO: Check we only have one matching session?
- parentSession = info;
- packageSession = child;
- break;
- }
- }
- } else if (sessionMatchesForEnableRollback(info, installFlags, newPackageCodePath)) {
- // TODO: Check we only have one matching session?
- parentSession = info;
- packageSession = info;
- break;
- }
- }
-
- if (parentSession == null || packageSession == null) {
- Slog.e(TAG, "Unable to find session for enabled rollback.");
+ PackageInstaller.SessionInfo parentSession = packageSession.hasParentSessionId()
+ ? installer.getSessionInfo(packageSession.getParentSessionId()) : packageSession;
+ if (parentSession == null) {
+ Slog.e(TAG, "Unable to find parent session for enabled rollback.");
return false;
}
@@ -804,7 +745,6 @@
newRollback = createNewRollbackLocked(parentSession);
}
}
- newRollback.addToken(token);
return enableRollbackForPackageSession(newRollback, packageSession);
}
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index 4916c31..f86aeb2 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -172,6 +172,7 @@
private static final int MAX_CLIP_REVEAL_TRANSITION_DURATION = 420;
private static final int THUMBNAIL_APP_TRANSITION_DURATION = 336;
private static final long APP_TRANSITION_TIMEOUT_MS = 5000;
+ static final int MAX_APP_TRANSITION_DURATION = 3 * 1000; // 3 secs.
private final Context mContext;
private final WindowManagerService mService;
diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
index f6cdac5..68975b9 100644
--- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -205,7 +205,7 @@
SurfaceControl.ScreenshotGraphicBuffer gb =
mService.mDisplayManagerInternal.screenshot(displayId);
if (gb != null) {
- mStartLuma = RotationAnimationUtils.getAvgBorderLuma(gb.getGraphicBuffer(),
+ mStartLuma = RotationAnimationUtils.getMedianBorderLuma(gb.getGraphicBuffer(),
gb.getColorSpace());
try {
surface.attachAndQueueBufferWithColorSpace(gb.getGraphicBuffer(),
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index a0a70dc..b12c698 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -29,6 +29,7 @@
import static android.view.SurfaceControl.Transaction;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+import static com.android.server.wm.AppTransition.MAX_APP_TRANSITION_DURATION;
import static com.android.server.wm.IdentifierProto.HASH_CODE;
import static com.android.server.wm.IdentifierProto.TITLE;
import static com.android.server.wm.IdentifierProto.USER_ID;
@@ -2172,7 +2173,16 @@
displayConfig.uiMode, displayConfig.orientation, frame, displayFrame, insets,
surfaceInsets, stableInsets, isVoiceInteraction, inFreeformWindowingMode(), this);
if (a != null) {
- if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + this);
+ if (a != null) {
+ // Setup the maximum app transition duration to prevent malicious app may set a long
+ // animation duration or infinite repeat counts for the app transition through
+ // ActivityOption#makeCustomAnimation or WindowManager#overridePendingTransition.
+ a.restrictDuration(MAX_APP_TRANSITION_DURATION);
+ }
+ if (DEBUG_ANIM) {
+ logWithStack(TAG, "Loaded animation " + a + " for " + this
+ + ", duration: " + ((a != null) ? a.getDuration() : 0));
+ }
final int containingWidth = frame.width();
final int containingHeight = frame.height();
a.initialize(containingWidth, containingHeight, width, height);
diff --git a/services/core/java/com/android/server/wm/utils/RotationAnimationUtils.java b/services/core/java/com/android/server/wm/utils/RotationAnimationUtils.java
index 0c09c88..d02f79f 100644
--- a/services/core/java/com/android/server/wm/utils/RotationAnimationUtils.java
+++ b/services/core/java/com/android/server/wm/utils/RotationAnimationUtils.java
@@ -26,6 +26,8 @@
import android.view.Surface;
import android.view.SurfaceControl;
+import java.util.Arrays;
+
/** Helper functions for the {@link com.android.server.wm.ScreenRotationAnimation} class*/
public class RotationAnimationUtils {
@@ -35,31 +37,35 @@
* luminance at the borders of the bitmap
* @return the average luminance of all the pixels at the borders of the bitmap
*/
- public static float getAvgBorderLuma(GraphicBuffer graphicBuffer, ColorSpace colorSpace) {
+ public static float getMedianBorderLuma(GraphicBuffer graphicBuffer, ColorSpace colorSpace) {
Bitmap hwBitmap = Bitmap.wrapHardwareBuffer(graphicBuffer, colorSpace);
if (hwBitmap == null) {
return 0;
}
Bitmap swaBitmap = hwBitmap.copy(Bitmap.Config.ARGB_8888, false);
- float totalLuma = 0;
int height = swaBitmap.getHeight();
int width = swaBitmap.getWidth();
+ float[] borderLumas = new float[2 * width + 2 * height];
int i;
- for (i = 0; i < width; i++) {
- totalLuma += swaBitmap.getColor(i, 0).luminance();
- totalLuma += swaBitmap.getColor(i, height - 1).luminance();
+ int index = 0;
+ for (i = 0; i < width; i++, index += 2) {
+ borderLumas[index] = swaBitmap.getColor(i, 0).luminance();
+ borderLumas[index + 1] = swaBitmap.getColor(i, height - 1).luminance();
}
- for (i = 0; i < height; i++) {
- totalLuma += swaBitmap.getColor(0, i).luminance();
- totalLuma += swaBitmap.getColor(width - 1, i).luminance();
+ for (i = 0; i < height; i++, index += 2) {
+ borderLumas[index] = swaBitmap.getColor(0, i).luminance();
+ borderLumas[index + 1] = swaBitmap.getColor(width - 1, i).luminance();
}
- return totalLuma / (2 * width + 2 * height);
+ // Oh, is this too simple and inefficient for you?
+ // How about implementing a O(n) solution? https://en.wikipedia.org/wiki/Median_of_medians
+ Arrays.sort(borderLumas);
+ return borderLumas[borderLumas.length / 2];
}
/**
* Gets the average border luma by taking a screenshot of the {@param surfaceControl}.
- * @see #getAvgBorderLuma(GraphicBuffer, ColorSpace)
+ * @see #getMedianBorderLuma(GraphicBuffer, ColorSpace)
*/
public static float getLumaOfSurfaceControl(Display display, SurfaceControl surfaceControl) {
if (surfaceControl == null) {
@@ -75,7 +81,7 @@
return 0;
}
- return RotationAnimationUtils.getAvgBorderLuma(buffer.getGraphicBuffer(),
+ return RotationAnimationUtils.getMedianBorderLuma(buffer.getGraphicBuffer(),
buffer.getColorSpace());
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/utils/RotationAnimationUtilsTest.java b/services/tests/wmtests/src/com/android/server/wm/utils/RotationAnimationUtilsTest.java
index 9cda084..e5497a2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/utils/RotationAnimationUtilsTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/utils/RotationAnimationUtilsTest.java
@@ -50,7 +50,7 @@
public void blackLuma() {
Bitmap swBitmap = createBitmap(0);
GraphicBuffer gb = swBitmapToGraphicsBuffer(swBitmap);
- float borderLuma = RotationAnimationUtils.getAvgBorderLuma(gb, mColorSpace);
+ float borderLuma = RotationAnimationUtils.getMedianBorderLuma(gb, mColorSpace);
assertEquals(0, borderLuma, 0);
}
@@ -58,7 +58,15 @@
public void whiteLuma() {
Bitmap swBitmap = createBitmap(1);
GraphicBuffer gb = swBitmapToGraphicsBuffer(swBitmap);
- float borderLuma = RotationAnimationUtils.getAvgBorderLuma(gb, mColorSpace);
+ float borderLuma = RotationAnimationUtils.getMedianBorderLuma(gb, mColorSpace);
+ assertEquals(1, borderLuma, 0);
+ }
+
+ @Test
+ public void unevenBitmapDimens() {
+ Bitmap swBitmap = createBitmap(1, BITMAP_WIDTH + 1, BITMAP_HEIGHT + 1);
+ GraphicBuffer gb = swBitmapToGraphicsBuffer(swBitmap);
+ float borderLuma = RotationAnimationUtils.getMedianBorderLuma(gb, mColorSpace);
assertEquals(1, borderLuma, 0);
}
@@ -67,7 +75,7 @@
Bitmap swBitmap = createBitmap(1);
setBorderLuma(swBitmap, 0);
GraphicBuffer gb = swBitmapToGraphicsBuffer(swBitmap);
- float borderLuma = RotationAnimationUtils.getAvgBorderLuma(gb, mColorSpace);
+ float borderLuma = RotationAnimationUtils.getMedianBorderLuma(gb, mColorSpace);
assertEquals(0, borderLuma, 0);
}
@@ -76,7 +84,7 @@
Bitmap swBitmap = createBitmap(0);
setBorderLuma(swBitmap, 1);
GraphicBuffer gb = swBitmapToGraphicsBuffer(swBitmap);
- float borderLuma = RotationAnimationUtils.getAvgBorderLuma(gb, mColorSpace);
+ float borderLuma = RotationAnimationUtils.getMedianBorderLuma(gb, mColorSpace);
assertEquals(1, borderLuma, 0);
}
@@ -123,9 +131,13 @@
}
private Bitmap createBitmap(float luma) {
- Bitmap bitmap = Bitmap.createBitmap(BITMAP_WIDTH, BITMAP_HEIGHT, ARGB_8888);
- for (int i = 0; i < BITMAP_WIDTH; i++) {
- for (int j = 0; j < BITMAP_HEIGHT; j++) {
+ return createBitmap(luma, BITMAP_WIDTH, BITMAP_HEIGHT);
+ }
+
+ private Bitmap createBitmap(float luma, int width, int height) {
+ Bitmap bitmap = Bitmap.createBitmap(width, height, ARGB_8888);
+ for (int i = 0; i < width; i++) {
+ for (int j = 0; j < height; j++) {
bitmap.setPixel(i, j, Color.argb(1, luma, luma, luma));
}
}
diff --git a/tools/stats_log_api_gen/Android.bp b/tools/stats_log_api_gen/Android.bp
index d5031d7..843e820 100644
--- a/tools/stats_log_api_gen/Android.bp
+++ b/tools/stats_log_api_gen/Android.bp
@@ -121,7 +121,6 @@
shared_libs: [
"liblog",
"libcutils",
- "libstatssocket",
],
apex_available: [
"//apex_available:platform",
@@ -129,5 +128,13 @@
"com.android.os.statsd",
"test_com.android.os.statsd",
],
+ target: {
+ android: {
+ shared_libs: ["libstatssocket"],
+ },
+ host: {
+ static_libs: ["libstatssocket"],
+ },
+ },
}
diff --git a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
index 4507cc2..d1d1780 100644
--- a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
+++ b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
@@ -722,7 +722,7 @@
if (mSubscriptionUpdate != null && !mSubscriptionUpdate.validate()) {
return false;
}
- return validateForCommonR1andR2(true);
+ return validateForCommonR1andR2();
}
/**
@@ -741,17 +741,17 @@
if (mSubscriptionUpdate == null || !mSubscriptionUpdate.validate()) {
return false;
}
- return validateForCommonR1andR2(false);
+ return validateForCommonR1andR2();
}
- private boolean validateForCommonR1andR2(boolean isR1) {
+ private boolean validateForCommonR1andR2() {
// Required: PerProviderSubscription/<X+>/HomeSP
if (mHomeSp == null || !mHomeSp.validate()) {
return false;
}
// Required: PerProviderSubscription/<X+>/Credential
- if (mCredential == null || !mCredential.validate(isR1)) {
+ if (mCredential == null || !mCredential.validate()) {
return false;
}
diff --git a/wifi/java/android/net/wifi/hotspot2/pps/Credential.java b/wifi/java/android/net/wifi/hotspot2/pps/Credential.java
index 9c01d36..65e8b3d 100644
--- a/wifi/java/android/net/wifi/hotspot2/pps/Credential.java
+++ b/wifi/java/android/net/wifi/hotspot2/pps/Credential.java
@@ -1081,11 +1081,10 @@
/**
* Validate the configuration data.
*
- * @param isR1 {@code true} if the configuration is for R1
* @return true on success or false on failure
* @hide
*/
- public boolean validate(boolean isR1) {
+ public boolean validate() {
if (TextUtils.isEmpty(mRealm)) {
Log.d(TAG, "Missing realm");
return false;
@@ -1098,11 +1097,11 @@
// Verify the credential.
if (mUserCredential != null) {
- if (!verifyUserCredential(isR1)) {
+ if (!verifyUserCredential()) {
return false;
}
} else if (mCertCredential != null) {
- if (!verifyCertCredential(isR1)) {
+ if (!verifyCertCredential()) {
return false;
}
} else if (mSimCredential != null) {
@@ -1143,11 +1142,11 @@
/**
* Verify user credential.
+ * If no CA certificate is provided, then the system uses the CAs in the trust store.
*
- * @param isR1 {@code true} if credential is for R1
* @return true if user credential is valid, false otherwise.
*/
- private boolean verifyUserCredential(boolean isR1) {
+ private boolean verifyUserCredential() {
if (mUserCredential == null) {
Log.d(TAG, "Missing user credential");
return false;
@@ -1160,24 +1159,17 @@
return false;
}
- // CA certificate is required for R1 Passpoint profile.
- // For R2, it is downloaded using cert URL provided in PPS MO after validation completes.
- if (isR1 && mCaCertificates == null) {
- Log.d(TAG, "Missing CA Certificate for user credential");
- return false;
- }
-
return true;
}
/**
* Verify certificate credential, which is used for EAP-TLS. This will verify
* that the necessary client key and certificates are provided.
+ * If no CA certificate is provided, then the system uses the CAs in the trust store.
*
- * @param isR1 {@code true} if credential is for R1
* @return true if certificate credential is valid, false otherwise.
*/
- private boolean verifyCertCredential(boolean isR1) {
+ private boolean verifyCertCredential() {
if (mCertCredential == null) {
Log.d(TAG, "Missing certificate credential");
return false;
@@ -1191,13 +1183,6 @@
return false;
}
- // Verify required key and certificates for certificate credential.
- // CA certificate is required for R1 Passpoint profile.
- // For R2, it is downloaded using cert URL provided in PPS MO after validation completes.
- if (isR1 && mCaCertificates == null) {
- Log.d(TAG, "Missing CA Certificate for certificate credential");
- return false;
- }
if (mClientPrivateKey == null) {
Log.d(TAG, "Missing client private key for certificate credential");
return false;
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java b/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java
index 0a3e989d..c682582 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java
@@ -158,7 +158,7 @@
}
/**
- * Verify parcel read/write for an user credential.
+ * Verify parcel read/write for a user credential.
*
* @throws Exception
*/
@@ -176,14 +176,14 @@
Credential cred = createCredentialWithUserCredential();
// For R1 validation
- assertTrue(cred.validate(true));
+ assertTrue(cred.validate());
// For R2 validation
- assertTrue(cred.validate(false));
+ assertTrue(cred.validate());
}
/**
- * Verify that an user credential without CA Certificate is invalid.
+ * Verify that a user credential without CA Certificate is valid.
*
* @throws Exception
*/
@@ -192,15 +192,12 @@
Credential cred = createCredentialWithUserCredential();
cred.setCaCertificate(null);
- // For R1 validation
- assertFalse(cred.validate(true));
-
- // For R2 validation
- assertTrue(cred.validate(false));
+ // Accept a configuration with no CA certificate, the system will use the default cert store
+ assertTrue(cred.validate());
}
/**
- * Verify that an user credential with EAP type other than EAP-TTLS is invalid.
+ * Verify that a user credential with EAP type other than EAP-TTLS is invalid.
*
* @throws Exception
*/
@@ -210,15 +207,15 @@
cred.getUserCredential().setEapType(EAPConstants.EAP_TLS);
// For R1 validation
- assertFalse(cred.validate(true));
+ assertFalse(cred.validate());
// For R2 validation
- assertFalse(cred.validate(false));
+ assertFalse(cred.validate());
}
/**
- * Verify that an user credential without realm is invalid.
+ * Verify that a user credential without realm is invalid.
*
* @throws Exception
*/
@@ -228,14 +225,14 @@
cred.setRealm(null);
// For R1 validation
- assertFalse(cred.validate(true));
+ assertFalse(cred.validate());
// For R2 validation
- assertFalse(cred.validate(false));
+ assertFalse(cred.validate());
}
/**
- * Verify that an user credential without username is invalid.
+ * Verify that a user credential without username is invalid.
*
* @throws Exception
*/
@@ -245,14 +242,14 @@
cred.getUserCredential().setUsername(null);
// For R1 validation
- assertFalse(cred.validate(true));
+ assertFalse(cred.validate());
// For R2 validation
- assertFalse(cred.validate(false));
+ assertFalse(cred.validate());
}
/**
- * Verify that an user credential without password is invalid.
+ * Verify that a user credential without password is invalid.
*
* @throws Exception
*/
@@ -262,14 +259,14 @@
cred.getUserCredential().setPassword(null);
// For R1 validation
- assertFalse(cred.validate(true));
+ assertFalse(cred.validate());
// For R2 validation
- assertFalse(cred.validate(false));
+ assertFalse(cred.validate());
}
/**
- * Verify that an user credential without auth methoh (non-EAP inner method) is invalid.
+ * Verify that a user credential without auth methoh (non-EAP inner method) is invalid.
*
* @throws Exception
*/
@@ -279,10 +276,10 @@
cred.getUserCredential().setNonEapInnerMethod(null);
// For R1 validation
- assertFalse(cred.validate(true));
+ assertFalse(cred.validate());
// For R2 validation
- assertFalse(cred.validate(false));
+ assertFalse(cred.validate());
}
/**
@@ -297,10 +294,10 @@
Credential cred = createCredentialWithCertificateCredential();
// For R1 validation
- assertTrue(cred.validate(true));
+ assertTrue(cred.validate());
// For R2 validation
- assertTrue(cred.validate(true));
+ assertTrue(cred.validate());
}
/**
@@ -313,11 +310,8 @@
Credential cred = createCredentialWithCertificateCredential();
cred.setCaCertificate(null);
- // For R1 validation
- assertFalse(cred.validate(true));
-
- // For R2 validation
- assertTrue(cred.validate(false));
+ // Accept a configuration with no CA certificate, the system will use the default cert store
+ assertTrue(cred.validate());
}
/**
@@ -331,10 +325,10 @@
cred.setClientCertificateChain(null);
// For R1 validation
- assertFalse(cred.validate(true));
+ assertFalse(cred.validate());
// For R2 validation
- assertFalse(cred.validate(false));
+ assertFalse(cred.validate());
}
/**
@@ -348,10 +342,10 @@
cred.setClientPrivateKey(null);
// For R1 validation
- assertFalse(cred.validate(true));
+ assertFalse(cred.validate());
// For R2 validation
- assertFalse(cred.validate(false));
+ assertFalse(cred.validate());
}
/**
@@ -366,10 +360,10 @@
cred.getCertCredential().setCertSha256Fingerprint(new byte[32]);
// For R1 validation
- assertFalse(cred.validate(true));
+ assertFalse(cred.validate());
// For R2 validation
- assertFalse(cred.validate(false));
+ assertFalse(cred.validate());
}
/**
@@ -382,10 +376,10 @@
Credential cred = createCredentialWithSimCredential();
// For R1 validation
- assertTrue(cred.validate(true));
+ assertTrue(cred.validate());
// For R2 validation
- assertTrue(cred.validate(false));
+ assertTrue(cred.validate());
}
/**
@@ -399,10 +393,10 @@
cred.getSimCredential().setEapType(EAPConstants.EAP_AKA);
// For R1 validation
- assertTrue(cred.validate(true));
+ assertTrue(cred.validate());
// For R2 validation
- assertTrue(cred.validate(false));
+ assertTrue(cred.validate());
}
/**
@@ -416,10 +410,10 @@
cred.getSimCredential().setEapType(EAPConstants.EAP_AKA_PRIME);
// For R1 validation
- assertTrue(cred.validate(true));
+ assertTrue(cred.validate());
// For R2 validation
- assertTrue(cred.validate(false));
+ assertTrue(cred.validate());
}
/**
@@ -433,10 +427,10 @@
cred.getSimCredential().setImsi(null);
// For R1 validation
- assertFalse(cred.validate(true));
+ assertFalse(cred.validate());
// For R2 validation
- assertFalse(cred.validate(false));
+ assertFalse(cred.validate());
}
/**
@@ -450,10 +444,10 @@
cred.getSimCredential().setImsi("dummy");
// For R1 validation
- assertFalse(cred.validate(true));
+ assertFalse(cred.validate());
// For R2 validation
- assertFalse(cred.validate(false));
+ assertFalse(cred.validate());
}
/**
@@ -467,14 +461,14 @@
cred.getSimCredential().setEapType(EAPConstants.EAP_TLS);
// For R1 validation
- assertFalse(cred.validate(true));
+ assertFalse(cred.validate());
// For R2 validation
- assertFalse(cred.validate(false));
+ assertFalse(cred.validate());
}
/**
- * Verify that a credential contained both an user and a SIM credential is invalid.
+ * Verify that a credential contained both a user and a SIM credential is invalid.
*
* @throws Exception
*/
@@ -488,10 +482,10 @@
cred.setSimCredential(simCredential);
// For R1 validation
- assertFalse(cred.validate(true));
+ assertFalse(cred.validate());
// For R2 validation
- assertFalse(cred.validate(false));
+ assertFalse(cred.validate());
}
/**