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