Revert "Add a service to rank apps for ResolverActivity."

This reverts commit 90370e0b2497deba9382ab7ff1539b6849df8139.

b: 36952725

Change-Id: Ifa8f182c707cdbbc989b1f61630f7a8fa856d32d
(cherry picked from commit c88749fb5a8de40572582e6eceefd46cda3afa2d)
diff --git a/Android.mk b/Android.mk
index e27aa30..ee7d471 100644
--- a/Android.mk
+++ b/Android.mk
@@ -320,8 +320,6 @@
 	core/java/android/service/wallpaper/IWallpaperService.aidl \
 	core/java/android/service/chooser/IChooserTargetService.aidl \
 	core/java/android/service/chooser/IChooserTargetResult.aidl \
-	core/java/android/service/resolver/IResolverRankerService.aidl \
-	core/java/android/service/resolver/IResolverRankerResult.aidl \
 	core/java/android/text/ITextClassificationService.aidl \
 	core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl\
 	core/java/android/view/accessibility/IAccessibilityInteractionConnectionCallback.aidl\
@@ -730,7 +728,6 @@
 	frameworks/base/core/java/android/service/notification/SnoozeCriterion.aidl \
 	frameworks/base/core/java/android/service/notification/StatusBarNotification.aidl \
 	frameworks/base/core/java/android/service/chooser/ChooserTarget.aidl \
-	frameworks/base/core/java/android/service/resolver/ResolverTarget.aidl \
 	frameworks/base/core/java/android/speech/tts/Voice.aidl \
 	frameworks/base/core/java/android/app/usage/CacheQuotaHint.aidl \
 	frameworks/base/core/java/android/app/usage/ExternalStorageStats.aidl \
diff --git a/api/system-current.txt b/api/system-current.txt
index fa2a69e..f4eefe3 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -53,7 +53,6 @@
     field public static final java.lang.String BIND_PRINT_SERVICE = "android.permission.BIND_PRINT_SERVICE";
     field public static final java.lang.String BIND_QUICK_SETTINGS_TILE = "android.permission.BIND_QUICK_SETTINGS_TILE";
     field public static final java.lang.String BIND_REMOTEVIEWS = "android.permission.BIND_REMOTEVIEWS";
-    field public static final java.lang.String BIND_RESOLVER_RANKER_SERVICE = "android.permission.BIND_RESOLVER_RANKER_SERVICE";
     field public static final java.lang.String BIND_RUNTIME_PERMISSION_PRESENTER_SERVICE = "android.permission.BIND_RUNTIME_PERMISSION_PRESENTER_SERVICE";
     field public static final java.lang.String BIND_SCREENING_SERVICE = "android.permission.BIND_SCREENING_SERVICE";
     field public static final java.lang.String BIND_TELECOM_CONNECTION_SERVICE = "android.permission.BIND_TELECOM_CONNECTION_SERVICE";
@@ -40619,36 +40618,6 @@
 
 }
 
