1 /* 2 * Copyright (C) 2016 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 17 package com.android.settings.applications; 18 19 import static com.google.common.truth.Truth.assertThat; 20 import static org.mockito.Matchers.any; 21 import static org.mockito.Mockito.mock; 22 import static org.mockito.Mockito.verify; 23 import static org.mockito.Mockito.when; 24 25 import android.app.AlertDialog; 26 import android.content.BroadcastReceiver; 27 import android.content.Context; 28 import android.content.Intent; 29 import android.content.pm.ApplicationInfo; 30 import android.content.pm.PackageInfo; 31 import android.content.pm.PackageManager; 32 import android.net.Uri; 33 import android.os.UserHandle; 34 import android.support.v7.preference.PreferenceManager; 35 import android.support.v7.preference.PreferenceScreen; 36 37 import com.android.internal.logging.nano.MetricsProto; 38 import com.android.settings.testutils.FakeFeatureFactory; 39 import com.android.settings.testutils.SettingsRobolectricTestRunner; 40 import com.android.settings.testutils.shadow.ShadowEntityHeaderController; 41 import com.android.settings.widget.EntityHeaderController; 42 import com.android.settingslib.applications.AppUtils; 43 import com.android.settingslib.applications.ApplicationsState; 44 import com.android.settingslib.applications.instantapps.InstantAppDataProvider; 45 46 import org.junit.After; 47 import org.junit.Before; 48 import org.junit.Test; 49 import org.junit.runner.RunWith; 50 import org.mockito.Answers; 51 import org.mockito.Mock; 52 import org.mockito.MockitoAnnotations; 53 import org.robolectric.RuntimeEnvironment; 54 import org.robolectric.annotation.Config; 55 import org.robolectric.util.ReflectionHelpers; 56 57 @RunWith(SettingsRobolectricTestRunner.class) 58 @Config(shadows = ShadowEntityHeaderController.class) 59 public class AppInfoWithHeaderTest { 60 61 @Mock(answer = Answers.RETURNS_DEEP_STUBS) 62 private EntityHeaderController mHeaderController; 63 64 private FakeFeatureFactory mFactory; 65 private TestFragment mAppInfoWithHeader; 66 67 @Before 68 public void setUp() { 69 MockitoAnnotations.initMocks(this); 70 mFactory = FakeFeatureFactory.setupForTest(); 71 when(mFactory.metricsFeatureProvider.getMetricsCategory(any(Object.class))) 72 .thenReturn(MetricsProto.MetricsEvent.SETTINGS_APP_NOTIF_CATEGORY); 73 mAppInfoWithHeader = new TestFragment(); 74 ShadowEntityHeaderController.setUseMock(mHeaderController); 75 } 76 77 @After 78 public void tearDown() { 79 ShadowEntityHeaderController.reset(); 80 } 81 82 @Test 83 public void testAppHeaderIsAdded() { 84 mAppInfoWithHeader.onActivityCreated(null); 85 86 verify(mAppInfoWithHeader.mScreen).addPreference(any(LayoutPreference.class)); 87 } 88 89 @Test 90 public void packageRemoved_noAppEntry_shouldFinishActivity() { 91 BroadcastReceiver packageRemovedReceiver = 92 ReflectionHelpers.getField(mAppInfoWithHeader, "mPackageRemovedReceiver"); 93 ReflectionHelpers.setField(mAppInfoWithHeader, "mAppEntry", null); 94 95 final Intent packageRemovedBroadcast = new Intent(); 96 packageRemovedBroadcast.setData(Uri.parse("package:com.android.settings")); 97 packageRemovedReceiver.onReceive(RuntimeEnvironment.application, packageRemovedBroadcast); 98 99 assertThat(mAppInfoWithHeader.mPackageRemovedCalled).isTrue(); 100 } 101 102 @Test 103 public void packageRemoved_appEntryMatchesPackageName_shouldFinishActivity() { 104 BroadcastReceiver packageRemovedReceiver = 105 ReflectionHelpers.getField(mAppInfoWithHeader, "mPackageRemovedReceiver"); 106 final ApplicationsState.AppEntry entry = mock(ApplicationsState.AppEntry.class); 107 entry.info = new ApplicationInfo(); 108 entry.info.packageName = "com.android.settings"; 109 ReflectionHelpers.setField(mAppInfoWithHeader, "mAppEntry", entry); 110 111 final Intent packageRemovedBroadcast = new Intent(); 112 packageRemovedBroadcast.setData(Uri.parse("package:" + entry.info.packageName)); 113 packageRemovedReceiver.onReceive(RuntimeEnvironment.application, packageRemovedBroadcast); 114 115 assertThat(mAppInfoWithHeader.mPackageRemovedCalled).isTrue(); 116 } 117 118 @Test 119 public void noExtraUserHandleInIntent_retrieveAppEntryWithMyUserId() 120 throws PackageManager.NameNotFoundException { 121 final String packageName = "com.android.settings"; 122 123 mAppInfoWithHeader.mIntent.setData(Uri.fromParts("package", packageName, null)); 124 final ApplicationsState.AppEntry entry = mock(ApplicationsState.AppEntry.class); 125 entry.info = new ApplicationInfo(); 126 entry.info.packageName = packageName; 127 128 when(mAppInfoWithHeader.mState.getEntry(packageName, 129 UserHandle.myUserId())).thenReturn(entry); 130 when(mAppInfoWithHeader.mPm.getPackageInfoAsUser(entry.info.packageName, 131 PackageManager.MATCH_DISABLED_COMPONENTS | 132 PackageManager.GET_SIGNING_CERTIFICATES | 133 PackageManager.GET_PERMISSIONS, UserHandle.myUserId())).thenReturn( 134 mAppInfoWithHeader.mPackageInfo); 135 136 mAppInfoWithHeader.retrieveAppEntry(); 137 138 assertThat(mAppInfoWithHeader.mUserId).isEqualTo(UserHandle.myUserId()); 139 assertThat(mAppInfoWithHeader.mPackageInfo).isNotNull(); 140 assertThat(mAppInfoWithHeader.mAppEntry).isNotNull(); 141 } 142 143 @Test 144 public void extraUserHandleInIntent_retrieveAppEntryWithMyUserId() 145 throws PackageManager.NameNotFoundException { 146 final int USER_ID = 1002; 147 final String packageName = "com.android.settings"; 148 149 mAppInfoWithHeader.mIntent.putExtra(Intent.EXTRA_USER_HANDLE, new UserHandle(USER_ID)); 150 mAppInfoWithHeader.mIntent.setData(Uri.fromParts("package", 151 packageName, null)); 152 final ApplicationsState.AppEntry entry = mock(ApplicationsState.AppEntry.class); 153 entry.info = new ApplicationInfo(); 154 entry.info.packageName = packageName; 155 156 when(mAppInfoWithHeader.mState.getEntry(packageName, USER_ID)).thenReturn(entry); 157 when(mAppInfoWithHeader.mPm.getPackageInfoAsUser(entry.info.packageName, 158 PackageManager.MATCH_DISABLED_COMPONENTS | 159 PackageManager.GET_SIGNING_CERTIFICATES | 160 PackageManager.GET_PERMISSIONS, USER_ID)).thenReturn( 161 mAppInfoWithHeader.mPackageInfo); 162 163 mAppInfoWithHeader.retrieveAppEntry(); 164 165 assertThat(mAppInfoWithHeader.mUserId).isEqualTo(USER_ID); 166 assertThat(mAppInfoWithHeader.mPackageInfo).isNotNull(); 167 assertThat(mAppInfoWithHeader.mAppEntry).isNotNull(); 168 } 169 170 public static class TestFragment extends AppInfoWithHeader { 171 172 PreferenceManager mManager; 173 PreferenceScreen mScreen; 174 Context mShadowContext; 175 boolean mPackageRemovedCalled; 176 Intent mIntent; 177 178 public TestFragment() { 179 mPm = mock(PackageManager.class); 180 mManager = mock(PreferenceManager.class); 181 mScreen = mock(PreferenceScreen.class); 182 mPackageInfo = new PackageInfo(); 183 mPackageInfo.applicationInfo = new ApplicationInfo(); 184 mState = mock(ApplicationsState.class); 185 mIntent = new Intent(); 186 mShadowContext = RuntimeEnvironment.application; 187 ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider", 188 (InstantAppDataProvider) (info -> false)); 189 when(mManager.getContext()).thenReturn(mShadowContext); 190 } 191 192 @Override 193 public int getMetricsCategory() { 194 return 0; 195 } 196 197 @Override 198 protected boolean refreshUi() { 199 return false; 200 } 201 202 @Override 203 protected AlertDialog createDialog(int id, int errorCode) { 204 return null; 205 } 206 207 @Override 208 public PreferenceScreen getPreferenceScreen() { 209 return mScreen; 210 } 211 212 @Override 213 public PreferenceManager getPreferenceManager() { 214 return mManager; 215 } 216 217 @Override 218 public Context getContext() { 219 return mShadowContext; 220 } 221 222 @Override 223 protected void onPackageRemoved() { 224 mPackageRemovedCalled = true; 225 } 226 227 @Override 228 protected Intent getIntent() { return mIntent; } 229 } 230 } 231