1 /* 2 * Copyright (C) 2016 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.dialer.shortcuts; 18 19 import android.annotation.TargetApi; 20 import android.content.pm.ShortcutInfo; 21 import android.net.Uri; 22 import android.os.Build.VERSION_CODES; 23 import android.provider.ContactsContract.Contacts; 24 import android.support.annotation.NonNull; 25 import com.google.auto.value.AutoValue; 26 27 /** 28 * Convenience data structure. 29 * 30 * <p>This differs from {@link ShortcutInfo} in that it doesn't hold an icon or intent, and provides 31 * convenience methods for doing things like constructing labels. 32 */ 33 @TargetApi(VERSION_CODES.N_MR1) // Shortcuts introduced in N MR1 34 @AutoValue 35 abstract class DialerShortcut { 36 37 /** Marker value indicates that shortcut has no setRank. Used by pinned shortcuts. */ 38 static final int NO_RANK = -1; 39 40 /** 41 * Contact ID from contacts provider. Note that this a numeric row ID from the 42 * ContactsContract.Contacts._ID column. 43 */ getContactId()44 abstract long getContactId(); 45 46 /** 47 * Lookup key from contacts provider. An example lookup key is: "0r8-47392D". This is the value 48 * from ContactsContract.Contacts.LOOKUP_KEY. 49 */ 50 @NonNull getLookupKey()51 abstract String getLookupKey(); 52 53 /** Display name from contacts provider. */ 54 @NonNull getDisplayName()55 abstract String getDisplayName(); 56 57 /** 58 * Rank for dynamic shortcuts. This value should be positive or {@link #NO_RANK}. 59 * 60 * <p>For floating shortcuts (pinned shortcuts with no corresponding dynamic shortcut), setRank 61 * has no meaning and the setRank may be set to {@link #NO_RANK}. 62 */ getRank()63 abstract int getRank(); 64 65 /** The short label for the shortcut. Used when pinning shortcuts, for example. */ 66 @NonNull getShortLabel()67 String getShortLabel() { 68 // Be sure to update getDisplayNameFromShortcutInfo when updating this. 69 return getDisplayName(); 70 } 71 72 /** 73 * The long label for the shortcut. Used for shortcuts displayed when pressing and holding the app 74 * launcher icon, for example. 75 */ 76 @NonNull getLongLabel()77 String getLongLabel() { 78 return getDisplayName(); 79 } 80 81 /** The display name for the provided shortcut. */ getDisplayNameFromShortcutInfo(ShortcutInfo shortcutInfo)82 static String getDisplayNameFromShortcutInfo(ShortcutInfo shortcutInfo) { 83 return shortcutInfo.getShortLabel().toString(); 84 } 85 86 /** 87 * The id used to identify launcher shortcuts. Used for updating/deleting shortcuts. 88 * 89 * <p>Lookup keys are used for shortcut IDs. See {@link #getLookupKey()}. 90 * 91 * <p>If you change this, you probably also need to change {@link #getLookupKeyFromShortcutInfo}. 92 */ 93 @NonNull getShortcutId()94 String getShortcutId() { 95 return getLookupKey(); 96 } 97 98 /** 99 * Returns the contact lookup key from the provided {@link ShortcutInfo}. 100 * 101 * <p>Lookup keys are used for shortcut IDs. See {@link #getLookupKey()}. 102 */ 103 @NonNull getLookupKeyFromShortcutInfo(@onNull ShortcutInfo shortcutInfo)104 static String getLookupKeyFromShortcutInfo(@NonNull ShortcutInfo shortcutInfo) { 105 return shortcutInfo.getId(); // Lookup keys are used for shortcut IDs. 106 } 107 108 /** 109 * Returns the lookup URI from the provided {@link ShortcutInfo}. 110 * 111 * <p>Lookup URIs are constructed from lookup key and contact ID. Here is an example lookup URI 112 * where lookup key is "0r8-47392D" and contact ID is 8: 113 * 114 * <p>"content://com.android.contacts/contacts/lookup/0r8-47392D/8" 115 */ 116 @NonNull getLookupUriFromShortcutInfo(@onNull ShortcutInfo shortcutInfo)117 static Uri getLookupUriFromShortcutInfo(@NonNull ShortcutInfo shortcutInfo) { 118 long contactId = 119 shortcutInfo.getIntent().getLongExtra(ShortcutInfoFactory.EXTRA_CONTACT_ID, -1); 120 if (contactId == -1) { 121 throw new IllegalStateException("No contact ID found for shortcut: " + shortcutInfo.getId()); 122 } 123 String lookupKey = getLookupKeyFromShortcutInfo(shortcutInfo); 124 return Contacts.getLookupUri(contactId, lookupKey); 125 } 126 127 /** 128 * Contacts provider URI which uses the contact lookup key. 129 * 130 * <p>Lookup URIs are constructed from lookup key and contact ID. Here is an example lookup URI 131 * where lookup key is "0r8-47392D" and contact ID is 8: 132 * 133 * <p>"content://com.android.contacts/contacts/lookup/0r8-47392D/8" 134 */ 135 @NonNull getLookupUri()136 Uri getLookupUri() { 137 return Contacts.getLookupUri(getContactId(), getLookupKey()); 138 } 139 140 /** 141 * Given an existing shortcut with the same shortcut ID, returns true if the existing shortcut 142 * needs to be updated, e.g. if the contact's name or rank has changed. 143 * 144 * <p>Does not detect photo updates. 145 */ needsUpdate(@onNull ShortcutInfo oldInfo)146 boolean needsUpdate(@NonNull ShortcutInfo oldInfo) { 147 if (this.getRank() != NO_RANK && oldInfo.getRank() != this.getRank()) { 148 return true; 149 } 150 if (!oldInfo.getShortLabel().equals(this.getShortLabel())) { 151 return true; 152 } 153 if (!oldInfo.getLongLabel().equals(this.getLongLabel())) { 154 return true; 155 } 156 return false; 157 } 158 builder()159 static Builder builder() { 160 return new AutoValue_DialerShortcut.Builder().setRank(NO_RANK); 161 } 162 163 @AutoValue.Builder 164 abstract static class Builder { 165 166 /** 167 * Sets the contact ID. This should be a value from the contact provider's Contact._ID column. 168 */ setContactId(long value)169 abstract Builder setContactId(long value); 170 171 /** 172 * Sets the lookup key. This should be a contact lookup key as provided by the contact provider. 173 */ setLookupKey(@onNull String value)174 abstract Builder setLookupKey(@NonNull String value); 175 176 /** Sets the display name. This should be a value provided by the contact provider. */ setDisplayName(@onNull String value)177 abstract Builder setDisplayName(@NonNull String value); 178 179 /** 180 * Sets the rank for the shortcut, used for ordering dynamic shortcuts. This is required for 181 * dynamic shortcuts but unused for floating shortcuts because rank has no meaning for floating 182 * shortcuts. (Floating shortcuts are shortcuts which are pinned but have no corresponding 183 * dynamic shortcut.) 184 */ setRank(int value)185 abstract Builder setRank(int value); 186 187 /** Builds the immutable {@link DialerShortcut} object from this builder. */ build()188 abstract DialerShortcut build(); 189 } 190 } 191