diff options
| author | 2018-05-22 18:50:24 +0000 | |
|---|---|---|
| committer | 2018-05-22 18:50:24 +0000 | |
| commit | a828705fc90d35d85d8775e4929b4fe2c0dd69c7 (patch) | |
| tree | de92d29d918984fbde24b2e6ab3363bec4c68238 | |
| parent | 2d6dbbac04a3f47cbdce91476337a8c7d7c0d0eb (diff) | |
| parent | e009a8ed6ed309d0e75d6fc5739eb67eb174777c (diff) | |
Merge "Optimize slice permission checks a bit" into pi-dev
| -rw-r--r-- | services/core/java/com/android/server/slice/SliceManagerService.java | 64 | ||||
| -rw-r--r-- | services/tests/uiservicestests/src/com/android/server/slice/PackageMatchingCacheTest.java | 75 | 
2 files changed, 132 insertions, 7 deletions
| diff --git a/services/core/java/com/android/server/slice/SliceManagerService.java b/services/core/java/com/android/server/slice/SliceManagerService.java index 2621c50fb2f2..c3b984172802 100644 --- a/services/core/java/com/android/server/slice/SliceManagerService.java +++ b/services/core/java/com/android/server/slice/SliceManagerService.java @@ -55,6 +55,7 @@ import android.os.ShellCallback;  import android.os.UserHandle;  import android.util.ArrayMap;  import android.util.Slog; +import android.util.SparseArray;  import android.util.Xml.Encoding;  import com.android.internal.annotations.GuardedBy; @@ -77,6 +78,7 @@ import java.io.IOException;  import java.util.ArrayList;  import java.util.List;  import java.util.Objects; +import java.util.function.Supplier;  public class SliceManagerService extends ISliceManager.Stub { @@ -90,6 +92,10 @@ public class SliceManagerService extends ISliceManager.Stub {      @GuardedBy("mLock")      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 SlicePermissionManager mPermissions; @@ -453,17 +459,37 @@ public class SliceManagerService extends ISliceManager.Stub {      }      private boolean isAssistant(String pkg, int userId) { -        final ComponentName cn = mAssistUtils.getAssistComponentForUser(userId); -        if (cn == null) { -            return false; -        } -        return cn.getPackageName().equals(pkg); +        return getAssistantMatcher(userId).matches(pkg);      }      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. @@ -559,6 +585,30 @@ public class SliceManagerService extends ISliceManager.Stub {          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 {          private SliceManagerService mService; diff --git a/services/tests/uiservicestests/src/com/android/server/slice/PackageMatchingCacheTest.java b/services/tests/uiservicestests/src/com/android/server/slice/PackageMatchingCacheTest.java new file mode 100644 index 000000000000..c6aea882b7ca --- /dev/null +++ b/services/tests/uiservicestests/src/com/android/server/slice/PackageMatchingCacheTest.java @@ -0,0 +1,75 @@ +/* + * 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(); +    } +} |