1 /* 2 * Copyright (C) 2019 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.chooser; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.app.Activity; 22 import android.content.ComponentName; 23 import android.content.Context; 24 import android.content.Intent; 25 import android.content.pm.ActivityInfo; 26 import android.content.pm.ApplicationInfo; 27 import android.content.pm.ResolveInfo; 28 import android.graphics.drawable.Drawable; 29 import android.os.Bundle; 30 import android.os.UserHandle; 31 32 import com.android.internal.app.ResolverActivity; 33 import com.android.internal.app.ResolverListAdapter.ResolveInfoPresentationGetter; 34 35 import java.util.ArrayList; 36 import java.util.List; 37 38 /** 39 * A TargetInfo plus additional information needed to render it (such as icon and label) and 40 * resolve it to an activity. 41 */ 42 public class DisplayResolveInfo implements TargetInfo { 43 // Temporary flag for new chooser delegate behavior. There are occassional token 44 // permission errors from bouncing through the delegate. Watch out before reenabling: 45 // b/157272342 is one example but this issue has been reported many times 46 private static final boolean ENABLE_CHOOSER_DELEGATE = false; 47 48 private final ResolveInfo mResolveInfo; 49 private CharSequence mDisplayLabel; 50 private Drawable mDisplayIcon; 51 private CharSequence mExtendedInfo; 52 private final Intent mResolvedIntent; 53 private final List<Intent> mSourceIntents = new ArrayList<>(); 54 private boolean mIsSuspended; 55 private ResolveInfoPresentationGetter mResolveInfoPresentationGetter; 56 private boolean mPinned = false; 57 DisplayResolveInfo(Intent originalIntent, ResolveInfo pri, Intent pOrigIntent, ResolveInfoPresentationGetter resolveInfoPresentationGetter)58 public DisplayResolveInfo(Intent originalIntent, ResolveInfo pri, Intent pOrigIntent, 59 ResolveInfoPresentationGetter resolveInfoPresentationGetter) { 60 this(originalIntent, pri, null /*mDisplayLabel*/, null /*mExtendedInfo*/, pOrigIntent, 61 resolveInfoPresentationGetter); 62 } 63 DisplayResolveInfo(Intent originalIntent, ResolveInfo pri, CharSequence pLabel, CharSequence pInfo, @NonNull Intent resolvedIntent, @Nullable ResolveInfoPresentationGetter resolveInfoPresentationGetter)64 public DisplayResolveInfo(Intent originalIntent, ResolveInfo pri, CharSequence pLabel, 65 CharSequence pInfo, @NonNull Intent resolvedIntent, 66 @Nullable ResolveInfoPresentationGetter resolveInfoPresentationGetter) { 67 mSourceIntents.add(originalIntent); 68 mResolveInfo = pri; 69 mDisplayLabel = pLabel; 70 mExtendedInfo = pInfo; 71 mResolveInfoPresentationGetter = resolveInfoPresentationGetter; 72 73 final Intent intent = new Intent(resolvedIntent); 74 intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT 75 | Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP); 76 final ActivityInfo ai = mResolveInfo.activityInfo; 77 intent.setComponent(new ComponentName(ai.applicationInfo.packageName, ai.name)); 78 79 mIsSuspended = (ai.applicationInfo.flags & ApplicationInfo.FLAG_SUSPENDED) != 0; 80 81 mResolvedIntent = intent; 82 } 83 DisplayResolveInfo(DisplayResolveInfo other, Intent fillInIntent, int flags, ResolveInfoPresentationGetter resolveInfoPresentationGetter)84 private DisplayResolveInfo(DisplayResolveInfo other, Intent fillInIntent, int flags, 85 ResolveInfoPresentationGetter resolveInfoPresentationGetter) { 86 mSourceIntents.addAll(other.getAllSourceIntents()); 87 mResolveInfo = other.mResolveInfo; 88 mDisplayLabel = other.mDisplayLabel; 89 mDisplayIcon = other.mDisplayIcon; 90 mExtendedInfo = other.mExtendedInfo; 91 mResolvedIntent = new Intent(other.mResolvedIntent); 92 mResolvedIntent.fillIn(fillInIntent, flags); 93 mResolveInfoPresentationGetter = resolveInfoPresentationGetter; 94 } 95 DisplayResolveInfo(DisplayResolveInfo other)96 DisplayResolveInfo(DisplayResolveInfo other) { 97 mSourceIntents.addAll(other.getAllSourceIntents()); 98 mResolveInfo = other.mResolveInfo; 99 mDisplayLabel = other.mDisplayLabel; 100 mDisplayIcon = other.mDisplayIcon; 101 mExtendedInfo = other.mExtendedInfo; 102 mResolvedIntent = other.mResolvedIntent; 103 mResolveInfoPresentationGetter = other.mResolveInfoPresentationGetter; 104 } 105 getResolveInfo()106 public ResolveInfo getResolveInfo() { 107 return mResolveInfo; 108 } 109 getDisplayLabel()110 public CharSequence getDisplayLabel() { 111 if (mDisplayLabel == null && mResolveInfoPresentationGetter != null) { 112 mDisplayLabel = mResolveInfoPresentationGetter.getLabel(); 113 mExtendedInfo = mResolveInfoPresentationGetter.getSubLabel(); 114 } 115 return mDisplayLabel; 116 } 117 hasDisplayLabel()118 public boolean hasDisplayLabel() { 119 return mDisplayLabel != null; 120 } 121 setDisplayLabel(CharSequence displayLabel)122 public void setDisplayLabel(CharSequence displayLabel) { 123 mDisplayLabel = displayLabel; 124 } 125 setExtendedInfo(CharSequence extendedInfo)126 public void setExtendedInfo(CharSequence extendedInfo) { 127 mExtendedInfo = extendedInfo; 128 } 129 getDisplayIcon(Context context)130 public Drawable getDisplayIcon(Context context) { 131 return mDisplayIcon; 132 } 133 134 @Override cloneFilledIn(Intent fillInIntent, int flags)135 public TargetInfo cloneFilledIn(Intent fillInIntent, int flags) { 136 return new DisplayResolveInfo(this, fillInIntent, flags, mResolveInfoPresentationGetter); 137 } 138 139 @Override getAllSourceIntents()140 public List<Intent> getAllSourceIntents() { 141 return mSourceIntents; 142 } 143 addAlternateSourceIntent(Intent alt)144 public void addAlternateSourceIntent(Intent alt) { 145 mSourceIntents.add(alt); 146 } 147 setDisplayIcon(Drawable icon)148 public void setDisplayIcon(Drawable icon) { 149 mDisplayIcon = icon; 150 } 151 hasDisplayIcon()152 public boolean hasDisplayIcon() { 153 return mDisplayIcon != null; 154 } 155 getExtendedInfo()156 public CharSequence getExtendedInfo() { 157 return mExtendedInfo; 158 } 159 getResolvedIntent()160 public Intent getResolvedIntent() { 161 return mResolvedIntent; 162 } 163 164 @Override getResolvedComponentName()165 public ComponentName getResolvedComponentName() { 166 return new ComponentName(mResolveInfo.activityInfo.packageName, 167 mResolveInfo.activityInfo.name); 168 } 169 170 @Override start(Activity activity, Bundle options)171 public boolean start(Activity activity, Bundle options) { 172 activity.startActivity(mResolvedIntent, options); 173 return true; 174 } 175 176 @Override startAsCaller(ResolverActivity activity, Bundle options, int userId)177 public boolean startAsCaller(ResolverActivity activity, Bundle options, int userId) { 178 if (ENABLE_CHOOSER_DELEGATE) { 179 return activity.startAsCallerImpl(mResolvedIntent, options, false, userId); 180 } else { 181 activity.startActivityAsCaller(mResolvedIntent, options, null, false, userId); 182 return true; 183 } 184 } 185 186 @Override startAsUser(Activity activity, Bundle options, UserHandle user)187 public boolean startAsUser(Activity activity, Bundle options, UserHandle user) { 188 activity.startActivityAsUser(mResolvedIntent, options, user); 189 return false; 190 } 191 isSuspended()192 public boolean isSuspended() { 193 return mIsSuspended; 194 } 195 196 @Override isPinned()197 public boolean isPinned() { 198 return mPinned; 199 } 200 setPinned(boolean pinned)201 public void setPinned(boolean pinned) { 202 mPinned = pinned; 203 } 204 205 } 206