1 /* 2 * Copyright (C) 2021 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.systemui.people.widget; 18 19 import static com.android.systemui.people.PeopleSpaceUtils.EMPTY_STRING; 20 import static com.android.systemui.people.PeopleSpaceUtils.INVALID_USER_ID; 21 22 import android.app.people.PeopleSpaceTile; 23 import android.text.TextUtils; 24 25 import com.android.systemui.statusbar.notification.collection.NotificationEntry; 26 27 import java.util.Objects; 28 import java.util.regex.Matcher; 29 import java.util.regex.Pattern; 30 31 /** Class that encapsulates fields identifying a Conversation. */ 32 public class PeopleTileKey { 33 private String mShortcutId; 34 private int mUserId; 35 private String mPackageName; 36 37 private static final Pattern KEY_PATTERN = Pattern.compile("(.+)/(-?\\d+)/(\\p{L}.*)"); 38 PeopleTileKey(String shortcutId, int userId, String packageName)39 public PeopleTileKey(String shortcutId, int userId, String packageName) { 40 mShortcutId = shortcutId; 41 mUserId = userId; 42 mPackageName = packageName; 43 } 44 PeopleTileKey(PeopleSpaceTile tile)45 public PeopleTileKey(PeopleSpaceTile tile) { 46 mShortcutId = tile.getId(); 47 mUserId = tile.getUserHandle().getIdentifier(); 48 mPackageName = tile.getPackageName(); 49 } 50 PeopleTileKey(NotificationEntry entry)51 public PeopleTileKey(NotificationEntry entry) { 52 mShortcutId = entry.getRanking() != null 53 && entry.getRanking().getConversationShortcutInfo() != null 54 ? entry.getRanking().getConversationShortcutInfo().getId() 55 : EMPTY_STRING; 56 mUserId = entry.getSbn().getUser() != null 57 ? entry.getSbn().getUser().getIdentifier() : INVALID_USER_ID; 58 mPackageName = entry.getSbn().getPackageName(); 59 } 60 getShortcutId()61 public String getShortcutId() { 62 return mShortcutId; 63 } 64 getUserId()65 public int getUserId() { 66 return mUserId; 67 } 68 getPackageName()69 public String getPackageName() { 70 return mPackageName; 71 } 72 setUserId(int userId)73 public void setUserId(int userId) { 74 mUserId = userId; 75 } 76 77 /** Returns whether PeopleTileKey is valid/well-formed. */ validate()78 private boolean validate() { 79 return !TextUtils.isEmpty(mShortcutId) && !TextUtils.isEmpty(mPackageName) && mUserId >= 0; 80 } 81 82 /** 83 * Returns the uniquely identifying key for the conversation. 84 * 85 * <p>{@code userId} will always be a number, so we put user ID as the 86 * delimiter between the app-provided strings of shortcut ID and package name. 87 * 88 * <p>There aren't restrictions on shortcut ID characters, but there are restrictions requiring 89 * a {@code packageName} to always start with a letter. This restriction means we are 90 * guaranteed to avoid cases like "a/b/0/0/package.name" having two potential keys, as the first 91 * case is impossible given the package name restrictions: 92 * <ul> 93 * <li>"a/b" + "/" + 0 + "/" + "0/packageName"</li> 94 * <li>"a/b/0" + "/" + 0 + "/" + "packageName"</li> 95 * </ul> 96 */ 97 @Override toString()98 public String toString() { 99 return mShortcutId + "/" + mUserId + "/" + mPackageName; 100 } 101 102 /** Parses {@code key} into a {@link PeopleTileKey}. */ fromString(String key)103 public static PeopleTileKey fromString(String key) { 104 if (key == null) { 105 return null; 106 } 107 Matcher m = KEY_PATTERN.matcher(key); 108 if (m.find()) { 109 try { 110 int userId = Integer.parseInt(m.group(2)); 111 return new PeopleTileKey(m.group(1), userId, m.group(3)); 112 } catch (NumberFormatException e) { 113 return null; 114 } 115 } 116 return null; 117 } 118 119 /** Returns whether {@code key} is a valid {@link PeopleTileKey}. */ isValid(PeopleTileKey key)120 public static boolean isValid(PeopleTileKey key) { 121 return key != null && key.validate(); 122 } 123 124 @Override equals(Object other)125 public boolean equals(Object other) { 126 if (this == other) { 127 return true; 128 } 129 if (!(other instanceof PeopleTileKey)) { 130 return false; 131 } 132 final PeopleTileKey o = (PeopleTileKey) other; 133 return Objects.equals(o.toString(), this.toString()); 134 } 135 136 @Override hashCode()137 public int hashCode() { 138 return mPackageName.hashCode() + Integer.valueOf(mUserId).hashCode() 139 + mShortcutId.hashCode(); 140 } 141 } 142