1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.server.tv; 17 18 import static org.hamcrest.Matchers.not; 19 import static org.junit.Assert.assertFalse; 20 import static org.junit.Assert.assertTrue; 21 import static org.mockito.ArgumentMatchers.anyInt; 22 import static org.mockito.ArgumentMatchers.anyString; 23 import static org.mockito.Mockito.reset; 24 import static org.mockito.Mockito.when; 25 import static org.mockito.hamcrest.MockitoHamcrest.argThat; 26 27 import android.Manifest; 28 import android.content.Context; 29 import android.content.pm.PackageManager; 30 import android.content.pm.ServiceInfo; 31 import android.content.res.Resources; 32 import android.os.Handler; 33 import android.os.Looper; 34 35 import androidx.test.filters.SmallTest; 36 37 import org.junit.Before; 38 import org.junit.Test; 39 import org.mockito.Mock; 40 import org.mockito.MockitoAnnotations; 41 42 @SmallTest 43 public class TvRemoteProviderWatcherTest { 44 private static final String TV_REMOTE_SERVICE_PACKAGE_NAME = 45 "com.google.android.tv.remote.service"; 46 47 @Mock 48 Context mMockContext; 49 @Mock 50 PackageManager mMockPackageManager; 51 @Mock 52 Resources mMockResources; 53 54 private TvRemoteProviderWatcher mTvRemoteProviderWatcher; 55 56 @Before setUp()57 public void setUp() throws Exception { 58 MockitoAnnotations.initMocks(this); 59 60 if (Looper.myLooper() == null) { 61 Looper.prepare(); 62 } 63 64 when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager); 65 when(mMockContext.getResources()).thenReturn(mMockResources); 66 67 when(mMockResources.getString(com.android.internal.R.string.config_tvRemoteServicePackage)) 68 .thenReturn(TV_REMOTE_SERVICE_PACKAGE_NAME); 69 70 71 when(mMockPackageManager.checkPermission( 72 argThat(not(Manifest.permission.TV_VIRTUAL_REMOTE_CONTROLLER)), 73 anyString())).thenReturn( 74 PackageManager.PERMISSION_DENIED); 75 76 when(mMockPackageManager.checkPermission( 77 anyString(), 78 argThat(not(TV_REMOTE_SERVICE_PACKAGE_NAME)))).thenReturn( 79 PackageManager.PERMISSION_DENIED); 80 81 when(mMockPackageManager.checkPermission(Manifest.permission.TV_VIRTUAL_REMOTE_CONTROLLER, 82 TV_REMOTE_SERVICE_PACKAGE_NAME)).thenReturn(PackageManager.PERMISSION_GRANTED); 83 84 mTvRemoteProviderWatcher = new TvRemoteProviderWatcher(mMockContext, new Object()); 85 } 86 87 @Test acceptsValidCsvPackageName()88 public void acceptsValidCsvPackageName() { 89 // Test intentionally includes empty spacing for a more complex test 90 when(mMockResources.getString(com.android.internal.R.string.config_tvRemoteServicePackage)) 91 .thenReturn(",,foo, " + TV_REMOTE_SERVICE_PACKAGE_NAME + ",bar, baz,,"); 92 93 // Re-create the object since package name is loaded in the constructor 94 TvRemoteProviderWatcher watcher = 95 new TvRemoteProviderWatcher( 96 mMockContext, new Object(), new Handler(Looper.getMainLooper())); 97 assertTrue(watcher.verifyServiceTrusted(createTvServiceInfo())); 98 } 99 100 @Test rejectsInvalidCsvPackageName()101 public void rejectsInvalidCsvPackageName() { 102 // Checks include empty strings to validate that processing as well 103 when(mMockResources.getString(com.android.internal.R.string.config_tvRemoteServicePackage)) 104 .thenReturn(",,foo,, ,bar, baz,,"); 105 106 // Re-create the object since package name is loaded in the constructor 107 TvRemoteProviderWatcher watcher = 108 new TvRemoteProviderWatcher( 109 mMockContext, new Object(), new Handler(Looper.getMainLooper())); 110 assertFalse(watcher.verifyServiceTrusted(createTvServiceInfo())); 111 } 112 113 @Test tvServiceIsTrusted()114 public void tvServiceIsTrusted() { 115 assertTrue(mTvRemoteProviderWatcher.verifyServiceTrusted(createTvServiceInfo())); 116 } 117 118 @Test permissionIsRequired()119 public void permissionIsRequired() { 120 ServiceInfo serviceInfo = createTvServiceInfo(); 121 serviceInfo.permission = null; 122 123 assertFalse(mTvRemoteProviderWatcher.verifyServiceTrusted(serviceInfo)); 124 } 125 126 @Test permissionMustBeBindRemote()127 public void permissionMustBeBindRemote() { 128 ServiceInfo serviceInfo = createTvServiceInfo(); 129 serviceInfo.permission = Manifest.permission.BIND_TV_INPUT; 130 assertFalse(mTvRemoteProviderWatcher.verifyServiceTrusted(serviceInfo)); 131 } 132 133 @Test packageNameMustMatch()134 public void packageNameMustMatch() { 135 ServiceInfo serviceInfo = createTvServiceInfo(); 136 serviceInfo.packageName = "some.random.package"; 137 assertFalse(mTvRemoteProviderWatcher.verifyServiceTrusted(serviceInfo)); 138 } 139 140 @Test packageManagerPermissionIsRequired()141 public void packageManagerPermissionIsRequired() { 142 reset(mMockPackageManager); 143 when(mMockPackageManager.checkPermission(anyString(), anyString())).thenReturn( 144 PackageManager.PERMISSION_DENIED); 145 146 assertFalse(mTvRemoteProviderWatcher.verifyServiceTrusted(createTvServiceInfo())); 147 } 148 149 @Test whitelistingPackageNameIsRequired()150 public void whitelistingPackageNameIsRequired() { 151 reset(mMockResources); 152 when(mMockResources.getString(anyInt())).thenReturn(""); 153 TvRemoteProviderWatcher watcher = 154 new TvRemoteProviderWatcher( 155 mMockContext, new Object(), new Handler(Looper.getMainLooper())); 156 assertFalse(watcher.verifyServiceTrusted(createTvServiceInfo())); 157 } 158 createTvServiceInfo()159 private ServiceInfo createTvServiceInfo() { 160 ServiceInfo serviceInfo = new ServiceInfo(); 161 162 serviceInfo.name = "ATV Remote Service"; 163 serviceInfo.packageName = TV_REMOTE_SERVICE_PACKAGE_NAME; 164 serviceInfo.permission = Manifest.permission.BIND_TV_REMOTE_SERVICE; 165 166 return serviceInfo; 167 } 168 } 169