Home | History | Annotate | Download | only in core
      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 
     17 package com.android.settings.core;
     18 
     19 import android.annotation.StringRes;
     20 import android.app.Fragment;
     21 import android.content.Context;
     22 import android.content.Intent;
     23 import android.os.Bundle;
     24 import android.os.UserHandle;
     25 import android.support.annotation.VisibleForTesting;
     26 import android.text.TextUtils;
     27 
     28 import com.android.settings.SettingsActivity;
     29 import com.android.settings.SubSettings;
     30 import com.android.settingslib.core.instrumentation.VisibilityLoggerMixin;
     31 
     32 public 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