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