1 /* 2 * Copyright (C) 2022 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.networkconnection; 18 19 import static java.util.Objects.requireNonNull; 20 21 import android.content.Context; 22 import android.content.Intent; 23 import android.os.UserHandle; 24 25 import androidx.annotation.NonNull; 26 import androidx.lifecycle.MutableLiveData; 27 import androidx.lifecycle.ViewModel; 28 import androidx.lifecycle.ViewModelProvider; 29 30 import com.android.managedprovisioning.common.ErrorWrapper; 31 import com.android.managedprovisioning.common.IllegalProvisioningArgumentException; 32 import com.android.managedprovisioning.common.ProvisionLogger; 33 import com.android.managedprovisioning.common.SettingsFacade; 34 import com.android.managedprovisioning.common.SharedPreferences; 35 import com.android.managedprovisioning.common.Utils; 36 import com.android.managedprovisioning.model.ProvisioningParams; 37 import com.android.managedprovisioning.parser.MessageParser; 38 import com.android.managedprovisioning.provisioning.ProvisioningControllerCallback; 39 import com.android.managedprovisioning.provisioning.ProvisioningManagerHelper; 40 import com.android.managedprovisioning.task.TaskFactory; 41 import com.android.managedprovisioning.util.LazyStringResource; 42 43 /** 44 * A {@link ViewModel} which manages the state for the network connection establishing screen. 45 */ 46 public final class EstablishNetworkConnectionViewModel extends ViewModel implements 47 ProvisioningControllerCallback { 48 49 public static final int STATE_IDLE = 1; 50 public static final int STATE_CONNECTING = 2; 51 public static final int STATE_SHOW_NETWORK_PICKER = 3; 52 public static final int STATE_ERROR = 4; 53 public static final int STATE_CONNECTED = 5; 54 55 private final ProvisioningManagerHelper mProvisioningManagerHelper = 56 new ProvisioningManagerHelper(); 57 private final MutableLiveData<Integer> mState = new MutableLiveData<>(STATE_IDLE); 58 private final Utils mUtils; 59 private final SettingsFacade mSettingsFacade; 60 private final SharedPreferences mSharedPreferences; 61 private ErrorWrapper mErrorWrapper; 62 EstablishNetworkConnectionViewModel( Utils utils, SettingsFacade settingsFacade, SharedPreferences sharedPreferences)63 public EstablishNetworkConnectionViewModel( 64 Utils utils, 65 SettingsFacade settingsFacade, 66 SharedPreferences sharedPreferences) { 67 mUtils = requireNonNull(utils); 68 mSettingsFacade = requireNonNull(settingsFacade); 69 mSharedPreferences = requireNonNull(sharedPreferences); 70 } 71 72 /** 73 * Parses and returns the provisioning extras contained in {@code intent}. 74 */ parseExtras(Context context, Intent intent)75 public ProvisioningParams parseExtras(Context context, Intent intent) { 76 requireNonNull(context); 77 requireNonNull(intent); 78 ProvisioningParams params = null; 79 try { 80 params = new MessageParser(context, mUtils).parse(intent); 81 } catch (IllegalProvisioningArgumentException e) { 82 ProvisionLogger.loge("Error parsing intent extras", e); 83 } 84 return params; 85 } 86 87 /** 88 * Returns {@link MutableLiveData} describing the state. 89 */ observeState()90 public MutableLiveData<Integer> observeState() { 91 return mState; 92 } 93 94 /** 95 * Connects to wifi or mobile data if needed. 96 */ connectToNetwork(Context context, ProvisioningParams params)97 public void connectToNetwork(Context context, 98 ProvisioningParams params) { 99 requireNonNull(context); 100 requireNonNull(params); 101 mSharedPreferences.setIsEstablishNetworkConnectionRun(true); 102 var networkCapabilities = mUtils.getActiveNetworkCapabilities(context); 103 if (networkCapabilities != null 104 && mUtils.isNetworkConnectedToInternetViaEthernet(networkCapabilities)) { 105 updateState(STATE_CONNECTED); 106 return; 107 } else if (params.wifiInfo == null 108 && !params.useMobileData) { 109 updateState(STATE_SHOW_NETWORK_PICKER); 110 return; 111 } 112 mProvisioningManagerHelper.startNewProvisioningLocked( 113 EstablishNetworkConnectionController.createInstance( 114 context, 115 params, 116 UserHandle.USER_SYSTEM, 117 this, 118 mUtils, 119 mSettingsFacade, 120 new TaskFactory())); 121 updateState(STATE_CONNECTING); 122 } 123 124 @Override cleanUpCompleted()125 public void cleanUpCompleted() { 126 mProvisioningManagerHelper.clearResourcesLocked(); 127 } 128 129 @Override provisioningTasksCompleted()130 public void provisioningTasksCompleted() { 131 updateState(STATE_CONNECTED); 132 } 133 134 @Override error(int dialogTitleId, int errorMessageId, boolean factoryResetRequired)135 public void error(int dialogTitleId, int errorMessageId, boolean factoryResetRequired) { 136 mErrorWrapper = new ErrorWrapper(dialogTitleId, LazyStringResource.of(errorMessageId), 137 factoryResetRequired); 138 updateState(STATE_ERROR); 139 } 140 141 @Override error(int dialogTitleId, String errorMessage, boolean factoryResetRequired)142 public void error(int dialogTitleId, String errorMessage, boolean factoryResetRequired) { 143 mErrorWrapper = new ErrorWrapper(dialogTitleId, LazyStringResource.of(errorMessage), 144 factoryResetRequired); 145 updateState(STATE_ERROR); 146 } 147 updateState(int stateDownloading)148 private void updateState(int stateDownloading) { 149 if (stateDownloading != STATE_ERROR) { 150 mErrorWrapper = null; 151 } 152 mState.postValue(stateDownloading); 153 } 154 155 /** 156 * Returns an {@link ErrorWrapper} which describes the last error that happened. This will 157 * only be non-{@code null} if {@link #observeState()} returns {@link #STATE_ERROR}. 158 */ getError()159 public ErrorWrapper getError() { 160 return mErrorWrapper; 161 } 162 163 @Override preFinalizationCompleted()164 public void preFinalizationCompleted() { 165 } 166 167 static class EstablishNetworkConnectionViewModelFactory implements ViewModelProvider.Factory { 168 private final Utils mUtils; 169 private final SettingsFacade mSettingsFacade; 170 private final SharedPreferences mSharedPreferences; 171 EstablishNetworkConnectionViewModelFactory( Utils utils, SettingsFacade settingsFacade, SharedPreferences sharedPreferences)172 EstablishNetworkConnectionViewModelFactory( 173 Utils utils, 174 SettingsFacade settingsFacade, 175 SharedPreferences sharedPreferences) { 176 mUtils = requireNonNull(utils); 177 mSettingsFacade = requireNonNull(settingsFacade); 178 mSharedPreferences = requireNonNull(sharedPreferences); 179 } 180 181 @NonNull 182 @Override 183 @SuppressWarnings("unchecked") create(@onNull Class<T> modelClass)184 public <T extends ViewModel> T create(@NonNull Class<T> modelClass) { 185 if (!EstablishNetworkConnectionViewModel.class.isAssignableFrom(modelClass)) { 186 throw new IllegalArgumentException("Invalid class for creating a " 187 + "EstablishNetworkConnectionViewModel: " + modelClass); 188 } 189 return (T) new EstablishNetworkConnectionViewModel( 190 mUtils, mSettingsFacade, mSharedPreferences); 191 } 192 } 193 } 194