1/* 2 * Copyright (C) 2018 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 17package com.android.settings.core; 18 19import android.annotation.StringRes; 20import android.app.Fragment; 21import android.content.Context; 22import android.content.Intent; 23import android.os.Bundle; 24import android.os.UserHandle; 25import android.support.annotation.VisibleForTesting; 26import android.text.TextUtils; 27 28import com.android.settings.SettingsActivity; 29import com.android.settings.SubSettings; 30import com.android.settingslib.core.instrumentation.VisibilityLoggerMixin; 31 32public class SubSettingLauncher { 33 34 private final Context mContext; 35 private final LaunchRequest mLaunchRequest; 36 private boolean mLaunched; 37 38 public SubSettingLauncher(Context context) { 39 if (context == null) { 40 throw new IllegalArgumentException("Context must be non-null."); 41 } 42 mContext = context; 43 mLaunchRequest = new LaunchRequest(); 44 } 45 46 public SubSettingLauncher setDestination(String fragmentName) { 47 mLaunchRequest.destinationName = fragmentName; 48 return this; 49 } 50 51 public SubSettingLauncher setTitle(@StringRes int titleResId) { 52 return setTitle(null /*titlePackageName*/, titleResId); 53 } 54 55 public SubSettingLauncher setTitle(String titlePackageName, @StringRes int titleResId) { 56 mLaunchRequest.titleResPackageName = titlePackageName; 57 mLaunchRequest.titleResId = titleResId; 58 mLaunchRequest.title = null; 59 return this; 60 } 61 62 public SubSettingLauncher setTitle(CharSequence title) { 63 mLaunchRequest.title = title; 64 return this; 65 } 66 67 public SubSettingLauncher setIsShortCut(boolean isShortCut) { 68 mLaunchRequest.isShortCut = isShortCut; 69 return this; 70 } 71 72 public SubSettingLauncher setArguments(Bundle arguments) { 73 mLaunchRequest.arguments = arguments; 74 return this; 75 } 76 77 public SubSettingLauncher setSourceMetricsCategory(int sourceMetricsCategory) { 78 mLaunchRequest.sourceMetricsCategory = sourceMetricsCategory; 79 return this; 80 } 81 82 public SubSettingLauncher setResultListener(Fragment listener, int resultRequestCode) { 83 mLaunchRequest.mRequestCode = resultRequestCode; 84 mLaunchRequest.mResultListener = listener; 85 return this; 86 } 87 88 public SubSettingLauncher addFlags(int flags) { 89 mLaunchRequest.flags |= flags; 90 return this; 91 } 92 93 public SubSettingLauncher setUserHandle(UserHandle userHandle) { 94 mLaunchRequest.userHandle = userHandle; 95 return this; 96 } 97 98 public void launch() { 99 if (mLaunched) { 100 throw new IllegalStateException( 101 "This launcher has already been executed. Do not reuse"); 102 } 103 mLaunched = true; 104 105 final Intent intent = toIntent(); 106 107 boolean launchAsUser = mLaunchRequest.userHandle != null 108 && mLaunchRequest.userHandle.getIdentifier() != UserHandle.myUserId(); 109 boolean launchForResult = mLaunchRequest.mResultListener != null; 110 if (launchAsUser && launchForResult) { 111 launchForResultAsUser(intent, mLaunchRequest.userHandle, mLaunchRequest.mResultListener, 112 mLaunchRequest.mRequestCode); 113 } else if (launchAsUser && !launchForResult) { 114 launchAsUser(intent, mLaunchRequest.userHandle); 115 } else if (!launchAsUser && launchForResult) { 116 launchForResult(mLaunchRequest.mResultListener, intent, mLaunchRequest.mRequestCode); 117 } else { 118 launch(intent); 119 } 120 } 121 122 public Intent toIntent() { 123 final Intent intent = new Intent(Intent.ACTION_MAIN); 124 intent.setClass(mContext, SubSettings.class); 125 if (TextUtils.isEmpty(mLaunchRequest.destinationName)) { 126 throw new IllegalArgumentException("Destination fragment must be set"); 127 } 128 intent.putExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT, mLaunchRequest.destinationName); 129 130 if (mLaunchRequest.sourceMetricsCategory < 0) { 131 throw new IllegalArgumentException("Source metrics category must be set"); 132 } 133 intent.putExtra(VisibilityLoggerMixin.EXTRA_SOURCE_METRICS_CATEGORY, 134 mLaunchRequest.sourceMetricsCategory); 135 136 intent.putExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS, mLaunchRequest.arguments); 137 intent.putExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_TITLE_RES_PACKAGE_NAME, 138 mLaunchRequest.titleResPackageName); 139 intent.putExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_TITLE_RESID, 140 mLaunchRequest.titleResId); 141 intent.putExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_TITLE, mLaunchRequest.title); 142 intent.putExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_AS_SHORTCUT, 143 mLaunchRequest.isShortCut); 144 intent.addFlags(mLaunchRequest.flags); 145 return intent; 146 } 147 148 @VisibleForTesting 149 void launch(Intent intent) { 150 mContext.startActivity(intent); 151 } 152 153 @VisibleForTesting 154 void launchAsUser(Intent intent, UserHandle userHandle) { 155 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 156 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); 157 mContext.startActivityAsUser(intent, userHandle); 158 } 159 160 @VisibleForTesting 161 void launchForResultAsUser(Intent intent, UserHandle userHandle, 162 Fragment resultListener, int requestCode) { 163 resultListener.getActivity().startActivityForResultAsUser(intent, requestCode, userHandle); 164 } 165 166 private void launchForResult(Fragment listener, Intent intent, int requestCode) { 167 listener.startActivityForResult(intent, requestCode); 168 } 169 170 /** 171 * Simple container that has information about how to launch a subsetting. 172 */ 173 static class LaunchRequest { 174 String destinationName; 175 int titleResId; 176 String titleResPackageName; 177 CharSequence title; 178 boolean isShortCut; 179 int sourceMetricsCategory = -100; 180 int flags; 181 Fragment mResultListener; 182 int mRequestCode; 183 UserHandle userHandle; 184 Bundle arguments; 185 } 186} 187