summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/res/AndroidManifest.xml2
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerService.java37
-rw-r--r--services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java6
-rw-r--r--services/core/java/com/android/server/wm/RootWindowContainer.java40
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java33
-rw-r--r--tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java27
-rw-r--r--tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java37
-rw-r--r--tests/net/integration/src/com/android/server/net/integrationtests/TestNetworkStackService.kt3
8 files changed, 134 insertions, 51 deletions
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 049959823942..b5fe21d81fd8 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -396,6 +396,8 @@
<protected-broadcast android:name="android.net.wifi.p2p.action.WIFI_P2P_PERSISTENT_GROUPS_CHANGED" />
<protected-broadcast android:name="android.net.conn.TETHER_STATE_CHANGED" />
<protected-broadcast android:name="android.net.conn.INET_CONDITION_ACTION" />
+ <!-- This broadcast is no longer sent in S but it should stay protected to avoid third party
+ apps broadcasting this and confusing old system apps that may not have been updated. -->
<protected-broadcast android:name="android.net.conn.NETWORK_CONDITIONS_MEASURED" />
<protected-broadcast
android:name="android.net.ConnectivityService.action.PKT_CNT_SAMPLE_INTERVAL_ELAPSED" />
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index b500e1631fb5..8d2363b6e831 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -2293,23 +2293,30 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
final int callingUid = Binder.getCallingUid();
- final int userId = UserHandle.getUserId(newPackage.getUid());
- int numRequestedPermissions = newPackage.getRequestedPermissions().size();
- for (int i = 0; i < numRequestedPermissions; i++) {
- PermissionInfo permInfo = getPermissionInfo(newPackage.getRequestedPermissions().get(i),
- newPackage.getPackageName(), 0);
- if (permInfo == null || !STORAGE_PERMISSIONS.contains(permInfo.name)) {
- continue;
- }
+ for (int userId: mUserManagerInt.getUserIds()) {
+ int numRequestedPermissions = newPackage.getRequestedPermissions().size();
+ for (int i = 0; i < numRequestedPermissions; i++) {
+ PermissionInfo permInfo = getPermissionInfo(
+ newPackage.getRequestedPermissions().get(i),
+ newPackage.getPackageName(), 0);
+ if (permInfo == null || !STORAGE_PERMISSIONS.contains(permInfo.name)) {
+ continue;
+ }
- EventLog.writeEvent(0x534e4554, "171430330", newPackage.getUid(),
- "Revoking permission " + permInfo.name + " from package "
- + newPackage.getPackageName() + " as either the sdk downgraded "
- + downgradedSdk + " or newly requested legacy full storage "
- + newlyRequestsLegacy);
+ EventLog.writeEvent(0x534e4554, "171430330", newPackage.getUid(),
+ "Revoking permission " + permInfo.name + " from package "
+ + newPackage.getPackageName() + " as either the sdk downgraded "
+ + downgradedSdk + " or newly requested legacy full storage "
+ + newlyRequestsLegacy);
- revokeRuntimePermissionInternal(permInfo.name, newPackage.getPackageName(),
- false, callingUid, userId, null, permissionCallback);
+ try {
+ revokeRuntimePermissionInternal(permInfo.name, newPackage.getPackageName(),
+ false, callingUid, userId, null, permissionCallback);
+ } catch (IllegalStateException | SecurityException e) {
+ Log.e(TAG, "unable to revoke " + permInfo.name + " for "
+ + newPackage.getPackageName() + " user " + userId, e);
+ }
+ }
}
}
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index f075790a2fa0..d5dbf6bed913 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -554,8 +554,10 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
PackageInstaller.SessionInfo session = mContext.getPackageManager()
.getPackageInstaller().getSessionInfo(rollback.getStagedSessionId());
if (session == null || session.isStagedSessionFailed()) {
- iter.remove();
- rollback.delete(mAppDataRollbackHelper);
+ if (rollback.isEnabling()) {
+ iter.remove();
+ rollback.delete(mAppDataRollbackHelper);
+ }
continue;
}
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index eaf76938e2e8..ddad1dbd9b3d 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -3372,7 +3372,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
}
/**
- * Find all visible task stacks containing {@param userId} and intercept them with an activity
+ * Find all task stacks containing {@param userId} and intercept them with an activity
* to block out the contents and possibly start a credential-confirming intent.
*
* @param userId user handle for the locked managed profile.
@@ -3380,42 +3380,18 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
void lockAllProfileTasks(@UserIdInt int userId) {
mService.deferWindowLayout();
try {
- final PooledConsumer c = PooledLambda.obtainConsumer(
- RootWindowContainer::taskTopActivityIsUser, this, PooledLambda.__(Task.class),
- userId);
- forAllLeafTasks(c, true /* traverseTopToBottom */);
- c.recycle();
+ forAllLeafTasks(task -> {
+ if (task.getActivity(activity -> !activity.finishing && activity.mUserId == userId)
+ != null) {
+ mService.getTaskChangeNotificationController().notifyTaskProfileLocked(
+ task.mTaskId, userId);
+ }
+ }, true /* traverseTopToBottom */);
} finally {
mService.continueWindowLayout();
}
}
- /**
- * Detects whether we should show a lock screen in front of this task for a locked user.
- * <p>
- * We'll do this if either of the following holds:
- * <ul>
- * <li>The top activity explicitly belongs to {@param userId}.</li>
- * <li>The top activity returns a result to an activity belonging to {@param userId}.</li>
- * </ul>
- *
- * @return {@code true} if the top activity looks like it belongs to {@param userId}.
- */
- private void taskTopActivityIsUser(Task task, @UserIdInt int userId) {
- // To handle the case that work app is in the task but just is not the top one.
- final ActivityRecord activityRecord = task.getTopNonFinishingActivity();
- final ActivityRecord resultTo = (activityRecord != null ? activityRecord.resultTo : null);
-
- // Check the task for a top activity belonging to userId, or returning a
- // result to an activity belonging to userId. Example case: a document
- // picker for personal files, opened by a work app, should still get locked.
- if ((activityRecord != null && activityRecord.mUserId == userId)
- || (resultTo != null && resultTo.mUserId == userId)) {
- mService.getTaskChangeNotificationController().notifyTaskProfileLocked(
- task.mTaskId, userId);
- }
- }
-
void cancelInitializingActivities() {
for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
final DisplayContent display = getChildAt(displayNdx);
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
index 35d1b17d5822..1aff8a7b5382 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
@@ -25,6 +25,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.server.wm.ActivityStack.ActivityState.FINISHING;
import static com.android.server.wm.ActivityStack.ActivityState.PAUSED;
import static com.android.server.wm.ActivityStack.ActivityState.PAUSING;
@@ -36,10 +37,13 @@ import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.verify;
import android.app.WindowConfiguration;
import android.content.ComponentName;
import android.content.pm.ActivityInfo;
+import android.os.UserHandle;
import android.platform.test.annotations.Presubmit;
import androidx.test.filters.SmallTest;
@@ -169,5 +173,34 @@ public class RootWindowContainerTests extends WindowTestsBase {
activity.setState(FINISHING, "test FINISHING");
assertThat(mWm.mRoot.allPausedActivitiesComplete()).isTrue();
}
+
+ @Test
+ public void testLockAllProfileTasks() {
+ // Make an activity visible with the user id set to 0
+ DisplayContent displayContent = mWm.mRoot.getDisplayContent(DEFAULT_DISPLAY);
+ TaskDisplayArea taskDisplayArea = displayContent.getTaskDisplayAreaAt(0);
+ final ActivityStack stack = createTaskStackOnDisplay(WINDOWING_MODE_FULLSCREEN,
+ ACTIVITY_TYPE_STANDARD, displayContent);
+ final ActivityRecord activity = new ActivityTestsBase.ActivityBuilder(stack.mAtmService)
+ .setStack(stack)
+ .setUid(0)
+ .setCreateTask(true)
+ .build();
+
+ // Create another activity on top and the user id is 1
+ Task task = activity.getTask();
+ final ActivityRecord topActivity = new ActivityTestsBase.ActivityBuilder(mWm.mAtmService)
+ .setStack(stack)
+ .setUid(UserHandle.PER_USER_RANGE + 1)
+ .setTask(task)
+ .build();
+
+ // Make sure the listeners will be notified for putting the task to locked state
+ TaskChangeNotificationController controller =
+ mWm.mAtmService.getTaskChangeNotificationController();
+ spyOn(controller);
+ mWm.mRoot.lockAllProfileTasks(0);
+ verify(controller).notifyTaskProfileLocked(eq(task.mTaskId), eq(0));
+ }
}
diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
index 00bd4cf388ce..eaf9c7b4cb2e 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
@@ -482,6 +482,33 @@ public class StagedRollbackTest {
}
@Test
+ public void testExpireSession_Phase1_Install() throws Exception {
+ assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(-1);
+ Install.single(TestApp.A1).commit();
+ assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
+ Install.single(TestApp.A2).setEnableRollback().setStaged().commit();
+ }
+
+ @Test
+ public void testExpireSession_Phase2_VerifyInstall() throws Exception {
+ assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
+ RollbackManager rm = RollbackUtils.getRollbackManager();
+ RollbackInfo rollback = getUniqueRollbackInfoForPackage(
+ rm.getAvailableRollbacks(), TestApp.A);
+ assertThat(rollback).isNotNull();
+ assertThat(rollback).packagesContainsExactly(Rollback.from(TestApp.A2).to(TestApp.A1));
+ assertThat(rollback.isStaged()).isTrue();
+ }
+
+ @Test
+ public void testExpireSession_Phase3_VerifyRollback() throws Exception {
+ RollbackManager rm = RollbackUtils.getRollbackManager();
+ RollbackInfo rollback = getUniqueRollbackInfoForPackage(
+ rm.getAvailableRollbacks(), TestApp.A);
+ assertThat(rollback).isNotNull();
+ }
+
+ @Test
public void hasMainlineModule() throws Exception {
String pkgName = getModuleMetadataPackageName();
boolean existed = InstrumentationRegistry.getInstrumentation().getContext()
diff --git a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
index 9169ef517bf7..bebb991f5802 100644
--- a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
+++ b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
@@ -38,7 +38,9 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import java.io.File;
+import java.time.Instant;
import java.util.Collections;
+import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@@ -441,6 +443,27 @@ public class StagedRollbackTest extends BaseHostJUnit4Test {
after.forEach(dir -> assertDirectoryIsEmpty(dir));
}
+ /**
+ * Tests an available rollback shouldn't be deleted when its session expires.
+ */
+ @Test
+ public void testExpireSession() throws Exception {
+ runPhase("testExpireSession_Phase1_Install");
+ getDevice().reboot();
+ runPhase("testExpireSession_Phase2_VerifyInstall");
+
+ // Advance system clock by 7 days to expire the staged session
+ Instant t1 = Instant.ofEpochMilli(getDevice().getDeviceDate());
+ Instant t2 = t1.plusMillis(TimeUnit.DAYS.toMillis(7));
+ runAsRoot(() -> getDevice().setDate(Date.from(t2)));
+
+ // Somehow we need to wait for a while before reboot. Otherwise the change to the
+ // system clock will be reset after reboot.
+ Thread.sleep(3000);
+ getDevice().reboot();
+ runPhase("testExpireSession_Phase3_VerifyRollback");
+ }
+
private void pushTestApex() throws Exception {
CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(getBuild());
final String fileName = APK_IN_APEX_TESTAPEX_NAME + "_v1.apex";
@@ -521,4 +544,18 @@ public class StagedRollbackTest extends BaseHostJUnit4Test {
return false;
}
}
+
+ @FunctionalInterface
+ private interface ExceptionalRunnable {
+ void run() throws Exception;
+ }
+
+ private void runAsRoot(ExceptionalRunnable runnable) throws Exception {
+ try {
+ getDevice().enableAdbRoot();
+ runnable.run();
+ } finally {
+ getDevice().disableAdbRoot();
+ }
+ }
}
diff --git a/tests/net/integration/src/com/android/server/net/integrationtests/TestNetworkStackService.kt b/tests/net/integration/src/com/android/server/net/integrationtests/TestNetworkStackService.kt
index 8c2de4035d0b..649f71d4293f 100644
--- a/tests/net/integration/src/com/android/server/net/integrationtests/TestNetworkStackService.kt
+++ b/tests/net/integration/src/com/android/server/net/integrationtests/TestNetworkStackService.kt
@@ -59,7 +59,6 @@ class TestNetworkStackService : Service() {
private class NetworkMonitorDeps(private val privateDnsBypassNetwork: Network) :
NetworkMonitor.Dependencies() {
override fun getPrivateDnsBypassNetwork(network: Network?) = privateDnsBypassNetwork
- override fun sendNetworkConditionsBroadcast(context: Context, broadcast: Intent) = Unit
}
private inner class TestNetworkStackConnector(context: Context) : NetworkStackConnector(
@@ -94,4 +93,4 @@ class TestNetworkStackService : Service() {
cb.onNetworkMonitorCreated(NetworkMonitorConnector(nm, TestPermissionChecker()))
}
}
-} \ No newline at end of file
+}