• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.devicelockcontroller.activities;
18 
19 import static com.android.devicelockcontroller.common.DeviceLockConstants.MANDATORY_PROVISION_DEVICE_RESET_COUNTDOWN_MINUTE;
20 import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionEvent.PROVISION_FAILURE;
21 import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionState.PROVISION_FAILED;
22 
23 import static com.google.common.base.Preconditions.checkNotNull;
24 
25 import android.content.Context;
26 import android.os.Bundle;
27 import android.os.SystemClock;
28 import android.view.LayoutInflater;
29 import android.view.View;
30 import android.view.ViewGroup;
31 import android.widget.Button;
32 import android.widget.Chronometer;
33 import android.widget.ImageView;
34 import android.widget.ProgressBar;
35 import android.widget.TextView;
36 
37 import androidx.annotation.Nullable;
38 import androidx.annotation.VisibleForTesting;
39 import androidx.fragment.app.Fragment;
40 import androidx.lifecycle.ViewModelProvider;
41 import androidx.work.WorkManager;
42 
43 import com.android.devicelockcontroller.R;
44 import com.android.devicelockcontroller.activities.util.UrlUtils;
45 import com.android.devicelockcontroller.policy.PolicyObjectsProvider;
46 import com.android.devicelockcontroller.policy.ProvisionHelper;
47 import com.android.devicelockcontroller.policy.ProvisionHelperImpl;
48 import com.android.devicelockcontroller.policy.ProvisionStateController;
49 import com.android.devicelockcontroller.provision.worker.ReportDeviceProvisionStateWorker;
50 import com.android.devicelockcontroller.provision.worker.ReviewDeviceProvisionStateWorker;
51 import com.android.devicelockcontroller.util.LogUtil;
52 
53 import com.google.common.util.concurrent.FutureCallback;
54 import com.google.common.util.concurrent.Futures;
55 
56 import java.util.concurrent.TimeUnit;
57 
58 /**
59  * A screen which always displays a progress bar.
60  */
61 public final class ProgressFragment extends Fragment {
62 
63     private static final String TAG = ProgressFragment.class.getSimpleName();
64 
65     private ProvisionHelper mProvisionHelper;
66 
ProgressFragment()67     public ProgressFragment() {
68         super();
69     }
70 
71     @VisibleForTesting
ProgressFragment(ProvisionHelper provisionHelper)72     ProgressFragment(ProvisionHelper provisionHelper) {
73         super();
74         mProvisionHelper = provisionHelper;
75     }
76 
77     @Nullable
78     @Override
onCreateView( LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState)79     public View onCreateView(
80             LayoutInflater inflater,
81             @Nullable ViewGroup container,
82             @Nullable Bundle savedInstanceState) {
83         View v = inflater.inflate(R.layout.fragment_progress, container, false);
84 
85         ImageView headerIconImageView = v.findViewById(R.id.header_icon);
86         checkNotNull(headerIconImageView);
87 
88         TextView headerTextView = v.findViewById(R.id.header_text);
89         checkNotNull(headerTextView);
90 
91         TextView subheaderTextView = v.findViewById(R.id.subheader_text);
92         checkNotNull(subheaderTextView);
93 
94         ProgressBar progressBar = v.findViewById(R.id.progress_bar);
95         checkNotNull(progressBar);
96 
97         View bottomView = v.findViewById(R.id.bottom);
98         checkNotNull(bottomView);
99 
100         Chronometer countDownTimeView = v.findViewById(R.id.countdown_text);
101         checkNotNull(countDownTimeView);
102 
103         ProvisioningProgressViewModel provisioningProgressViewModel =
104                 new ViewModelProvider(requireActivity()).get(ProvisioningProgressViewModel.class);
105         provisioningProgressViewModel.getProvisioningProgressLiveData().observe(
106                 getViewLifecycleOwner(), provisioningProgress -> {
107                     if (provisioningProgress.mIconId != 0) {
108                         headerIconImageView.setImageResource(provisioningProgress.mIconId);
109                     }
110                     Context context = requireContext();
111                     if (provisioningProgress.mHeaderId != 0) {
112                         headerTextView.setText(
113                                 context.getString(provisioningProgress.mHeaderId,
114                                         provisioningProgressViewModel
115                                                 .mProviderNameLiveData.getValue()));
116                     }
117                     if (provisioningProgress.mSubheaderId != 0) {
118                         UrlUtils.setUrlText(subheaderTextView,
119                                 context.getString(provisioningProgress.mSubheaderId,
120                                         provisioningProgressViewModel
121                                                 .mProviderNameLiveData
122                                                 .getValue(),
123                                         provisioningProgressViewModel
124                                                 .mSupportUrlLiveData
125                                                 .getValue()));
126                     }
127                     if (provisioningProgress.mProgressBarVisible) {
128                         progressBar.setVisibility(View.VISIBLE);
129                     } else {
130                         progressBar.setVisibility(View.GONE);
131                     }
132                     if (provisioningProgress.mBottomViewVisible) {
133                         bottomView.setVisibility(View.VISIBLE);
134                         Button retryButton = bottomView.findViewById(R.id.button_retry);
135                         checkNotNull(retryButton);
136                         PolicyObjectsProvider policyObjects =
137                                 (PolicyObjectsProvider) context.getApplicationContext();
138                         ProvisionStateController provisionStateController =
139                                 policyObjects.getProvisionStateController();
140                         if (mProvisionHelper == null) {
141                             mProvisionHelper = new ProvisionHelperImpl(
142                                     context,
143                                     provisionStateController);
144                         }
145                         retryButton.setOnClickListener(
146                                 view -> mProvisionHelper.scheduleKioskAppInstallation(
147                                         requireActivity(),
148                                         provisioningProgressViewModel,
149                                         /* isProvisionMandatory= */ false));
150 
151                         Button exitButton = bottomView.findViewById(R.id.button_exit);
152                         checkNotNull(exitButton);
153                         FutureCallback<Integer> getProvisionStateCallback =
154                                 new FutureCallback<>() {
155                                     @Override
156                                     public void onSuccess(Integer result) {
157                                         if (result == PROVISION_FAILED) {
158                                             // Already reported set up failure. Finish normally
159                                             getActivity().finish();
160                                             return;
161                                         }
162                                         ReviewDeviceProvisionStateWorker.cancelJobs(
163                                                 WorkManager.getInstance(requireContext()));
164                                         ReportDeviceProvisionStateWorker.reportSetupFailed(
165                                                 WorkManager.getInstance(requireContext()),
166                                                 provisioningProgress.mFailureReason);
167                                         provisionStateController.postSetNextStateForEventRequest(
168                                                 PROVISION_FAILURE);
169                                     }
170 
171                                     @Override
172                                     public void onFailure(Throwable t) {
173                                         LogUtil.e(TAG, "Failed to get provision state", t);
174                                     }
175                                 };
176                         exitButton.setOnClickListener(
177                                 view -> Futures.addCallback(provisionStateController.getState(),
178                                         getProvisionStateCallback,
179                                         context.getMainExecutor()));
180                     } else {
181                         bottomView.setVisibility(View.GONE);
182                     }
183                     if (provisioningProgress.mCountDownTimerVisible) {
184                         countDownTimeView.setBase(
185                                 SystemClock.elapsedRealtime() + TimeUnit.MINUTES.toMillis(
186                                         MANDATORY_PROVISION_DEVICE_RESET_COUNTDOWN_MINUTE));
187                         countDownTimeView.start();
188                         countDownTimeView.setVisibility(View.VISIBLE);
189                     } else {
190                         countDownTimeView.setVisibility(View.GONE);
191                     }
192                 });
193         return v;
194     }
195 }
196