Automatic sources dropoff on 2020-06-10 18:32:38.095721

The change is generated with prebuilt drop tool.

Change-Id: I24cbf6ba6db262a1ae1445db1427a08fee35b3b4
diff --git a/android/app/prediction/AppPredictionContext.java b/android/app/prediction/AppPredictionContext.java
new file mode 100644
index 0000000..d14238b
--- /dev/null
+++ b/android/app/prediction/AppPredictionContext.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2018 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 android.app.prediction;
+
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
+import android.content.Context;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Class that provides contextual information about the environment in which the app prediction is
+ * used, such as package name, UI in which the app targets are shown, and number of targets.
+ *
+ * @hide
+ */
+@SystemApi
+@TestApi
+public final class AppPredictionContext implements Parcelable {
+
+    private final int mPredictedTargetCount;
+    @NonNull
+    private final String mUiSurface;
+    @NonNull
+    private final String mPackageName;
+    @Nullable
+    private final Bundle mExtras;
+
+    private AppPredictionContext(@NonNull String uiSurface, int numPredictedTargets,
+            @NonNull String packageName, @Nullable Bundle extras) {
+        mUiSurface = uiSurface;
+        mPredictedTargetCount = numPredictedTargets;
+        mPackageName = packageName;
+        mExtras = extras;
+    }
+
+    private AppPredictionContext(@NonNull Parcel parcel) {
+        mUiSurface = parcel.readString();
+        mPredictedTargetCount = parcel.readInt();
+        mPackageName = parcel.readString();
+        mExtras = parcel.readBundle();
+    }
+
+    /**
+     * Returns the UI surface of the prediction context.
+     */
+    @NonNull
+    public String getUiSurface() {
+        return mUiSurface;
+    }
+
+    /**
+     * Returns the predicted target count
+     */
+    public @IntRange(from = 0) int getPredictedTargetCount() {
+        return mPredictedTargetCount;
+    }
+
+    /**
+     * Returns the package name of the prediction context.
+     */
+    @NonNull
+    public String getPackageName() {
+        return mPackageName;
+    }
+
+    /**
+     * Returns the extras of the prediction context.
+     */
+    @Nullable
+    public Bundle getExtras() {
+        return mExtras;
+    }
+
+    @Override
+    public boolean equals(@Nullable Object o) {
+        if (o == this) return true;
+        if (!getClass().equals(o != null ? o.getClass() : null)) return false;
+
+        AppPredictionContext other = (AppPredictionContext) o;
+        return mPredictedTargetCount == other.mPredictedTargetCount
+                && mUiSurface.equals(other.mUiSurface)
+                && mPackageName.equals(other.mPackageName);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeString(mUiSurface);
+        dest.writeInt(mPredictedTargetCount);
+        dest.writeString(mPackageName);
+        dest.writeBundle(mExtras);
+    }
+
+    public static final @android.annotation.NonNull Parcelable.Creator<AppPredictionContext> CREATOR =
+            new Parcelable.Creator<AppPredictionContext>() {
+                public AppPredictionContext createFromParcel(Parcel parcel) {
+                    return new AppPredictionContext(parcel);
+                }
+
+                public AppPredictionContext[] newArray(int size) {
+                    return new AppPredictionContext[size];
+                }
+            };
+
+    /**
+     * A builder for app prediction contexts.
+     * @hide
+     */
+    @SystemApi
+    @TestApi
+    public static final class Builder {
+
+        @NonNull
+        private final String mPackageName;
+
+        private int mPredictedTargetCount;
+        @Nullable
+        private String mUiSurface;
+        @Nullable
+        private Bundle mExtras;
+
+        /**
+         * @param context The {@link Context} of the prediction client.
+         *
+         * @hide
+         */
+        @SystemApi
+        @TestApi
+        public Builder(@NonNull Context context) {
+            mPackageName = context.getPackageName();
+        }
+
+
+        /**
+         * Sets the number of prediction targets as a hint.
+         */
+        @NonNull
+        public Builder setPredictedTargetCount(@IntRange(from = 0) int predictedTargetCount) {
+            mPredictedTargetCount = predictedTargetCount;
+            return this;
+        }
+
+        /**
+         * Sets the UI surface.
+         */
+        @NonNull
+        public Builder setUiSurface(@NonNull String uiSurface) {
+            mUiSurface = uiSurface;
+            return this;
+        }
+
+        /**
+         * Sets the extras.
+         */
+        @NonNull
+        public Builder setExtras(@Nullable Bundle extras) {
+            mExtras = extras;
+            return this;
+        }
+
+        /**
+         * Builds a new context instance.
+         */
+        @NonNull
+        public AppPredictionContext build() {
+            return new AppPredictionContext(mUiSurface, mPredictedTargetCount, mPackageName,
+                    mExtras);
+        }
+    }
+}
diff --git a/android/app/prediction/AppPredictionManager.java b/android/app/prediction/AppPredictionManager.java
new file mode 100644
index 0000000..ca22721
--- /dev/null
+++ b/android/app/prediction/AppPredictionManager.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2018 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 android.app.prediction;
+
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
+import android.content.Context;
+
+import java.util.Objects;
+
+/**
+ * Class that provides methods to create prediction clients.
+ *
+ * @hide
+ */
+@SystemApi
+@TestApi
+public final class AppPredictionManager {
+
+    private final Context mContext;
+
+    /**
+     * @hide
+     */
+    public AppPredictionManager(Context context) {
+        mContext = Objects.requireNonNull(context);
+    }
+
+    /**
+     * Creates a new app prediction session.
+     */
+    @NonNull
+    public AppPredictor createAppPredictionSession(
+            @NonNull AppPredictionContext predictionContext) {
+        return new AppPredictor(mContext, predictionContext);
+    }
+}
diff --git a/android/app/prediction/AppPredictionSessionId.java b/android/app/prediction/AppPredictionSessionId.java
new file mode 100644
index 0000000..876bafd
--- /dev/null
+++ b/android/app/prediction/AppPredictionSessionId.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2018 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 android.app.prediction;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * The id for an app prediction session. See {@link AppPredictor}.
+ *
+ * @hide
+ */
+@SystemApi
+@TestApi
+public final class AppPredictionSessionId implements Parcelable {
+
+    private final String mId;
+    private final int mUserId;
+
+    /**
+     * Creates a new id for a prediction session.
+     *
+     * @hide
+     */
+    public AppPredictionSessionId(@NonNull final String id, final int userId) {
+        mId = id;
+        mUserId = userId;
+    }
+
+    private AppPredictionSessionId(Parcel p) {
+        mId = p.readString();
+        mUserId = p.readInt();
+    }
+
+    /**
+     * @hide
+     */
+    public int getUserId() {
+        return mUserId;
+    }
+
+    @Override
+    public boolean equals(@Nullable Object o) {
+        if (!getClass().equals(o != null ? o.getClass() : null)) return false;
+
+        AppPredictionSessionId other = (AppPredictionSessionId) o;
+        return mId.equals(other.mId) && mUserId == other.mUserId;
+    }
+
+    @Override
+    public @NonNull String toString() {
+        return mId + "," + mUserId;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mId, mUserId);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeString(mId);
+        dest.writeInt(mUserId);
+    }
+
+    public static final @android.annotation.NonNull Parcelable.Creator<AppPredictionSessionId> CREATOR =
+            new Parcelable.Creator<AppPredictionSessionId>() {
+                public AppPredictionSessionId createFromParcel(Parcel parcel) {
+                    return new AppPredictionSessionId(parcel);
+                }
+
+                public AppPredictionSessionId[] newArray(int size) {
+                    return new AppPredictionSessionId[size];
+                }
+            };
+}
diff --git a/android/app/prediction/AppPredictor.java b/android/app/prediction/AppPredictor.java
new file mode 100644
index 0000000..7f43640
--- /dev/null
+++ b/android/app/prediction/AppPredictor.java
@@ -0,0 +1,326 @@
+/*
+ * Copyright (C) 2018 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 android.app.prediction;
+
+import android.annotation.CallbackExecutor;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
+import android.app.prediction.IPredictionCallback.Stub;
+import android.content.Context;
+import android.content.pm.ParceledListSlice;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.ArrayMap;
+import android.util.Log;
+
+import dalvik.system.CloseGuard;
+
+import java.util.List;
+import java.util.UUID;
+import java.util.concurrent.Executor;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.Consumer;
+
+/**
+ * Class that represents an App Prediction client.
+ *
+ * <p>
+ * Usage: <pre> {@code
+ *
+ * class MyActivity {
+ *    private AppPredictor mClient
+ *
+ *    void onCreate() {
+ *         mClient = new AppPredictor(...)
+ *         mClient.registerPredictionUpdates(...)
+ *    }
+ *
+ *    void onStart() {
+ *        mClient.requestPredictionUpdate()
+ *    }
+ *
+ *    void onClick(...) {
+ *        mClient.notifyAppTargetEvent(...)
+ *    }
+ *
+ *    void onDestroy() {
+ *        mClient.unregisterPredictionUpdates()
+ *        mClient.close()
+ *    }
+ *
+ * }</pre>
+ *
+ * @hide
+ */
+@SystemApi
+@TestApi
+public final class AppPredictor {
+
+    private static final String TAG = AppPredictor.class.getSimpleName();
+
+
+    private final IPredictionManager mPredictionManager;
+    private final CloseGuard mCloseGuard = CloseGuard.get();
+    private final AtomicBoolean mIsClosed = new AtomicBoolean(false);
+
+    private final AppPredictionSessionId mSessionId;
+    private final ArrayMap<Callback, CallbackWrapper> mRegisteredCallbacks = new ArrayMap<>();
+
+    /**
+     * Creates a new Prediction client.
+     * <p>
+     * The caller should call {@link AppPredictor#destroy()} to dispose the client once it
+     * no longer used.
+     *
+     * @param context The {@link Context} of the user of this {@link AppPredictor}.
+     * @param predictionContext The prediction context.
+     */
+    AppPredictor(@NonNull Context context, @NonNull AppPredictionContext predictionContext) {
+        IBinder b = ServiceManager.getService(Context.APP_PREDICTION_SERVICE);
+        mPredictionManager = IPredictionManager.Stub.asInterface(b);
+        mSessionId = new AppPredictionSessionId(
+                context.getPackageName() + ":" + UUID.randomUUID().toString(), context.getUserId());
+        try {
+            mPredictionManager.createPredictionSession(predictionContext, mSessionId);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to create predictor", e);
+            e.rethrowAsRuntimeException();
+        }
+
+        mCloseGuard.open("close");
+    }
+
+    /**
+     * Notifies the prediction service of an app target event.
+     *
+     * @param event The {@link AppTargetEvent} that represents the app target event.
+     */
+    public void notifyAppTargetEvent(@NonNull AppTargetEvent event) {
+        if (mIsClosed.get()) {
+            throw new IllegalStateException("This client has already been destroyed.");
+        }
+
+        try {
+            mPredictionManager.notifyAppTargetEvent(mSessionId, event);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to notify app target event", e);
+            e.rethrowAsRuntimeException();
+        }
+    }
+
+    /**
+     * Notifies the prediction service when the targets in a launch location are shown to the user.
+     *
+     * @param launchLocation The launch location where the targets are shown to the user.
+     * @param targetIds List of {@link AppTargetId}s that are shown to the user.
+     */
+    public void notifyLaunchLocationShown(@NonNull String launchLocation,
+            @NonNull List<AppTargetId> targetIds) {
+        if (mIsClosed.get()) {
+            throw new IllegalStateException("This client has already been destroyed.");
+        }
+
+        try {
+            mPredictionManager.notifyLaunchLocationShown(mSessionId, launchLocation,
+                    new ParceledListSlice<>(targetIds));
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to notify location shown event", e);
+            e.rethrowAsRuntimeException();
+        }
+    }
+
+    /**
+     * Requests the prediction service provide continuous updates of App predictions via the
+     * provided callback, until the given callback is unregistered.
+     *
+     * @see Callback#onTargetsAvailable(List).
+     *
+     * @param callbackExecutor The callback executor to use when calling the callback.
+     * @param callback The Callback to be called when updates of App predictions are available.
+     */
+    public void registerPredictionUpdates(@NonNull @CallbackExecutor Executor callbackExecutor,
+            @NonNull AppPredictor.Callback callback) {
+        if (mIsClosed.get()) {
+            throw new IllegalStateException("This client has already been destroyed.");
+        }
+
+        if (mRegisteredCallbacks.containsKey(callback)) {
+            // Skip if this callback is already registered
+            return;
+        }
+        try {
+            final CallbackWrapper callbackWrapper = new CallbackWrapper(callbackExecutor,
+                    callback::onTargetsAvailable);
+            mPredictionManager.registerPredictionUpdates(mSessionId, callbackWrapper);
+            mRegisteredCallbacks.put(callback, callbackWrapper);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to register for prediction updates", e);
+            e.rethrowAsRuntimeException();
+        }
+    }
+
+    /**
+     * Requests the prediction service to stop providing continuous updates to the provided
+     * callback until the callback is re-registered.
+     *
+     * @see {@link AppPredictor#registerPredictionUpdates(Executor, Callback)}.
+     *
+     * @param callback The callback to be unregistered.
+     */
+    public void unregisterPredictionUpdates(@NonNull AppPredictor.Callback callback) {
+        if (mIsClosed.get()) {
+            throw new IllegalStateException("This client has already been destroyed.");
+        }
+
+        if (!mRegisteredCallbacks.containsKey(callback)) {
+            // Skip if this callback was never registered
+            return;
+        }
+        try {
+            final CallbackWrapper callbackWrapper = mRegisteredCallbacks.remove(callback);
+            mPredictionManager.unregisterPredictionUpdates(mSessionId, callbackWrapper);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to unregister for prediction updates", e);
+            e.rethrowAsRuntimeException();
+        }
+    }
+
+    /**
+     * Requests the prediction service to dispatch a new set of App predictions via the provided
+     * callback.
+     *
+     * @see Callback#onTargetsAvailable(List).
+     */
+    public void requestPredictionUpdate() {
+        if (mIsClosed.get()) {
+            throw new IllegalStateException("This client has already been destroyed.");
+        }
+
+        try {
+            mPredictionManager.requestPredictionUpdate(mSessionId);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to request prediction update", e);
+            e.rethrowAsRuntimeException();
+        }
+    }
+
+    /**
+     * Returns a new list of AppTargets sorted based on prediction rank or {@code null} if the
+     * ranker is not available.
+     *
+     * @param targets List of app targets to be sorted.
+     * @param callbackExecutor The callback executor to use when calling the callback.
+     * @param callback The callback to return the sorted list of app targets.
+     */
+    @Nullable
+    public void sortTargets(@NonNull List<AppTarget> targets,
+            @NonNull Executor callbackExecutor, @NonNull Consumer<List<AppTarget>> callback) {
+        if (mIsClosed.get()) {
+            throw new IllegalStateException("This client has already been destroyed.");
+        }
+
+        try {
+            mPredictionManager.sortAppTargets(mSessionId, new ParceledListSlice(targets),
+                    new CallbackWrapper(callbackExecutor, callback));
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to sort targets", e);
+            e.rethrowAsRuntimeException();
+        }
+    }
+
+    /**
+     * Destroys the client and unregisters the callback. Any method on this class after this call
+     * with throw {@link IllegalStateException}.
+     */
+    public void destroy() {
+        if (!mIsClosed.getAndSet(true)) {
+            mCloseGuard.close();
+
+            // Do destroy;
+            try {
+                mPredictionManager.onDestroyPredictionSession(mSessionId);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Failed to notify app target event", e);
+                e.rethrowAsRuntimeException();
+            }
+            mRegisteredCallbacks.clear();
+        } else {
+            throw new IllegalStateException("This client has already been destroyed.");
+        }
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        try {
+            if (mCloseGuard != null) {
+                mCloseGuard.warnIfOpen();
+            }
+            if (!mIsClosed.get()) {
+                destroy();
+            }
+        } finally {
+            super.finalize();
+        }
+    }
+
+    /**
+     * Returns the id of this prediction session.
+     *
+     * @hide
+     */
+    @TestApi
+    public AppPredictionSessionId getSessionId() {
+        return mSessionId;
+    }
+
+    /**
+     * Callback for receiving prediction updates.
+     */
+    public interface Callback {
+
+        /**
+         * Called when a new set of predicted app targets are available.
+         * @param targets Sorted list of predicted targets.
+         */
+        void onTargetsAvailable(@NonNull List<AppTarget> targets);
+    }
+
+    static class CallbackWrapper extends Stub {
+
+        private final Consumer<List<AppTarget>> mCallback;
+        private final Executor mExecutor;
+
+        CallbackWrapper(@NonNull Executor callbackExecutor,
+                @NonNull Consumer<List<AppTarget>> callback) {
+            mCallback = callback;
+            mExecutor = callbackExecutor;
+        }
+
+        @Override
+        public void onResult(ParceledListSlice result) {
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                mExecutor.execute(() -> mCallback.accept(result.getList()));
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+    }
+}
diff --git a/android/app/prediction/AppTarget.java b/android/app/prediction/AppTarget.java
new file mode 100644
index 0000000..14e32b8
--- /dev/null
+++ b/android/app/prediction/AppTarget.java
@@ -0,0 +1,320 @@
+/*
+ * Copyright (C) 2018 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 android.app.prediction;
+
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
+import android.content.pm.ShortcutInfo;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.UserHandle;
+
+import java.util.Objects;
+
+/**
+ * A representation of a launchable target.
+ *
+ * @hide
+ */
+@SystemApi
+@TestApi
+public final class AppTarget implements Parcelable {
+
+    private final AppTargetId mId;
+    private final String mPackageName;
+    private final String mClassName;
+    private final UserHandle mUser;
+
+    private final ShortcutInfo mShortcutInfo;
+
+    private final int mRank;
+
+    /**
+     * @deprecated use the Builder class
+     * @hide
+     */
+    @Deprecated
+    public AppTarget(@NonNull AppTargetId id, @NonNull String packageName,
+            @Nullable String className, @NonNull UserHandle user) {
+        mId = id;
+        mShortcutInfo = null;
+
+        mPackageName = Objects.requireNonNull(packageName);
+        mClassName = className;
+        mUser = Objects.requireNonNull(user);
+        mRank = 0;
+    }
+
+    /**
+     * @deprecated use the Builder class
+     * @hide
+     */
+    @Deprecated
+    public AppTarget(@NonNull AppTargetId id, @NonNull ShortcutInfo shortcutInfo,
+            @Nullable String className) {
+        mId = id;
+        mShortcutInfo = Objects.requireNonNull(shortcutInfo);
+
+        mPackageName = mShortcutInfo.getPackage();
+        mUser = mShortcutInfo.getUserHandle();
+        mClassName = className;
+        mRank = 0;
+    }
+
+    private AppTarget(AppTargetId id, String packageName, UserHandle user,
+            ShortcutInfo shortcutInfo, String className, int rank) {
+        mId = id;
+        mShortcutInfo = shortcutInfo;
+        mPackageName = packageName;
+        mClassName = className;
+        mUser = user;
+        mRank = rank;
+    }
+
+    private AppTarget(Parcel parcel) {
+        mId = parcel.readTypedObject(AppTargetId.CREATOR);
+        mShortcutInfo = parcel.readTypedObject(ShortcutInfo.CREATOR);
+        if (mShortcutInfo == null) {
+            mPackageName = parcel.readString();
+            mUser = UserHandle.of(parcel.readInt());
+        } else {
+            mPackageName = mShortcutInfo.getPackage();
+            mUser = mShortcutInfo.getUserHandle();
+        }
+        mClassName = parcel.readString();
+        mRank = parcel.readInt();
+    }
+
+    /**
+     * Returns the target id.
+     */
+    @NonNull
+    public AppTargetId getId() {
+        return mId;
+    }
+
+    /**
+     * Returns the class name for the app target.
+     */
+    @Nullable
+    public String getClassName() {
+        return mClassName;
+    }
+
+    /**
+     * Returns the package name for the app target.
+     */
+    @NonNull
+    public String getPackageName() {
+        return mPackageName;
+    }
+
+    /**
+     * Returns the user for the app target.
+     */
+    @NonNull
+    public UserHandle getUser() {
+        return mUser;
+    }
+
+    /**
+     * Returns the shortcut info for the target.
+     */
+    @Nullable
+    public ShortcutInfo getShortcutInfo() {
+        return mShortcutInfo;
+    }
+
+    /**
+     * Returns the rank for the target. Rank of an AppTarget is a non-negative integer that
+     * represents the importance of this target compared to other candidate targets. A smaller value
+     * means higher importance in the list.
+     */
+    public @IntRange(from = 0) int getRank() {
+        return mRank;
+    }
+
+    @Override
+    public boolean equals(@Nullable Object o) {
+        if (!getClass().equals(o != null ? o.getClass() : null)) return false;
+
+        AppTarget other = (AppTarget) o;
+        boolean sameClassName = (mClassName == null && other.mClassName == null)
+                || (mClassName != null && mClassName.equals(other.mClassName));
+        boolean sameShortcutInfo = (mShortcutInfo == null && other.mShortcutInfo == null)
+                || (mShortcutInfo != null && other.mShortcutInfo != null
+                        && mShortcutInfo.getId() == other.mShortcutInfo.getId());
+        return mId.equals(other.mId)
+                && mPackageName.equals(other.mPackageName)
+                && sameClassName
+                && mUser.equals(other.mUser)
+                && sameShortcutInfo
+                && mRank == other.mRank;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeTypedObject(mId, flags);
+        dest.writeTypedObject(mShortcutInfo, flags);
+        if (mShortcutInfo == null) {
+            dest.writeString(mPackageName);
+            dest.writeInt(mUser.getIdentifier());
+        }
+        dest.writeString(mClassName);
+        dest.writeInt(mRank);
+    }
+
+    /**
+     * A builder for app targets.
+     * @hide
+     */
+    @SystemApi
+    @TestApi
+    public static final class Builder {
+
+        @NonNull
+        private final AppTargetId mId;
+
+        private String mPackageName;
+        private UserHandle mUser;
+        private ShortcutInfo mShortcutInfo;
+
+        private String mClassName;
+        private int mRank;
+
+        /**
+         * @deprecated Use the other Builder constructors.
+         * @hide
+         * @removed
+         */
+        @Deprecated
+        @SystemApi
+        public Builder(@NonNull AppTargetId id) {
+            mId = id;
+        }
+
+        /**
+         * @param id A unique id for this launchable target.
+         * @param packageName PackageName of the target.
+         * @param user The UserHandle of the user which this target belongs to.
+         * @hide
+         */
+        @SystemApi
+        @TestApi
+        public Builder(@NonNull AppTargetId id, @NonNull String packageName,
+                @NonNull UserHandle user) {
+            mId = Objects.requireNonNull(id);
+            mPackageName = Objects.requireNonNull(packageName);
+            mUser = Objects.requireNonNull(user);
+        }
+
+        /**
+         * @param id A unique id for this launchable target.
+         * @param info The ShortcutInfo that represents this launchable target.
+         * @hide
+         */
+        @SystemApi
+        @TestApi
+        public Builder(@NonNull AppTargetId id, @NonNull ShortcutInfo info) {
+            mId = Objects.requireNonNull(id);
+            mShortcutInfo = Objects.requireNonNull(info);
+            mPackageName = info.getPackage();
+            mUser = info.getUserHandle();
+        }
+
+        /**
+         * @deprecated Use the appropriate constructor.
+         * @removed
+         */
+        @NonNull
+        @Deprecated
+        public Builder setTarget(@NonNull String packageName, @NonNull UserHandle user) {
+            if (mPackageName != null) {
+                throw new IllegalArgumentException("Target is already set");
+            }
+            mPackageName = Objects.requireNonNull(packageName);
+            mUser = Objects.requireNonNull(user);
+            return this;
+        }
+
+        /**
+         * @deprecated Use the appropriate constructor.
+         * @removed
+         */
+        @NonNull
+        @Deprecated
+        public Builder setTarget(@NonNull ShortcutInfo info) {
+            setTarget(info.getPackage(), info.getUserHandle());
+            mShortcutInfo = Objects.requireNonNull(info);
+            return this;
+        }
+
+        /**
+         * Sets the className for the target.
+         */
+        @NonNull
+        public Builder setClassName(@NonNull String className) {
+            mClassName = Objects.requireNonNull(className);
+            return this;
+        }
+
+        /**
+         * Sets the rank of the target.
+         */
+        @NonNull
+        public Builder setRank(@IntRange(from = 0) int rank) {
+            if (rank < 0) {
+                throw new IllegalArgumentException("rank cannot be a negative value");
+            }
+            mRank = rank;
+            return this;
+        }
+
+        /**
+         * Builds a new AppTarget instance.
+         *
+         * @throws IllegalStateException if no target is set
+         * @see #setTarget(ShortcutInfo)
+         * @see #setTarget(String, UserHandle)
+         */
+        @NonNull
+        public AppTarget build() {
+            if (mPackageName == null) {
+                throw new IllegalStateException("No target is set");
+            }
+            return new AppTarget(mId, mPackageName, mUser, mShortcutInfo, mClassName, mRank);
+        }
+    }
+
+    public static final @android.annotation.NonNull Parcelable.Creator<AppTarget> CREATOR =
+            new Parcelable.Creator<AppTarget>() {
+                public AppTarget createFromParcel(Parcel parcel) {
+                    return new AppTarget(parcel);
+                }
+
+                public AppTarget[] newArray(int size) {
+                    return new AppTarget[size];
+                }
+            };
+}
diff --git a/android/app/prediction/AppTargetEvent.java b/android/app/prediction/AppTargetEvent.java
new file mode 100644
index 0000000..f519145
--- /dev/null
+++ b/android/app/prediction/AppTargetEvent.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2018 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 android.app.prediction;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * A representation of an app target event.
+ *
+ * @hide
+ */
+@SystemApi
+@TestApi
+public final class AppTargetEvent implements Parcelable {
+
+    /**
+     * @hide
+     */
+    @IntDef({ACTION_LAUNCH, ACTION_DISMISS, ACTION_PIN, ACTION_UNPIN})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ActionType {}
+
+    /**
+     * Event type constant indicating an app target has been launched.
+     */
+    public static final int ACTION_LAUNCH = 1;
+
+    /**
+     * Event type constant indicating an app target has been dismissed.
+     */
+    public static final int ACTION_DISMISS = 2;
+
+    /**
+     * Event type constant indicating an app target has been pinned.
+     */
+    public static final int ACTION_PIN = 3;
+
+    /**
+     * Event type constant indicating an app target has been un-pinned.
+     */
+    public static final int ACTION_UNPIN = 4;
+
+    private final AppTarget mTarget;
+    private final String mLocation;
+    private final int mAction;
+
+    private AppTargetEvent(@Nullable AppTarget target, @Nullable String location,
+            @ActionType int actionType) {
+        mTarget = target;
+        mLocation = location;
+        mAction = actionType;
+    }
+
+    private AppTargetEvent(Parcel parcel) {
+        mTarget = parcel.readParcelable(null);
+        mLocation = parcel.readString();
+        mAction = parcel.readInt();
+    }
+
+    /**
+     * Returns the app target.
+     */
+    @Nullable
+    public AppTarget getTarget() {
+        return mTarget;
+    }
+
+    /**
+     * Returns the launch location.
+     */
+    @Nullable
+    public String getLaunchLocation() {
+        return mLocation;
+    }
+
+    /**
+     * Returns the action type.
+     */
+    public @ActionType int getAction() {
+        return mAction;
+    }
+
+    @Override
+    public boolean equals(@Nullable Object o) {
+        if (!getClass().equals(o != null ? o.getClass() : null)) return false;
+
+        AppTargetEvent other = (AppTargetEvent) o;
+        return mTarget.equals(other.mTarget)
+                && mLocation.equals(other.mLocation)
+                && mAction == other.mAction;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeParcelable(mTarget, 0);
+        dest.writeString(mLocation);
+        dest.writeInt(mAction);
+    }
+
+    public static final @android.annotation.NonNull Creator<AppTargetEvent> CREATOR =
+            new Creator<AppTargetEvent>() {
+                public AppTargetEvent createFromParcel(Parcel parcel) {
+                    return new AppTargetEvent(parcel);
+                }
+
+                public AppTargetEvent[] newArray(int size) {
+                    return new AppTargetEvent[size];
+                }
+            };
+
+    /**
+     * A builder for app target events.
+     *
+     * @hide
+     */
+    @SystemApi
+    @TestApi
+    public static final class Builder {
+        private AppTarget mTarget;
+        private String mLocation;
+        private @ActionType int mAction;
+
+        /**
+         * @param target The app target that is associated with this event.
+         * @param actionType The event type, which is one of the values in {@link ActionType}.
+         */
+        public Builder(@Nullable AppTarget target, @ActionType int actionType) {
+            mTarget = target;
+            mAction = actionType;
+        }
+
+        /**
+         * Sets the launch location.
+         */
+        @NonNull
+        public Builder setLaunchLocation(@Nullable String location) {
+            mLocation = location;
+            return this;
+        }
+
+        /**
+         * Builds a new event instance.
+         */
+        @NonNull
+        public AppTargetEvent build() {
+            return new AppTargetEvent(mTarget, mLocation, mAction);
+        }
+    }
+}
diff --git a/android/app/prediction/AppTargetId.java b/android/app/prediction/AppTargetId.java
new file mode 100644
index 0000000..052fdc1
--- /dev/null
+++ b/android/app/prediction/AppTargetId.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2018 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 android.app.prediction;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * The id for a prediction target. See {@link AppTarget}.
+ *
+ * @hide
+ */
+@SystemApi
+@TestApi
+public final class AppTargetId implements Parcelable {
+
+    @NonNull
+    private final String mId;
+
+    /**
+     * Creates a new id for a prediction target.
+     *
+     * @hide
+     */
+    @SystemApi
+    @TestApi
+    public AppTargetId(@NonNull String id) {
+        mId = id;
+    }
+
+    private AppTargetId(Parcel parcel) {
+        mId = parcel.readString();
+    }
+
+    /**
+     * Returns the id.
+     *
+     * @hide
+     */
+    @NonNull
+    public String getId() {
+        return mId;
+    }
+
+    @Override
+    public boolean equals(@Nullable Object o) {
+        if (!getClass().equals(o != null ? o.getClass() : null)) return false;
+
+        AppTargetId other = (AppTargetId) o;
+        return mId.equals(other.mId);
+    }
+
+    @Override
+    public int hashCode() {
+        return mId.hashCode();
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeString(mId);
+    }
+
+    public static final @android.annotation.NonNull Creator<AppTargetId> CREATOR =
+            new Creator<AppTargetId>() {
+                public AppTargetId createFromParcel(Parcel parcel) {
+                    return new AppTargetId(parcel);
+                }
+
+                public AppTargetId[] newArray(int size) {
+                    return new AppTargetId[size];
+                }
+            };
+}