1 /* 2 * Copyright (C) 2023 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.privatespace; 18 19 import static android.text.Layout.BREAK_STRATEGY_SIMPLE; 20 21 import static com.android.settings.privatespace.PrivateSpaceSetupActivity.EXTRA_ACTION_TYPE; 22 import static com.android.settings.privatespace.PrivateSpaceSetupActivity.SET_LOCK_ACTION; 23 24 import android.app.settings.SettingsEnums; 25 import android.content.Intent; 26 import android.os.Bundle; 27 import android.os.UserHandle; 28 import android.util.Log; 29 import android.view.LayoutInflater; 30 import android.view.View; 31 import android.view.ViewGroup; 32 33 import androidx.activity.OnBackPressedCallback; 34 import androidx.annotation.Nullable; 35 import androidx.navigation.fragment.NavHostFragment; 36 37 import com.android.settings.R; 38 import com.android.settings.core.InstrumentedFragment; 39 import com.android.settingslib.widget.LottieColorUtils; 40 41 import com.airbnb.lottie.LottieAnimationView; 42 import com.google.android.setupcompat.template.FooterBarMixin; 43 import com.google.android.setupcompat.template.FooterButton; 44 import com.google.android.setupdesign.GlifLayout; 45 46 /** 47 * Fragment that provides an option to user to choose between the existing screen lock or set a 48 * separate private profile lock. 49 */ 50 public class PrivateSpaceSetLockFragment extends InstrumentedFragment { 51 private static final String TAG = "PrivateSpaceSetLockFrag"; 52 private static final int HEADER_TEXT_MAX_LINES = 4; 53 54 private boolean mIsAnimationPlaying = true; 55 56 @Override onCreateView( LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState)57 public View onCreateView( 58 LayoutInflater inflater, 59 @Nullable ViewGroup container, 60 @Nullable Bundle savedInstanceState) { 61 if (!android.os.Flags.allowPrivateProfile() 62 || !android.multiuser.Flags.enablePrivateSpaceFeatures()) { 63 return null; 64 } 65 GlifLayout rootView = 66 (GlifLayout) 67 inflater.inflate(R.layout.private_space_setlock_screen, container, false); 68 rootView.getHeaderTextView().setBreakStrategy(BREAK_STRATEGY_SIMPLE); 69 rootView.getHeaderTextView().setMaxLines(HEADER_TEXT_MAX_LINES); 70 final FooterBarMixin mixin = rootView.getMixin(FooterBarMixin.class); 71 mixin.setPrimaryButton( 72 new FooterButton.Builder(getContext()) 73 .setText(R.string.private_space_set_lock_label) 74 .setListener(onClickNewLock()) 75 .setButtonType(FooterButton.ButtonType.NEXT) 76 .setTheme(com.google.android.setupdesign.R.style.SudGlifButton_Primary) 77 .build()); 78 mixin.setSecondaryButton( 79 new FooterButton.Builder(getContext()) 80 .setText(R.string.private_space_use_screenlock_label) 81 .setListener(onClickUse()) 82 .setButtonType(FooterButton.ButtonType.SKIP) 83 .setTheme(com.google.android.setupdesign.R.style.SudGlifButton_Secondary) 84 .build()); 85 OnBackPressedCallback callback = 86 new OnBackPressedCallback(true /* enabled by default */) { 87 @Override 88 public void handleOnBackPressed() { 89 // Handle the back button event. We intentionally don't want to allow back 90 // button to work in this screen during the setup flow. 91 } 92 }; 93 requireActivity().getOnBackPressedDispatcher().addCallback(this, callback); 94 LottieAnimationView lottieAnimationView = rootView.findViewById(R.id.lottie_animation); 95 LottieColorUtils.applyDynamicColors(getContext(), lottieAnimationView); 96 lottieAnimationView.setOnClickListener(v -> handleAnimationClick(lottieAnimationView)); 97 PrivateSpaceAccessibilityUtils.updateAccessibilityActionForAnimation(getContext(), 98 lottieAnimationView, mIsAnimationPlaying); 99 100 return rootView; 101 } 102 103 @Override getMetricsCategory()104 public int getMetricsCategory() { 105 return SettingsEnums.PRIVATE_SPACE_SETUP_LOCK; 106 } 107 onClickUse()108 private View.OnClickListener onClickUse() { 109 return v -> { 110 mMetricsFeatureProvider.action( 111 getContext(), SettingsEnums.ACTION_PRIVATE_SPACE_SETUP_USE_SCREEN_LOCK); 112 // Simply Use default screen lock. No need to handle 113 NavHostFragment.findNavController(PrivateSpaceSetLockFragment.this) 114 .navigate(R.id.action_pre_finish_delay_fragment); 115 }; 116 } 117 onClickNewLock()118 private View.OnClickListener onClickNewLock() { 119 return v -> { 120 mMetricsFeatureProvider.action( 121 getContext(), SettingsEnums.ACTION_PRIVATE_SPACE_SETUP_NEW_LOCK); 122 launchActivityForAction(SET_LOCK_ACTION); 123 }; 124 } 125 126 private void launchActivityForAction(int action) { 127 UserHandle userHandle = 128 PrivateSpaceMaintainer.getInstance(getActivity()).getPrivateProfileHandle(); 129 if (userHandle != null) { 130 Intent intent = new Intent(getContext(), PrivateProfileContextHelperActivity.class); 131 intent.putExtra(EXTRA_ACTION_TYPE, action); 132 Log.i(TAG, "Start separate lock setup for private profile"); 133 getActivity().startActivityForResultAsUser(intent, action, userHandle); 134 } else { 135 Log.w(TAG, "Private profile user handle is null"); 136 } 137 } 138 139 private void handleAnimationClick(LottieAnimationView lottieAnimationView) { 140 if (mIsAnimationPlaying) { 141 lottieAnimationView.pauseAnimation(); 142 } else { 143 lottieAnimationView.playAnimation(); 144 } 145 mIsAnimationPlaying = !mIsAnimationPlaying; 146 PrivateSpaceAccessibilityUtils.updateAccessibilityActionForAnimation(getContext(), 147 lottieAnimationView, mIsAnimationPlaying); 148 } 149 } 150