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 android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.annotation.StringRes; 22 import android.app.admin.DevicePolicyEventLogger; 23 import android.app.admin.DevicePolicyManager; 24 import android.content.Context; 25 import android.os.UserHandle; 26 27 import com.android.internal.app.AbstractMultiProfilePagerAdapter.CrossProfileIntentsChecker; 28 import com.android.internal.app.AbstractMultiProfilePagerAdapter.EmptyState; 29 import com.android.internal.app.AbstractMultiProfilePagerAdapter.EmptyStateProvider; 30 31 /** 32 * Empty state provider that does not allow cross profile sharing, it will return a blocker 33 * in case if the profile of the current tab is not the same as the profile of the calling app. 34 */ 35 public class NoCrossProfileEmptyStateProvider implements EmptyStateProvider { 36 37 private final UserHandle mPersonalProfileUserHandle; 38 private final EmptyState mNoWorkToPersonalEmptyState; 39 private final EmptyState mNoPersonalToWorkEmptyState; 40 private final CrossProfileIntentsChecker mCrossProfileIntentsChecker; 41 private final UserHandle mTabOwnerUserHandleForLaunch; 42 NoCrossProfileEmptyStateProvider(UserHandle personalUserHandle, EmptyState noWorkToPersonalEmptyState, EmptyState noPersonalToWorkEmptyState, CrossProfileIntentsChecker crossProfileIntentsChecker, UserHandle preselectedTabOwnerUserHandle)43 public NoCrossProfileEmptyStateProvider(UserHandle personalUserHandle, 44 EmptyState noWorkToPersonalEmptyState, 45 EmptyState noPersonalToWorkEmptyState, 46 CrossProfileIntentsChecker crossProfileIntentsChecker, 47 UserHandle preselectedTabOwnerUserHandle) { 48 mPersonalProfileUserHandle = personalUserHandle; 49 mNoWorkToPersonalEmptyState = noWorkToPersonalEmptyState; 50 mNoPersonalToWorkEmptyState = noPersonalToWorkEmptyState; 51 mCrossProfileIntentsChecker = crossProfileIntentsChecker; 52 mTabOwnerUserHandleForLaunch = preselectedTabOwnerUserHandle; 53 } 54 55 @Nullable 56 @Override getEmptyState(ResolverListAdapter resolverListAdapter)57 public EmptyState getEmptyState(ResolverListAdapter resolverListAdapter) { 58 boolean shouldShowBlocker = 59 !mTabOwnerUserHandleForLaunch.equals(resolverListAdapter.getUserHandle()) 60 && !mCrossProfileIntentsChecker 61 .hasCrossProfileIntents(resolverListAdapter.getIntents(), 62 mTabOwnerUserHandleForLaunch.getIdentifier(), 63 resolverListAdapter.getUserHandle().getIdentifier()); 64 65 if (!shouldShowBlocker) { 66 return null; 67 } 68 69 if (resolverListAdapter.getUserHandle().equals(mPersonalProfileUserHandle)) { 70 return mNoWorkToPersonalEmptyState; 71 } else { 72 return mNoPersonalToWorkEmptyState; 73 } 74 } 75 76 77 /** 78 * Empty state that gets strings from the device policy manager and tracks events into 79 * event logger of the device policy events. 80 */ 81 public static class DevicePolicyBlockerEmptyState implements EmptyState { 82 83 @NonNull 84 private final Context mContext; 85 private final String mDevicePolicyStringTitleId; 86 @StringRes 87 private final int mDefaultTitleResource; 88 private final String mDevicePolicyStringSubtitleId; 89 @StringRes 90 private final int mDefaultSubtitleResource; 91 private final int mEventId; 92 @NonNull 93 private final String mEventCategory; 94 DevicePolicyBlockerEmptyState(Context context, String devicePolicyStringTitleId, @StringRes int defaultTitleResource, String devicePolicyStringSubtitleId, @StringRes int defaultSubtitleResource, int devicePolicyEventId, String devicePolicyEventCategory)95 public DevicePolicyBlockerEmptyState(Context context, String devicePolicyStringTitleId, 96 @StringRes int defaultTitleResource, String devicePolicyStringSubtitleId, 97 @StringRes int defaultSubtitleResource, 98 int devicePolicyEventId, String devicePolicyEventCategory) { 99 mContext = context; 100 mDevicePolicyStringTitleId = devicePolicyStringTitleId; 101 mDefaultTitleResource = defaultTitleResource; 102 mDevicePolicyStringSubtitleId = devicePolicyStringSubtitleId; 103 mDefaultSubtitleResource = defaultSubtitleResource; 104 mEventId = devicePolicyEventId; 105 mEventCategory = devicePolicyEventCategory; 106 } 107 108 @Nullable 109 @Override getTitle()110 public String getTitle() { 111 return mContext.getSystemService(DevicePolicyManager.class).getResources().getString( 112 mDevicePolicyStringTitleId, 113 () -> mContext.getString(mDefaultTitleResource)); 114 } 115 116 @Nullable 117 @Override getSubtitle()118 public String getSubtitle() { 119 return mContext.getSystemService(DevicePolicyManager.class).getResources().getString( 120 mDevicePolicyStringSubtitleId, 121 () -> mContext.getString(mDefaultSubtitleResource)); 122 } 123 124 @Override onEmptyStateShown()125 public void onEmptyStateShown() { 126 DevicePolicyEventLogger.createEvent(mEventId) 127 .setStrings(mEventCategory) 128 .write(); 129 } 130 131 @Override shouldSkipDataRebuild()132 public boolean shouldSkipDataRebuild() { 133 return true; 134 } 135 } 136 } 137