-package android.service.resolver {
-
-  public abstract class ResolverRankerService extends android.app.Service {
-    ctor public ResolverRankerService();
-    method public android.os.IBinder onBind(android.content.Intent);
-    method public void onPredictSharingProbabilities(java.util.List<android.service.resolver.ResolverTarget>);
-    method public void onTrainRankingModel(java.util.List<android.service.resolver.ResolverTarget>, int);
-    field public static final java.lang.String BIND_PERMISSION = "android.permission.BIND_RESOLVER_RANKER_SERVICE";
-    field public static final java.lang.String SERVICE_INTERFACE = "android.service.resolver.ResolverRankerService";
-  }
-
-  public final class ResolverTarget implements android.os.Parcelable {
-    ctor public ResolverTarget();
-    method public int describeContents();
-    method public float getChooserScore();
-    method public float getLaunchScore();
-    method public float getRecencyScore();
-    method public float getSelectProbability();
-    method public float getTimeSpentScore();
-    method public void setChooserScore(float);
-    method public void setLaunchScore(float);
-    method public void setRecencyScore(float);
-    method public void setSelectProbability(float);
-    method public void setTimeSpentScore(float);
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator<android.service.resolver.ResolverTarget> CREATOR;
-  }
-
-}
-
 package android.service.restrictions {
 
   public abstract class RestrictionsReceiver extends android.content.BroadcastReceiver {
diff --git a/core/java/android/service/resolver/IResolverRankerResult.aidl b/core/java/android/service/resolver/IResolverRankerResult.aidl
deleted file mode 100644
index bda3154..0000000
--- a/core/java/android/service/resolver/IResolverRankerResult.aidl
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * 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 android.service.resolver;
-
-import android.service.resolver.ResolverTarget;
-
-/**
- * @hide
- */
-oneway interface IResolverRankerResult
-{
-    void sendResult(in List<ResolverTarget> results);
-}
\ No newline at end of file
diff --git a/core/java/android/service/resolver/IResolverRankerService.aidl b/core/java/android/service/resolver/IResolverRankerService.aidl
deleted file mode 100644
index f0d747d..0000000
--- a/core/java/android/service/resolver/IResolverRankerService.aidl
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * 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 android.service.resolver;
-
-import android.service.resolver.IResolverRankerResult;
-import android.service.resolver.ResolverTarget;
-
-/**
- * @hide
- */
-oneway interface IResolverRankerService
-{
-    void predict(in List<ResolverTarget> targets, IResolverRankerResult result);
-    void train(in List<ResolverTarget> targets, int selectedPosition);
-}
\ No newline at end of file
diff --git a/core/java/android/service/resolver/ResolverRankerService.java b/core/java/android/service/resolver/ResolverRankerService.java
deleted file mode 100644
index 0506747..0000000
--- a/core/java/android/service/resolver/ResolverRankerService.java
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * 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 android.service.resolver;
-
-import android.annotation.SdkConstant;
-import android.annotation.SystemApi;
-import android.app.Service;
-import android.content.ComponentName;
-import android.content.Intent;
-import android.os.IBinder;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.RemoteException;
-import android.service.resolver.ResolverTarget;
-import android.util.Log;
-
-import java.util.List;
-import java.util.Map;
-
-/**
- * A service to rank apps according to usage stats of apps, when the system is resolving targets for
- * an Intent.
- *
- * <p>To extend this class, you must declare the service in your manifest file with the
- * {@link android.Manifest.permission#BIND_RESOLVER_RANKER_SERVICE} permission, and include an
- * intent filter with the {@link #SERVICE_INTERFACE} action. For example:</p>
- * <pre>
- *     &lt;service android:name=".MyResolverRankerService"
- *             android:exported="true"
- *             android:priority="100"
- *             android:permission="android.permission.BIND_RESOLVER_RANKER_SERVICE"&gt;
- *         &lt;intent-filter&gt;
- *             &lt;action android:name="android.service.resolver.ResolverRankerService" /&gt;
- *         &lt;/intent-filter&gt;
- *     &lt;/service&gt;
- * </pre>
- * @hide
- */
-@SystemApi
-public abstract class ResolverRankerService extends Service {
-
-    private static final String TAG = "ResolverRankerService";
-
-    private static final boolean DEBUG = false;
-
-    /**
-     * The Intent action that a service must respond to. Add it to the intent filter of the service
-     * in its manifest.
-     */
-    @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
-    public static final String SERVICE_INTERFACE = "android.service.resolver.ResolverRankerService";
-
-    /**
-     * The permission that a service must require to ensure that only Android system can bind to it.
-     * If this permission is not enforced in the AndroidManifest of the service, the system will
-     * skip that service.
-     */
-    public static final String BIND_PERMISSION = "android.permission.BIND_RESOLVER_RANKER_SERVICE";
-
-    private ResolverRankerServiceWrapper mWrapper = null;
-
-    /**
-     * Called by the system to retrieve a list of probabilities to rank apps/options. To implement
-     * it, set selectProbability of each input {@link ResolverTarget}. The higher the
-     * selectProbability is, the more likely the {@link ResolverTarget} will be selected by the
-     * user. Override this function to provide prediction results.
-     *
-     * @param targets a list of {@link ResolverTarget}, for the list of apps to be ranked.
-     *
-     * @throws Exception when the prediction task fails.
-     */
-    public void onPredictSharingProbabilities(final List<ResolverTarget> targets) {}
-
-    /**
-     * Called by the system to train/update a ranking service, after the user makes a selection from
-     * the ranked list of apps. Override this function to enable model updates.
-     *
-     * @param targets a list of {@link ResolverTarget}, for the list of apps to be ranked.
-     * @param selectedPosition the position of the selected app in the list.
-     *
-     * @throws Exception when the training task fails.
-     */
-    public void onTrainRankingModel(
-            final List<ResolverTarget> targets, final int selectedPosition) {}
-
-    private static final String HANDLER_THREAD_NAME = "RESOLVER_RANKER_SERVICE";
-    private volatile Handler mHandler;
-    private HandlerThread mHandlerThread;
-
-    @Override
-    public IBinder onBind(Intent intent) {
-        if (DEBUG) Log.d(TAG, "onBind " + intent);
-        if (!SERVICE_INTERFACE.equals(intent.getAction())) {
-            if (DEBUG) Log.d(TAG, "bad intent action " + intent.getAction() + "; returning null");
-            return null;
-        }
-        if (mHandlerThread == null) {
-            mHandlerThread = new HandlerThread(HANDLER_THREAD_NAME);
-            mHandlerThread.start();
-            mHandler = new Handler(mHandlerThread.getLooper());
-        }
-        if (mWrapper == null) {
-            mWrapper = new ResolverRankerServiceWrapper();
-        }
-        return mWrapper;
-    }
-
-    @Override
-    public void onDestroy() {
-        mHandler = null;
-        if (mHandlerThread != null) {
-            mHandlerThread.quitSafely();
-        }
-        super.onDestroy();
-    }
-
-    private static void sendResult(List<ResolverTarget> targets, IResolverRankerResult result) {
-        try {
-            result.sendResult(targets);
-        } catch (Exception e) {
-            Log.e(TAG, "failed to send results: " + e);
-        }
-    }
-
-    private class ResolverRankerServiceWrapper extends IResolverRankerService.Stub {
-
-        @Override
-        public void predict(final List<ResolverTarget> targets, final IResolverRankerResult result)
-                throws RemoteException {
-            Runnable predictRunnable = new Runnable() {
-                @Override
-                public void run() {
-                    try {
-                        if (DEBUG) {
-                            Log.d(TAG, "predict calls onPredictSharingProbabilities.");
-                        }
-                        onPredictSharingProbabilities(targets);
-                        sendResult(targets, result);
-                    } catch (Exception e) {
-                        Log.e(TAG, "onPredictSharingProbabilities failed; send null results: " + e);
-                        sendResult(null, result);
-                    }
-                }
-            };
-            final Handler h = mHandler;
-            if (h != null) {
-                h.post(predictRunnable);
-            }
-        }
-
-        @Override
-        public void train(final List<ResolverTarget> targets, final int selectedPosition)
-                throws RemoteException {
-            Runnable trainRunnable = new Runnable() {
-                @Override
-                public void run() {
-                    try {
-                        if (DEBUG) {
-                            Log.d(TAG, "train calls onTranRankingModel");
-                        }
-                        onTrainRankingModel(targets, selectedPosition);
-                    } catch (Exception e) {
-                        Log.e(TAG, "onTrainRankingModel failed; skip train: " + e);
-                    }
-                }
-            };
-            final Handler h = mHandler;
-            if (h != null) {
-                h.post(trainRunnable);
-            }
-        }
-    }
-}
diff --git a/core/java/android/service/resolver/ResolverTarget.aidl b/core/java/android/service/resolver/ResolverTarget.aidl
deleted file mode 100644
index 6cab2d4..0000000
--- a/core/java/android/service/resolver/ResolverTarget.aidl
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * 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 android.service.resolver;
-
-/**
- * @hide
- */
-parcelable ResolverTarget;
diff --git a/core/java/android/service/resolver/ResolverTarget.java b/core/java/android/service/resolver/ResolverTarget.java
deleted file mode 100644
index fb3e2d7..0000000
--- a/core/java/android/service/resolver/ResolverTarget.java
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * 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 android.service.resolver;
-
-import android.annotation.SystemApi;
-import android.os.Bundle;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.ArrayMap;
-
-import java.util.Map;
-
-/**
- * A ResolverTarget contains features by which an app or option will be ranked, in
- * {@link ResolverRankerService}.
- * @hide
- */
-@SystemApi
-public final class ResolverTarget implements Parcelable {
-    private static final String TAG = "ResolverTarget";
-
-    /**
-     * a float score for recency of last use.
-     */
-    private float mRecencyScore;
-
-    /**
-     * a float score for total time spent.
-     */
-    private float mTimeSpentScore;
-
-    /**
-     * a float score for number of launches.
-     */
-    private float mLaunchScore;
-
-    /**
-     * a float score for number of selected.
-     */
-    private float mChooserScore;
-
-    /**
-     * a float score for the probability to be selected.
-     */
-    private float mSelectProbability;
-
-    // constructor for the class.
-    public ResolverTarget() {}
-
-    ResolverTarget(Parcel in) {
-        mRecencyScore = in.readFloat();
-        mTimeSpentScore = in.readFloat();
-        mLaunchScore = in.readFloat();
-        mChooserScore = in.readFloat();
-        mSelectProbability = in.readFloat();
-    }
-
-    /**
-     * Gets the score for how recently the target was used in the foreground.
-     *
-     * @return a float score whose range is [0, 1]. The higher the score is, the more recently the
-     * target was used.
-     */
-    public float getRecencyScore() {
-        return mRecencyScore;
-    }
-
-    /**
-     * Sets the score for how recently the target was used in the foreground.
-     *
-     * @param recencyScore a float score whose range is [0, 1]. The higher the score is, the more
-     *                     recently the target was used.
-     */
-    public void setRecencyScore(float recencyScore) {
-        this.mRecencyScore = recencyScore;
-    }
-
-    /**
-     * Gets the score for how long the target has been used in the foreground.
-     *
-     * @return a float score whose range is [0, 1]. The higher the score is, the longer the target
-     * has been used for.
-     */
-    public float getTimeSpentScore() {
-        return mTimeSpentScore;
-    }
-
-    /**
-     * Sets the score for how long the target has been used in the foreground.
-     *
-     * @param timeSpentScore a float score whose range is [0, 1]. The higher the score is, the
-     *                       longer the target has been used for.
-     */
-    public void setTimeSpentScore(float timeSpentScore) {
-        this.mTimeSpentScore = timeSpentScore;
-    }
-
-    /**
-     * Gets the score for how many times the target has been launched to the foreground.
-     *
-     * @return a float score whose range is [0, 1]. The higher the score is, the more times the
-     * target has been launched.
-     */
-    public float getLaunchScore() {
-        return mLaunchScore;
-    }
-
-    /**
-     * Sets the score for how many times the target has been launched to the foreground.
-     *
-     * @param launchScore a float score whose range is [0, 1]. The higher the score is, the more
-     *                    times the target has been launched.
-     */
-    public void setLaunchScore(float launchScore) {
-        this.mLaunchScore = launchScore;
-    }
-
-    /**
-     * Gets the score for how many times the target has been selected by the user to share the same
-     * types of content.
-     *
-     * @return a float score whose range is [0, 1]. The higher the score is, the
-     * more times the target has been selected by the user to share the same types of content for.
-     */
-    public float getChooserScore() {
-        return mChooserScore;
-    }
-
-    /**
-     * Sets the score for how many times the target has been selected by the user to share the same
-     * types of content.
-     *
-     * @param chooserScore a float score whose range is [0, 1]. The higher the score is, the more
-     *                     times the target has been selected by the user to share the same types
-     *                     of content for.
-     */
-    public void setChooserScore(float chooserScore) {
-        this.mChooserScore = chooserScore;
-    }
-
-    /**
-     * Gets the probability of how likely this target will be selected by the user.
-     *
-     * @return a float score whose range is [0, 1]. The higher the score is, the more likely the
-     * user is going to select this target.
-     */
-    public float getSelectProbability() {
-        return mSelectProbability;
-    }
-
-    /**
-     * Sets the probability for how like this target will be selected by the user.
-     *
-     * @param selectProbability a float score whose range is [0, 1]. The higher the score is, the
-     *                          more likely tht user is going to select this target.
-     */
-    public void setSelectProbability(float selectProbability) {
-        this.mSelectProbability = selectProbability;
-    }
-
-    // serialize the class to a string.
-    @Override
-    public String toString() {
-        return "ResolverTarget{"
-                + mRecencyScore + ", "
-                + mTimeSpentScore + ", "
-                + mLaunchScore + ", "
-                + mChooserScore + ", "
-                + mSelectProbability + "}";
-    }
-
-    // describes the kinds of special objects contained in this Parcelable instance's marshaled
-    // representation.
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    // flattens this object in to a Parcel.
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeFloat(mRecencyScore);
-        dest.writeFloat(mTimeSpentScore);
-        dest.writeFloat(mLaunchScore);
-        dest.writeFloat(mChooserScore);
-        dest.writeFloat(mSelectProbability);
-    }
-
-    // creator definition for the class.
-    public static final Creator<ResolverTarget> CREATOR
-            = new Creator<ResolverTarget>() {
-        @Override
-        public ResolverTarget createFromParcel(Parcel source) {
-            return new ResolverTarget(source);
-        }
-
-        @Override
-        public ResolverTarget[] newArray(int size) {
-            return new ResolverTarget[size];
-        }
-    };
-}
diff --git a/core/java/com/android/internal/app/LRResolverRankerService.java b/core/java/com/android/internal/app/LRResolverRankerService.java
deleted file mode 100644
index 1cad7c7..0000000
--- a/core/java/com/android/internal/app/LRResolverRankerService.java
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * 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 com.android.internal.app;
-
-import android.content.Context;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.os.Environment;
-import android.os.IBinder;
-import android.os.storage.StorageManager;
-import android.service.resolver.ResolverRankerService;
-import android.service.resolver.ResolverTarget;
-import android.util.ArrayMap;
-import android.util.Log;
-
-import java.io.File;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-
-/**
- * A Logistic Regression based {@link android.service.resolver.ResolverRankerService}, to be used
- * in {@link ResolverComparator}.
- */
-public final class LRResolverRankerService extends ResolverRankerService {
-    private static final String TAG = "LRResolverRankerService";
-
-    private static final boolean DEBUG = false;
-
-    private static final String PARAM_SHARED_PREF_NAME = "resolver_ranker_params";
-    private static final String BIAS_PREF_KEY = "bias";
-    private static final String VERSION_PREF_KEY = "version";
-
-    private static final String LAUNCH_SCORE = "launch";
-    private static final String TIME_SPENT_SCORE = "timeSpent";
-    private static final String RECENCY_SCORE = "recency";
-    private static final String CHOOSER_SCORE = "chooser";
-
-    // parameters for a pre-trained model, to initialize the app ranker. When updating the
-    // pre-trained model, please update these params, as well as initModel().
-    private static final int CURRENT_VERSION = 1;
-    private static final float LEARNING_RATE = 0.0001f;
-    private static final float REGULARIZER_PARAM = 0.0001f;
-
-    private SharedPreferences mParamSharedPref;
-    private ArrayMap<String, Float> mFeatureWeights;
-    private float mBias;
-
-    @Override
-    public IBinder onBind(Intent intent) {
-        initModel();
-        return super.onBind(intent);
-    }
-
-    @Override
-    public void onPredictSharingProbabilities(List<ResolverTarget> targets) {
-        final int size = targets.size();
-        for (int i = 0; i < size; ++i) {
-            ResolverTarget target = targets.get(i);
-            ArrayMap<String, Float> features = getFeatures(target);
-            target.setSelectProbability(predict(features));
-        }
-    }
-
-    @Override
-    public void onTrainRankingModel(List<ResolverTarget> targets, int selectedPosition) {
-        final int size = targets.size();
-        if (selectedPosition < 0 || selectedPosition >= size) {
-            if (DEBUG) {
-                Log.d(TAG, "Invalid Position of Selected App " + selectedPosition);
-            }
-            return;
-        }
-        final ArrayMap<String, Float> positive = getFeatures(targets.get(selectedPosition));
-        final float positiveProbability = targets.get(selectedPosition).getSelectProbability();
-        final int targetSize = targets.size();
-        for (int i = 0; i < targetSize; ++i) {
-            if (i == selectedPosition) {
-                continue;
-            }
-            final ArrayMap<String, Float> negative = getFeatures(targets.get(i));
-            final float negativeProbability = targets.get(i).getSelectProbability();
-            if (negativeProbability > positiveProbability) {
-                update(negative, negativeProbability, false);
-                update(positive, positiveProbability, true);
-            }
-        }
-        commitUpdate();
-    }
-
-    private void initModel() {
-        mParamSharedPref = getParamSharedPref();
-        mFeatureWeights = new ArrayMap<>(4);
-        if (mParamSharedPref == null ||
-                mParamSharedPref.getInt(VERSION_PREF_KEY, 0) < CURRENT_VERSION) {
-            // Initializing the app ranker to a pre-trained model. When updating the pre-trained
-            // model, please increment CURRENT_VERSION, and update LEARNING_RATE and
-            // REGULARIZER_PARAM.
-            mBias = -1.6568f;
-            mFeatureWeights.put(LAUNCH_SCORE, 2.5543f);
-            mFeatureWeights.put(TIME_SPENT_SCORE, 2.8412f);
-            mFeatureWeights.put(RECENCY_SCORE, 0.269f);
-            mFeatureWeights.put(CHOOSER_SCORE, 4.2222f);
-        } else {
-            mBias = mParamSharedPref.getFloat(BIAS_PREF_KEY, 0.0f);
-            mFeatureWeights.put(LAUNCH_SCORE, mParamSharedPref.getFloat(LAUNCH_SCORE, 0.0f));
-            mFeatureWeights.put(
-                    TIME_SPENT_SCORE, mParamSharedPref.getFloat(TIME_SPENT_SCORE, 0.0f));
-            mFeatureWeights.put(RECENCY_SCORE, mParamSharedPref.getFloat(RECENCY_SCORE, 0.0f));
-            mFeatureWeights.put(CHOOSER_SCORE, mParamSharedPref.getFloat(CHOOSER_SCORE, 0.0f));
-        }
-    }
-
-    private ArrayMap<String, Float> getFeatures(ResolverTarget target) {
-        ArrayMap<String, Float> features = new ArrayMap<>(4);
-        features.put(RECENCY_SCORE, target.getRecencyScore());
-        features.put(TIME_SPENT_SCORE, target.getTimeSpentScore());
-        features.put(LAUNCH_SCORE, target.getLaunchScore());
-        features.put(CHOOSER_SCORE, target.getChooserScore());
-        return features;
-    }
-
-    private float predict(ArrayMap<String, Float> target) {
-        if (target == null) {
-            return 0.0f;
-        }
-        final int featureSize = target.size();
-        float sum = 0.0f;
-        for (int i = 0; i < featureSize; i++) {
-            String featureName = target.keyAt(i);
-            float weight = mFeatureWeights.getOrDefault(featureName, 0.0f);
-            sum += weight * target.valueAt(i);
-        }
-        return (float) (1.0 / (1.0 + Math.exp(-mBias - sum)));
-    }
-
-    private void update(ArrayMap<String, Float> target, float predict, boolean isSelected) {
-        if (target == null) {
-            return;
-        }
-        final int featureSize = target.size();
-        float error = isSelected ? 1.0f - predict : -predict;
-        for (int i = 0; i < featureSize; i++) {
-            String featureName = target.keyAt(i);
-            float currentWeight = mFeatureWeights.getOrDefault(featureName, 0.0f);
-            mBias += LEARNING_RATE * error;
-            currentWeight = currentWeight - LEARNING_RATE * REGULARIZER_PARAM * currentWeight +
-                    LEARNING_RATE * error * target.valueAt(i);
-            mFeatureWeights.put(featureName, currentWeight);
-        }
-        if (DEBUG) {
-            Log.d(TAG, "Weights: " + mFeatureWeights + " Bias: " + mBias);
-        }
-    }
-
-    private void commitUpdate() {
-        try {
-            SharedPreferences.Editor editor = mParamSharedPref.edit();
-            editor.putFloat(BIAS_PREF_KEY, mBias);
-            final int size = mFeatureWeights.size();
-            for (int i = 0; i < size; i++) {
-                editor.putFloat(mFeatureWeights.keyAt(i), mFeatureWeights.valueAt(i));
-            }
-            editor.putInt(VERSION_PREF_KEY, CURRENT_VERSION);
-            editor.apply();
-        } catch (Exception e) {
-            Log.e(TAG, "Failed to commit update" + e);
-        }
-    }
-
-    private SharedPreferences getParamSharedPref() {
-        // The package info in the context isn't initialized in the way it is for normal apps,
-        // so the standard, name-based context.getSharedPreferences doesn't work. Instead, we
-        // build the path manually below using the same policy that appears in ContextImpl.
-        if (DEBUG) {
-            Log.d(TAG, "Context Package Name: " + getPackageName());
-        }
-        final File prefsFile = new File(new File(
-                Environment.getDataUserCePackageDirectory(
-                        StorageManager.UUID_PRIVATE_INTERNAL, getUserId(), getPackageName()),
-                "shared_prefs"),
-                PARAM_SHARED_PREF_NAME + ".xml");
-        return getSharedPreferences(prefsFile, Context.MODE_PRIVATE);
-    }
-}
\ No newline at end of file
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 622b708..3f1c9ad 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -530,9 +530,6 @@
             getMainThreadHandler().removeCallbacks(mPostListReadyRunnable);
             mPostListReadyRunnable = null;
         }
