1 /*
2  * Copyright (C) 2024 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.delete;
18 
19 import static com.android.settings.privatespace.PrivateSpaceMaintainer.ErrorDeletingPrivateSpace.DELETE_PS_ERROR_INTERNAL;
20 import static com.android.settings.privatespace.PrivateSpaceMaintainer.ErrorDeletingPrivateSpace.DELETE_PS_ERROR_NONE;
21 
22 import android.app.settings.SettingsEnums;
23 import android.content.Context;
24 import android.graphics.drawable.Drawable;
25 import android.os.Bundle;
26 import android.os.Handler;
27 import android.os.Looper;
28 import android.util.Log;
29 import android.view.LayoutInflater;
30 import android.view.View;
31 import android.view.ViewGroup;
32 import android.widget.Toast;
33 
34 import androidx.activity.OnBackPressedCallback;
35 import androidx.annotation.NonNull;
36 import androidx.annotation.Nullable;
37 
38 import com.android.internal.annotations.VisibleForTesting;
39 import com.android.settings.R;
40 import com.android.settings.core.InstrumentedFragment;
41 import com.android.settings.privatespace.PrivateSpaceMaintainer;
42 
43 /** Fragment to show loading animation screen while deleting private space. */
44 public class PrivateSpaceDeletionProgressFragment extends InstrumentedFragment {
45     private static final String TAG = "PrivateSpaceDeleteProg";
46     private static final int PRIVATE_SPACE_DELETE_POST_DELAY_MS = 1000;
47     private Handler mHandler;
48     private PrivateSpaceMaintainer mPrivateSpaceMaintainer;
49     private Runnable mDeletePrivateSpace =
50             new Runnable() {
51                 @Override
52                 public void run() {
53                     deletePrivateSpace();
54                     getActivity().finish();
55                 }
56             };
57 
58     static class Injector {
injectPrivateSpaceMaintainer(Context context)59         PrivateSpaceMaintainer injectPrivateSpaceMaintainer(Context context) {
60             return PrivateSpaceMaintainer.getInstance(context);
61         }
62     }
63 
64     @Override
onCreate(@ullable Bundle savedInstanceState)65     public void onCreate(@Nullable Bundle savedInstanceState) {
66         if (android.os.Flags.allowPrivateProfile()
67                 && android.multiuser.Flags.enablePrivateSpaceFeatures()) {
68             super.onCreate(savedInstanceState);
69         }
70     }
71 
72     @Override
getMetricsCategory()73     public int getMetricsCategory() {
74         return SettingsEnums.PRIVATE_SPACE_SETTINGS;
75     }
76 
77     @NonNull
78     @Override
onCreateView( @onNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState)79     public View onCreateView(
80             @NonNull LayoutInflater inflater,
81             @Nullable ViewGroup container,
82             @Nullable Bundle savedInstanceState) {
83         mPrivateSpaceMaintainer =
84                 new PrivateSpaceDeletionProgressFragment.Injector()
85                         .injectPrivateSpaceMaintainer(getActivity().getApplicationContext());
86         if (!mPrivateSpaceMaintainer.doesPrivateSpaceExist()) {
87             // Ideally this should never happen as PS Settings is not available when there's no
88             // Private Profile.
89             Log.e(TAG, "Unexpected attempt to delete non-existent PS");
90             getActivity().finish();
91         }
92         View contentView =
93                 inflater.inflate(R.layout.private_space_confirm_deletion, container, false);
94         OnBackPressedCallback callback =
95                 new OnBackPressedCallback(true /* enabled by default */) {
96                     @Override
97                     public void handleOnBackPressed() {
98                         // Handle the back button event. We intentionally don't want to allow back
99                         // button to work in this screen during the setup flow.
100                     }
101                 };
102         requireActivity().getOnBackPressedDispatcher().addCallback(this, callback);
103         mHandler = new Handler(Looper.getMainLooper());
104         // Ensures screen visibility to user by introducing a 1-second delay before deleting private
105         // space.
106         mHandler.postDelayed(mDeletePrivateSpace, PRIVATE_SPACE_DELETE_POST_DELAY_MS);
107         return contentView;
108     }
109 
110     @Override
onDestroy()111     public void onDestroy() {
112         mHandler.removeCallbacks(mDeletePrivateSpace);
113         super.onDestroy();
114     }
115 
116     /** Deletes private space and shows a toast message */
117     @VisibleForTesting
deletePrivateSpace()118     public void deletePrivateSpace() {
119         PrivateSpaceMaintainer.ErrorDeletingPrivateSpace error =
120                 mPrivateSpaceMaintainer.deletePrivateSpace();
121         if (error == DELETE_PS_ERROR_NONE) {
122             showSuccessfulDeletionToast();
123         } else if (error == DELETE_PS_ERROR_INTERNAL) {
124             showDeletionInternalErrorToast();
125         }
126     }
127 
128     @VisibleForTesting
setPrivateSpaceMaintainer(@onNull Injector injector)129     public void setPrivateSpaceMaintainer(@NonNull Injector injector) {
130         mPrivateSpaceMaintainer = injector.injectPrivateSpaceMaintainer(getActivity());
131     }
132 
133     /** Shows a toast saying that the private space was deleted */
134     @VisibleForTesting
showSuccessfulDeletionToast()135     public void showSuccessfulDeletionToast() {
136         showToastWithCustomIcon(R.string.private_space_deleted);
137     }
138 
139     /** Shows a toast saying that the private space could not be deleted */
140     @VisibleForTesting
showDeletionInternalErrorToast()141     public void showDeletionInternalErrorToast() {
142         showToastWithCustomIcon(R.string.private_space_delete_failed);
143     }
144 
showToastWithCustomIcon(int stringRes)145     private void showToastWithCustomIcon(int stringRes) {
146         Drawable drawable = getContext().getDrawable(R.drawable.ic_private_space_icon);
147         Toast.makeCustomToastWithIcon(
148                         getContext(),
149                         null /* looper */ ,
150                         getContext().getString(stringRes),
151                         Toast.LENGTH_SHORT,
152                         drawable)
153                 .show();
154     }
155 }
156