Loading services/core/java/com/android/server/wm/TaskFragment.java +20 −7 Original line number Diff line number Diff line Loading @@ -732,17 +732,30 @@ class TaskFragment extends WindowContainer<WindowContainer> { return true; } final AndroidPackage hostPackage = mAtmService.getPackageManagerInternalLocked() .getPackage(uid); return hostPackage != null && isAllowedToEmbedActivityInTrustedModeByHostPackage(a, hostPackage); } @VisibleForTesting boolean isAllowedToEmbedActivityInTrustedModeByHostPackage( @NonNull ActivityRecord a, @NonNull AndroidPackage hostPackage) { // Known certs declared in the <activity> tag Set<String> knownActivityEmbeddingCerts = a.info.getKnownActivityEmbeddingCerts(); // If the activity-level value is specified, it takes precedence. Otherwise, we read the // application-level value. if (knownActivityEmbeddingCerts.isEmpty()) { // An application must either declare that it allows untrusted embedding, or specify // a set of app certificates that are allowed to embed it in trusted mode. return false; // Known certs declared in the <application> tag knownActivityEmbeddingCerts = a.info.applicationInfo.getKnownActivityEmbeddingCerts(); } AndroidPackage hostPackage = mAtmService.getPackageManagerInternalLocked() .getPackage(uid); return hostPackage != null && hostPackage.getSigningDetails().hasAncestorOrSelfWithDigest( // An application must specify a set of app certificates that are allowed to embed it in // trusted mode. return hostPackage.getSigningDetails().hasAncestorOrSelfWithDigest( knownActivityEmbeddingCerts); } Loading services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java +6 −0 Original line number Diff line number Diff line Loading @@ -425,6 +425,12 @@ public class ActivityStarterTests extends WindowTestsBase { doNothing().when(mMockPackageManager).notifyPackageUse(anyString(), anyInt()); doReturn(mock(PackageArchiver.class)).when(mMockPackageManager).getPackageArchiver(); final AndroidPackage mockPackage = mock(AndroidPackage.class); final SigningDetails signingDetails = mock(SigningDetails.class); doReturn(mockPackage).when(mMockPackageManager).getPackage(anyInt()); doReturn(signingDetails).when(mockPackage).getSigningDetails(); doReturn(false).when(signingDetails).hasAncestorOrSelfWithDigest(any()); final Intent intent = new Intent(); intent.addFlags(launchFlags); intent.setComponent(ActivityBuilder.getDefaultComponent()); Loading services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java +52 −1 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.never; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; import static com.android.dx.mockito.inline.extended.ExtendedMockito.when; import static com.android.server.wm.ActivityRecord.State.RESUMED; import static com.android.server.wm.TaskFragment.EMBEDDED_DIM_AREA_PARENT_TASK; import static com.android.server.wm.TaskFragment.EMBEDDED_DIM_AREA_TASK_FRAGMENT; Loading @@ -46,7 +47,9 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.mock; import android.content.pm.SigningDetails; import android.content.res.Configuration; import android.graphics.Color; import android.graphics.Rect; Loading @@ -61,12 +64,17 @@ import android.window.TaskFragmentOrganizer; import androidx.test.filters.MediumTest; import com.android.server.pm.pkg.AndroidPackage; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.util.Collections; import java.util.Set; /** * Test class for {@link TaskFragment}. * Loading Loading @@ -536,6 +544,49 @@ public class TaskFragmentTest extends WindowTestsBase { taskFragment.isAllowedToEmbedActivity(activity)); } @Test public void testIsAllowedToEmbedActivityInTrustedModeByHostPackage() { final TaskFragment taskFragment = new TaskFragmentBuilder(mAtm) .setCreateParentTask() .createActivityCount(1) .build(); final ActivityRecord activity = taskFragment.getTopMostActivity(); final String mockCert = "MOCKCERT"; final AndroidPackage hostPackage = mock(AndroidPackage.class); final SigningDetails signingDetails = mock(SigningDetails.class); when(signingDetails.hasAncestorOrSelfWithDigest(any())) .thenAnswer(invocation -> ((Set) invocation.getArgument(0)).contains(mockCert)); doReturn(signingDetails).when(hostPackage).getSigningDetails(); // Should return false when no certs are specified assertFalse(taskFragment.isAllowedToEmbedActivityInTrustedModeByHostPackage( activity, hostPackage)); // Should return true when the cert is specified in <activity> activity.info.setKnownActivityEmbeddingCerts(Set.of(mockCert)); assertTrue(taskFragment.isAllowedToEmbedActivityInTrustedModeByHostPackage( activity, hostPackage)); // Should return false when the certs specified in <activity> doesn't match activity.info.setKnownActivityEmbeddingCerts(Set.of("WRONGCERT")); assertFalse(taskFragment.isAllowedToEmbedActivityInTrustedModeByHostPackage( activity, hostPackage)); // Should return true when the certs is specified in <application> activity.info.setKnownActivityEmbeddingCerts(Collections.emptySet()); activity.info.applicationInfo.setKnownActivityEmbeddingCerts(Set.of(mockCert)); assertTrue(taskFragment.isAllowedToEmbedActivityInTrustedModeByHostPackage( activity, hostPackage)); // When the certs is specified in both <activity> and <application>, <activity> takes // precedence activity.info.setKnownActivityEmbeddingCerts(Set.of("WRONGCERT")); activity.info.applicationInfo.setKnownActivityEmbeddingCerts(Set.of(mockCert)); assertFalse(taskFragment.isAllowedToEmbedActivityInTrustedModeByHostPackage( activity, hostPackage)); } @Test public void testIgnoreRequestedOrientationForActivityEmbeddingSplit() { // Setup two activities in ActivityEmbedding split. Loading Loading
services/core/java/com/android/server/wm/TaskFragment.java +20 −7 Original line number Diff line number Diff line Loading @@ -732,17 +732,30 @@ class TaskFragment extends WindowContainer<WindowContainer> { return true; } final AndroidPackage hostPackage = mAtmService.getPackageManagerInternalLocked() .getPackage(uid); return hostPackage != null && isAllowedToEmbedActivityInTrustedModeByHostPackage(a, hostPackage); } @VisibleForTesting boolean isAllowedToEmbedActivityInTrustedModeByHostPackage( @NonNull ActivityRecord a, @NonNull AndroidPackage hostPackage) { // Known certs declared in the <activity> tag Set<String> knownActivityEmbeddingCerts = a.info.getKnownActivityEmbeddingCerts(); // If the activity-level value is specified, it takes precedence. Otherwise, we read the // application-level value. if (knownActivityEmbeddingCerts.isEmpty()) { // An application must either declare that it allows untrusted embedding, or specify // a set of app certificates that are allowed to embed it in trusted mode. return false; // Known certs declared in the <application> tag knownActivityEmbeddingCerts = a.info.applicationInfo.getKnownActivityEmbeddingCerts(); } AndroidPackage hostPackage = mAtmService.getPackageManagerInternalLocked() .getPackage(uid); return hostPackage != null && hostPackage.getSigningDetails().hasAncestorOrSelfWithDigest( // An application must specify a set of app certificates that are allowed to embed it in // trusted mode. return hostPackage.getSigningDetails().hasAncestorOrSelfWithDigest( knownActivityEmbeddingCerts); } Loading
services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java +6 −0 Original line number Diff line number Diff line Loading @@ -425,6 +425,12 @@ public class ActivityStarterTests extends WindowTestsBase { doNothing().when(mMockPackageManager).notifyPackageUse(anyString(), anyInt()); doReturn(mock(PackageArchiver.class)).when(mMockPackageManager).getPackageArchiver(); final AndroidPackage mockPackage = mock(AndroidPackage.class); final SigningDetails signingDetails = mock(SigningDetails.class); doReturn(mockPackage).when(mMockPackageManager).getPackage(anyInt()); doReturn(signingDetails).when(mockPackage).getSigningDetails(); doReturn(false).when(signingDetails).hasAncestorOrSelfWithDigest(any()); final Intent intent = new Intent(); intent.addFlags(launchFlags); intent.setComponent(ActivityBuilder.getDefaultComponent()); Loading
services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java +52 −1 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.never; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; import static com.android.dx.mockito.inline.extended.ExtendedMockito.when; import static com.android.server.wm.ActivityRecord.State.RESUMED; import static com.android.server.wm.TaskFragment.EMBEDDED_DIM_AREA_PARENT_TASK; import static com.android.server.wm.TaskFragment.EMBEDDED_DIM_AREA_TASK_FRAGMENT; Loading @@ -46,7 +47,9 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.mock; import android.content.pm.SigningDetails; import android.content.res.Configuration; import android.graphics.Color; import android.graphics.Rect; Loading @@ -61,12 +64,17 @@ import android.window.TaskFragmentOrganizer; import androidx.test.filters.MediumTest; import com.android.server.pm.pkg.AndroidPackage; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.util.Collections; import java.util.Set; /** * Test class for {@link TaskFragment}. * Loading Loading @@ -536,6 +544,49 @@ public class TaskFragmentTest extends WindowTestsBase { taskFragment.isAllowedToEmbedActivity(activity)); } @Test public void testIsAllowedToEmbedActivityInTrustedModeByHostPackage() { final TaskFragment taskFragment = new TaskFragmentBuilder(mAtm) .setCreateParentTask() .createActivityCount(1) .build(); final ActivityRecord activity = taskFragment.getTopMostActivity(); final String mockCert = "MOCKCERT"; final AndroidPackage hostPackage = mock(AndroidPackage.class); final SigningDetails signingDetails = mock(SigningDetails.class); when(signingDetails.hasAncestorOrSelfWithDigest(any())) .thenAnswer(invocation -> ((Set) invocation.getArgument(0)).contains(mockCert)); doReturn(signingDetails).when(hostPackage).getSigningDetails(); // Should return false when no certs are specified assertFalse(taskFragment.isAllowedToEmbedActivityInTrustedModeByHostPackage( activity, hostPackage)); // Should return true when the cert is specified in <activity> activity.info.setKnownActivityEmbeddingCerts(Set.of(mockCert)); assertTrue(taskFragment.isAllowedToEmbedActivityInTrustedModeByHostPackage( activity, hostPackage)); // Should return false when the certs specified in <activity> doesn't match activity.info.setKnownActivityEmbeddingCerts(Set.of("WRONGCERT")); assertFalse(taskFragment.isAllowedToEmbedActivityInTrustedModeByHostPackage( activity, hostPackage)); // Should return true when the certs is specified in <application> activity.info.setKnownActivityEmbeddingCerts(Collections.emptySet()); activity.info.applicationInfo.setKnownActivityEmbeddingCerts(Set.of(mockCert)); assertTrue(taskFragment.isAllowedToEmbedActivityInTrustedModeByHostPackage( activity, hostPackage)); // When the certs is specified in both <activity> and <application>, <activity> takes // precedence activity.info.setKnownActivityEmbeddingCerts(Set.of("WRONGCERT")); activity.info.applicationInfo.setKnownActivityEmbeddingCerts(Set.of(mockCert)); assertFalse(taskFragment.isAllowedToEmbedActivityInTrustedModeByHostPackage( activity, hostPackage)); } @Test public void testIgnoreRequestedOrientationForActivityEmbeddingSplit() { // Setup two activities in ActivityEmbedding split. Loading