From 386e21808c336313771ff667ca81102af1a72cef Mon Sep 17 00:00:00 2001 From: Doris Ling Date: Fri, 14 Apr 2017 12:43:07 -0700 Subject: [PATCH] Fix crash when Assist app does not have settings activity. Check for null settings activity before trying to create settings intent. If there is no settings activity, we will not show settings gear for the preference. Change-Id: I16f9d695cf9ef09ff65f4511d53d5778760125b5 Fix: 37161567 Test: make RunSettingsRoboTests --- .../DefaultAssistPreferenceController.java | 18 +++++-- ...DefaultAssistPreferenceControllerTest.java | 51 +++++++++++++++++++ 2 files changed, 64 insertions(+), 5 deletions(-) diff --git a/src/com/android/settings/applications/assist/DefaultAssistPreferenceController.java b/src/com/android/settings/applications/assist/DefaultAssistPreferenceController.java index 747ce4da596..b8d6a87c94f 100644 --- a/src/com/android/settings/applications/assist/DefaultAssistPreferenceController.java +++ b/src/com/android/settings/applications/assist/DefaultAssistPreferenceController.java @@ -24,6 +24,7 @@ import android.content.pm.ResolveInfo; import android.service.voice.VoiceInteractionService; import android.service.voice.VoiceInteractionServiceInfo; +import android.support.annotation.VisibleForTesting; import com.android.internal.app.AssistUtils; import com.android.settings.applications.defaultapps.DefaultAppInfo; import com.android.settings.applications.defaultapps.DefaultAppPreferenceController; @@ -56,13 +57,10 @@ public class DefaultAssistPreferenceController extends DefaultAppPreferenceContr if (services == null || services.isEmpty()) { return null; } - final ResolveInfo resolveInfo = services.get(0); - final VoiceInteractionServiceInfo voiceInfo = - new VoiceInteractionServiceInfo(pm, resolveInfo.serviceInfo); - if (!voiceInfo.getSupportsAssist()) { + final String activity = getAssistSettingsActivity(cn, services.get(0), pm); + if (activity == null) { return null; } - final String activity = voiceInfo.getSettingsActivity(); return new Intent(Intent.ACTION_MAIN) .setComponent(new ComponentName(cn.getPackageName(), activity)); } @@ -85,4 +83,14 @@ public class DefaultAssistPreferenceController extends DefaultAppPreferenceContr } return new DefaultAppInfo(mPackageManager, mUserId, cn); } + + @VisibleForTesting + String getAssistSettingsActivity(ComponentName cn, ResolveInfo resolveInfo, PackageManager pm) { + final VoiceInteractionServiceInfo voiceInfo = + new VoiceInteractionServiceInfo(pm, resolveInfo.serviceInfo); + if (!voiceInfo.getSupportsAssist()) { + return null; + } + return voiceInfo.getSettingsActivity(); + } } diff --git a/tests/robotests/src/com/android/settings/applications/assist/DefaultAssistPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/assist/DefaultAssistPreferenceControllerTest.java index 1182762ae3a..728a8a56c67 100644 --- a/tests/robotests/src/com/android/settings/applications/assist/DefaultAssistPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/applications/assist/DefaultAssistPreferenceControllerTest.java @@ -16,7 +16,16 @@ package com.android.settings.applications.assist; +import android.Manifest; +import android.app.SearchManager; +import android.content.ComponentName; import android.content.Context; +import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.content.pm.ServiceInfo; import android.provider.Settings; import com.android.settings.SettingsRobolectricTestRunner; @@ -24,6 +33,8 @@ import com.android.settings.TestConfig; import com.android.settings.applications.defaultapps.DefaultAppInfo; import com.android.settings.testutils.shadow.ShadowSecureSettings; +import java.util.ArrayList; +import java.util.List; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -32,6 +43,13 @@ import org.mockito.MockitoAnnotations; import org.robolectric.annotation.Config; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyBoolean; +import static org.mockito.Matchers.anyInt; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; @RunWith(SettingsRobolectricTestRunner.class) @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) @@ -39,6 +57,10 @@ public class DefaultAssistPreferenceControllerTest { @Mock private Context mContext; + @Mock + private SearchManager mSearchManager; + @Mock + private PackageManager mPackageManager; private DefaultAssistPreferenceController mController; @Before @@ -61,4 +83,33 @@ public class DefaultAssistPreferenceControllerTest { assertThat(appInfo.getKey()).isEqualTo(flattenKey); } + + @Test + public void getSettingIntent_noSettingsActivity_shouldNotCrash() { + final String flattenKey = "com.android.settings/assist"; + ShadowSecureSettings.putString(null, Settings.Secure.ASSISTANT, flattenKey); + when(mContext.getPackageManager()).thenReturn(mPackageManager); + DefaultAssistPreferenceController controller = + spy(new DefaultAssistPreferenceController(mContext)); + final ResolveInfo resolveInfo = new ResolveInfo(); + resolveInfo.activityInfo = new ActivityInfo(); + resolveInfo.activityInfo.name = "assist"; + resolveInfo.activityInfo.applicationInfo = new ApplicationInfo(); + resolveInfo.activityInfo.applicationInfo.packageName = "com.android.settings"; + when(mPackageManager.resolveActivityAsUser(any(Intent.class), anyInt(), anyInt())) + .thenReturn(resolveInfo); + when(mContext.getSystemService(Context.SEARCH_SERVICE)).thenReturn(mSearchManager); + when(mSearchManager.getAssistIntent(anyBoolean())).thenReturn(mock(Intent.class)); + final ServiceInfo serviceInfo = new ServiceInfo(); + serviceInfo.permission = Manifest.permission.BIND_VOICE_INTERACTION; + resolveInfo.serviceInfo = serviceInfo; + final List services = new ArrayList<>(); + services.add(resolveInfo); + when(mPackageManager.queryIntentServices(any(Intent.class), anyInt())).thenReturn(services); + doReturn(null).when(controller).getAssistSettingsActivity( + ComponentName.unflattenFromString(flattenKey), resolveInfo, mPackageManager); + + controller.getSettingIntent(null); + // should not crash + } }