Merge "Move timeout from RankerResolverServiceComparator to abstract class." into qt-dev

This commit is contained in:
TreeHugger Robot
2019-05-01 00:00:33 +00:00
committed by Android (Google) Code Review
3 changed files with 126 additions and 90 deletions

View File

@@ -22,9 +22,14 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.UserHandle;
import android.util.Log;
import com.android.internal.app.ResolverActivity.ResolvedComponentInfo;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
@@ -35,6 +40,8 @@ import java.util.List;
abstract class AbstractResolverComparator implements Comparator<ResolvedComponentInfo> {
private static final int NUM_OF_TOP_ANNOTATIONS_TO_USE = 3;
private static final boolean DEBUG = false;
private static final String TAG = "AbstractResolverComp";
private AfterCompute mAfterCompute;
protected final PackageManager mPm;
@@ -47,6 +54,46 @@ abstract class AbstractResolverComparator implements Comparator<ResolvedComponen
// can be null if mHttp == false or current user has no default browser package
private final String mDefaultBrowserPackageName;
// message types
static final int RANKER_SERVICE_RESULT = 0;
static final int RANKER_RESULT_TIMEOUT = 1;
// timeout for establishing connections with a ResolverRankerService, collecting features and
// predicting ranking scores.
private static final int WATCHDOG_TIMEOUT_MILLIS = 500;
protected final Handler mHandler = new Handler(Looper.getMainLooper()) {
public void handleMessage(Message msg) {
switch (msg.what) {
case RANKER_SERVICE_RESULT:
if (DEBUG) {
Log.d(TAG, "RANKER_SERVICE_RESULT");
}
if (mHandler.hasMessages(RANKER_RESULT_TIMEOUT)) {
if (msg.obj != null) {
handleResultMessage(msg);
} else {
Log.e(TAG, "Receiving null prediction results.");
}
mHandler.removeMessages(RANKER_RESULT_TIMEOUT);
afterCompute();
}
break;
case RANKER_RESULT_TIMEOUT:
if (DEBUG) {
Log.d(TAG, "RANKER_RESULT_TIMEOUT; unbinding services");
}
mHandler.removeMessages(RANKER_SERVICE_RESULT);
afterCompute();
break;
default:
super.handleMessage(msg);
}
}
};
AbstractResolverComparator(Context context, Intent intent) {
String scheme = intent.getScheme();
mHttp = "http".equals(scheme) || "https".equals(scheme);
@@ -142,9 +189,16 @@ abstract class AbstractResolverComparator implements Comparator<ResolvedComponen
* #getScore(ComponentName)} or {@link #compare(Object, Object)}, in order to prepare the
* comparator for those calls. Note that {@link #getScore(ComponentName)} uses {@link
* ComponentName}, so the implementation will have to be prepared to identify a {@link
* ResolvedComponentInfo} by {@link ComponentName}.
* ResolvedComponentInfo} by {@link ComponentName}. {@link #beforeCompute()} will be called
* before doing any computing.
*/
abstract void compute(List<ResolvedComponentInfo> targets);
final void compute(List<ResolvedComponentInfo> targets) {
beforeCompute();
doCompute(targets);
}
/** Implementation of compute called after {@link #beforeCompute()}. */
abstract void doCompute(List<ResolvedComponentInfo> targets);
/**
* Returns the score that was calculated for the corresponding {@link ResolvedComponentInfo}
@@ -152,6 +206,9 @@ abstract class AbstractResolverComparator implements Comparator<ResolvedComponen
*/
abstract float getScore(ComponentName name);
/** Handles result message sent to mHandler. */
abstract void handleResultMessage(Message message);
/**
* Reports to UsageStats what was chosen.
*/
@@ -172,10 +229,26 @@ abstract class AbstractResolverComparator implements Comparator<ResolvedComponen
void updateModel(ComponentName componentName) {
}
/** Called before {@link #doCompute(List)}. Sets up 500ms timeout. */
void beforeCompute() {
if (DEBUG) Log.d(TAG, "Setting watchdog timer for " + WATCHDOG_TIMEOUT_MILLIS + "ms");
if (mHandler == null) {
Log.d(TAG, "Error: Handler is Null; Needs to be initialized.");
return;
}
mHandler.sendEmptyMessageDelayed(RANKER_RESULT_TIMEOUT, WATCHDOG_TIMEOUT_MILLIS);
}
/**
* Called when the {@link ResolverActivity} is destroyed.
* Called when the {@link ResolverActivity} is destroyed. This calls {@link #afterCompute()}. If
* this call needs to happen at a different time during destroy, the method should be
* overridden.
*/
abstract void destroy();
void destroy() {
mHandler.removeMessages(RANKER_SERVICE_RESULT);
mHandler.removeMessages(RANKER_RESULT_TIMEOUT);
afterCompute();
}
private boolean isDefaultBrowser(ResolveInfo ri) {
// It makes sense to prefer the default browser

View File

@@ -26,6 +26,7 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.os.Message;
import android.os.UserHandle;
import android.view.textclassifier.Log;
@@ -73,7 +74,7 @@ class AppPredictionServiceResolverComparator extends AbstractResolverComparator
}
@Override
void compute(List<ResolvedComponentInfo> targets) {
void doCompute(List<ResolvedComponentInfo> targets) {
List<AppTarget> appTargets = new ArrayList<>();
for (ResolvedComponentInfo target : targets) {
appTargets.add(new AppTarget.Builder(new AppTargetId(target.name.flattenToString()))
@@ -82,14 +83,23 @@ class AppPredictionServiceResolverComparator extends AbstractResolverComparator
}
mAppPredictor.sortTargets(appTargets, mContext.getMainExecutor(),
sortedAppTargets -> {
for (int i = 0; i < sortedAppTargets.size(); i++) {
mTargetRanks.put(new ComponentName(sortedAppTargets.get(i).getPackageName(),
sortedAppTargets.get(i).getClassName()), i);
}
afterCompute();
Message msg =
Message.obtain(mHandler, RANKER_SERVICE_RESULT, sortedAppTargets);
msg.sendToTarget();
});
}
@Override
void handleResultMessage(Message msg) {
if (msg.what == RANKER_SERVICE_RESULT) {
final List<AppTarget> sortedAppTargets = (List<AppTarget>) msg.obj;
for (int i = 0; i < sortedAppTargets.size(); i++) {
mTargetRanks.put(new ComponentName(sortedAppTargets.get(i).getPackageName(),
sortedAppTargets.get(i).getClassName()), i);
}
}
}
@Override
float getScore(ComponentName name) {
Integer rank = mTargetRanks.get(name);
@@ -111,9 +121,4 @@ class AppPredictionServiceResolverComparator extends AbstractResolverComparator
.setClassName(componentName.getClassName()).build(),
ACTION_LAUNCH).build());
}
@Override
void destroy() {
// Do nothing. App Predictor destruction is handled by caller.
}
}

View File

@@ -18,7 +18,6 @@
package com.android.internal.app;
import android.app.usage.UsageStats;
import android.app.usage.UsageStatsManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -28,9 +27,7 @@ import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.metrics.LogMaker;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import android.os.UserHandle;
@@ -67,10 +64,6 @@ class ResolverRankerServiceResolverComparator extends AbstractResolverComparator
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
@@ -93,57 +86,6 @@ class ResolverRankerServiceResolverComparator extends AbstractResolverComparator
private Context mContext;
private CountDownLatch mConnectSignal;
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();
boolean isUpdated = false;
for (int i = 0; i < size; ++i) {
final float predictedProb =
receivedTargets.get(i).getSelectProbability();
if (predictedProb != mTargets.get(i).getSelectProbability()) {
mTargets.get(i).setSelectProbability(predictedProb);
isUpdated = true;
}
}
if (isUpdated) {
mRankerServiceName = mResolvedRankerName;
}
} 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);
afterCompute();
}
break;
case RESOLVER_RANKER_RESULT_TIMEOUT:
if (DEBUG) {
Log.d(TAG, "RESOLVER_RANKER_RESULT_TIMEOUT; unbinding services");
}
mHandler.removeMessages(RESOLVER_RANKER_SERVICE_RESULT);
afterCompute();
break;
default:
super.handleMessage(msg);
}
}
};
public ResolverRankerServiceResolverComparator(Context context, Intent intent,
String referrerPackage, AfterCompute afterCompute) {
super(context, intent);
@@ -159,11 +101,35 @@ class ResolverRankerServiceResolverComparator extends AbstractResolverComparator
setCallBack(afterCompute);
}
@Override
public void handleResultMessage(Message msg) {
if (msg.what != RANKER_SERVICE_RESULT) {
return;
}
final List<ResolverTarget> receivedTargets = (List<ResolverTarget>) msg.obj;
if (receivedTargets != null && mTargets != null
&& receivedTargets.size() == mTargets.size()) {
final int size = mTargets.size();
boolean isUpdated = false;
for (int i = 0; i < size; ++i) {
final float predictedProb =
receivedTargets.get(i).getSelectProbability();
if (predictedProb != mTargets.get(i).getSelectProbability()) {
mTargets.get(i).setSelectProbability(predictedProb);
isUpdated = true;
}
}
if (isUpdated) {
mRankerServiceName = mResolvedRankerName;
}
} else {
Log.e(TAG, "Sizes of sent and received ResolverTargets diff.");
}
}
// compute features for each target according to usage stats of targets.
@Override
public void compute(List<ResolvedComponentInfo> targets) {
reset();
public void doCompute(List<ResolvedComponentInfo> targets) {
final long recentSinceTime = mCurrentTime - RECENCY_TIME_PERIOD;
float mostRecencyScore = 1.0f;
@@ -322,8 +288,8 @@ class ResolverRankerServiceResolverComparator extends AbstractResolverComparator
// unbind the service and clear unhandled messges.
@Override
public void destroy() {
mHandler.removeMessages(RESOLVER_RANKER_SERVICE_RESULT);
mHandler.removeMessages(RESOLVER_RANKER_RESULT_TIMEOUT);
mHandler.removeMessages(RANKER_SERVICE_RESULT);
mHandler.removeMessages(RANKER_RESULT_TIMEOUT);
if (mConnection != null) {
mContext.unbindService(mConnection);
mConnection.destroy();
@@ -417,15 +383,6 @@ class ResolverRankerServiceResolverComparator extends AbstractResolverComparator
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;
@@ -442,7 +399,7 @@ class ResolverRankerServiceResolverComparator extends AbstractResolverComparator
}
synchronized (mLock) {
final Message msg = Message.obtain();
msg.what = RESOLVER_RANKER_SERVICE_RESULT;
msg.what = RANKER_SERVICE_RESULT;
msg.obj = targets;
mHandler.sendMessage(msg);
}
@@ -477,12 +434,13 @@ class ResolverRankerServiceResolverComparator extends AbstractResolverComparator
}
}
private void reset() {
@Override
void beforeCompute() {
super.beforeCompute();
mTargetsDict.clear();
mTargets = null;
mRankerServiceName = new ComponentName(mContext, this.getClass());
mResolvedRankerName = null;
startWatchDog(WATCHDOG_TIMEOUT_MILLIS);
initRanker(mContext);
}