1 /* 2 * Copyright (C) 2014 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 android.telecom; 18 19 import android.annotation.Nullable; 20 import android.annotation.SystemApi; 21 import android.content.ComponentName; 22 import android.content.Context; 23 import android.graphics.drawable.Drawable; 24 import android.graphics.drawable.Icon; 25 import android.os.Binder; 26 import android.os.Bundle; 27 import android.os.Parcel; 28 import android.os.Parcelable; 29 import android.os.UserHandle; 30 31 import com.android.internal.annotations.VisibleForTesting; 32 33 import java.util.Objects; 34 35 /** 36 * Contains status label and icon displayed in the in-call UI. 37 */ 38 public final class StatusHints implements Parcelable { 39 40 private final CharSequence mLabel; 41 private Icon mIcon; 42 private final Bundle mExtras; 43 44 /** 45 * @hide 46 */ 47 @SystemApi @Deprecated StatusHints(ComponentName packageName, CharSequence label, int iconResId, Bundle extras)48 public StatusHints(ComponentName packageName, CharSequence label, int iconResId, 49 Bundle extras) { 50 this(label, iconResId == 0 ? null : Icon.createWithResource(packageName.getPackageName(), 51 iconResId), extras); 52 } 53 StatusHints(CharSequence label, Icon icon, Bundle extras)54 public StatusHints(CharSequence label, Icon icon, Bundle extras) { 55 mLabel = label; 56 mIcon = validateAccountIconUserBoundary(icon, Binder.getCallingUserHandle()); 57 mExtras = extras; 58 } 59 60 /** 61 * @param icon 62 * @hide 63 */ 64 @VisibleForTesting StatusHints(@ullable Icon icon)65 public StatusHints(@Nullable Icon icon) { 66 mLabel = null; 67 mExtras = null; 68 mIcon = icon; 69 } 70 71 /** 72 * 73 * @param icon 74 * @hide 75 */ setIcon(@ullable Icon icon)76 public void setIcon(@Nullable Icon icon) { 77 mIcon = icon; 78 } 79 80 /** 81 * @return A package used to load the icon. 82 * 83 * @hide 84 */ 85 @SystemApi @Deprecated getPackageName()86 public ComponentName getPackageName() { 87 // Minimal compatibility shim for legacy apps' tests 88 return new ComponentName("", ""); 89 } 90 91 /** 92 * @return The label displayed in the in-call UI. 93 */ getLabel()94 public CharSequence getLabel() { 95 return mLabel; 96 } 97 98 /** 99 * The icon resource ID for the icon to show. 100 * 101 * @return A resource ID. 102 * 103 * @hide 104 */ 105 @SystemApi @Deprecated getIconResId()106 public int getIconResId() { 107 // Minimal compatibility shim for legacy apps' tests 108 return 0; 109 } 110 111 /** 112 * @return An icon displayed in the in-call UI. 113 * 114 * @hide 115 */ 116 @SystemApi @Deprecated getIcon(Context context)117 public Drawable getIcon(Context context) { 118 return mIcon.loadDrawable(context); 119 } 120 121 /** 122 * @return An icon depicting the status. 123 */ getIcon()124 public Icon getIcon() { 125 return mIcon; 126 } 127 128 /** 129 * @return Extra data used to display status. 130 */ getExtras()131 public Bundle getExtras() { 132 return mExtras; 133 } 134 135 @Override describeContents()136 public int describeContents() { 137 return 0; 138 } 139 140 /** 141 * Validates the StatusHints image icon to see if it's not in the calling user space. 142 * Invalidates the icon if so, otherwise returns back the original icon. 143 * 144 * @param icon 145 * @return icon (validated) 146 * @hide 147 */ validateAccountIconUserBoundary(Icon icon, UserHandle callingUserHandle)148 public static Icon validateAccountIconUserBoundary(Icon icon, UserHandle callingUserHandle) { 149 // Refer to Icon#getUriString for context. The URI string is invalid for icons of 150 // incompatible types. 151 if (icon != null && (icon.getType() == Icon.TYPE_URI 152 || icon.getType() == Icon.TYPE_URI_ADAPTIVE_BITMAP)) { 153 String encodedUser = icon.getUri().getEncodedUserInfo(); 154 // If there is no encoded user, the URI is calling into the calling user space 155 if (encodedUser != null) { 156 int userId = Integer.parseInt(encodedUser); 157 // Do not try to save the icon if the user id isn't in the calling user space. 158 if (userId != callingUserHandle.getIdentifier()) return null; 159 } 160 } 161 return icon; 162 } 163 164 @Override writeToParcel(Parcel out, int flags)165 public void writeToParcel(Parcel out, int flags) { 166 out.writeCharSequence(mLabel); 167 out.writeParcelable(mIcon, 0); 168 out.writeParcelable(mExtras, 0); 169 } 170 171 public static final @android.annotation.NonNull Creator<StatusHints> CREATOR 172 = new Creator<StatusHints>() { 173 public StatusHints createFromParcel(Parcel in) { 174 return new StatusHints(in); 175 } 176 177 public StatusHints[] newArray(int size) { 178 return new StatusHints[size]; 179 } 180 }; 181 StatusHints(Parcel in)182 private StatusHints(Parcel in) { 183 mLabel = in.readCharSequence(); 184 mIcon = in.readParcelable(getClass().getClassLoader(), android.graphics.drawable.Icon.class); 185 mExtras = in.readParcelable(getClass().getClassLoader(), android.os.Bundle.class); 186 } 187 188 @Override equals(Object other)189 public boolean equals(Object other) { 190 if (other != null && other instanceof StatusHints) { 191 StatusHints otherHints = (StatusHints) other; 192 return Objects.equals(otherHints.getLabel(), getLabel()) && 193 Objects.equals(otherHints.getIcon(), getIcon()) && 194 Objects.equals(otherHints.getExtras(), getExtras()); 195 } 196 return false; 197 } 198 199 @Override hashCode()200 public int hashCode() { 201 return Objects.hashCode(mLabel) + Objects.hashCode(mIcon) + Objects.hashCode(mExtras); 202 } 203 } 204