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