blob: 04928e22679aedd41a13ab2495c8c43e4ffc27ff [file] [log] [blame]
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.providers.media.photopicker.viewmodel;
import android.annotation.UserIdInt;
import android.content.Context;
import android.os.UserHandle;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import com.android.providers.media.photopicker.data.UserIdManager;
import com.android.providers.media.util.ForegroundThread;
import com.android.providers.media.util.PerUser;
class BannerManager {
private static final String TAG = "BannerManager";
private final UserIdManager mUserIdManager;
// Authority of the current CloudMediaProvider of the current user
private final MutableLiveData<String> mCloudMediaProviderAuthority = new MutableLiveData<>();
// Label of the current CloudMediaProvider of the current user
private final MutableLiveData<String> mCloudMediaProviderLabel = new MutableLiveData<>();
// Account name of the current CloudMediaProvider of the current user
private final MutableLiveData<String> mCloudMediaAccountName = new MutableLiveData<>();
// Boolean Choose App Banner visibility
private final MutableLiveData<Boolean> mShowChooseAppBanner = new MutableLiveData<>(false);
// Boolean Cloud Media Available Banner visibility
private final MutableLiveData<Boolean> mShowCloudMediaAvailableBanner =
new MutableLiveData<>(false);
// Boolean 'Account Updated' banner visibility
private final MutableLiveData<Boolean> mShowAccountUpdatedBanner = new MutableLiveData<>(false);
// Boolean 'Choose Account' banner visibility
private final MutableLiveData<Boolean> mShowChooseAccountBanner = new MutableLiveData<>(false);
// The banner controllers per user
private final PerUser<BannerController> mBannerControllers;
BannerManager(@NonNull Context context, @NonNull UserIdManager userIdManager) {
mUserIdManager = userIdManager;
mBannerControllers = new PerUser<BannerController>() {
@NonNull
@Override
protected BannerController create(@UserIdInt int userId) {
return new BannerController(context, UserHandle.of(userId));
}
};
maybeInitialiseAndSetBannersForCurrentUser();
}
@UserIdInt int getCurrentUserProfileId() {
return mUserIdManager.getCurrentUserProfileId().getIdentifier();
}
PerUser<BannerController> getBannerControllersPerUser() {
return mBannerControllers;
}
/**
* @return a {@link LiveData} that holds the value (once it's fetched) of the
* {@link android.content.ContentProvider#mAuthority authority} of the current
* {@link android.provider.CloudMediaProvider}.
*/
@NonNull
MutableLiveData<String> getCloudMediaProviderAuthorityLiveData() {
return mCloudMediaProviderAuthority;
}
/**
* @return a {@link LiveData} that holds the value (once it's fetched) of the label
* of the current {@link android.provider.CloudMediaProvider}.
*/
@NonNull
MutableLiveData<String> getCloudMediaProviderAppTitleLiveData() {
return mCloudMediaProviderLabel;
}
/**
* @return a {@link LiveData} that holds the value (once it's fetched) of the account name
* of the current {@link android.provider.CloudMediaProvider}.
*/
@NonNull
MutableLiveData<String> getCloudMediaAccountNameLiveData() {
return mCloudMediaAccountName;
}
/**
* @return the {@link LiveData} of the 'Choose App' banner visibility.
*/
@NonNull
MutableLiveData<Boolean> shouldShowChooseAppBannerLiveData() {
return mShowChooseAppBanner;
}
/**
* @return the {@link LiveData} of the 'Cloud Media Available' banner visibility.
*/
@NonNull
MutableLiveData<Boolean> shouldShowCloudMediaAvailableBannerLiveData() {
return mShowCloudMediaAvailableBanner;
}
/**
* @return the {@link LiveData} of the 'Account Updated' banner visibility.
*/
@NonNull
MutableLiveData<Boolean> shouldShowAccountUpdatedBannerLiveData() {
return mShowAccountUpdatedBanner;
}
/**
* @return the {@link LiveData} of the 'Choose Account' banner visibility.
*/
@NonNull
MutableLiveData<Boolean> shouldShowChooseAccountBannerLiveData() {
return mShowChooseAccountBanner;
}
/**
* Dismiss (hide) the 'Choose App' banner for the current user.
*/
@UiThread
void onUserDismissedChooseAppBanner() {
if (Boolean.FALSE.equals(mShowChooseAppBanner.getValue())) {
Log.d(TAG, "Choose App banner visibility live data value is false on dismiss");
} else {
mShowChooseAppBanner.setValue(false);
}
final BannerController bannerController = getCurrentBannerController();
if (bannerController != null) {
bannerController.onUserDismissedChooseAppBanner();
}
}
/**
* Dismiss (hide) the 'Cloud Media Available' banner for the current user.
*/
@UiThread
void onUserDismissedCloudMediaAvailableBanner() {
if (Boolean.FALSE.equals(mShowCloudMediaAvailableBanner.getValue())) {
Log.d(TAG, "Cloud Media Available banner visibility live data value is false on "
+ "dismiss");
} else {
mShowCloudMediaAvailableBanner.setValue(false);
}
final BannerController bannerController = getCurrentBannerController();
if (bannerController != null) {
bannerController.onUserDismissedCloudMediaAvailableBanner();
}
}
/**
* Dismiss (hide) the 'Account Updated' banner for the current user.
*/
@UiThread
void onUserDismissedAccountUpdatedBanner() {
if (Boolean.FALSE.equals(mShowAccountUpdatedBanner.getValue())) {
Log.d(TAG, "Account Updated banner visibility live data value is false on dismiss");
} else {
mShowAccountUpdatedBanner.setValue(false);
}
final BannerController bannerController = getCurrentBannerController();
if (bannerController != null) {
bannerController.onUserDismissedAccountUpdatedBanner();
}
}
/**
* Dismiss (hide) the 'Choose Account' banner for the current user.
*/
@UiThread
void onUserDismissedChooseAccountBanner() {
if (Boolean.FALSE.equals(mShowChooseAccountBanner.getValue())) {
Log.d(TAG, "Choose Account banner visibility live data value is false on dismiss");
} else {
mShowChooseAccountBanner.setValue(false);
}
final BannerController bannerController = getCurrentBannerController();
if (bannerController != null) {
bannerController.onUserDismissedChooseAccountBanner();
}
}
@Nullable
private BannerController getCurrentBannerController() {
final int currentUserProfileId = getCurrentUserProfileId();
return mBannerControllers.get(currentUserProfileId);
}
/**
* Resets the banner controller per user.
*
* Note - Since {@link BannerController#reset()} cannot be called in the Main thread, using
* {@link ForegroundThread} here.
*/
void maybeResetAllBannerData() {
for (int arrayIndex = 0, numControllers = mBannerControllers.size();
arrayIndex < numControllers; arrayIndex++) {
final BannerController bannerController = mBannerControllers.valueAt(arrayIndex);
ForegroundThread.getExecutor().execute(bannerController::reset);
}
}
/**
* Update the banner {@link LiveData} values.
*
* 1. {@link #hideAllBanners()} in the Main thread to ensure consistency with the media items
* displayed for the period when the items and categories have been updated but the
* {@link BannerController} construction or {@link BannerController#reset()} is still in
* progress.
*
* 2. Initialise and set the banner data for the current user
* {@link #maybeInitialiseAndSetBannersForCurrentUser()}.
*/
@UiThread
void maybeUpdateBannerLiveDatas() {
// Hide all banners in the Main thread to ensure consistency with the media items
hideAllBanners();
// Initialise and set the banner data for the current user
maybeInitialiseAndSetBannersForCurrentUser();
}
/**
* Hide all banners in the Main thread.
*
* Set all banner {@link LiveData} values to {@code false}.
*/
@UiThread
private void hideAllBanners() {
mShowChooseAppBanner.setValue(false);
mShowCloudMediaAvailableBanner.setValue(false);
mShowAccountUpdatedBanner.setValue(false);
mShowChooseAccountBanner.setValue(false);
}
/**
* Initialise and set the banner data for the current user.
*
* No-op by default, overridden for cloud.
*/
void maybeInitialiseAndSetBannersForCurrentUser() {
// No-op, may be overridden
}
static class CloudBannerManager extends BannerManager {
CloudBannerManager(@NonNull Context context, @NonNull UserIdManager userIdManager) {
super(context, userIdManager);
}
/**
* Initialise and set the banner data for the current user.
*
* 1. Get or create the {@link BannerController} for
* {@link UserIdManager#getCurrentUserProfileId()} using {@link PerUser#forUser(int)}.
* Since, the {@link BannerController} construction cannot be done in the Main thread,
* using {@link ForegroundThread} here.
*
* 2. Post the updated {@link BannerController} {@link LiveData} values.
*/
@Override
void maybeInitialiseAndSetBannersForCurrentUser() {
final int currentUserProfileId = getCurrentUserProfileId();
ForegroundThread.getExecutor().execute(() -> {
// Get (iff exists) or create the banner controller for the current user
final BannerController bannerController =
getBannerControllersPerUser().forUser(currentUserProfileId);
// Post the banner related live data values from this current user banner controller
getCloudMediaProviderAuthorityLiveData()
.postValue(bannerController.getCloudMediaProviderAuthority());
getCloudMediaProviderAppTitleLiveData()
.postValue(bannerController.getCloudMediaProviderLabel());
getCloudMediaAccountNameLiveData()
.postValue(bannerController.getCloudMediaProviderAccountName());
shouldShowChooseAppBannerLiveData()
.postValue(bannerController.shouldShowChooseAppBanner());
shouldShowCloudMediaAvailableBannerLiveData()
.postValue(bannerController.shouldShowCloudMediaAvailableBanner());
shouldShowAccountUpdatedBannerLiveData()
.postValue(bannerController.shouldShowAccountUpdatedBanner());
shouldShowChooseAccountBannerLiveData()
.postValue(bannerController.shouldShowChooseAccountBanner());
});
}
}
}