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 com.android.settings.SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS; 20 import static com.android.settings.SettingsActivity.EXTRA_SHOW_FRAGMENT_TAB; 21 import static com.android.settings.activityembedding.EmbeddedDeepLinkUtils.getTrampolineIntent; 22 23 import android.app.Activity; 24 import android.content.Intent; 25 import android.net.Uri; 26 import android.os.Bundle; 27 import android.provider.Settings; 28 import android.text.TextUtils; 29 import android.util.FeatureFlagUtils; 30 import android.util.Log; 31 32 import com.android.settings.SettingsActivity; 33 import com.android.settings.SettingsApplication; 34 import com.android.settings.SubSettings; 35 import com.android.settings.activityembedding.ActivityEmbeddingRulesController; 36 import com.android.settings.activityembedding.ActivityEmbeddingUtils; 37 import com.android.settings.core.FeatureFlags; 38 import com.android.settings.homepage.DeepLinkHomepageActivityInternal; 39 import com.android.settings.homepage.SettingsHomepageActivity; 40 import com.android.settings.overlay.FeatureFactory; 41 42 import java.net.URISyntaxException; 43 44 /** 45 * A trampoline activity that launches setting result page. 46 */ 47 public class SearchResultTrampoline extends Activity { 48 49 private static final String TAG = "SearchResultTrampoline"; 50 51 @Override onCreate(Bundle savedInstanceState)52 protected void onCreate(Bundle savedInstanceState) { 53 super.onCreate(savedInstanceState); 54 55 final String callerPackage = getLaunchedFromPackage(); 56 // First make sure caller has privilege to launch a search result page. 57 FeatureFactory.getFeatureFactory() 58 .getSearchFeatureProvider() 59 .verifyLaunchSearchResultPageCaller(this, callerPackage); 60 // Didn't crash, proceed and launch the result as a subsetting. 61 Intent intent = getIntent(); 62 final String highlightMenuKey = intent.getStringExtra( 63 Settings.EXTRA_SETTINGS_EMBEDDED_DEEP_LINK_HIGHLIGHT_MENU_KEY); 64 65 final String fragment = intent.getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT); 66 if (!TextUtils.isEmpty(fragment)) { 67 // Hack to take EXTRA_FRAGMENT_ARG_KEY from intent and set into 68 // EXTRA_SHOW_FRAGMENT_ARGUMENTS. This is necessary because intent could be from 69 // external caller and args may not persisted. 70 final String settingKey = intent.getStringExtra( 71 SettingsActivity.EXTRA_FRAGMENT_ARG_KEY); 72 final int tab = intent.getIntExtra(EXTRA_SHOW_FRAGMENT_TAB, 0); 73 final Bundle args = new Bundle(); 74 args.putString(SettingsActivity.EXTRA_FRAGMENT_ARG_KEY, settingKey); 75 args.putInt(EXTRA_SHOW_FRAGMENT_TAB, tab); 76 intent.putExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS, args); 77 78 // Reroute request to SubSetting. 79 intent.setClass(this /* context */, SubSettings.class); 80 } else { 81 // Direct link case 82 final String intentUriString = intent.getStringExtra( 83 Settings.EXTRA_SETTINGS_EMBEDDED_DEEP_LINK_INTENT_URI); 84 if (TextUtils.isEmpty(intentUriString)) { 85 Log.e(TAG, "No EXTRA_SETTINGS_EMBEDDED_DEEP_LINK_INTENT_URI for deep link"); 86 finish(); 87 return; 88 } 89 90 final Uri data = intent.getParcelableExtra( 91 SettingsHomepageActivity.EXTRA_SETTINGS_LARGE_SCREEN_DEEP_LINK_INTENT_DATA, 92 Uri.class); 93 try { 94 intent = Intent.parseUri(intentUriString, Intent.URI_INTENT_SCHEME); 95 intent.setData(data); 96 } catch (URISyntaxException e) { 97 Log.e(TAG, "Failed to parse deep link intent: " + e); 98 finish(); 99 return; 100 } 101 } 102 103 intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT); 104 105 if (!ActivityEmbeddingUtils.isEmbeddingActivityEnabled(this) 106 || ActivityEmbeddingUtils.isAlreadyEmbedded(this)) { 107 startActivity(intent); 108 } else if (isSettingsIntelligence(callerPackage)) { 109 if (FeatureFlagUtils.isEnabled(this, FeatureFlags.SETTINGS_SEARCH_ALWAYS_EXPAND)) { 110 startActivity(getTrampolineIntent(intent, highlightMenuKey) 111 .setClass(this, DeepLinkHomepageActivityInternal.class) 112 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK 113 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)); 114 } else { 115 // Register SplitPairRule for SubSettings, set clearTop false to prevent unexpected 116 // back navigation behavior. 117 ActivityEmbeddingRulesController.registerSubSettingsPairRule(this, 118 false /* clearTop */); 119 120 intent.setFlags(intent.getFlags() & ~Intent.FLAG_ACTIVITY_NEW_TASK); 121 startActivity(intent); 122 123 // Pass menu key to homepage 124 final SettingsHomepageActivity homeActivity = 125 ((SettingsApplication) getApplicationContext()).getHomeActivity(); 126 if (homeActivity != null) { 127 homeActivity.getMainFragment().setHighlightMenuKey(highlightMenuKey, 128 /* scrollNeeded= */ true); 129 } 130 } 131 } else { 132 // Two-pane case 133 startActivity(getTrampolineIntent(intent, highlightMenuKey) 134 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); 135 } 136 137 // Done. 138 finish(); 139 } 140 isSettingsIntelligence(String callerPackage)141 private boolean isSettingsIntelligence(String callerPackage) { 142 return TextUtils.equals( 143 callerPackage, 144 FeatureFactory.getFeatureFactory().getSearchFeatureProvider() 145 .getSettingsIntelligencePkgName(this)); 146 } 147 } 148