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.password;
18 
19 import android.app.Activity;
20 import android.app.Dialog;
21 import android.app.settings.SettingsEnums;
22 import android.content.Context;
23 import android.content.DialogInterface;
24 import android.content.DialogInterface.OnClickListener;
25 import android.content.Intent;
26 import android.graphics.drawable.Drawable;
27 import android.os.Bundle;
28 import android.view.LayoutInflater;
29 import android.view.View;
30 import android.view.ViewGroup;
31 import android.widget.ArrayAdapter;
32 import android.widget.TextView;
33 
34 import androidx.appcompat.app.AlertDialog.Builder;
35 import androidx.fragment.app.Fragment;
36 
37 import com.android.internal.widget.LockPatternUtils;
38 import com.android.settings.R;
39 import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
40 import com.android.settings.password.ChooseLockGeneric.ChooseLockGenericFragment;
41 
42 import com.google.android.setupcompat.util.WizardManagerHelper;
43 
44 import java.util.List;
45 
46 /**
47  * A dialog fragment similar to {@link ChooseLockGeneric} where the user can select from a few
48  * lock screen types.
49  */
50 public class ChooseLockTypeDialogFragment extends InstrumentedDialogFragment
51         implements OnClickListener {
52 
53     private static final String ARG_USER_ID = "userId";
54 
55     private ScreenLockAdapter mAdapter;
56     private ChooseLockGenericController mController;
57 
newInstance(int userId)58     public static ChooseLockTypeDialogFragment newInstance(int userId) {
59         Bundle args = new Bundle();
60         args.putInt(ARG_USER_ID, userId);
61         ChooseLockTypeDialogFragment fragment = new ChooseLockTypeDialogFragment();
62         fragment.setArguments(args);
63         return fragment;
64     }
65 
66     public interface OnLockTypeSelectedListener {
onLockTypeSelected(ScreenLockType lock)67         void onLockTypeSelected(ScreenLockType lock);
68 
startChooseLockActivity(ScreenLockType selectedLockType, Activity activity)69         default void startChooseLockActivity(ScreenLockType selectedLockType, Activity activity) {
70             Intent activityIntent = activity.getIntent();
71             Intent intent = new Intent(activity, SetupChooseLockGeneric.class);
72             intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
73 
74             // Copy the original extras into the new intent
75             copyBooleanExtra(activityIntent, intent,
76                     ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW_HANDLE, false);
77             copyBooleanExtra(activityIntent, intent,
78                     ChooseLockGenericFragment.EXTRA_SHOW_OPTIONS_BUTTON, false);
79             if (activityIntent.hasExtra(
80                     ChooseLockGenericFragment.EXTRA_CHOOSE_LOCK_GENERIC_EXTRAS)) {
81                 intent.putExtras(activityIntent.getBundleExtra(
82                         ChooseLockGenericFragment.EXTRA_CHOOSE_LOCK_GENERIC_EXTRAS));
83             }
84             intent.putExtra(LockPatternUtils.PASSWORD_TYPE_KEY, selectedLockType.defaultQuality);
85             WizardManagerHelper.copyWizardManagerExtras(activityIntent, intent);
86             activity.startActivity(intent);
87             activity.finish();
88         }
89 
90     }
91 
copyBooleanExtra(Intent from, Intent to, String name, boolean defaultValue)92     private static void copyBooleanExtra(Intent from, Intent to, String name,
93             boolean defaultValue) {
94         to.putExtra(name, from.getBooleanExtra(name, defaultValue));
95     }
96 
97 
98     @Override
onCreate(Bundle savedInstanceState)99     public void onCreate(Bundle savedInstanceState) {
100         super.onCreate(savedInstanceState);
101         final int userId = getArguments().getInt(ARG_USER_ID);
102         mController = new ChooseLockGenericController.Builder(getContext(), userId)
103                 .setHideInsecureScreenLockTypes(true)
104                 .build();
105     }
106 
107     @Override
onClick(DialogInterface dialogInterface, int i)108     public void onClick(DialogInterface dialogInterface, int i) {
109         OnLockTypeSelectedListener listener = null;
110         Fragment parentFragment = getParentFragment();
111         if (parentFragment instanceof OnLockTypeSelectedListener) {
112             listener = (OnLockTypeSelectedListener) parentFragment;
113         } else {
114             Context context = getContext();
115             if (context instanceof OnLockTypeSelectedListener) {
116                 listener = (OnLockTypeSelectedListener) context;
117             }
118         }
119         if (listener != null) {
120             listener.onLockTypeSelected(mAdapter.getItem(i));
121         }
122     }
123 
124     @Override
onCreateDialog(Bundle savedInstanceState)125     public Dialog onCreateDialog(Bundle savedInstanceState) {
126         Context context = getContext();
127         Builder builder = new Builder(context);
128         List<ScreenLockType> locks = mController.getVisibleAndEnabledScreenLockTypes();
129         mAdapter = new ScreenLockAdapter(context, locks, mController);
130         builder.setAdapter(mAdapter, this);
131         builder.setTitle(R.string.setup_lock_settings_options_dialog_title);
132         Dialog alertDialog = builder.create();
133         return alertDialog;
134     }
135 
136     @Override
getMetricsCategory()137     public int getMetricsCategory() {
138         return SettingsEnums.SETTINGS_CHOOSE_LOCK_DIALOG;
139     }
140 
141     private static class ScreenLockAdapter extends ArrayAdapter<ScreenLockType> {
142 
143         private final ChooseLockGenericController mController;
144 
ScreenLockAdapter( Context context, List<ScreenLockType> locks, ChooseLockGenericController controller)145         ScreenLockAdapter(
146                 Context context,
147                 List<ScreenLockType> locks,
148                 ChooseLockGenericController controller) {
149             super(context, R.layout.choose_lock_dialog_item, locks);
150             mController = controller;
151         }
152 
153         @Override
getView(int position, View view, ViewGroup parent)154         public View getView(int position, View view, ViewGroup parent) {
155             Context context = parent.getContext();
156             if (view == null) {
157                 view = LayoutInflater.from(context)
158                         .inflate(R.layout.choose_lock_dialog_item, parent, false);
159             }
160             ScreenLockType lock = getItem(position);
161             TextView textView = (TextView) view;
162             textView.setText(mController.getTitle(lock));
163             textView.setCompoundDrawablesRelativeWithIntrinsicBounds(
164                     getIconForScreenLock(context, lock), null, null, null);
165             return view;
166         }
167 
getIconForScreenLock(Context context, ScreenLockType lock)168         private static Drawable getIconForScreenLock(Context context, ScreenLockType lock) {
169             switch (lock) {
170                 case PATTERN:
171                     return context.getDrawable(R.drawable.ic_pattern);
172                 case PIN:
173                     return context.getDrawable(R.drawable.ic_pin);
174                 case PASSWORD:
175                     return context.getDrawable(R.drawable.ic_password);
176                 case NONE:
177                 case SWIPE:
178                 case MANAGED:
179                 default:
180                         return null;
181             }
182         }
183     }
184 }
185