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 android.text.TextUtils; 20 21 import androidx.lifecycle.LiveData; 22 import androidx.lifecycle.MediatorLiveData; 23 import androidx.lifecycle.MutableLiveData; 24 import androidx.lifecycle.Observer; 25 import androidx.lifecycle.ViewModel; 26 27 import com.android.devicelockcontroller.storage.SetupParametersClient; 28 import com.android.devicelockcontroller.util.LogUtil; 29 30 import com.google.common.util.concurrent.FutureCallback; 31 import com.google.common.util.concurrent.Futures; 32 import com.google.common.util.concurrent.MoreExecutors; 33 34 /** 35 * A {@link ViewModel} which provides {@link ProvisioningProgress} to the 36 * {@link ProvisioningActivity}. 37 */ 38 public final class ProvisioningProgressViewModel extends ViewModel { 39 40 private static final String TAG = "ProvisioningProgressViewModel"; 41 42 final MutableLiveData<String> mProviderNameLiveData; 43 private final MediatorLiveData<ProvisioningProgress> mProvisioningProgressLiveData; 44 private ProvisioningProgress mProvisioningProgress; 45 ProvisioningProgressViewModel()46 public ProvisioningProgressViewModel() { 47 mProviderNameLiveData = new MutableLiveData<>(); 48 Futures.addCallback( 49 SetupParametersClient.getInstance().getKioskAppProviderName(), 50 new FutureCallback<>() { 51 @Override 52 public void onSuccess(String providerName) { 53 if (TextUtils.isEmpty(providerName)) { 54 LogUtil.e(TAG, "Device provider name is empty, should not reach here."); 55 return; 56 } 57 mProviderNameLiveData.postValue(providerName); 58 } 59 60 @Override 61 public void onFailure(Throwable t) { 62 LogUtil.e(TAG, "Failed to get Kiosk app provider name", t); 63 } 64 }, MoreExecutors.directExecutor()); 65 66 mProvisioningProgressLiveData = new MediatorLiveData<>(); 67 Observer<String> observer = unused -> { 68 LogUtil.d(TAG, "The upstream ProviderNameLiveData is complete"); 69 if (mProvisioningProgress != null) { 70 LogUtil.d(TAG, "Sending ProvisioningProgress to observers."); 71 mProvisioningProgressLiveData.postValue(mProvisioningProgress); 72 } 73 }; 74 mProvisioningProgressLiveData.addSource(mProviderNameLiveData, observer); 75 } 76 77 /** 78 * Returns the {@link LiveData} which provides the latest {@link ProvisioningProgress}. 79 * 80 * <p>Note, the caller of this method MUST NOT update the LiveData directly, use 81 * {@link #setProvisioningProgress} instead. 82 */ getProvisioningProgressLiveData()83 public LiveData<ProvisioningProgress> getProvisioningProgressLiveData() { 84 return mProvisioningProgressLiveData; 85 } 86 87 /** 88 * Set the {@link ProvisioningProgress} to the given state. 89 * 90 * <p>This method is thread-safe and can be called from any thread. 91 */ setProvisioningProgress(ProvisioningProgress provisioningProgress)92 public void setProvisioningProgress(ProvisioningProgress provisioningProgress) { 93 if (mProviderNameLiveData.getValue() != null) { 94 LogUtil.d(TAG, "Updating ProvisioningProgress"); 95 mProvisioningProgressLiveData.postValue(provisioningProgress); 96 } else { 97 LogUtil.d(TAG, 98 "The upstream ProviderNameLiveData is not ready yet, hold on until it " 99 + "completes"); 100 mProvisioningProgress = provisioningProgress; 101 } 102 } 103 104 } 105