• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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;
18 
19 import static com.android.settings.privatespace.PrivateSpaceSetupActivity.ACCOUNT_LOGIN_ACTION;
20 import static com.android.settings.privatespace.PrivateSpaceSetupActivity.EXTRA_ACTION_TYPE;
21 
22 import android.app.settings.SettingsEnums;
23 import android.content.BroadcastReceiver;
24 import android.content.Context;
25 import android.content.Intent;
26 import android.content.IntentFilter;
27 import android.net.ConnectivityManager;
28 import android.net.NetworkInfo;
29 import android.os.Bundle;
30 import android.os.Handler;
31 import android.os.Looper;
32 import android.os.UserManager;
33 import android.util.Log;
34 import android.view.LayoutInflater;
35 import android.view.View;
36 import android.view.ViewGroup;
37 
38 import androidx.activity.OnBackPressedCallback;
39 import androidx.annotation.NonNull;
40 import androidx.annotation.Nullable;
41 import androidx.navigation.fragment.NavHostFragment;
42 
43 import com.android.settings.R;
44 import com.android.settings.core.InstrumentedFragment;
45 
46 import com.google.android.setupdesign.GlifLayout;
47 
48 /** Fragment to a show loading screen and create private profile during private space setup flow */
49 public class PrivateSpaceCreationFragment extends InstrumentedFragment {
50     private static final String TAG = "PrivateSpaceCreateFrag";
51     private static final int PRIVATE_SPACE_CREATE_POST_DELAY_MS = 1000;
52     private static final int PRIVATE_SPACE_ACCOUNT_LOGIN_POST_DELAY_MS = 5000;
53     private static final int PRIVATE_SPACE_SETUP_NO_ERROR = 0;
54     private static final Handler sHandler = new Handler(Looper.getMainLooper());
55     private Runnable mRunnable =
56             () -> {
57                 createPrivateSpace();
58             };
59 
60     private Runnable mAccountLoginRunnable =
61             () -> {
62                 unRegisterReceiver();
63                 startAccountLogin();
64             };
65 
66     final BroadcastReceiver mProfileAccessReceiver = new  BroadcastReceiver() {
67         @Override
68         public void onReceive(Context context, Intent intent) {
69             final String action = intent.getAction();
70             if (action.equals(Intent.ACTION_PROFILE_ACCESSIBLE)) {
71                 Log.i(TAG, "onReceive " + action);
72                 sHandler.removeCallbacks(mAccountLoginRunnable);
73                 sHandler.post(mAccountLoginRunnable);
74             }
75         }
76     };
77 
78     @Override
onCreate(@ullable Bundle savedInstanceState)79     public void onCreate(@Nullable Bundle savedInstanceState) {
80         if (android.os.Flags.allowPrivateProfile()
81                 && android.multiuser.Flags.enablePrivateSpaceFeatures()) {
82             super.onCreate(savedInstanceState);
83         }
84     }
85 
86     @NonNull
87     @Override
onCreateView( @onNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState)88     public View onCreateView(
89             @NonNull LayoutInflater inflater,
90             @Nullable ViewGroup container,
91             @Nullable Bundle savedInstanceState) {
92         GlifLayout rootView =
93                 (GlifLayout)
94                         inflater.inflate(R.layout.private_space_create_screen, container, false);
95         OnBackPressedCallback callback =
96                 new OnBackPressedCallback(true /* enabled by default */) {
97                     @Override
98                     public void handleOnBackPressed() {
99                         // Handle the back button event. We intentionally don't want to allow back
100                         // button to work in this screen during the setup flow.
101                     }
102                 };
103         requireActivity().getOnBackPressedDispatcher().addCallback(this, callback);
104         return rootView;
105     }
106 
107     @Override
onResume()108     public void onResume() {
109         super.onResume();
110         // Ensures screen visibility to user by introducing a 1-second delay before creating private
111         // space.
112         sHandler.removeCallbacks(mRunnable);
113         sHandler.postDelayed(mRunnable, PRIVATE_SPACE_CREATE_POST_DELAY_MS);
114     }
115 
116     @Override
onDestroy()117     public void onDestroy() {
118         sHandler.removeCallbacks(mRunnable);
119         super.onDestroy();
120     }
121 
createPrivateSpace()122     private void createPrivateSpace() {
123         if (PrivateSpaceMaintainer.getInstance(getActivity()).createPrivateSpace()) {
124             Log.i(TAG, "Private Space created");
125             mMetricsFeatureProvider.action(
126                     getContext(), SettingsEnums.ACTION_PRIVATE_SPACE_SETUP_SPACE_CREATED, true);
127             if (android.multiuser.Flags.showDifferentCreationErrorForUnsupportedDevices()) {
128                 mMetricsFeatureProvider.action(
129                         getContext(), SettingsEnums.ACTION_PRIVATE_SPACE_SETUP_SPACE_ERRORS,
130                         PRIVATE_SPACE_SETUP_NO_ERROR);
131             }
132             if (isConnectedToInternet()) {
133                 registerReceiver();
134                 sHandler.postDelayed(
135                         mAccountLoginRunnable, PRIVATE_SPACE_ACCOUNT_LOGIN_POST_DELAY_MS);
136             } else {
137                 NavHostFragment.findNavController(PrivateSpaceCreationFragment.this)
138                         .navigate(R.id.action_set_lock_fragment);
139             }
140         } else {
141             mMetricsFeatureProvider.action(
142                     getContext(), SettingsEnums.ACTION_PRIVATE_SPACE_SETUP_SPACE_CREATED,
143                     false);
144             if (android.multiuser.Flags.showDifferentCreationErrorForUnsupportedDevices()) {
145                 int errorCode = PrivateSpaceMaintainer.getInstance(
146                         getActivity()).getPrivateSpaceCreateError();
147                 mMetricsFeatureProvider.action(
148                         getContext(), SettingsEnums.ACTION_PRIVATE_SPACE_SETUP_SPACE_ERRORS,
149                         errorCode);
150                 showPrivateSpaceErrorScreen(errorCode);
151             } else {
152                 showPrivateSpaceErrorScreen();
153             }
154         }
155     }
156 
157     @Override
getMetricsCategory()158     public int getMetricsCategory() {
159         return SettingsEnums.PRIVATE_SPACE_SETUP_SPACE_CREATION;
160     }
161 
showPrivateSpaceErrorScreen()162     private void showPrivateSpaceErrorScreen() {
163         NavHostFragment.findNavController(PrivateSpaceCreationFragment.this)
164                 .navigate(R.id.action_create_profile_error);
165     }
166 
showPrivateSpaceErrorScreen(int errorCode)167     private void showPrivateSpaceErrorScreen(int errorCode) {
168         if (errorCode == UserManager.USER_OPERATION_ERROR_USER_RESTRICTED
169                 || errorCode == UserManager.USER_OPERATION_ERROR_PRIVATE_PROFILE) {
170             NavHostFragment.findNavController(PrivateSpaceCreationFragment.this)
171                     .navigate(R.id.action_create_profile_error_restrict);
172         } else {
173             showPrivateSpaceErrorScreen();
174         }
175     }
176 
177     /** Returns true if device has an active internet connection, false otherwise. */
isConnectedToInternet()178     private boolean isConnectedToInternet() {
179         ConnectivityManager cm =
180                 (ConnectivityManager) getActivity().getSystemService(Context.CONNECTIVITY_SERVICE);
181         NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
182         return activeNetwork != null && activeNetwork.isConnectedOrConnecting();
183     }
184 
185     /** Start new activity in private profile to add an account to private profile */
startAccountLogin()186     private void startAccountLogin() {
187         if (isAdded() && getContext() != null && getActivity() != null) {
188             Intent intent = new Intent(getContext(), PrivateProfileContextHelperActivity.class);
189             intent.putExtra(EXTRA_ACTION_TYPE, ACCOUNT_LOGIN_ACTION);
190             mMetricsFeatureProvider.action(
191                     getContext(), SettingsEnums.ACTION_PRIVATE_SPACE_SETUP_ACCOUNT_LOGIN_START);
192             getActivity().startActivityForResult(intent, ACCOUNT_LOGIN_ACTION);
193         }
194     }
195 
registerReceiver()196     private void registerReceiver() {
197         IntentFilter filter = new IntentFilter();
198         filter.addAction(Intent.ACTION_PROFILE_ACCESSIBLE);
199         if (getContext() != null) {
200             getContext().registerReceiver(mProfileAccessReceiver, filter);
201         }
202     }
203 
unRegisterReceiver()204     private void unRegisterReceiver() {
205         if (mProfileAccessReceiver != null && isAdded() && getContext() != null) {
206             getContext().unregisterReceiver(mProfileAccessReceiver);
207         }
208     }
209 }
210