[go: nahoru, domu]

blob: a51728f53d02b2e5236481bb640cb2d7377d7e25 [file] [log] [blame]
/**
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.core.content.pm;
import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ShortcutInfo;
import android.content.pm.ShortcutManager;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.PersistableBundle;
import android.os.UserHandle;
import android.text.TextUtils;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.annotation.RestrictTo;
import androidx.annotation.VisibleForTesting;
import androidx.core.app.Person;
import androidx.core.content.LocusIdCompat;
import androidx.core.graphics.drawable.IconCompat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* Helper for accessing features in {@link ShortcutInfo}.
*/
public class ShortcutInfoCompat {
private static final String EXTRA_PERSON_COUNT = "extraPersonCount";
private static final String EXTRA_PERSON_ = "extraPerson_";
private static final String EXTRA_LOCUS_ID = "extraLocusId";
private static final String EXTRA_LONG_LIVED = "extraLongLived";
Context mContext;
String mId;
String mPackageName;
Intent[] mIntents;
ComponentName mActivity;
CharSequence mLabel;
CharSequence mLongLabel;
CharSequence mDisabledMessage;
IconCompat mIcon;
boolean mIsAlwaysBadged;
Person[] mPersons;
Set<String> mCategories;
@Nullable
LocusIdCompat mLocusId;
// TODO: Support |auto| when the value of mIsLongLived is not set
boolean mIsLongLived;
int mRank;
PersistableBundle mExtras;
// Read-Only fields
long mLastChangedTimestamp;
UserHandle mUser;
boolean mIsCached;
boolean mIsDynamic;
boolean mIsPinned;
boolean mIsDeclaredInManifest;
boolean mIsImmutable;
boolean mIsEnabled = true;
boolean mHasKeyFieldsOnly;
int mDisabledReason;
ShortcutInfoCompat() { }
/**
* @return {@link ShortcutInfo} object from this compat object.
*/
@RequiresApi(25)
public ShortcutInfo toShortcutInfo() {
ShortcutInfo.Builder builder = new ShortcutInfo.Builder(mContext, mId)
.setShortLabel(mLabel)
.setIntents(mIntents);
if (mIcon != null) {
builder.setIcon(mIcon.toIcon(mContext));
}
if (!TextUtils.isEmpty(mLongLabel)) {
builder.setLongLabel(mLongLabel);
}
if (!TextUtils.isEmpty(mDisabledMessage)) {
builder.setDisabledMessage(mDisabledMessage);
}
if (mActivity != null) {
builder.setActivity(mActivity);
}
if (mCategories != null) {
builder.setCategories(mCategories);
}
builder.setRank(mRank);
if (mExtras != null) {
builder.setExtras(mExtras);
}
if (Build.VERSION.SDK_INT >= 29) {
if (mPersons != null && mPersons.length > 0) {
android.app.Person[] persons = new android.app.Person[mPersons.length];
for (int i = 0; i < persons.length; i++) {
persons[i] = mPersons[i].toAndroidPerson();
}
builder.setPersons(persons);
}
if (mLocusId != null) {
builder.setLocusId(mLocusId.toLocusId());
}
builder.setLongLived(mIsLongLived);
} else {
// ShortcutInfo.Builder#setPersons(...) and ShortcutInfo.Builder#setLongLived(...) are
// introduced in API 29. On older API versions, we store mPersons and mIsLongLived in
// the extras field of ShortcutInfo for backwards compatibility.
builder.setExtras(buildLegacyExtrasBundle());
}
return builder.build();
}
/**
* @hide
*/
@RequiresApi(22)
@RestrictTo(LIBRARY_GROUP_PREFIX)
private PersistableBundle buildLegacyExtrasBundle() {
if (mExtras == null) {
mExtras = new PersistableBundle();
}
if (mPersons != null && mPersons.length > 0) {
mExtras.putInt(EXTRA_PERSON_COUNT, mPersons.length);
for (int i = 0; i < mPersons.length; i++) {
mExtras.putPersistableBundle(EXTRA_PERSON_ + (i + 1),
mPersons[i].toPersistableBundle());
}
}
if (mLocusId != null) {
mExtras.putString(EXTRA_LOCUS_ID, mLocusId.getId());
}
mExtras.putBoolean(EXTRA_LONG_LIVED, mIsLongLived);
return mExtras;
}
Intent addToIntent(Intent outIntent) {
outIntent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, mIntents[mIntents.length - 1])
.putExtra(Intent.EXTRA_SHORTCUT_NAME, mLabel.toString());
if (mIcon != null) {
Drawable badge = null;
if (mIsAlwaysBadged) {
PackageManager pm = mContext.getPackageManager();
if (mActivity != null) {
try {
badge = pm.getActivityIcon(mActivity);
} catch (PackageManager.NameNotFoundException e) {
// Ignore
}
}
if (badge == null) {
badge = mContext.getApplicationInfo().loadIcon(pm);
}
}
mIcon.addToShortcutIntent(outIntent, badge, mContext);
}
return outIntent;
}
/**
* Returns the ID of a shortcut.
*
* <p>Shortcut IDs are unique within each publisher app and must be stable across
* devices so that shortcuts will still be valid when restored on a different device.
* See {@link android.content.pm.ShortcutManager} for details.
*/
@NonNull
public String getId() {
return mId;
}
/**
* Return the package name of the publisher app.
*/
@NonNull
public String getPackage() {
return mPackageName;
}
/**
* Return the target activity.
*
* <p>This has nothing to do with the activity that this shortcut will launch.
* Launcher apps should show the launcher icon for the returned activity alongside
* this shortcut.
*
* @see Builder#setActivity(ComponentName)
*/
@Nullable
public ComponentName getActivity() {
return mActivity;
}
/**
* Return the short description of a shortcut.
*
* @see Builder#setShortLabel(CharSequence)
*/
@NonNull
public CharSequence getShortLabel() {
return mLabel;
}
/**
* Return the long description of a shortcut.
*
* @see Builder#setLongLabel(CharSequence)
*/
@Nullable
public CharSequence getLongLabel() {
return mLongLabel;
}
/**
* Return the message that should be shown when the user attempts to start a shortcut
* that is disabled.
*
* @see Builder#setDisabledMessage(CharSequence)
*/
@Nullable
public CharSequence getDisabledMessage() {
return mDisabledMessage;
}
/**
* Returns why a shortcut has been disabled.
*/
public int getDisabledReason() {
return mDisabledReason;
}
/**
* Returns the intent that is executed when the user selects this shortcut.
* If setIntents() was used, then return the last intent in the array.
*
* @see Builder#setIntent(Intent)
*/
@NonNull
public Intent getIntent() {
return mIntents[mIntents.length - 1];
}
/**
* Return the intent set with {@link Builder#setIntents(Intent[])}.
*
* @see Builder#setIntents(Intent[])
*/
@NonNull
public Intent[] getIntents() {
return Arrays.copyOf(mIntents, mIntents.length);
}
/**
* Return the categories set with {@link Builder#setCategories(Set)}.
*
* @see Builder#setCategories(Set)
*/
@Nullable
public Set<String> getCategories() {
return mCategories;
}
/**
* Gets the {@link LocusIdCompat} associated with this shortcut.
*
* <p>Used by the device's intelligence services to correlate objects (such as
* {@link androidx.core.app.NotificationCompat} and
* {@link android.view.contentcapture.ContentCaptureContext}) that are correlated.
*/
@Nullable
public LocusIdCompat getLocusId() {
return mLocusId;
}
/**
* Returns the rank of the shortcut set with {@link Builder#setRank(int)}.
*
* @see Builder#setRank(int)
*/
public int getRank() {
return mRank;
}
/**
* @hide
*/
@RestrictTo(LIBRARY_GROUP_PREFIX)
public IconCompat getIcon() {
return mIcon;
}
/**
* @hide
*/
@RequiresApi(25)
@RestrictTo(LIBRARY_GROUP_PREFIX)
@VisibleForTesting
@Nullable
static Person[] getPersonsFromExtra(@NonNull PersistableBundle bundle) {
if (bundle == null || !bundle.containsKey(EXTRA_PERSON_COUNT)) {
return null;
}
int personsLength = bundle.getInt(EXTRA_PERSON_COUNT);
Person[] persons = new Person[personsLength];
for (int i = 0; i < personsLength; i++) {
persons[i] = Person.fromPersistableBundle(
bundle.getPersistableBundle(EXTRA_PERSON_ + (i + 1)));
}
return persons;
}
/**
* @hide
*/
@RequiresApi(25)
@RestrictTo(LIBRARY_GROUP_PREFIX)
@VisibleForTesting
static boolean getLongLivedFromExtra(@Nullable PersistableBundle bundle) {
if (bundle == null || !bundle.containsKey(EXTRA_LONG_LIVED)) {
return false;
}
return bundle.getBoolean(EXTRA_LONG_LIVED);
}
/**
* @hide
*/
@RequiresApi(25)
@RestrictTo(LIBRARY_GROUP_PREFIX)
static List<ShortcutInfoCompat> fromShortcuts(@NonNull final Context context,
@NonNull final List<ShortcutInfo> shortcuts) {
final List<ShortcutInfoCompat> results = new ArrayList<>(shortcuts.size());
for (ShortcutInfo s : shortcuts) {
results.add(new ShortcutInfoCompat.Builder(context, s).build());
}
return results;
}
@Nullable
public PersistableBundle getExtras() {
return mExtras;
}
/**
* {@link UserHandle} on which the publisher created this shortcut.
*/
@Nullable
public UserHandle getUserHandle() {
return mUser;
}
/**
* Last time when any of the fields was updated.
*/
public long getLastChangedTimestamp() {
return mLastChangedTimestamp;
}
/** Return whether a shortcut is cached. */
public boolean isCached() {
return mIsCached;
}
/** Return whether a shortcut is dynamic. */
public boolean isDynamic() {
return mIsDynamic;
}
/** Return whether a shortcut is pinned. */
public boolean isPinned() {
return mIsPinned;
}
/**
* Return whether a shortcut is static; that is, whether a shortcut is
* published from AndroidManifest.xml. If {@code true}, the shortcut is
* also {@link #isImmutable()}.
*
* <p>When an app is upgraded and a shortcut is no longer published from AndroidManifest.xml,
* this will be set to {@code false}. If the shortcut is not pinned, then it'll disappear.
* However, if it's pinned, it will still be visible, {@link #isEnabled()} will be
* {@code false} and {@link #isEnabled()} will be {@code true}.
*/
public boolean isDeclaredInManifest() {
return mIsDeclaredInManifest;
}
/**
* Return if a shortcut is immutable, in which case it cannot be modified with any of
* {@link ShortcutManagerCompat} APIs.
*
* <p>All static shortcuts are immutable. When a static shortcut is pinned and is then
* disabled because it doesn't appear in AndroidManifest.xml for a newer version of the
* app, {@link #isDeclaredInManifest} returns {@code false}, but the shortcut is still
* immutable.
*
* <p>All shortcuts originally published via the {@link ShortcutManager} APIs
* are all mutable.
*/
public boolean isImmutable() {
return mIsImmutable;
}
/**
* Returns {@code false} if a shortcut is disabled with
* {@link ShortcutManagerCompat#disableShortcuts}.
*/
public boolean isEnabled() {
return mIsEnabled;
}
/**
* Return whether a shortcut only contains "key" information only or not. If true, only the
* following fields are available.
* <ul>
* <li>{@link #getId()}
* <li>{@link #getPackage()}
* <li>{@link #getActivity()}
* <li>{@link #getLastChangedTimestamp()}
* <li>{@link #isDynamic()}
* <li>{@link #isPinned()}
* <li>{@link #isDeclaredInManifest()}
* <li>{@link #isImmutable()}
* <li>{@link #isEnabled()}
* <li>{@link #getUserHandle()}
* </ul>
*/
public boolean hasKeyFieldsOnly() {
return mHasKeyFieldsOnly;
}
@RequiresApi(25)
@Nullable
static LocusIdCompat getLocusId(@NonNull final ShortcutInfo shortcutInfo) {
if (Build.VERSION.SDK_INT >= 29) {
if (shortcutInfo.getLocusId() == null) return null;
return LocusIdCompat.toLocusIdCompat(shortcutInfo.getLocusId());
} else {
return getLocusIdFromExtra(shortcutInfo.getExtras());
}
}
/**
* @hide
*/
@RequiresApi(25)
@RestrictTo(LIBRARY_GROUP_PREFIX)
@Nullable
private static LocusIdCompat getLocusIdFromExtra(@Nullable PersistableBundle bundle) {
if (bundle == null) return null;
final String locusId = bundle.getString(EXTRA_LOCUS_ID);
return locusId == null ? null : new LocusIdCompat(locusId);
}
/**
* Builder class for {@link ShortcutInfoCompat} objects.
*/
public static class Builder {
private final ShortcutInfoCompat mInfo;
private boolean mIsConversation;
public Builder(@NonNull Context context, @NonNull String id) {
mInfo = new ShortcutInfoCompat();
mInfo.mContext = context;
mInfo.mId = id;
}
/**
* @hide
*/
@RestrictTo(LIBRARY_GROUP_PREFIX)
public Builder(@NonNull ShortcutInfoCompat shortcutInfo) {
mInfo = new ShortcutInfoCompat();
mInfo.mContext = shortcutInfo.mContext;
mInfo.mId = shortcutInfo.mId;
mInfo.mPackageName = shortcutInfo.mPackageName;
mInfo.mIntents = Arrays.copyOf(shortcutInfo.mIntents, shortcutInfo.mIntents.length);
mInfo.mActivity = shortcutInfo.mActivity;
mInfo.mLabel = shortcutInfo.mLabel;
mInfo.mLongLabel = shortcutInfo.mLongLabel;
mInfo.mDisabledMessage = shortcutInfo.mDisabledMessage;
mInfo.mDisabledReason = shortcutInfo.mDisabledReason;
mInfo.mIcon = shortcutInfo.mIcon;
mInfo.mIsAlwaysBadged = shortcutInfo.mIsAlwaysBadged;
mInfo.mUser = shortcutInfo.mUser;
mInfo.mLastChangedTimestamp = shortcutInfo.mLastChangedTimestamp;
mInfo.mIsCached = shortcutInfo.mIsCached;
mInfo.mIsDynamic = shortcutInfo.mIsDynamic;
mInfo.mIsPinned = shortcutInfo.mIsPinned;
mInfo.mIsDeclaredInManifest = shortcutInfo.mIsDeclaredInManifest;
mInfo.mIsImmutable = shortcutInfo.mIsImmutable;
mInfo.mIsEnabled = shortcutInfo.mIsEnabled;
mInfo.mLocusId = shortcutInfo.mLocusId;
mInfo.mIsLongLived = shortcutInfo.mIsLongLived;
mInfo.mHasKeyFieldsOnly = shortcutInfo.mHasKeyFieldsOnly;
mInfo.mRank = shortcutInfo.mRank;
if (shortcutInfo.mPersons != null) {
mInfo.mPersons = Arrays.copyOf(shortcutInfo.mPersons, shortcutInfo.mPersons.length);
}
if (shortcutInfo.mCategories != null) {
mInfo.mCategories = new HashSet<>(shortcutInfo.mCategories);
}
if (shortcutInfo.mExtras != null) {
mInfo.mExtras = shortcutInfo.mExtras;
}
}
/**
* @hide
*/
@RequiresApi(25)
@RestrictTo(LIBRARY_GROUP_PREFIX)
public Builder(@NonNull Context context, @NonNull ShortcutInfo shortcutInfo) {
mInfo = new ShortcutInfoCompat();
mInfo.mContext = context;
mInfo.mId = shortcutInfo.getId();
mInfo.mPackageName = shortcutInfo.getPackage();
Intent[] intents = shortcutInfo.getIntents();
mInfo.mIntents = Arrays.copyOf(intents, intents.length);
mInfo.mActivity = shortcutInfo.getActivity();
mInfo.mLabel = shortcutInfo.getShortLabel();
mInfo.mLongLabel = shortcutInfo.getLongLabel();
mInfo.mDisabledMessage = shortcutInfo.getDisabledMessage();
if (Build.VERSION.SDK_INT >= 28) {
mInfo.mDisabledReason = shortcutInfo.getDisabledReason();
} else {
mInfo.mDisabledReason = shortcutInfo.isEnabled()
? ShortcutInfo.DISABLED_REASON_NOT_DISABLED
: ShortcutInfo.DISABLED_REASON_UNKNOWN;
}
mInfo.mCategories = shortcutInfo.getCategories();
mInfo.mPersons = ShortcutInfoCompat.getPersonsFromExtra(shortcutInfo.getExtras());
mInfo.mUser = shortcutInfo.getUserHandle();
mInfo.mLastChangedTimestamp = shortcutInfo.getLastChangedTimestamp();
if (Build.VERSION.SDK_INT >= 30) {
mInfo.mIsCached = shortcutInfo.isCached();
}
mInfo.mIsDynamic = shortcutInfo.isDynamic();
mInfo.mIsPinned = shortcutInfo.isPinned();
mInfo.mIsDeclaredInManifest = shortcutInfo.isDeclaredInManifest();
mInfo.mIsImmutable = shortcutInfo.isImmutable();
mInfo.mIsEnabled = shortcutInfo.isEnabled();
mInfo.mHasKeyFieldsOnly = shortcutInfo.hasKeyFieldsOnly();
mInfo.mLocusId = ShortcutInfoCompat.getLocusId(shortcutInfo);
mInfo.mRank = shortcutInfo.getRank();
mInfo.mExtras = shortcutInfo.getExtras();
}
/**
* Sets the short title of a shortcut.
*
* <p>This is a mandatory field when publishing a new shortcut.
*
* <p>This field is intended to be a concise description of a shortcut.
*
* <p>The recommended maximum length is 10 characters.
*/
@NonNull
public Builder setShortLabel(@NonNull CharSequence shortLabel) {
mInfo.mLabel = shortLabel;
return this;
}
/**
* Sets the text of a shortcut.
*
* <p>This field is intended to be more descriptive than the shortcut title. The launcher
* shows this instead of the short title when it has enough space.
*
* <p>The recommend maximum length is 25 characters.
*/
@NonNull
public Builder setLongLabel(@NonNull CharSequence longLabel) {
mInfo.mLongLabel = longLabel;
return this;
}
/**
* Sets the message that should be shown when the user attempts to start a shortcut that
* is disabled.
*
* @see ShortcutInfo#getDisabledMessage()
*/
@NonNull
public Builder setDisabledMessage(@NonNull CharSequence disabledMessage) {
mInfo.mDisabledMessage = disabledMessage;
return this;
}
/**
* Sets the intent of a shortcut. Alternatively, {@link #setIntents(Intent[])} can be used
* to launch an activity with other activities in the back stack.
*
* <p>This is a mandatory field when publishing a new shortcut.
*
* <p>The given {@code intent} can contain extras, but these extras must contain values
* of primitive types in order for the system to persist these values.
*/
@NonNull
public Builder setIntent(@NonNull Intent intent) {
return setIntents(new Intent[]{intent});
}
/**
* Sets multiple intents instead of a single intent, in order to launch an activity with
* other activities in back stack. Use {@link android.app.TaskStackBuilder} to build
* intents. The last element in the list represents the only intent that doesn't place
* an activity on the back stack.
*/
@NonNull
public Builder setIntents(@NonNull Intent[] intents) {
mInfo.mIntents = intents;
return this;
}
/**
* Sets an icon of a shortcut.
*/
@NonNull
public Builder setIcon(IconCompat icon) {
mInfo.mIcon = icon;
return this;
}
/**
* Sets the {@link LocusIdCompat} associated with this shortcut.
*
* <p>This method should be called when the {@link LocusIdCompat} is used in other places
* (such as {@link androidx.core.app.NotificationCompat} and
* {@link android.view.contentcapture.ContentCaptureContext}) so the device's intelligence
* services can correlate them.
*/
@NonNull
public Builder setLocusId(@Nullable final LocusIdCompat locusId) {
mInfo.mLocusId = locusId;
return this;
}
/**
* Sets the corresponding fields indicating this shortcut is aimed for conversation.
*
* <p>
* If the shortcut is not associated with a {@link LocusIdCompat}, a {@link LocusIdCompat}
* based on {@link ShortcutInfoCompat#getId()} will be added upon {@link #build()}
* <p>
* Additionally, the shortcut will be long-lived.
* @see #setLongLived(boolean)
*/
@NonNull
public Builder setIsConversation() {
mIsConversation = true;
return this;
}
/**
* Sets the target activity. A shortcut will be shown along with this activity's icon
* on the launcher.
*
* @see ShortcutInfo#getActivity()
* @see ShortcutInfo.Builder#setActivity(ComponentName)
*/
@NonNull
public Builder setActivity(@NonNull ComponentName activity) {
mInfo.mActivity = activity;
return this;
}
/**
* Badges the icon before passing it over to the Launcher.
* <p>
* Launcher automatically badges {@link ShortcutInfo}, so only the legacy shortcut icon,
* {@link Intent.ShortcutIconResource} is badged. This field is ignored when using
* {@link ShortcutInfo} on API 25 and above.
* <p>
* If the shortcut is associated with an activity, the activity icon is used as the badge,
* otherwise application icon is used.
*
* @see #setActivity(ComponentName)
*/
@NonNull
public Builder setAlwaysBadged() {
mInfo.mIsAlwaysBadged = true;
return this;
}
/**
* Associate a person to a shortcut. Alternatively, {@link #setPersons(Person[])} can be
* used to add multiple persons to a shortcut.
*
* <p>This is an optional field when publishing a new shortcut.
*
* @see Person
*/
@NonNull
public Builder setPerson(@NonNull Person person) {
return setPersons(new Person[]{person});
}
/**
* Sets multiple persons instead of a single person.
*/
@NonNull
public Builder setPersons(@NonNull Person[] persons) {
mInfo.mPersons = persons;
return this;
}
/**
* Sets categories for a shortcut. Launcher apps may use this information to categorize
* shortcuts.
*
* @see ShortcutInfo#getCategories()
*/
@NonNull
public Builder setCategories(@NonNull Set<String> categories) {
mInfo.mCategories = categories;
return this;
}
/**
* @deprecated Use {@ink #setLongLived(boolean)) instead.
*/
@Deprecated
@NonNull
public Builder setLongLived() {
mInfo.mIsLongLived = true;
return this;
}
/**
* Sets if a shortcut would be valid even if it has been unpublished/invisible by the app
* (as a dynamic or pinned shortcut). If it is long lived, it can be cached by various
* system services even after it has been unpublished as a dynamic shortcut.
*/
@NonNull
public Builder setLongLived(boolean longLived) {
mInfo.mIsLongLived = longLived;
return this;
}
/**
* Sets rank of a shortcut, which is a non-negative value that's used by the system to sort
* shortcuts. Lower value means higher importance.
*
* @see ShortcutInfo#getRank() for details.
*/
@NonNull
public Builder setRank(int rank) {
mInfo.mRank = rank;
return this;
}
/**
* Extras that the app can set for any purpose.
*
* <p>Apps can store arbitrary shortcut metadata in extras and retrieve the
* metadata later using {@link ShortcutInfo#getExtras()}.
*
* @see ShortcutInfo#getExtras
*/
@NonNull
public Builder setExtras(@NonNull PersistableBundle extras) {
mInfo.mExtras = extras;
return this;
}
/**
* Creates a {@link ShortcutInfoCompat} instance.
*/
@NonNull
public ShortcutInfoCompat build() {
// Verify the arguments
if (TextUtils.isEmpty(mInfo.mLabel)) {
throw new IllegalArgumentException("Shortcut must have a non-empty label");
}
if (mInfo.mIntents == null || mInfo.mIntents.length == 0) {
throw new IllegalArgumentException("Shortcut must have an intent");
}
if (mIsConversation) {
if (mInfo.mLocusId == null) {
mInfo.mLocusId = new LocusIdCompat(mInfo.mId);
}
mInfo.mIsLongLived = true;
}
return mInfo;
}
}
}