-        if (mAdapter != null && mAdapter.mResolverListController != null) {
-            mAdapter.mResolverListController.destroy();
-        }
     }
 
     @Override
diff --git a/core/java/com/android/internal/app/ResolverComparator.java b/core/java/com/android/internal/app/ResolverComparator.java
index 73b62a5..096fcb8 100644
--- a/core/java/com/android/internal/app/ResolverComparator.java
+++ b/core/java/com/android/internal/app/ResolverComparator.java
@@ -26,34 +26,20 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.ComponentInfo;
 import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ResolveInfo;
 import android.content.SharedPreferences;
-import android.content.ServiceConnection;
 import android.os.Environment;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.Message;
-import android.os.RemoteException;
 import android.os.storage.StorageManager;
 import android.os.UserHandle;
-import android.service.resolver.IResolverRankerService;
-import android.service.resolver.IResolverRankerResult;
-import android.service.resolver.ResolverRankerService;
-import android.service.resolver.ResolverTarget;
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.Log;
 import com.android.internal.app.ResolverActivity.ResolvedComponentInfo;
 
 import java.io.File;
-import java.lang.InterruptedException;
 import java.text.Collator;
 import java.util.ArrayList;
 import java.util.Comparator;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
@@ -75,15 +61,11 @@
 
     private static final float RECENCY_MULTIPLIER = 2.f;
 
