Loading services/core/java/com/android/server/slice/SliceManagerService.java +57 −7 Original line number Original line Diff line number Diff line Loading @@ -55,6 +55,7 @@ import android.os.ShellCallback; import android.os.UserHandle; import android.os.UserHandle; import android.util.ArrayMap; import android.util.ArrayMap; import android.util.Slog; import android.util.Slog; import android.util.SparseArray; import android.util.Xml.Encoding; import android.util.Xml.Encoding; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.GuardedBy; Loading @@ -77,6 +78,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.ArrayList; import java.util.List; import java.util.List; import java.util.Objects; import java.util.Objects; import java.util.function.Supplier; public class SliceManagerService extends ISliceManager.Stub { public class SliceManagerService extends ISliceManager.Stub { Loading @@ -90,6 +92,10 @@ public class SliceManagerService extends ISliceManager.Stub { @GuardedBy("mLock") @GuardedBy("mLock") private final ArrayMap<Uri, PinnedSliceState> mPinnedSlicesByUri = new ArrayMap<>(); private final ArrayMap<Uri, PinnedSliceState> mPinnedSlicesByUri = new ArrayMap<>(); @GuardedBy("mLock") private final SparseArray<PackageMatchingCache> mAssistantLookup = new SparseArray<>(); @GuardedBy("mLock") private final SparseArray<PackageMatchingCache> mHomeLookup = new SparseArray<>(); private final Handler mHandler; private final Handler mHandler; private final SlicePermissionManager mPermissions; private final SlicePermissionManager mPermissions; Loading Loading @@ -453,17 +459,37 @@ public class SliceManagerService extends ISliceManager.Stub { } } private boolean isAssistant(String pkg, int userId) { private boolean isAssistant(String pkg, int userId) { final ComponentName cn = mAssistUtils.getAssistComponentForUser(userId); return getAssistantMatcher(userId).matches(pkg); if (cn == null) { return false; } return cn.getPackageName().equals(pkg); } } private boolean isDefaultHomeApp(String pkg, int userId) { private boolean isDefaultHomeApp(String pkg, int userId) { String defaultHome = getDefaultHome(userId); return getHomeMatcher(userId).matches(pkg); } return pkg != null && Objects.equals(pkg, defaultHome); private PackageMatchingCache getAssistantMatcher(int userId) { PackageMatchingCache matcher = mAssistantLookup.get(userId); if (matcher == null) { matcher = new PackageMatchingCache(() -> getAssistant(userId)); mAssistantLookup.put(userId, matcher); } return matcher; } private PackageMatchingCache getHomeMatcher(int userId) { PackageMatchingCache matcher = mHomeLookup.get(userId); if (matcher == null) { matcher = new PackageMatchingCache(() -> getDefaultHome(userId)); mHomeLookup.put(userId, matcher); } return matcher; } private String getAssistant(int userId) { final ComponentName cn = mAssistUtils.getAssistComponentForUser(userId); if (cn == null) { return null; } return cn.getPackageName(); } } // Based on getDefaultHome in ShortcutService. // Based on getDefaultHome in ShortcutService. Loading Loading @@ -559,6 +585,30 @@ public class SliceManagerService extends ISliceManager.Stub { return mPermissions.getAllPackagesGranted(pkg); return mPermissions.getAllPackagesGranted(pkg); } } /** * Holder that caches a package that has access to a slice. */ static class PackageMatchingCache { private final Supplier<String> mPkgSource; private String mCurrentPkg; public PackageMatchingCache(Supplier<String> pkgSource) { mPkgSource = pkgSource; } public boolean matches(String pkgCandidate) { if (pkgCandidate == null) return false; if (Objects.equals(pkgCandidate, mCurrentPkg)) { return true; } // Failed on cached value, try updating. mCurrentPkg = mPkgSource.get(); return Objects.equals(pkgCandidate, mCurrentPkg); } } public static class Lifecycle extends SystemService { public static class Lifecycle extends SystemService { private SliceManagerService mService; private SliceManagerService mService; Loading services/tests/uiservicestests/src/com/android/server/slice/PackageMatchingCacheTest.java 0 → 100644 +75 −0 Original line number Original line Diff line number Diff line /* * 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.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.support.test.filters.SmallTest; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper.RunWithLooper; import com.android.server.UiServiceTestCase; import com.android.server.slice.SliceManagerService.PackageMatchingCache; import org.junit.Test; import org.junit.runner.RunWith; import java.util.function.Supplier; @SmallTest @RunWith(AndroidTestingRunner.class) @RunWithLooper public class PackageMatchingCacheTest extends UiServiceTestCase { private final Supplier<String> supplier = mock(Supplier.class); private final PackageMatchingCache cache = new PackageMatchingCache(supplier); @Test public void testNulls() { // Doesn't get for a null input cache.matches(null); verify(supplier, never()).get(); // Gets once valid input in sent. cache.matches(""); verify(supplier).get(); } @Test public void testCaching() { when(supplier.get()).thenReturn("ret.pkg"); assertTrue(cache.matches("ret.pkg")); assertTrue(cache.matches("ret.pkg")); assertTrue(cache.matches("ret.pkg")); verify(supplier, times(1)).get(); } @Test public void testGetOnFailure() { when(supplier.get()).thenReturn("ret.pkg"); assertTrue(cache.matches("ret.pkg")); when(supplier.get()).thenReturn("other.pkg"); assertTrue(cache.matches("other.pkg")); verify(supplier, times(2)).get(); } } Loading
services/core/java/com/android/server/slice/SliceManagerService.java +57 −7 Original line number Original line Diff line number Diff line Loading @@ -55,6 +55,7 @@ import android.os.ShellCallback; import android.os.UserHandle; import android.os.UserHandle; import android.util.ArrayMap; import android.util.ArrayMap; import android.util.Slog; import android.util.Slog; import android.util.SparseArray; import android.util.Xml.Encoding; import android.util.Xml.Encoding; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.GuardedBy; Loading @@ -77,6 +78,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.ArrayList; import java.util.List; import java.util.List; import java.util.Objects; import java.util.Objects; import java.util.function.Supplier; public class SliceManagerService extends ISliceManager.Stub { public class SliceManagerService extends ISliceManager.Stub { Loading @@ -90,6 +92,10 @@ public class SliceManagerService extends ISliceManager.Stub { @GuardedBy("mLock") @GuardedBy("mLock") private final ArrayMap<Uri, PinnedSliceState> mPinnedSlicesByUri = new ArrayMap<>(); private final ArrayMap<Uri, PinnedSliceState> mPinnedSlicesByUri = new ArrayMap<>(); @GuardedBy("mLock") private final SparseArray<PackageMatchingCache> mAssistantLookup = new SparseArray<>(); @GuardedBy("mLock") private final SparseArray<PackageMatchingCache> mHomeLookup = new SparseArray<>(); private final Handler mHandler; private final Handler mHandler; private final SlicePermissionManager mPermissions; private final SlicePermissionManager mPermissions; Loading Loading @@ -453,17 +459,37 @@ public class SliceManagerService extends ISliceManager.Stub { } } private boolean isAssistant(String pkg, int userId) { private boolean isAssistant(String pkg, int userId) { final ComponentName cn = mAssistUtils.getAssistComponentForUser(userId); return getAssistantMatcher(userId).matches(pkg); if (cn == null) { return false; } return cn.getPackageName().equals(pkg); } } private boolean isDefaultHomeApp(String pkg, int userId) { private boolean isDefaultHomeApp(String pkg, int userId) { String defaultHome = getDefaultHome(userId); return getHomeMatcher(userId).matches(pkg); } return pkg != null && Objects.equals(pkg, defaultHome); private PackageMatchingCache getAssistantMatcher(int userId) { PackageMatchingCache matcher = mAssistantLookup.get(userId); if (matcher == null) { matcher = new PackageMatchingCache(() -> getAssistant(userId)); mAssistantLookup.put(userId, matcher); } return matcher; } private PackageMatchingCache getHomeMatcher(int userId) { PackageMatchingCache matcher = mHomeLookup.get(userId); if (matcher == null) { matcher = new PackageMatchingCache(() -> getDefaultHome(userId)); mHomeLookup.put(userId, matcher); } return matcher; } private String getAssistant(int userId) { final ComponentName cn = mAssistUtils.getAssistComponentForUser(userId); if (cn == null) { return null; } return cn.getPackageName(); } } // Based on getDefaultHome in ShortcutService. // Based on getDefaultHome in ShortcutService. Loading Loading @@ -559,6 +585,30 @@ public class SliceManagerService extends ISliceManager.Stub { return mPermissions.getAllPackagesGranted(pkg); return mPermissions.getAllPackagesGranted(pkg); } } /** * Holder that caches a package that has access to a slice. */ static class PackageMatchingCache { private final Supplier<String> mPkgSource; private String mCurrentPkg; public PackageMatchingCache(Supplier<String> pkgSource) { mPkgSource = pkgSource; } public boolean matches(String pkgCandidate) { if (pkgCandidate == null) return false; if (Objects.equals(pkgCandidate, mCurrentPkg)) { return true; } // Failed on cached value, try updating. mCurrentPkg = mPkgSource.get(); return Objects.equals(pkgCandidate, mCurrentPkg); } } public static class Lifecycle extends SystemService { public static class Lifecycle extends SystemService { private SliceManagerService mService; private SliceManagerService mService; Loading
services/tests/uiservicestests/src/com/android/server/slice/PackageMatchingCacheTest.java 0 → 100644 +75 −0 Original line number Original line Diff line number Diff line /* * 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.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.support.test.filters.SmallTest; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper.RunWithLooper; import com.android.server.UiServiceTestCase; import com.android.server.slice.SliceManagerService.PackageMatchingCache; import org.junit.Test; import org.junit.runner.RunWith; import java.util.function.Supplier; @SmallTest @RunWith(AndroidTestingRunner.class) @RunWithLooper public class PackageMatchingCacheTest extends UiServiceTestCase { private final Supplier<String> supplier = mock(Supplier.class); private final PackageMatchingCache cache = new PackageMatchingCache(supplier); @Test public void testNulls() { // Doesn't get for a null input cache.matches(null); verify(supplier, never()).get(); // Gets once valid input in sent. cache.matches(""); verify(supplier).get(); } @Test public void testCaching() { when(supplier.get()).thenReturn("ret.pkg"); assertTrue(cache.matches("ret.pkg")); assertTrue(cache.matches("ret.pkg")); assertTrue(cache.matches("ret.pkg")); verify(supplier, times(1)).get(); } @Test public void testGetOnFailure() { when(supplier.get()).thenReturn("ret.pkg"); assertTrue(cache.matches("ret.pkg")); when(supplier.get()).thenReturn("other.pkg"); assertTrue(cache.matches("other.pkg")); verify(supplier, times(2)).get(); } }