1 /* 2 * Copyright (C) 2017 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.search; 18 19 import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_NO; 20 21 import android.annotation.NonNull; 22 import android.app.ActivityOptions; 23 import android.content.ComponentName; 24 import android.content.Context; 25 import android.content.Intent; 26 import android.content.pm.PackageManager; 27 import android.content.pm.ResolveInfo; 28 import android.os.Bundle; 29 import android.view.View; 30 import android.view.ViewGroup; 31 import android.widget.Toolbar; 32 33 import androidx.fragment.app.FragmentActivity; 34 35 import com.android.settings.R; 36 import com.android.settings.Utils; 37 import com.android.settings.activityembedding.ActivityEmbeddingRulesController; 38 import com.android.settings.overlay.FeatureFactory; 39 import com.android.settingslib.search.SearchIndexableResources; 40 41 import com.google.android.setupcompat.util.WizardManagerHelper; 42 43 import java.util.List; 44 45 /** 46 * FeatureProvider for Settings Search 47 */ 48 public interface SearchFeatureProvider { 49 50 String KEY_HOMEPAGE_SEARCH_BAR = "homepage_search_bar"; 51 int REQUEST_CODE = 501; 52 53 /** 54 * Ensures the caller has necessary privilege to launch search result page. 55 * 56 * @throws IllegalArgumentException when caller is null 57 * @throws SecurityException when caller is not allowed to launch search result page 58 */ verifyLaunchSearchResultPageCaller(Context context, @NonNull ComponentName caller)59 void verifyLaunchSearchResultPageCaller(Context context, @NonNull ComponentName caller) 60 throws SecurityException, IllegalArgumentException; 61 62 /** 63 * @return a {@link SearchIndexableResources} to be used for indexing search results. 64 */ getSearchIndexableResources()65 SearchIndexableResources getSearchIndexableResources(); 66 67 /** 68 * @return a package name of settings intelligence. 69 */ getSettingsIntelligencePkgName(Context context)70 default String getSettingsIntelligencePkgName(Context context) { 71 return context.getString(R.string.config_settingsintelligence_package_name); 72 } 73 74 /** 75 * Send the pre-index intent. 76 */ sendPreIndexIntent(Context context)77 default void sendPreIndexIntent(Context context){ 78 } 79 80 /** 81 * Initializes the search toolbar. 82 */ initSearchToolbar(FragmentActivity activity, Toolbar toolbar, int pageId)83 default void initSearchToolbar(FragmentActivity activity, Toolbar toolbar, int pageId) { 84 if (activity == null || toolbar == null) { 85 return; 86 } 87 88 if (!WizardManagerHelper.isDeviceProvisioned(activity) 89 || !Utils.isPackageEnabled(activity, getSettingsIntelligencePkgName(activity)) 90 || WizardManagerHelper.isAnySetupWizard(activity.getIntent())) { 91 final ViewGroup parent = (ViewGroup) toolbar.getParent(); 92 if (parent != null) { 93 parent.setVisibility(View.GONE); 94 } 95 return; 96 } 97 // Please forgive me for what I am about to do. 98 // 99 // Need to make the navigation icon non-clickable so that the entire card is clickable 100 // and goes to the search UI. Also set the background to null so there's no ripple. 101 final View navView = toolbar.getNavigationView(); 102 navView.setClickable(false); 103 navView.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO); 104 navView.setBackground(null); 105 106 final Context context = activity.getApplicationContext(); 107 final Intent intent = buildSearchIntent(context, pageId) 108 .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 109 final List<ResolveInfo> resolveInfos = 110 activity.getPackageManager().queryIntentActivities(intent, 111 PackageManager.MATCH_DEFAULT_ONLY); 112 if (resolveInfos.isEmpty()) { 113 return; 114 } 115 116 final ComponentName searchComponentName = resolveInfos.get(0) 117 .getComponentInfo().getComponentName(); 118 // Set a component name since activity embedding requires a component name for 119 // registering a rule. 120 intent.setComponent(searchComponentName); 121 ActivityEmbeddingRulesController.registerTwoPanePairRuleForSettingsHome( 122 context, 123 searchComponentName, 124 intent.getAction(), 125 false /* finishPrimaryWithSecondary */, 126 true /* finishSecondaryWithPrimary */, 127 false /* clearTop */); 128 129 toolbar.setOnClickListener(tb -> { 130 FeatureFactory.getFactory(context).getSlicesFeatureProvider() 131 .indexSliceDataAsync(context); 132 133 FeatureFactory.getFactory(context).getMetricsFeatureProvider() 134 .logSettingsTileClick(KEY_HOMEPAGE_SEARCH_BAR, pageId); 135 136 final Bundle bundle = ActivityOptions.makeSceneTransitionAnimation(activity).toBundle(); 137 activity.startActivity(intent, bundle); 138 }); 139 } 140 buildSearchIntent(Context context, int pageId)141 Intent buildSearchIntent(Context context, int pageId); 142 } 143