-    // message types
-    private static final int RESOLVER_RANKER_SERVICE_RESULT = 0;
-    private static final int RESOLVER_RANKER_RESULT_TIMEOUT = 1;
-
-    // timeout for establishing connections with a ResolverRankerService.
-    private static final int CONNECTION_COST_TIMEOUT_MILLIS = 200;
-    // timeout for establishing connections with a ResolverRankerService, collecting features and
-    // predicting ranking scores.
-    private static final int WATCHDOG_TIMEOUT_MILLIS = 500;
+    // feature names used in ranking.
+    private static final String LAUNCH_SCORE = "launch";
+    private static final String TIME_SPENT_SCORE = "timeSpent";
+    private static final String RECENCY_SCORE = "recency";
+    private static final String CHOOSER_SCORE = "chooser";
 
     private final Collator mCollator;
     private final boolean mHttp;
@@ -92,74 +74,18 @@
     private final Map<String, UsageStats> mStats;
     private final long mCurrentTime;
     private final long mSinceTime;
-    private final LinkedHashMap<ComponentName, ResolverTarget> mTargetsDict = new LinkedHashMap<>();
+    private final LinkedHashMap<ComponentName, ScoredTarget> mScoredTargets = new LinkedHashMap<>();
     private final String mReferrerPackage;
-    private final Object mLock = new Object();
-    private ArrayList<ResolverTarget> mTargets;
     private String mContentType;
     private String[] mAnnotations;
     private String mAction;
-    private IResolverRankerService mRanker;
-    private ResolverRankerServiceConnection mConnection;
-    private AfterCompute mAfterCompute;
-    private Context mContext;
-    private CountDownLatch mConnectSignal;
+    private LogisticRegressionAppRanker mRanker;
 
