| /* |
| * Copyright (C) 2018 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.slice; |
| |
| 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.clearInvocations; |
| import static org.mockito.Mockito.mock; |
| import static org.mockito.Mockito.verify; |
| |
| import android.content.ContentResolver; |
| import android.net.Uri; |
| import android.testing.AndroidTestingRunner; |
| import android.testing.TestableLooper.RunWithLooper; |
| import android.util.Xml.Encoding; |
| |
| import androidx.test.filters.SmallTest; |
| |
| import com.android.server.UiServiceTestCase; |
| import com.android.server.slice.SliceClientPermissions.SliceAuthority; |
| import com.android.server.slice.SlicePermissionManager.PkgUser; |
| |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| import org.xmlpull.v1.XmlPullParser; |
| import org.xmlpull.v1.XmlPullParserException; |
| import org.xmlpull.v1.XmlPullParserFactory; |
| import org.xmlpull.v1.XmlSerializer; |
| |
| import java.io.ByteArrayInputStream; |
| import java.io.ByteArrayOutputStream; |
| import java.io.IOException; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Comparator; |
| |
| @SmallTest |
| @RunWith(AndroidTestingRunner.class) |
| @RunWithLooper |
| public class SliceClientPermissionsTest extends UiServiceTestCase { |
| |
| @Test |
| public void testRemoveBasic() { |
| PkgUser pkg = new PkgUser("com.android.pkg", 0); |
| DirtyTracker tracker = mock(DirtyTracker.class); |
| SliceClientPermissions client = new SliceClientPermissions(pkg, tracker); |
| Uri base = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT) |
| .authority("com.android.pkg.slices").build(); |
| |
| PkgUser testPkg = new PkgUser("other", 2); |
| |
| client.grantUri(base.buildUpon() |
| .appendPath("first") |
| .build(), testPkg); |
| client.revokeUri(base.buildUpon() |
| .appendPath("first") |
| .build(), testPkg); |
| |
| assertFalse(client.hasPermission(base.buildUpon() |
| .appendPath("first") |
| .appendPath("third") |
| .build(), testPkg.getUserId())); |
| |
| ArrayList<SliceAuthority> authorities = new ArrayList<>(client.getAuthorities()); |
| assertEquals(0, authorities.get(0).getPaths().size()); |
| } |
| |
| @Test |
| public void testRemoveSubtrees() { |
| PkgUser pkg = new PkgUser("com.android.pkg", 0); |
| DirtyTracker tracker = mock(DirtyTracker.class); |
| SliceClientPermissions client = new SliceClientPermissions(pkg, tracker); |
| Uri base = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT) |
| .authority("com.android.pkg.slices").build(); |
| |
| PkgUser testPkg = new PkgUser("other", 2); |
| |
| client.grantUri(base.buildUpon() |
| .appendPath("first") |
| .appendPath("second") |
| .build(), testPkg); |
| client.grantUri(base.buildUpon() |
| .appendPath("first") |
| .appendPath("third") |
| .build(), testPkg); |
| client.revokeUri(base.buildUpon() |
| .appendPath("first") |
| .build(), testPkg); |
| |
| assertFalse(client.hasPermission(base.buildUpon() |
| .appendPath("first") |
| .appendPath("fourth") |
| .build(), testPkg.getUserId())); |
| |
| ArrayList<SliceAuthority> authorities = new ArrayList<>(client.getAuthorities()); |
| assertEquals(0, authorities.get(0).getPaths().size()); |
| } |
| |
| @Test |
| public void testAddConsolidate_addFirst() { |
| PkgUser pkg = new PkgUser("com.android.pkg", 0); |
| DirtyTracker tracker = mock(DirtyTracker.class); |
| SliceClientPermissions client = new SliceClientPermissions(pkg, tracker); |
| Uri base = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT) |
| .authority("com.android.pkg.slices").build(); |
| |
| PkgUser testPkg = new PkgUser("other", 2); |
| |
| client.grantUri(base.buildUpon() |
| .appendPath("first") |
| .build(), testPkg); |
| client.grantUri(base.buildUpon() |
| .appendPath("first") |
| .appendPath("second") |
| .build(), testPkg); |
| |
| assertTrue(client.hasPermission(base.buildUpon() |
| .appendPath("first") |
| .appendPath("third") |
| .build(), testPkg.getUserId())); |
| |
| ArrayList<SliceAuthority> authorities = new ArrayList<>(client.getAuthorities()); |
| assertEquals(1, authorities.get(0).getPaths().size()); |
| } |
| |
| @Test |
| public void testAddConsolidate_addSecond() { |
| PkgUser pkg = new PkgUser("com.android.pkg", 0); |
| DirtyTracker tracker = mock(DirtyTracker.class); |
| SliceClientPermissions client = new SliceClientPermissions(pkg, tracker); |
| Uri base = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT) |
| .authority("com.android.pkg.slices").build(); |
| |
| PkgUser testPkg = new PkgUser("other", 2); |
| |
| client.grantUri(base.buildUpon() |
| .appendPath("first") |
| .appendPath("second") |
| .build(), testPkg); |
| client.grantUri(base.buildUpon() |
| .appendPath("first") |
| .build(), testPkg); |
| |
| assertTrue(client.hasPermission(base.buildUpon() |
| .appendPath("first") |
| .appendPath("third") |
| .build(), testPkg.getUserId())); |
| |
| ArrayList<SliceAuthority> authorities = new ArrayList<>(client.getAuthorities()); |
| assertEquals(1, authorities.get(0).getPaths().size()); |
| } |
| |
| @Test |
| public void testDirty_addAuthority() { |
| PkgUser pkg = new PkgUser("com.android.pkg", 0); |
| DirtyTracker tracker = mock(DirtyTracker.class); |
| SliceClientPermissions client = new SliceClientPermissions(pkg, tracker); |
| |
| client.getOrCreateAuthority(new PkgUser("some_auth", 2), new PkgUser("com.pkg", 2)); |
| |
| verify(tracker).onPersistableDirty(eq(client)); |
| } |
| |
| @Test |
| public void testDirty_addPkg() { |
| PkgUser pkg = new PkgUser("com.android.pkg", 0); |
| DirtyTracker tracker = mock(DirtyTracker.class); |
| SliceClientPermissions client = new SliceClientPermissions(pkg, tracker); |
| |
| SliceAuthority auth = client.getOrCreateAuthority( |
| new PkgUser("some_auth", 2), |
| new PkgUser("com.pkg", 2)); |
| clearInvocations(tracker); |
| |
| auth.addPath(Arrays.asList("/something/")); |
| |
| verify(tracker).onPersistableDirty(eq(client)); |
| } |
| |
| @Test |
| public void testCreation() { |
| SliceClientPermissions client = createClient(); |
| ArrayList<SliceAuthority> authorities = new ArrayList<>(client.getAuthorities()); |
| authorities.sort(Comparator.comparing(SliceAuthority::getAuthority)); |
| |
| assertEquals(2, authorities.size()); |
| assertEquals("com.android.pkg", authorities.get(0).getAuthority()); |
| assertEquals("com.android.pkg.slices", authorities.get(1).getAuthority()); |
| |
| assertEquals(1, authorities.get(0).getPaths().size()); |
| assertEquals(2, authorities.get(1).getPaths().size()); |
| } |
| |
| @Test |
| public void testSerialization() throws XmlPullParserException, IOException { |
| SliceClientPermissions client = createClient(); |
| client.setHasFullAccess(true); |
| |
| ByteArrayOutputStream output = new ByteArrayOutputStream(); |
| XmlSerializer serializer = XmlPullParserFactory.newInstance().newSerializer(); |
| serializer.setOutput(output, Encoding.UTF_8.name()); |
| |
| client.writeTo(serializer); |
| serializer.flush(); |
| |
| ByteArrayInputStream input = new ByteArrayInputStream(output.toByteArray()); |
| XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser(); |
| parser.setInput(input, Encoding.UTF_8.name()); |
| |
| SliceClientPermissions deser = SliceClientPermissions.createFrom(parser, |
| mock(DirtyTracker.class)); |
| |
| assertEquivalent(client, deser); |
| } |
| |
| private void assertEquivalent(SliceClientPermissions o1, SliceClientPermissions o2) { |
| assertEquals(o1.getPkg(), o2.getPkg()); |
| ArrayList<SliceAuthority> a1 = new ArrayList<>(o1.getAuthorities()); |
| ArrayList<SliceAuthority> a2 = new ArrayList<>(o2.getAuthorities()); |
| a1.sort(Comparator.comparing(SliceAuthority::getAuthority)); |
| a2.sort(Comparator.comparing(SliceAuthority::getAuthority)); |
| assertEquals(a1, a2); |
| } |
| |
| private static SliceClientPermissions createClient() { |
| PkgUser pkg = new PkgUser("com.android.pkg", 2); |
| DirtyTracker tracker = mock(DirtyTracker.class); |
| SliceClientPermissions client = new SliceClientPermissions(pkg, tracker); |
| |
| SliceAuthority auth = client.getOrCreateAuthority( |
| new PkgUser("com.android.pkg.slices", 3), |
| new PkgUser("com.android.pkg", 3)); |
| auth.addPath(Arrays.asList("/something/")); |
| auth.addPath(Arrays.asList("/something/else")); |
| |
| auth = client.getOrCreateAuthority( |
| new PkgUser("com.android.pkg", 3), |
| new PkgUser("com.pkg", 1)); |
| auth.addPath(Arrays.asList("/somewhere")); |
| return client; |
| } |
| |
| } |