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.internal.app; 18 19 import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_NO_PERSONAL_APPS; 20 import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_NO_WORK_APPS; 21 22 import android.annotation.NonNull; 23 import android.annotation.Nullable; 24 import android.app.admin.DevicePolicyEventLogger; 25 import android.app.admin.DevicePolicyManager; 26 import android.content.Context; 27 import android.content.pm.ResolveInfo; 28 import android.os.UserHandle; 29 import android.stats.devicepolicy.nano.DevicePolicyEnums; 30 31 import com.android.internal.R; 32 import com.android.internal.app.AbstractMultiProfilePagerAdapter.EmptyState; 33 import com.android.internal.app.AbstractMultiProfilePagerAdapter.EmptyStateProvider; 34 35 import java.util.List; 36 37 /** 38 * Chooser/ResolverActivity empty state provider that returns empty state which is shown when 39 * there are no apps available. 40 */ 41 public class NoAppsAvailableEmptyStateProvider implements EmptyStateProvider { 42 43 @NonNull 44 private final Context mContext; 45 @Nullable 46 private final UserHandle mWorkProfileUserHandle; 47 @Nullable 48 private final UserHandle mPersonalProfileUserHandle; 49 @NonNull 50 private final String mMetricsCategory; 51 @NonNull 52 private final UserHandle mTabOwnerUserHandleForLaunch; 53 NoAppsAvailableEmptyStateProvider(Context context, UserHandle workProfileUserHandle, UserHandle personalProfileUserHandle, String metricsCategory, UserHandle tabOwnerUserHandleForLaunch)54 public NoAppsAvailableEmptyStateProvider(Context context, UserHandle workProfileUserHandle, 55 UserHandle personalProfileUserHandle, String metricsCategory, 56 UserHandle tabOwnerUserHandleForLaunch) { 57 mContext = context; 58 mWorkProfileUserHandle = workProfileUserHandle; 59 mPersonalProfileUserHandle = personalProfileUserHandle; 60 mMetricsCategory = metricsCategory; 61 mTabOwnerUserHandleForLaunch = tabOwnerUserHandleForLaunch; 62 } 63 64 @Nullable 65 @Override 66 @SuppressWarnings("ReferenceEquality") getEmptyState(ResolverListAdapter resolverListAdapter)67 public EmptyState getEmptyState(ResolverListAdapter resolverListAdapter) { 68 UserHandle listUserHandle = resolverListAdapter.getUserHandle(); 69 70 if (mWorkProfileUserHandle != null 71 && (mTabOwnerUserHandleForLaunch.equals(listUserHandle) 72 || !hasAppsInOtherProfile(resolverListAdapter))) { 73 74 String title; 75 if (listUserHandle == mPersonalProfileUserHandle) { 76 title = mContext.getSystemService( 77 DevicePolicyManager.class).getResources().getString( 78 RESOLVER_NO_PERSONAL_APPS, 79 () -> mContext.getString(R.string.resolver_no_personal_apps_available)); 80 } else { 81 title = mContext.getSystemService( 82 DevicePolicyManager.class).getResources().getString( 83 RESOLVER_NO_WORK_APPS, 84 () -> mContext.getString(R.string.resolver_no_work_apps_available)); 85 } 86 87 return new NoAppsAvailableEmptyState( 88 title, mMetricsCategory, 89 /* isPersonalProfile= */ listUserHandle == mPersonalProfileUserHandle 90 ); 91 } else if (mWorkProfileUserHandle == null) { 92 // Return default empty state without tracking 93 return new DefaultEmptyState(); 94 } 95 96 return null; 97 } 98 hasAppsInOtherProfile(ResolverListAdapter adapter)99 private boolean hasAppsInOtherProfile(ResolverListAdapter adapter) { 100 if (mWorkProfileUserHandle == null) { 101 return false; 102 } 103 List<ResolverActivity.ResolvedComponentInfo> resolversForIntent = 104 adapter.getResolversForUser(mTabOwnerUserHandleForLaunch); 105 for (ResolverActivity.ResolvedComponentInfo info : resolversForIntent) { 106 ResolveInfo resolveInfo = info.getResolveInfoAt(0); 107 if (resolveInfo.targetUserId != UserHandle.USER_CURRENT) { 108 return true; 109 } 110 } 111 return false; 112 } 113 114 public static class DefaultEmptyState implements EmptyState { 115 @Override useDefaultEmptyView()116 public boolean useDefaultEmptyView() { 117 return true; 118 } 119 } 120 121 public static class NoAppsAvailableEmptyState implements EmptyState { 122 123 @NonNull 124 private String mTitle; 125 126 @NonNull 127 private String mMetricsCategory; 128 129 private boolean mIsPersonalProfile; 130 NoAppsAvailableEmptyState(String title, String metricsCategory, boolean isPersonalProfile)131 public NoAppsAvailableEmptyState(String title, String metricsCategory, 132 boolean isPersonalProfile) { 133 mTitle = title; 134 mMetricsCategory = metricsCategory; 135 mIsPersonalProfile = isPersonalProfile; 136 } 137 138 @Nullable 139 @Override getTitle()140 public String getTitle() { 141 return mTitle; 142 } 143 144 @Override onEmptyStateShown()145 public void onEmptyStateShown() { 146 DevicePolicyEventLogger.createEvent( 147 DevicePolicyEnums.RESOLVER_EMPTY_STATE_NO_APPS_RESOLVED) 148 .setStrings(mMetricsCategory) 149 .setBoolean(/*isPersonalProfile*/ mIsPersonalProfile) 150 .write(); 151 } 152 } 153 }