-    private final Handler mHandler = new Handler(Looper.getMainLooper()) {
-        public void handleMessage(Message msg) {
-            switch (msg.what) {
-                case RESOLVER_RANKER_SERVICE_RESULT:
-                    if (DEBUG) {
-                        Log.d(TAG, "RESOLVER_RANKER_SERVICE_RESULT");
-                    }
-                    if (mHandler.hasMessages(RESOLVER_RANKER_RESULT_TIMEOUT)) {
-                        if (msg.obj != null) {
-                            final List<ResolverTarget> receivedTargets =
-                                    (List<ResolverTarget>) msg.obj;
-                            if (receivedTargets != null && mTargets != null
-                                    && receivedTargets.size() == mTargets.size()) {
-                                final int size = mTargets.size();
-                                for (int i = 0; i < size; ++i) {
-                                    mTargets.get(i).setSelectProbability(
-                                            receivedTargets.get(i).getSelectProbability());
-                                }
-                            } else {
-                                Log.e(TAG, "Sizes of sent and received ResolverTargets diff.");
-                            }
-                        } else {
-                            Log.e(TAG, "Receiving null prediction results.");
-                        }
-                        mHandler.removeMessages(RESOLVER_RANKER_RESULT_TIMEOUT);
-                        mAfterCompute.afterCompute();
-                    }
-                    break;
-
-                case RESOLVER_RANKER_RESULT_TIMEOUT:
-                    if (DEBUG) {
-                        Log.d(TAG, "RESOLVER_RANKER_RESULT_TIMEOUT; unbinding services");
-                    }
-                    mHandler.removeMessages(RESOLVER_RANKER_SERVICE_RESULT);
-                    mAfterCompute.afterCompute();
-                    break;
-
-                default:
-                    super.handleMessage(msg);
-            }
-        }
-    };
-
-    public interface AfterCompute {
-        public void afterCompute ();
-    }
-
-    public ResolverComparator(Context context, Intent intent, String referrerPackage,
-                              AfterCompute afterCompute) {
+    public ResolverComparator(Context context, Intent intent, String referrerPackage) {
         mCollator = Collator.getInstance(context.getResources().getConfiguration().locale);
         String scheme = intent.getScheme();
         mHttp = "http".equals(scheme) || "https".equals(scheme);
         mReferrerPackage = referrerPackage;
-        mAfterCompute = afterCompute;
-        mContext = context;
 
         mPm = context.getPackageManager();
         mUsm = (UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE);
@@ -170,9 +96,9 @@
         mContentType = intent.getType();
         getContentAnnotations(intent);
         mAction = intent.getAction();
+        mRanker = new LogisticRegressionAppRanker(context);
     }
 
-    // get annotations of content from intent.
     public void getContentAnnotations(Intent intent) {
         ArrayList<String> annotations = intent.getStringArrayListExtra(
                 Intent.EXTRA_CONTENT_ANNOTATIONS);
@@ -188,24 +114,20 @@
         }
     }
 
