> HEADER_ILLUSTRATION_PAIRS =
- ImmutableList.of(
- new Pair(R.string.private_space_notifications_hidden_title,
- R.raw.private_space_notifications_illustration),
- new Pair(R.string.private_space_apps_installed_title,
- R.raw.private_space_unlock_to_share_illustration),
- new Pair(R.string.private_space_explore_settings_title,
- R.raw.private_space_placeholder_illustration));
-
- private Runnable mUpdateScreenResources =
- new Runnable() {
- @Override
- public void run() {
- if (getActivity() != null) {
- if (++mScreenTitleIndex < HEADER_ILLUSTRATION_PAIRS.size()) {
- startFadeOutAnimation();
- sHandler.postDelayed(mUpdateScreenResources, DELAY_BETWEEN_SCREENS);
- } else if (PrivateSpaceMaintainer.getInstance(getActivity())
- .doesPrivateSpaceExist()) {
- mMetricsFeatureProvider.action(
- getContext(),
- SettingsEnums.ACTION_PRIVATE_SPACE_SETUP_SPACE_CREATED,
- true);
- if (isConnectedToInternet()) {
- NavHostFragment.findNavController(AutoAdvanceSetupFragment.this)
- .navigate(R.id.action_account_intro_fragment);
- } else {
- NavHostFragment.findNavController(AutoAdvanceSetupFragment.this)
- .navigate(R.id.action_set_lock_fragment);
- }
- } else {
- mMetricsFeatureProvider.action(
- getContext(),
- SettingsEnums.ACTION_PRIVATE_SPACE_SETUP_SPACE_CREATED,
- false);
- showPrivateSpaceErrorScreen();
- }
- }
- }
- };
-
- @Override
- public void onCreate(@Nullable Bundle savedInstanceState) {
- if (android.os.Flags.allowPrivateProfile()
- && android.multiuser.Flags.enablePrivateSpaceFeatures()) {
- super.onCreate(savedInstanceState);
- }
- }
-
- @Override
- public View onCreateView(
- LayoutInflater inflater,
- @Nullable ViewGroup container,
- @Nullable Bundle savedInstanceState) {
- if (savedInstanceState == null) {
- if (PrivateSpaceMaintainer.getInstance(getActivity()).createPrivateSpace()) {
- Log.i(TAG, "Private Space created");
- }
- } else {
- mScreenTitleIndex = savedInstanceState.getInt(TITLE_INDEX);
- if (mScreenTitleIndex >= HEADER_ILLUSTRATION_PAIRS.size()) {
- return super.onCreateView(inflater, container, savedInstanceState);
- }
- }
- mRootView =
- (GlifLayout)
- inflater.inflate(R.layout.private_space_advancing_screen, container, false);
- mRootView.getHeaderTextView().setMaxLines(HEADER_TEXT_MAX_LINES);
- mRootView.getHeaderTextView().setBreakStrategy(BREAK_STRATEGY_SIMPLE);
- mRootView.getHeaderTextView().setAccessibilityLiveRegion(ACCESSIBILITY_LIVE_REGION_POLITE);
- updateHeaderAndIllustration();
- OnBackPressedCallback callback =
- new OnBackPressedCallback(true /* enabled by default */) {
- @Override
- public void handleOnBackPressed() {
- // Handle the back button event. We intentionally don't want to allow back
- // button to work in this screen during the setup flow.
- }
- };
- requireActivity().getOnBackPressedDispatcher().addCallback(this, callback);
- return mRootView;
- }
-
- @Override
- public void onSaveInstanceState(@NotNull Bundle outState) {
- super.onSaveInstanceState(outState);
- outState.putInt(TITLE_INDEX, mScreenTitleIndex);
- }
-
- @Override
- public void onDestroy() {
- sHandler.removeCallbacks(mUpdateScreenResources);
- super.onDestroy();
- }
-
- @Override
- public void onResume() {
- sHandler.postDelayed(mUpdateScreenResources, DELAY_BETWEEN_SCREENS);
- super.onResume();
- }
-
- @Override
- public int getMetricsCategory() {
- return SettingsEnums.PRIVATE_SPACE_SETUP_SPACE_CREATION;
- }
-
- private void showPrivateSpaceErrorScreen() {
- NavHostFragment.findNavController(AutoAdvanceSetupFragment.this)
- .navigate(R.id.action_advance_profile_error);
- }
-
- private void updateHeaderAndIllustration() {
- mRootView.setHeaderText(HEADER_ILLUSTRATION_PAIRS.get(mScreenTitleIndex).first);
- LottieAnimationView animationView = mRootView.findViewById(R.id.lottie_animation);
- animationView.setAnimation(HEADER_ILLUSTRATION_PAIRS.get(mScreenTitleIndex).second);
- animationView.playAnimation();
- startFadeInAnimation();
- }
-
- private void startFadeInAnimation() {
- ValueAnimator textView = ObjectAnimator.ofFloat(
- mRootView.getHeaderTextView(), View.ALPHA, 0f, 1f);
- ValueAnimator lottieView = ObjectAnimator.ofFloat(
- mRootView.findViewById(R.id.lottie_animation), View.ALPHA, 0, 1f);
- AnimatorSet fadeIn = new AnimatorSet();
- fadeIn.playTogether(textView, lottieView);
- fadeIn.setDuration(ANIMATION_DURATION_MILLIS).start();
- }
-
- private void startFadeOutAnimation() {
- AnimatorSet fadeOut = new AnimatorSet();
- ValueAnimator textView = ObjectAnimator.ofFloat(
- mRootView.getHeaderTextView(), View.ALPHA, 1f, 0f);
- ValueAnimator lottieView = ObjectAnimator.ofFloat(
- mRootView.findViewById(R.id.lottie_animation), View.ALPHA, 1f, 0f);
- fadeOut.playTogether(textView, lottieView);
- fadeOut.setDuration(ANIMATION_DURATION_MILLIS).start();
- fadeOut.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- updateHeaderAndIllustration();
- }
- });
- }
-
- /** Returns true if device has an active internet connection, false otherwise. */
- private boolean isConnectedToInternet() {
- ConnectivityManager cm =
- (ConnectivityManager)
- getActivity().getSystemService(Context.CONNECTIVITY_SERVICE);
- NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
- return activeNetwork != null && activeNetwork.isConnectedOrConnecting();
- }
-}
diff --git a/src/com/android/settings/privatespace/PrivateSpaceCreationFragment.java b/src/com/android/settings/privatespace/PrivateSpaceCreationFragment.java
new file mode 100644
index 00000000000..1e0c65e0844
--- /dev/null
+++ b/src/com/android/settings/privatespace/PrivateSpaceCreationFragment.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.privatespace;
+
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.activity.OnBackPressedCallback;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.navigation.fragment.NavHostFragment;
+
+import com.android.settings.R;
+import com.android.settings.core.InstrumentedFragment;
+
+import com.google.android.setupdesign.GlifLayout;
+
+/** Fragment to a show loading screen and create private profile during private space setup flow */
+public class PrivateSpaceCreationFragment extends InstrumentedFragment {
+ private static final String TAG = "PrivateSpaceCreateFrag";
+ private static final int PRIVATE_SPACE_CREATE_POST_DELAY_MS = 1000;
+ private static final Handler sHandler = new Handler(Looper.getMainLooper());
+ private Runnable mRunnable =
+ () -> {
+ createPrivateSpace();
+ };
+
+ @Override
+ public void onCreate(@Nullable Bundle savedInstanceState) {
+ if (android.os.Flags.allowPrivateProfile()
+ && android.multiuser.Flags.enablePrivateSpaceFeatures()) {
+ super.onCreate(savedInstanceState);
+ }
+ }
+
+ @NonNull
+ @Override
+ public View onCreateView(
+ @NonNull LayoutInflater inflater,
+ @Nullable ViewGroup container,
+ @Nullable Bundle savedInstanceState) {
+ GlifLayout rootView =
+ (GlifLayout)
+ inflater.inflate(R.layout.private_space_create_screen, container, false);
+ OnBackPressedCallback callback =
+ new OnBackPressedCallback(true /* enabled by default */) {
+ @Override
+ public void handleOnBackPressed() {
+ // Handle the back button event. We intentionally don't want to allow back
+ // button to work in this screen during the setup flow.
+ }
+ };
+ requireActivity().getOnBackPressedDispatcher().addCallback(this, callback);
+ return rootView;
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ // Ensures screen visibility to user by introducing a 1-second delay before creating private
+ // space.
+ sHandler.postDelayed(mRunnable, PRIVATE_SPACE_CREATE_POST_DELAY_MS);
+ }
+
+ @Override
+ public void onDestroy() {
+ sHandler.removeCallbacks(mRunnable);
+ super.onDestroy();
+ }
+
+ private void createPrivateSpace() {
+ if (PrivateSpaceMaintainer.getInstance(getActivity()).createPrivateSpace()) {
+ Log.i(TAG, "Private Space created");
+ mMetricsFeatureProvider.action(
+ getContext(), SettingsEnums.ACTION_PRIVATE_SPACE_SETUP_SPACE_CREATED, true);
+ if (isConnectedToInternet()) {
+ NavHostFragment.findNavController(PrivateSpaceCreationFragment.this)
+ .navigate(R.id.action_account_intro_fragment);
+ } else {
+ NavHostFragment.findNavController(PrivateSpaceCreationFragment.this)
+ .navigate(R.id.action_set_lock_fragment);
+ }
+ } else {
+ mMetricsFeatureProvider.action(
+ getContext(), SettingsEnums.ACTION_PRIVATE_SPACE_SETUP_SPACE_CREATED, false);
+ showPrivateSpaceErrorScreen();
+ }
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return SettingsEnums.PRIVATE_SPACE_SETUP_SPACE_CREATION;
+ }
+
+ private void showPrivateSpaceErrorScreen() {
+ NavHostFragment.findNavController(PrivateSpaceCreationFragment.this)
+ .navigate(R.id.action_create_profile_error);
+ }
+
+ /** Returns true if device has an active internet connection, false otherwise. */
+ private boolean isConnectedToInternet() {
+ ConnectivityManager cm =
+ (ConnectivityManager) getActivity().getSystemService(Context.CONNECTIVITY_SERVICE);
+ NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
+ return activeNetwork != null && activeNetwork.isConnectedOrConnecting();
+ }
+}
diff --git a/src/com/android/settings/privatespace/PrivateSpaceEducation.java b/src/com/android/settings/privatespace/PrivateSpaceEducation.java
index a21aac3c82d..f688b8d9374 100644
--- a/src/com/android/settings/privatespace/PrivateSpaceEducation.java
+++ b/src/com/android/settings/privatespace/PrivateSpaceEducation.java
@@ -91,7 +91,7 @@ public class PrivateSpaceEducation extends InstrumentedFragment {
getContext(), SettingsEnums.ACTION_PRIVATE_SPACE_SETUP_START);
Log.i(TAG, "Starting private space setup");
NavHostFragment.findNavController(PrivateSpaceEducation.this)
- .navigate(R.id.action_education_to_auto_advance);
+ .navigate(R.id.action_education_to_create);
};
}
diff --git a/src/com/android/settings/privatespace/PrivateSpaceMaintainer.java b/src/com/android/settings/privatespace/PrivateSpaceMaintainer.java
index 6a9ea9dcbca..999da5964bf 100644
--- a/src/com/android/settings/privatespace/PrivateSpaceMaintainer.java
+++ b/src/com/android/settings/privatespace/PrivateSpaceMaintainer.java
@@ -77,7 +77,7 @@ public class PrivateSpaceMaintainer {
*
* This method should be used by the Private Space Setup Flow ONLY.
*/
- @VisibleForTesting
+ @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
public final synchronized boolean createPrivateSpace() {
if (!Flags.allowPrivateProfile()
|| !android.multiuser.Flags.enablePrivateSpaceFeatures()) {