Merge RQ3A.210705.001 to aosp-master - DO NOT MERGE
Merged-In: I867df303b8da1b9748e5a775dd8bf4a1b910c434 Merged-In: Ia19f336f9eca3b493157dcd3ad07d267b6526e8f Merged-In: Ia19f336f9eca3b493157dcd3ad07d267b6526e8f Change-Id: I16c6e1ee5e172100a22995ae464c5f2c596d2381
This commit is contained in:
commit
97f19415cd
@ -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);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -481,6 +481,33 @@ public class StagedRollbackTest {
|
||||
assertThat(sm.isCheckpointSupported()).isTrue();
|
||||
}
|
||||
|
||||
@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();
|
||||
|
@ -39,7 +39,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;
|
||||
@ -445,6 +447,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";
|
||||
@ -525,4 +548,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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License
|
||||
*/
|
||||
|
||||
package com.android.server.net.integrationtests
|
||||
|
||||
import android.app.Service
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.INetworkMonitorCallbacks
|
||||
import android.net.Network
|
||||
import android.net.metrics.IpConnectivityLog
|
||||
import android.net.util.SharedLog
|
||||
import android.os.IBinder
|
||||
import com.android.networkstack.netlink.TcpSocketTracker
|
||||
import com.android.server.NetworkStackService
|
||||
import com.android.server.NetworkStackService.NetworkMonitorConnector
|
||||
import com.android.server.NetworkStackService.NetworkStackConnector
|
||||
import com.android.server.connectivity.NetworkMonitor
|
||||
import com.android.server.net.integrationtests.NetworkStackInstrumentationService.InstrumentationConnector
|
||||
import org.mockito.Mockito.doReturn
|
||||
import org.mockito.Mockito.mock
|
||||
import org.mockito.Mockito.spy
|
||||
import java.net.HttpURLConnection
|
||||
import java.net.URL
|
||||
import java.net.URLConnection
|
||||
|
||||
private const val TEST_NETID = 42
|
||||
|
||||
/**
|
||||
* Android service that can return an [android.net.INetworkStackConnector] which can be instrumented
|
||||
* through [NetworkStackInstrumentationService].
|
||||
* Useful in tests to create test instrumented NetworkStack components that can receive
|
||||
* instrumentation commands through [NetworkStackInstrumentationService].
|
||||
*/
|
||||
class TestNetworkStackService : Service() {
|
||||
override fun onBind(intent: Intent): IBinder = TestNetworkStackConnector(makeTestContext())
|
||||
|
||||
private fun makeTestContext() = spy(applicationContext).also {
|
||||
doReturn(mock(IBinder::class.java)).`when`(it).getSystemService(Context.NETD_SERVICE)
|
||||
}
|
||||
|
||||
private class TestPermissionChecker : NetworkStackService.PermissionChecker() {
|
||||
override fun enforceNetworkStackCallingPermission() = Unit
|
||||
}
|
||||
|
||||
private class NetworkMonitorDeps(private val privateDnsBypassNetwork: Network) :
|
||||
NetworkMonitor.Dependencies() {
|
||||
override fun getPrivateDnsBypassNetwork(network: Network?) = privateDnsBypassNetwork
|
||||
}
|
||||
|
||||
private inner class TestNetworkStackConnector(context: Context) : NetworkStackConnector(
|
||||
context, TestPermissionChecker(), NetworkStackService.Dependencies()) {
|
||||
|
||||
private val network = Network(TEST_NETID)
|
||||
private val privateDnsBypassNetwork = TestNetwork(TEST_NETID)
|
||||
|
||||
private inner class TestNetwork(netId: Int) : Network(netId) {
|
||||
override fun openConnection(url: URL): URLConnection {
|
||||
val response = InstrumentationConnector.processRequest(url)
|
||||
|
||||
val connection = mock(HttpURLConnection::class.java)
|
||||
doReturn(response.responseCode).`when`(connection).responseCode
|
||||
doReturn(response.contentLength).`when`(connection).contentLengthLong
|
||||
doReturn(response.redirectUrl).`when`(connection).getHeaderField("location")
|
||||
return connection
|
||||
}
|
||||
}
|
||||
|
||||
override fun makeNetworkMonitor(
|
||||
network: Network,
|
||||
name: String?,
|
||||
cb: INetworkMonitorCallbacks
|
||||
) {
|
||||
val nm = NetworkMonitor(this@TestNetworkStackService, cb,
|
||||
this.network,
|
||||
mock(IpConnectivityLog::class.java), mock(SharedLog::class.java),
|
||||
mock(NetworkStackService.NetworkStackServiceManager::class.java),
|
||||
NetworkMonitorDeps(privateDnsBypassNetwork),
|
||||
mock(TcpSocketTracker::class.java))
|
||||
cb.onNetworkMonitorCreated(NetworkMonitorConnector(nm, TestPermissionChecker()))
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user