-    public void setCallBack(AfterCompute afterCompute) {
-        mAfterCompute = afterCompute;
-    }
-
-    // compute features for each target according to usage stats of targets.
     public void compute(List<ResolvedComponentInfo> targets) {
-        reset();
+        mScoredTargets.clear();
 
         final long recentSinceTime = mCurrentTime - RECENCY_TIME_PERIOD;
 
-        float mostRecencyScore = 1.0f;
-        float mostTimeSpentScore = 1.0f;
-        float mostLaunchScore = 1.0f;
-        float mostChooserScore = 1.0f;
+        long mostRecentlyUsedTime = recentSinceTime + 1;
+        long mostTimeSpent = 1;
+        int mostLaunched = 1;
+        int mostSelected = 1;
 
         for (ResolvedComponentInfo target : targets) {
-            final ResolverTarget resolverTarget = new ResolverTarget();
-            mTargetsDict.put(target.name, resolverTarget);
+            final ScoredTarget scoredTarget
+                    = new ScoredTarget(target.getResolveInfoAt(0).activityInfo);
+            mScoredTargets.put(target.name, scoredTarget);
             final UsageStats pkStats = mStats.get(target.name.getPackageName());
             if (pkStats != null) {
                 // Only count recency for apps that weren't the caller
@@ -213,33 +135,31 @@
                 // Persistent processes muck this up, so omit them too.
                 if (!target.name.getPackageName().equals(mReferrerPackage)
                         && !isPersistentProcess(target)) {
-                    final float recencyScore =
-                            (float) Math.max(pkStats.getLastTimeUsed() - recentSinceTime, 0);
-                    resolverTarget.setRecencyScore(recencyScore);
-                    if (recencyScore > mostRecencyScore) {
-                        mostRecencyScore = recencyScore;
+                    final long lastTimeUsed = pkStats.getLastTimeUsed();
+                    scoredTarget.lastTimeUsed = lastTimeUsed;
+                    if (lastTimeUsed > mostRecentlyUsedTime) {
+                        mostRecentlyUsedTime = lastTimeUsed;
                     }
                 }
-                final float timeSpentScore = (float) pkStats.getTotalTimeInForeground();
-                resolverTarget.setTimeSpentScore(timeSpentScore);
-                if (timeSpentScore > mostTimeSpentScore) {
-                    mostTimeSpentScore = timeSpentScore;
+                final long timeSpent = pkStats.getTotalTimeInForeground();
+                scoredTarget.timeSpent = timeSpent;
+                if (timeSpent > mostTimeSpent) {
+                    mostTimeSpent = timeSpent;
                 }
-                final float launchScore = (float) pkStats.mLaunchCount;
-                resolverTarget.setLaunchScore(launchScore);
-                if (launchScore > mostLaunchScore) {
-                    mostLaunchScore = launchScore;
+                final int launched = pkStats.mLaunchCount;
+                scoredTarget.launchCount = launched;
+                if (launched > mostLaunched) {
+                    mostLaunched = launched;
                 }
 
-                float chooserScore = 0.0f;
+                int selected = 0;
                 if (pkStats.mChooserCounts != null && mAction != null
                         && pkStats.mChooserCounts.get(mAction) != null) {
-                    chooserScore = (float) pkStats.mChooserCounts.get(mAction)
-                            .getOrDefault(mContentType, 0);
+                    selected = pkStats.mChooserCounts.get(mAction).getOrDefault(mContentType, 0);
                     if (mAnnotations != null) {
                         final int size = mAnnotations.length;
                         for (int i = 0; i < size; i++) {
-                            chooserScore += (float) pkStats.mChooserCounts.get(mAction)
+                            selected += pkStats.mChooserCounts.get(mAction)
                                     .getOrDefault(mAnnotations[i], 0);
                         }
                     }
@@ -249,37 +169,44 @@
                         Log.d(TAG, "Action type is null");
                     } else {
                         Log.d(TAG, "Chooser Count of " + mAction + ":" +
-                                target.name.getPackageName() + " is " +
-                                Float.toString(chooserScore));
+                                target.name.getPackageName() + " is " + Integer.toString(selected));
                     }
                 }
-                resolverTarget.setChooserScore(chooserScore);
-                if (chooserScore > mostChooserScore) {
-                    mostChooserScore = chooserScore;
+                scoredTarget.chooserCount = selected;
+                if (selected > mostSelected) {
+                    mostSelected = selected;
                 }
             }
         }
 
+
         if (DEBUG) {
-            Log.d(TAG, "compute - mostRecencyScore: " + mostRecencyScore
-                    + " mostTimeSpentScore: " + mostTimeSpentScore
-                    + " mostLaunchScore: " + mostLaunchScore
-                    + " mostChooserScore: " + mostChooserScore);
+            Log.d(TAG, "compute - mostRecentlyUsedTime: " + mostRecentlyUsedTime
+                    + " mostTimeSpent: " + mostTimeSpent
+                    + " recentSinceTime: " + recentSinceTime
+                    + " mostLaunched: " + mostLaunched);
         }
 
-        mTargets = new ArrayList<>(mTargetsDict.values());
-        for (ResolverTarget target : mTargets) {
-            final float recency = target.getRecencyScore() / mostRecencyScore;
-            setFeatures(target, recency * recency * RECENCY_MULTIPLIER,
-                    target.getLaunchScore() / mostLaunchScore,
-                    target.getTimeSpentScore() / mostTimeSpentScore,
-                    target.getChooserScore() / mostChooserScore);
-            addDefaultSelectProbability(target);
+        for (ScoredTarget target : mScoredTargets.values()) {
+            final float recency = (float) Math.max(target.lastTimeUsed - recentSinceTime, 0)
+                    / (mostRecentlyUsedTime - recentSinceTime);
+            target.setFeatures((float) target.launchCount / mostLaunched,
+                    (float) target.timeSpent / mostTimeSpent,
+                    recency * recency * RECENCY_MULTIPLIER,
+                    (float) target.chooserCount / mostSelected);
+            target.selectProb = mRanker.predict(target.getFeatures());
             if (DEBUG) {
                 Log.d(TAG, "Scores: " + target);
             }
         }
-        predictSelectProbabilities(mTargets);
+    }
+
+    static boolean isPersistentProcess(ResolvedComponentInfo rci) {
+        if (rci != null && rci.getCount() > 0) {
+            return (rci.getResolveInfoAt(0).activityInfo.applicationInfo.flags &
+                    ApplicationInfo.FLAG_PERSISTENT) != 0;
+        }
+        return false;
     }
 
     @Override
@@ -318,16 +245,16 @@
         // Pinned items stay stable within a normal lexical sort and ignore scoring.
         if (!lPinned && !rPinned) {
             if (mStats != null) {
-                final ResolverTarget lhsTarget = mTargetsDict.get(new ComponentName(
+                final ScoredTarget lhsTarget = mScoredTargets.get(new ComponentName(
                         lhs.activityInfo.packageName, lhs.activityInfo.name));
-                final ResolverTarget rhsTarget = mTargetsDict.get(new ComponentName(
+                final ScoredTarget rhsTarget = mScoredTargets.get(new ComponentName(
                         rhs.activityInfo.packageName, rhs.activityInfo.name));
 
-                final int selectProbabilityDiff = Float.compare(
-                        rhsTarget.getSelectProbability(), lhsTarget.getSelectProbability());
+                final int selectProbDiff = Float.compare(
+                        rhsTarget.selectProb, lhsTarget.selectProb);
 
-                if (selectProbabilityDiff != 0) {
-                    return selectProbabilityDiff > 0 ? 1 : -1;
+                if (selectProbDiff != 0) {
+                    return selectProbDiff > 0 ? 1 : -1;
                 }
             }
         }
@@ -341,234 +268,177 @@
     }
 
     public float getScore(ComponentName name) {
-        final ResolverTarget target = mTargetsDict.get(name);
+        final ScoredTarget target = mScoredTargets.get(name);
         if (target != null) {
-            return target.getSelectProbability();
+            return target.selectProb;
         }
         return 0;
     }
 
+    static class ScoredTarget {
+        public final ComponentInfo componentInfo;
+        public long lastTimeUsed;
+        public long timeSpent;
+        public long launchCount;
+        public long chooserCount;
+        public ArrayMap<String, Float> features;
+        public float selectProb;
+
+        public ScoredTarget(ComponentInfo ci) {
+            componentInfo = ci;
+            features = new ArrayMap<>(5);
+        }
+
+        @Override
+        public String toString() {
+            return "ScoredTarget{" + componentInfo
+                    + " lastTimeUsed: " + lastTimeUsed
+                    + " timeSpent: " + timeSpent
+                    + " launchCount: " + launchCount
+                    + " chooserCount: " + chooserCount
+                    + " selectProb: " + selectProb
+                    + "}";
+        }
+
+        public void setFeatures(float launchCountScore, float usageTimeScore, float recencyScore,
+                                float chooserCountScore) {
+            features.put(LAUNCH_SCORE, launchCountScore);
+            features.put(TIME_SPENT_SCORE, usageTimeScore);
+            features.put(RECENCY_SCORE, recencyScore);
+            features.put(CHOOSER_SCORE, chooserCountScore);
+        }
+
+        public ArrayMap<String, Float> getFeatures() {
+            return features;
+        }
+    }
+
     public void updateChooserCounts(String packageName, int userId, String action) {
         if (mUsm != null) {
             mUsm.reportChooserSelection(packageName, userId, mContentType, mAnnotations, action);
         }
     }
 
-    // update ranking model when the connection to it is valid.
     public void updateModel(ComponentName componentName) {
-        synchronized (mLock) {
-            if (mRanker != null) {
-                try {
-                    int selectedPos = new ArrayList<ComponentName>(mTargetsDict.keySet())
-                            .indexOf(componentName);
-                    if (selectedPos > 0) {
-                        mRanker.train(mTargets, selectedPos);
-                    } else {
-                        if (DEBUG) {
-                            Log.d(TAG, "Selected a unknown component: " + componentName);
-                        }
-                    }
-                } catch (RemoteException e) {
-                    Log.e(TAG, "Error in Train: " + e);
-                }
-            } else {
-                if (DEBUG) {
-                    Log.d(TAG, "Ranker is null; skip updateModel.");
-                }
+        if (mScoredTargets == null || componentName == null ||
+                !mScoredTargets.containsKey(componentName)) {
+            return;
+        }
+        ScoredTarget selected = mScoredTargets.get(componentName);
+        for (ComponentName targetComponent : mScoredTargets.keySet()) {
+            if (targetComponent.equals(componentName)) {
+                continue;
+            }
+            ScoredTarget target = mScoredTargets.get(targetComponent);
+            // A potential point of optimization. Save updates or derive a closed form for the
+            // positive case, to avoid calculating them repeatedly.
+            if (target.selectProb >= selected.selectProb) {
+                mRanker.update(target.getFeatures(), target.selectProb, false);
+                mRanker.update(selected.getFeatures(), selected.selectProb, true);
             }
         }
+        mRanker.commitUpdate();
     }
 
-    // unbind the service and clear unhandled messges.
-    public void destroy() {
-        mHandler.removeMessages(RESOLVER_RANKER_SERVICE_RESULT);
-        mHandler.removeMessages(RESOLVER_RANKER_RESULT_TIMEOUT);
-        if (mConnection != null) {
-            mContext.unbindService(mConnection);
-            mConnection.destroy();
-        }
-        if (DEBUG) {
-            Log.d(TAG, "Unbinded Resolver Ranker.");
-        }
-    }
+    class LogisticRegressionAppRanker {
+        private static final String PARAM_SHARED_PREF_NAME = "resolver_ranker_params";
+        private static final String BIAS_PREF_KEY = "bias";
+        private static final String VERSION_PREF_KEY = "version";
 
-    // connect to a ranking service.
-    private void initRanker(Context context) {
-        synchronized (mLock) {
-            if (mConnection != null && mRanker != null) {
-                if (DEBUG) {
-                    Log.d(TAG, "Ranker still exists; reusing the existing one.");
-                }
+        // parameters for a pre-trained model, to initialize the app ranker. When updating the
+        // pre-trained model, please update these params, as well as initModel().
+        private static final int CURRENT_VERSION = 1;
+        private static final float LEARNING_RATE = 0.0001f;
+        private static final float REGULARIZER_PARAM = 0.0001f;
+
+        private SharedPreferences mParamSharedPref;
+        private ArrayMap<String, Float> mFeatureWeights;
+        private float mBias;
+
+        public LogisticRegressionAppRanker(Context context) {
+            mParamSharedPref = getParamSharedPref(context);
+            initModel();
+        }
+
+        public float predict(ArrayMap<String, Float> target) {
+            if (target == null) {
+                return 0.0f;
+            }
+            final int featureSize = target.size();
+            float sum = 0.0f;
+            for (int i = 0; i < featureSize; i++) {
+                String featureName = target.keyAt(i);
+                float weight = mFeatureWeights.getOrDefault(featureName, 0.0f);
+                sum += weight * target.valueAt(i);
+            }
+            return (float) (1.0 / (1.0 + Math.exp(-mBias - sum)));
+        }
+
+        public void update(ArrayMap<String, Float> target, float predict, boolean isSelected) {
+            if (target == null) {
                 return;
             }
-        }
-        Intent intent = resolveRankerService();
-        if (intent == null) {
-            return;
-        }
-        mConnectSignal = new CountDownLatch(1);
-        mConnection = new ResolverRankerServiceConnection(mConnectSignal);
-        context.bindServiceAsUser(intent, mConnection, Context.BIND_AUTO_CREATE, UserHandle.SYSTEM);
-    }
-
-    // resolve the service for ranking.
-    private Intent resolveRankerService() {
-        Intent intent = new Intent(ResolverRankerService.SERVICE_INTERFACE);
-        final List<ResolveInfo> resolveInfos = mPm.queryIntentServices(intent, 0);
-        for (ResolveInfo resolveInfo : resolveInfos) {
-            if (resolveInfo == null || resolveInfo.serviceInfo == null
-                    || resolveInfo.serviceInfo.applicationInfo == null) {
-                if (DEBUG) {
-                    Log.d(TAG, "Failed to retrieve a ranker: " + resolveInfo);
-                }
-                continue;
-            }
-            ComponentName componentName = new ComponentName(
-                    resolveInfo.serviceInfo.applicationInfo.packageName,
-                    resolveInfo.serviceInfo.name);
-            try {
-                final String perm = mPm.getServiceInfo(componentName, 0).permission;
-                if (!ResolverRankerService.BIND_PERMISSION.equals(perm)) {
-                    Log.w(TAG, "ResolverRankerService " + componentName + " does not require"
-                            + " permission " + ResolverRankerService.BIND_PERMISSION
-                            + " - this service will not be queried for ResolverComparator."
-                            + " add android:permission=\""
-                            + ResolverRankerService.BIND_PERMISSION + "\""
-                            + " to the <service> tag for " + componentName
-                            + " in the manifest.");
-                    continue;
-                }
-            } catch (NameNotFoundException e) {
-                Log.e(TAG, "Could not look up service " + componentName
-                        + "; component name not found");
-                continue;
+            final int featureSize = target.size();
+            float error = isSelected ? 1.0f - predict : -predict;
+            for (int i = 0; i < featureSize; i++) {
+                String featureName = target.keyAt(i);
+                float currentWeight = mFeatureWeights.getOrDefault(featureName, 0.0f);
+                mBias += LEARNING_RATE * error;
+                currentWeight = currentWeight - LEARNING_RATE * REGULARIZER_PARAM * currentWeight +
+                        LEARNING_RATE * error * target.valueAt(i);
+                mFeatureWeights.put(featureName, currentWeight);
             }
             if (DEBUG) {
-                Log.d(TAG, "Succeeded to retrieve a ranker: " + componentName);
+                Log.d(TAG, "Weights: " + mFeatureWeights + " Bias: " + mBias);
             }
-            intent.setComponent(componentName);
-            return intent;
-        }
-        return null;
-    }
-
-    // set a watchdog, to avoid waiting for ranking service for too long.
-    private void startWatchDog(int timeOutLimit) {
-        if (DEBUG) Log.d(TAG, "Setting watchdog timer for " + timeOutLimit + "ms");
-        if (mHandler == null) {
-            Log.d(TAG, "Error: Handler is Null; Needs to be initialized.");
-        }
-        mHandler.sendEmptyMessageDelayed(RESOLVER_RANKER_RESULT_TIMEOUT, timeOutLimit);
-    }
-
-    private class ResolverRankerServiceConnection implements ServiceConnection {
-        private final CountDownLatch mConnectSignal;
-
-        public ResolverRankerServiceConnection(CountDownLatch connectSignal) {
-            mConnectSignal = connectSignal;
         }
 
-        public final IResolverRankerResult resolverRankerResult =
-                new IResolverRankerResult.Stub() {
-            @Override
-            public void sendResult(List<ResolverTarget> targets) throws RemoteException {
-                if (DEBUG) {
-                    Log.d(TAG, "Sending Result back to Resolver: " + targets);
-                }
-                synchronized (mLock) {
-                    final Message msg = Message.obtain();
-                    msg.what = RESOLVER_RANKER_SERVICE_RESULT;
-                    msg.obj = targets;
-                    mHandler.sendMessage(msg);
-                }
+        public void commitUpdate() {
+            SharedPreferences.Editor editor = mParamSharedPref.edit();
+            editor.putFloat(BIAS_PREF_KEY, mBias);
+            final int size = mFeatureWeights.size();
+            for (int i = 0; i < size; i++) {
+                editor.putFloat(mFeatureWeights.keyAt(i), mFeatureWeights.valueAt(i));
             }
-        };
+            editor.putInt(VERSION_PREF_KEY, CURRENT_VERSION);
+            editor.apply();
+        }
 
-        @Override
-        public void onServiceConnected(ComponentName name, IBinder service) {
+        private SharedPreferences getParamSharedPref(Context context) {
+            // The package info in the context isn't initialized in the way it is for normal apps,
+            // so the standard, name-based context.getSharedPreferences doesn't work. Instead, we
+            // build the path manually below using the same policy that appears in ContextImpl.
             if (DEBUG) {
-                Log.d(TAG, "onServiceConnected: " + name);
+                Log.d(TAG, "Context Package Name: " + context.getPackageName());
             }
-            synchronized (mLock) {
-                mRanker = IResolverRankerService.Stub.asInterface(service);
-                mConnectSignal.countDown();
-            }
+            final File prefsFile = new File(new File(
+                    Environment.getDataUserCePackageDirectory(StorageManager.UUID_PRIVATE_INTERNAL,
+                            context.getUserId(), context.getPackageName()),
+                    "shared_prefs"),
+                    PARAM_SHARED_PREF_NAME + ".xml");
+            return context.getSharedPreferences(prefsFile, Context.MODE_PRIVATE);
         }
 
-        @Override
-        public void onServiceDisconnected(ComponentName name) {
-            if (DEBUG) {
-                Log.d(TAG, "onServiceDisconnected: " + name);
-            }
-            synchronized (mLock) {
-                destroy();
+        private void initModel() {
+            mFeatureWeights = new ArrayMap<>(4);
+            if (mParamSharedPref == null ||
+                    mParamSharedPref.getInt(VERSION_PREF_KEY, 0) < CURRENT_VERSION) {
+                // Initializing the app ranker to a pre-trained model. When updating the pre-trained
+                // model, please increment CURRENT_VERSION, and update LEARNING_RATE and
+                // REGULARIZER_PARAM.
+                mBias = -1.6568f;
+                mFeatureWeights.put(LAUNCH_SCORE, 2.5543f);
+                mFeatureWeights.put(TIME_SPENT_SCORE, 2.8412f);
+                mFeatureWeights.put(RECENCY_SCORE, 0.269f);
+                mFeatureWeights.put(CHOOSER_SCORE, 4.2222f);
+            } else {
+                mBias = mParamSharedPref.getFloat(BIAS_PREF_KEY, 0.0f);
+                mFeatureWeights.put(LAUNCH_SCORE, mParamSharedPref.getFloat(LAUNCH_SCORE, 0.0f));
+                mFeatureWeights.put(
+                        TIME_SPENT_SCORE, mParamSharedPref.getFloat(TIME_SPENT_SCORE, 0.0f));
+                mFeatureWeights.put(RECENCY_SCORE, mParamSharedPref.getFloat(RECENCY_SCORE, 0.0f));
+                mFeatureWeights.put(CHOOSER_SCORE, mParamSharedPref.getFloat(CHOOSER_SCORE, 0.0f));
             }
         }
-
-        public void destroy() {
-            synchronized (mLock) {
-                mRanker = null;
-            }
-        }
-    }
-
-    private void reset() {
-        mTargetsDict.clear();
-        mTargets = null;
-        startWatchDog(WATCHDOG_TIMEOUT_MILLIS);
-        initRanker(mContext);
-    }
-
-    // predict select probabilities if ranking service is valid.
-    private void predictSelectProbabilities(List<ResolverTarget> targets) {
-        if (mConnection == null) {
-            if (DEBUG) {
-                Log.d(TAG, "Has not found valid ResolverRankerService; Skip Prediction");
-            }
-            return;
-        } else {
-            try {
-                mConnectSignal.await(CONNECTION_COST_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
-                synchronized (mLock) {
-                    if (mRanker != null) {
-                        mRanker.predict(targets, mConnection.resolverRankerResult);
-                        return;
-                    } else {
-                        if (DEBUG) {
-                            Log.d(TAG, "Ranker has not been initialized; skip predict.");
-                        }
-                    }
-                }
-            } catch (InterruptedException e) {
-                Log.e(TAG, "Error in Wait for Service Connection.");
-            } catch (RemoteException e) {
-                Log.e(TAG, "Error in Predict: " + e);
-            }
-        }
-        mAfterCompute.afterCompute();
-    }
-
-    // adds select prob as the default values, according to a pre-trained Logistic Regression model.
-    private void addDefaultSelectProbability(ResolverTarget target) {
-        float sum = 2.5543f * target.getLaunchScore() + 2.8412f * target.getTimeSpentScore() +
-                0.269f * target.getRecencyScore() + 4.2222f * target.getChooserScore();
-        target.setSelectProbability((float) (1.0 / (1.0 + Math.exp(1.6568f - sum))));
-    }
-
-    // sets features for each target
-    private void setFeatures(ResolverTarget target, float recencyScore, float launchScore,
-                             float timeSpentScore, float chooserScore) {
-        target.setRecencyScore(recencyScore);
-        target.setLaunchScore(launchScore);
-        target.setTimeSpentScore(timeSpentScore);
-        target.setChooserScore(chooserScore);
-    }
-
-    static boolean isPersistentProcess(ResolvedComponentInfo rci) {
-        if (rci != null && rci.getCount() > 0) {
-            return (rci.getResolveInfoAt(0).activityInfo.applicationInfo.flags &
-                    ApplicationInfo.FLAG_PERSISTENT) != 0;
-        }
-        return false;
     }
 }
diff --git a/core/java/com/android/internal/app/ResolverListController.java b/core/java/com/android/internal/app/ResolverListController.java
index e8bebb7..4071ff4 100644
--- a/core/java/com/android/internal/app/ResolverListController.java
+++ b/core/java/com/android/internal/app/ResolverListController.java
@@ -32,10 +32,8 @@
 import android.util.Log;
 import com.android.internal.annotations.VisibleForTesting;
 
-import java.lang.InterruptedException;
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.concurrent.CountDownLatch;
 import java.util.List;
 
 /**
@@ -207,42 +205,14 @@
         return listToReturn;
     }
 
-    private class ComputeCallback implements ResolverComparator.AfterCompute {
-
-        private CountDownLatch mFinishComputeSignal;
-
-        public ComputeCallback(CountDownLatch finishComputeSignal) {
-            mFinishComputeSignal = finishComputeSignal;
-        }
-
-        public void afterCompute () {
-            mFinishComputeSignal.countDown();
-        }
-    }
-
     @VisibleForTesting
     @WorkerThread
     public void sort(List<ResolverActivity.ResolvedComponentInfo> inputList) {
-        final CountDownLatch finishComputeSignal = new CountDownLatch(1);
-        ComputeCallback callback = new ComputeCallback(finishComputeSignal);
         if (mResolverComparator == null) {
-            mResolverComparator =
-                    new ResolverComparator(mContext, mTargetIntent, mReferrerPackage, callback);
-        } else {
-            mResolverComparator.setCallBack(callback);
+            mResolverComparator = new ResolverComparator(mContext, mTargetIntent, mReferrerPackage);
         }
-        try {
-            long beforeRank = System.currentTimeMillis();
-            mResolverComparator.compute(inputList);
-            finishComputeSignal.await();
-            Collections.sort(inputList, mResolverComparator);
-            long afterRank = System.currentTimeMillis();
-            if (DEBUG) {
-                Log.d(TAG, "Time Cost: " + Long.toString(afterRank - beforeRank));
-            }
-        } catch (InterruptedException e) {
-            Log.e(TAG, "Compute & Sort was interrupted: " + e);
-        }
+        mResolverComparator.compute(inputList);
+        Collections.sort(inputList, mResolverComparator);
     }
 
     private static boolean isSameResolvedComponent(ResolveInfo a,
@@ -263,7 +233,7 @@
     @VisibleForTesting
     public float getScore(ResolverActivity.DisplayResolveInfo target) {
         if (mResolverComparator == null) {
-            return 0.0f;
+            mResolverComparator = new ResolverComparator(mContext, mTargetIntent, mReferrerPackage);
         }
         return mResolverComparator.getScore(target.getResolvedComponentName());
     }
@@ -279,10 +249,4 @@
             mResolverComparator.updateChooserCounts(packageName, userId, action);
         }
     }
-
-    public void destroy() {
-        if (mResolverComparator != null) {
-            mResolverComparator.destroy();
-        }
-    }
 }
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index a73f543..7922250 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -3130,15 +3130,6 @@
     <permission android:name="android.permission.BIND_CHOOSER_TARGET_SERVICE"
         android:protectionLevel="signature" />
 
-    <!-- @SystemApi Must be required by services that extend
-         {@link android.service.resolver.ResolverRankerService}, to ensure that only the system can
-         bind to them.
-         <p>Protection level: signature
-         @hide
-    -->
-    <permission android:name="android.permission.BIND_RESOLVER_RANKER_SERVICE"
-        android:protectionLevel="signature" />
-
     <!-- Must be required by a {@link
          android.service.notification.ConditionProviderService},
          to ensure that only the system can bind to it.
@@ -3650,14 +3641,6 @@
                  android:permission="android.permission.BIND_JOB_SERVICE" >
         </service>
 
-        <service android:name="com.android.internal.app.LRResolverRankerService"
-            android:permission="android.permission.BIND_RESOLVER_RANKER_SERVICE"
-            android:exported="false"
-            android:priority="-1" >
-            <intent-filter>
-                <action android:name="android.service.resolver.ResolverRankerService" />
-            </intent-filter>
-        </service>
     </application>
 
 </manifest>