• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016, 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.managedprovisioning.provisioning;
18 
19 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PROVISIONING_TOTAL_TASK_TIME_MS;
20 import static com.android.managedprovisioning.analytics.ProvisioningAnalyticsTracker.CANCELLED_DURING_PROVISIONING;
21 
22 import static java.util.Objects.requireNonNull;
23 
24 import android.content.Context;
25 import android.os.Bundle;
26 
27 import androidx.appcompat.app.AppCompatActivity;
28 import androidx.lifecycle.ViewModelProvider;
29 import androidx.lifecycle.ViewModelStoreOwner;
30 
31 import com.android.internal.annotations.GuardedBy;
32 import com.android.internal.annotations.VisibleForTesting;
33 import com.android.managedprovisioning.analytics.MetricsWriterFactory;
34 import com.android.managedprovisioning.analytics.ProvisioningAnalyticsTracker;
35 import com.android.managedprovisioning.analytics.TimeLogger;
36 import com.android.managedprovisioning.common.ManagedProvisioningSharedPreferences;
37 import com.android.managedprovisioning.common.ProvisionLogger;
38 import com.android.managedprovisioning.common.SettingsFacade;
39 import com.android.managedprovisioning.model.ProvisioningParams;
40 import com.android.managedprovisioning.provisioning.ProvisioningViewModel.ProvisioningViewModelFactory;
41 import com.android.managedprovisioning.provisioning.TransitionAnimationHelper.TransitionAnimationState;
42 
43 /**
44  * Singleton instance that provides communications between the ongoing provisioning process and the
45  * UI layer.
46  * <p>{@link #setViewModelStoreOwner(ViewModelStoreOwner)} must be called when the view model store
47  * owner has been created (for example, {@link AppCompatActivity#onCreate(Bundle)}). In addition,
48  * to prevent memory leaks when the view model store owner is destroyed, {@link
49  * #clearViewModelStoreOwner()} must be called (for example, in {@link
50  * AppCompatActivity#onDestroy()} when {@link AppCompatActivity#isFinishing()} is {@code true}).
51  */
52 public class ProvisioningManager implements ProvisioningControllerCallback,
53         ProvisioningManagerInterface {
54 
55     private static ProvisioningManager sInstance;
56 
57     private final Context mContext;
58     private final ProvisioningControllerFactory mFactory;
59     private final ProvisioningAnalyticsTracker mProvisioningAnalyticsTracker;
60     private final TimeLogger mTimeLogger;
61     private final ProvisioningManagerHelper mHelper;
62     private ProvisioningViewModel mViewModel;
63 
64     @GuardedBy("this")
65     private AbstractProvisioningController mController;
66 
getInstance(Context context)67     public static ProvisioningManager getInstance(Context context) {
68         if (sInstance == null) {
69             sInstance = new ProvisioningManager(context.getApplicationContext());
70         }
71         return sInstance;
72     }
73 
ProvisioningManager(Context context)74     private ProvisioningManager(Context context) {
75         this(
76                 context,
77                 new ProvisioningControllerFactory(),
78                 new ProvisioningAnalyticsTracker(
79                         MetricsWriterFactory.getMetricsWriter(context, new SettingsFacade()),
80                         new ManagedProvisioningSharedPreferences(context)),
81                 new TimeLogger(context, PROVISIONING_TOTAL_TASK_TIME_MS));
82     }
83 
84     @VisibleForTesting
ProvisioningManager( Context context, ProvisioningControllerFactory factory, ProvisioningAnalyticsTracker analyticsTracker, TimeLogger timeLogger)85     ProvisioningManager(
86             Context context,
87             ProvisioningControllerFactory factory,
88             ProvisioningAnalyticsTracker analyticsTracker,
89             TimeLogger timeLogger) {
90         mContext = requireNonNull(context);
91         mFactory = requireNonNull(factory);
92         mProvisioningAnalyticsTracker = requireNonNull(analyticsTracker);
93         mTimeLogger = requireNonNull(timeLogger);
94         mHelper = new ProvisioningManagerHelper();
95     }
96 
97     /**
98      * Sets the view model store owner.
99      * <p>Must be called when the view model store owner has been created (for example, {@link
100      * AppCompatActivity#onCreate(Bundle)}).
101      * @see #clearViewModelStoreOwner()
102      */
setViewModelStoreOwner(ViewModelStoreOwner owner)103     void setViewModelStoreOwner(ViewModelStoreOwner owner) {
104         mViewModel = new ViewModelProvider(owner, new ProvisioningViewModelFactory())
105                 .get(ProvisioningViewModel.class);
106     }
107 
108     /**
109      * Clears the view model store owner.
110      * <p>Must be called when the view model store owner is getting destroyed (for example, in
111      * {@link AppCompatActivity#onDestroy()} when {@link AppCompatActivity#isFinishing()} is {@code
112      * true}), in order to clean the reference and prevent memory leaks.
113      */
clearViewModelStoreOwner()114     void clearViewModelStoreOwner() {
115         mViewModel = null;
116     }
117 
118     @Override
maybeStartProvisioning(final ProvisioningParams params)119     public void maybeStartProvisioning(final ProvisioningParams params) {
120         synchronized (this) {
121             if (mController == null) {
122                 mTimeLogger.start();
123                 mController = getController(params);
124                 mHelper.startNewProvisioningLocked(mController);
125                 mProvisioningAnalyticsTracker.logProvisioningStarted(mContext, params);
126             } else {
127                 ProvisionLogger.loge("Trying to start provisioning, but it's already running");
128             }
129         }
130     }
131 
132     @Override
registerListener(ProvisioningManagerCallback callback)133     public void registerListener(ProvisioningManagerCallback callback) {
134         mHelper.registerListener(callback);
135     }
136 
137     @Override
unregisterListener(ProvisioningManagerCallback callback)138     public void unregisterListener(ProvisioningManagerCallback callback) {
139         mHelper.unregisterListener(callback);
140     }
141 
142     @Override
cancelProvisioning()143     public void cancelProvisioning() {
144         synchronized (this) {
145             final boolean provisioningCanceled = mHelper.cancelProvisioning(mController);
146             if (provisioningCanceled) {
147                 mProvisioningAnalyticsTracker.logProvisioningCancelled(mContext,
148                         CANCELLED_DURING_PROVISIONING);
149             }
150         }
151     }
152 
153     @Override
provisioningTasksCompleted()154     public void provisioningTasksCompleted() {
155         synchronized (this) {
156             mTimeLogger.stop();
157             preFinalizationCompleted();
158         }
159     }
160 
161     @Override
preFinalizationCompleted()162     public void preFinalizationCompleted() {
163         synchronized (this) {
164             mHelper.notifyPreFinalizationCompleted();
165             mProvisioningAnalyticsTracker.logProvisioningSessionCompleted(mContext);
166             clearControllerLocked();
167             ProvisionLogger.logi("ProvisioningManager pre-finalization completed");
168         }
169     }
170 
171     @Override
cleanUpCompleted()172     public void cleanUpCompleted() {
173         synchronized (this) {
174             clearControllerLocked();
175         }
176     }
177 
178     @Override
error(int titleId, int messageId, boolean factoryResetRequired)179     public void error(int titleId, int messageId, boolean factoryResetRequired) {
180         mHelper.error(titleId, messageId, factoryResetRequired);
181     }
182 
saveTransitionAnimationState(TransitionAnimationState transitionAnimationState)183     void saveTransitionAnimationState(TransitionAnimationState transitionAnimationState) {
184         mViewModel.saveTransitionAnimationState(transitionAnimationState);
185     }
186 
restoreTransitionAnimationState()187     TransitionAnimationState restoreTransitionAnimationState() {
188         return mViewModel.restoreTransitionAnimationState();
189     }
190 
getController(ProvisioningParams params)191     private AbstractProvisioningController getController(ProvisioningParams params) {
192         return mFactory.createProvisioningController(mContext, params, this);
193     }
194 
clearControllerLocked()195     private void clearControllerLocked() {
196         mController = null;
197         mHelper.clearResourcesLocked();
198     }
199 }
200