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.applications.defaultapps;
18 
19 import android.app.Dialog;
20 import android.app.settings.SettingsEnums;
21 import android.content.Context;
22 import android.content.DialogInterface;
23 import android.content.pm.PackageManager;
24 import android.os.Bundle;
25 import android.text.TextUtils;
26 
27 import androidx.appcompat.app.AlertDialog;
28 import androidx.fragment.app.DialogFragment;
29 import androidx.fragment.app.Fragment;
30 import androidx.fragment.app.FragmentActivity;
31 
32 import com.android.settings.R;
33 import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
34 import com.android.settings.fuelgauge.BatteryUtils;
35 import com.android.settings.widget.RadioButtonPickerFragment;
36 import com.android.settingslib.applications.DefaultAppInfo;
37 import com.android.settingslib.widget.CandidateInfo;
38 import com.android.settingslib.widget.RadioButtonPreference;
39 
40 /**
41  * A generic app picker fragment that shows a list of app as radio button group.
42  */
43 public abstract class DefaultAppPickerFragment extends RadioButtonPickerFragment {
44 
45     protected PackageManager mPm;
46     protected BatteryUtils mBatteryUtils;
47 
48     @Override
onAttach(Context context)49     public void onAttach(Context context) {
50         super.onAttach(context);
51         mPm = context.getPackageManager();
52         mBatteryUtils = BatteryUtils.getInstance(context);
53     }
54 
55     @Override
onRadioButtonClicked(RadioButtonPreference selected)56     public void onRadioButtonClicked(RadioButtonPreference selected) {
57         final String selectedKey = selected.getKey();
58         final CharSequence confirmationMessage = getConfirmationMessage(getCandidate(selectedKey));
59         final FragmentActivity activity = getActivity();
60         if (TextUtils.isEmpty(confirmationMessage)) {
61             super.onRadioButtonClicked(selected);
62         } else if (activity != null) {
63             final DialogFragment fragment =
64                     newConfirmationDialogFragment(selectedKey, confirmationMessage);
65             fragment.show(activity.getSupportFragmentManager(), ConfirmationDialogFragment.TAG);
66         }
67     }
68 
69     @Override
onRadioButtonConfirmed(String selectedKey)70     protected void onRadioButtonConfirmed(String selectedKey) {
71         mMetricsFeatureProvider.action(
72                 mMetricsFeatureProvider.getAttribution(getActivity()),
73                 SettingsEnums.ACTION_SETTINGS_UPDATE_DEFAULT_APP,
74                 getMetricsCategory(),
75                 selectedKey,
76                 0 /* value */);
77         super.onRadioButtonConfirmed(selectedKey);
78     }
79 
80     @Override
bindPreferenceExtra(RadioButtonPreference pref, String key, CandidateInfo info, String defaultKey, String systemDefaultKey)81     public void bindPreferenceExtra(RadioButtonPreference pref,
82             String key, CandidateInfo info, String defaultKey, String systemDefaultKey) {
83         if (!(info instanceof DefaultAppInfo)) {
84             return;
85         }
86         if (TextUtils.equals(systemDefaultKey, key)) {
87             pref.setSummary(R.string.system_app);
88         } else if (!TextUtils.isEmpty(((DefaultAppInfo) info).summary)) {
89             pref.setSummary(((DefaultAppInfo) info).summary);
90         }
91     }
92 
newConfirmationDialogFragment(String selectedKey, CharSequence confirmationMessage)93     protected ConfirmationDialogFragment newConfirmationDialogFragment(String selectedKey,
94             CharSequence confirmationMessage) {
95         final ConfirmationDialogFragment fragment = new ConfirmationDialogFragment();
96         fragment.init(this, selectedKey, confirmationMessage);
97         return fragment;
98     }
99 
getConfirmationMessage(CandidateInfo info)100     protected CharSequence getConfirmationMessage(CandidateInfo info) {
101         return null;
102     }
103 
104     public static class ConfirmationDialogFragment extends InstrumentedDialogFragment
105             implements DialogInterface.OnClickListener {
106 
107         public static final String TAG = "DefaultAppConfirm";
108         public static final String EXTRA_KEY = "extra_key";
109         public static final String EXTRA_MESSAGE = "extra_message";
110 
111         private DialogInterface.OnClickListener mCancelListener;
112 
113         @Override
getMetricsCategory()114         public int getMetricsCategory() {
115             return SettingsEnums.DEFAULT_APP_PICKER_CONFIRMATION_DIALOG;
116         }
117 
118         /**
119          * Initializes the fragment.
120          *
121          * <p>Should be called after it's constructed.
122          */
init(DefaultAppPickerFragment parent, String key, CharSequence message)123         public void init(DefaultAppPickerFragment parent, String key, CharSequence message) {
124             final Bundle argument = new Bundle();
125             argument.putString(EXTRA_KEY, key);
126             argument.putCharSequence(EXTRA_MESSAGE, message);
127             setArguments(argument);
128             setTargetFragment(parent, 0);
129         }
130 
131         // TODO: add test case for cancelListener
setCancelListener(DialogInterface.OnClickListener cancelListener)132         public void setCancelListener(DialogInterface.OnClickListener cancelListener) {
133             this.mCancelListener = cancelListener;
134         }
135 
136         @Override
onCreateDialog(Bundle savedInstanceState)137         public Dialog onCreateDialog(Bundle savedInstanceState) {
138             final Bundle bundle = getArguments();
139             final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity())
140                     .setMessage(bundle.getCharSequence(EXTRA_MESSAGE))
141                     .setPositiveButton(android.R.string.ok, this)
142                     .setNegativeButton(android.R.string.cancel, mCancelListener);
143             return builder.create();
144         }
145 
146         @Override
onClick(DialogInterface dialog, int which)147         public void onClick(DialogInterface dialog, int which) {
148             final Fragment fragment = getTargetFragment();
149             if (fragment instanceof DefaultAppPickerFragment) {
150                 final Bundle bundle = getArguments();
151                 ((DefaultAppPickerFragment) fragment).onRadioButtonConfirmed(
152                         bundle.getString(EXTRA_KEY));
153             }
154         }
155     }
156 }
157