summaryrefslogtreecommitdiff
path: root/packages/ExtServices/src
diff options
context:
space:
mode:
Diffstat (limited to 'packages/ExtServices/src')
-rw-r--r--packages/ExtServices/src/android/ext/services/Version.java36
-rw-r--r--packages/ExtServices/src/android/ext/services/autofill/AutofillFieldClassificationServiceImpl.java52
-rw-r--r--packages/ExtServices/src/android/ext/services/autofill/EditDistanceScorer.java148
-rw-r--r--packages/ExtServices/src/android/ext/services/notification/Assistant.java382
-rw-r--r--packages/ExtServices/src/android/ext/services/notification/ChannelImpressions.java209
-rw-r--r--packages/ExtServices/src/android/ext/services/resolver/LRResolverRankerService.java199
-rw-r--r--packages/ExtServices/src/android/ext/services/storage/CacheQuotaServiceImpl.java143
7 files changed, 0 insertions, 1169 deletions
diff --git a/packages/ExtServices/src/android/ext/services/Version.java b/packages/ExtServices/src/android/ext/services/Version.java
deleted file mode 100644
index 026cccd37334..000000000000
--- a/packages/ExtServices/src/android/ext/services/Version.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2016 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.ext.services;
-
-/**
- * Class that provides the version of the library.
- */
-public final class Version {
-
- private Version() {
- /* do nothing - hide constructor */
- }
-
- /**
- * Gets the version of the library.
- *
- * @return The version.
- */
- public static int getVersionCode() {
- return 1;
- }
-} \ No newline at end of file
diff --git a/packages/ExtServices/src/android/ext/services/autofill/AutofillFieldClassificationServiceImpl.java b/packages/ExtServices/src/android/ext/services/autofill/AutofillFieldClassificationServiceImpl.java
deleted file mode 100644
index 9ba7e092f34b..000000000000
--- a/packages/ExtServices/src/android/ext/services/autofill/AutofillFieldClassificationServiceImpl.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * 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.ext.services.autofill;
-
-import static android.ext.services.autofill.EditDistanceScorer.DEFAULT_ALGORITHM;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.os.Bundle;
-import android.service.autofill.AutofillFieldClassificationService;
-import android.util.Log;
-import android.view.autofill.AutofillValue;
-
-import com.android.internal.util.ArrayUtils;
-
-import java.util.List;
-
-public class AutofillFieldClassificationServiceImpl extends AutofillFieldClassificationService {
-
- private static final String TAG = "AutofillFieldClassificationServiceImpl";
-
- @Nullable
- @Override
- public float[][] onGetScores(@Nullable String algorithmName,
- @Nullable Bundle algorithmArgs, @NonNull List<AutofillValue> actualValues,
- @NonNull List<String> userDataValues) {
- if (ArrayUtils.isEmpty(actualValues) || ArrayUtils.isEmpty(userDataValues)) {
- Log.w(TAG, "getScores(): empty currentvalues (" + actualValues + ") or userValues ("
- + userDataValues + ")");
- return null;
- }
- if (algorithmName != null && !algorithmName.equals(DEFAULT_ALGORITHM)) {
- Log.w(TAG, "Ignoring invalid algorithm (" + algorithmName + ") and using "
- + DEFAULT_ALGORITHM + " instead");
- }
-
- return EditDistanceScorer.getScores(actualValues, userDataValues);
- }
-}
diff --git a/packages/ExtServices/src/android/ext/services/autofill/EditDistanceScorer.java b/packages/ExtServices/src/android/ext/services/autofill/EditDistanceScorer.java
deleted file mode 100644
index 302b16022c26..000000000000
--- a/packages/ExtServices/src/android/ext/services/autofill/EditDistanceScorer.java
+++ /dev/null
@@ -1,148 +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.ext.services.autofill;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.util.Log;
-import android.view.autofill.AutofillValue;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.util.List;
-
-final class EditDistanceScorer {
-
- private static final String TAG = "EditDistanceScorer";
-
- // TODO(b/70291841): STOPSHIP - set to false before launching
- private static final boolean DEBUG = true;
-
- static final String DEFAULT_ALGORITHM = "EDIT_DISTANCE";
-
- /**
- * Gets the field classification score of 2 values based on the edit distance between them.
- *
- * <p>The score is defined as: @(max_length - edit_distance) / max_length
- */
- @VisibleForTesting
- static float getScore(@Nullable AutofillValue actualValue, @Nullable String userDataValue) {
- if (actualValue == null || !actualValue.isText() || userDataValue == null) return 0;
-
- final String actualValueText = actualValue.getTextValue().toString();
- final int actualValueLength = actualValueText.length();
- final int userDatalength = userDataValue.length();
- if (userDatalength == 0) {
- return (actualValueLength == 0) ? 1 : 0;
- }
-
- final int distance = editDistance(actualValueText.toLowerCase(),
- userDataValue.toLowerCase());
- final int maxLength = Math.max(actualValueLength, userDatalength);
- return ((float) maxLength - distance) / maxLength;
- }
-
- /**
- * Computes the edit distance (number of insertions, deletions or substitutions to edit one
- * string into the other) between two strings. In particular, this will compute the Levenshtein
- * distance.
- *
- * <p>See http://en.wikipedia.org/wiki/Levenshtein_distance for details.
- *
- * @param s the first string to compare
- * @param t the second string to compare
- * @return the edit distance between the two strings
- */
- // Note: copied verbatim from com.android.tools.lint.detector.api.LintUtils.java
- public static int editDistance(@NonNull String s, @NonNull String t) {
- return editDistance(s, t, Integer.MAX_VALUE);
- }
-
- /**
- * Computes the edit distance (number of insertions, deletions or substitutions to edit one
- * string into the other) between two strings. In particular, this will compute the Levenshtein
- * distance.
- *
- * <p>See http://en.wikipedia.org/wiki/Levenshtein_distance for details.
- *
- * @param s the first string to compare
- * @param t the second string to compare
- * @param max the maximum edit distance that we care about; if for example the string length
- * delta is greater than this we don't bother computing the exact edit distance since the
- * caller has indicated they're not interested in the result
- * @return the edit distance between the two strings, or some other value greater than that if
- * the edit distance is at least as big as the {@code max} parameter
- */
- // Note: copied verbatim from com.android.tools.lint.detector.api.LintUtils.java
- private static int editDistance(@NonNull String s, @NonNull String t, int max) {
- if (s.equals(t)) {
- return 0;
- }
-
- if (Math.abs(s.length() - t.length()) > max) {
- // The string lengths differ more than the allowed edit distance;
- // no point in even attempting to compute the edit distance (requires
- // O(n*m) storage and O(n*m) speed, where n and m are the string lengths)
- return Integer.MAX_VALUE;
- }
-
- int m = s.length();
- int n = t.length();
- int[][] d = new int[m + 1][n + 1];
- for (int i = 0; i <= m; i++) {
- d[i][0] = i;
- }
- for (int j = 0; j <= n; j++) {
- d[0][j] = j;
- }
- for (int j = 1; j <= n; j++) {
- for (int i = 1; i <= m; i++) {
- if (s.charAt(i - 1) == t.charAt(j - 1)) {
- d[i][j] = d[i - 1][j - 1];
- } else {
- int deletion = d[i - 1][j] + 1;
- int insertion = d[i][j - 1] + 1;
- int substitution = d[i - 1][j - 1] + 1;
- d[i][j] = Math.min(deletion, Math.min(insertion, substitution));
- }
- }
- }
-
- return d[m][n];
- }
- /**
- * Gets the scores in a batch.
- */
- static float[][] getScores(@NonNull List<AutofillValue> actualValues,
- @NonNull List<String> userDataValues) {
- final int actualValuesSize = actualValues.size();
- final int userDataValuesSize = userDataValues.size();
- if (DEBUG) {
- Log.d(TAG, "getScores() will return a " + actualValuesSize + "x"
- + userDataValuesSize + " matrix for " + DEFAULT_ALGORITHM);
- }
- final float[][] scores = new float[actualValuesSize][userDataValuesSize];
-
- for (int i = 0; i < actualValuesSize; i++) {
- for (int j = 0; j < userDataValuesSize; j++) {
- final float score = getScore(actualValues.get(i), userDataValues.get(j));
- scores[i][j] = score;
- }
- }
- return scores;
- }
-
-}
diff --git a/packages/ExtServices/src/android/ext/services/notification/Assistant.java b/packages/ExtServices/src/android/ext/services/notification/Assistant.java
deleted file mode 100644
index f8788226fc51..000000000000
--- a/packages/ExtServices/src/android/ext/services/notification/Assistant.java
+++ /dev/null
@@ -1,382 +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.ext.services.notification;
-
-import static android.app.NotificationManager.IMPORTANCE_MIN;
-import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE;
-
-import android.app.INotificationManager;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.database.ContentObserver;
-import android.ext.services.R;
-import android.net.Uri;
-import android.os.AsyncTask;
-import android.os.Bundle;
-import android.os.Environment;
-import android.os.Handler;
-import android.os.storage.StorageManager;
-import android.provider.Settings;
-import android.service.notification.Adjustment;
-import android.service.notification.NotificationAssistantService;
-import android.service.notification.NotificationStats;
-import android.service.notification.StatusBarNotification;
-import android.util.ArrayMap;
-import android.util.AtomicFile;
-import android.util.Log;
-import android.util.Slog;
-import android.util.Xml;
-
-import com.android.internal.util.FastXmlSerializer;
-import com.android.internal.util.XmlUtils;
-
-import libcore.io.IoUtils;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlSerializer;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.Map;
-
-/**
- * Notification assistant that provides guidance on notification channel blocking
- */
-public class Assistant extends NotificationAssistantService {
- private static final String TAG = "ExtAssistant";
- private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-
- private static final String TAG_ASSISTANT = "assistant";
- private static final String TAG_IMPRESSION = "impression-set";
- private static final String ATT_KEY = "key";
- private static final int DB_VERSION = 1;
- private static final String ATTR_VERSION = "version";
-
- private static final ArrayList<Integer> PREJUDICAL_DISMISSALS = new ArrayList<>();
- static {
- PREJUDICAL_DISMISSALS.add(REASON_CANCEL);
- PREJUDICAL_DISMISSALS.add(REASON_LISTENER_CANCEL);
- }
-
- private float mDismissToViewRatioLimit;
- private int mStreakLimit;
-
- // key : impressions tracker
- // TODO: prune deleted channels and apps
- final ArrayMap<String, ChannelImpressions> mkeyToImpressions = new ArrayMap<>();
- // SBN key : channel id
- ArrayMap<String, String> mLiveNotifications = new ArrayMap<>();
-
- private Ranking mFakeRanking = null;
- private AtomicFile mFile = null;
-
- public Assistant() {
- }
-
- @Override
- public void onCreate() {
- super.onCreate();
- // Contexts are correctly hooked up by the creation step, which is required for the observer
- // to be hooked up/initialized.
- new SettingsObserver(mHandler);
- }
-
- private void loadFile() {
- if (DEBUG) Slog.d(TAG, "loadFile");
- AsyncTask.execute(() -> {
- InputStream infile = null;
- try {
- infile = mFile.openRead();
- readXml(infile);
- } catch (FileNotFoundException e) {
- Log.d(TAG, "File doesn't exist or isn't readable yet");
- } catch (IOException e) {
- Log.e(TAG, "Unable to read channel impressions", e);
- } catch (NumberFormatException | XmlPullParserException e) {
- Log.e(TAG, "Unable to parse channel impressions", e);
- } finally {
- IoUtils.closeQuietly(infile);
- }
- });
- }
-
- protected void readXml(InputStream stream)
- throws XmlPullParserException, NumberFormatException, IOException {
- final XmlPullParser parser = Xml.newPullParser();
- parser.setInput(stream, StandardCharsets.UTF_8.name());
- final int outerDepth = parser.getDepth();
- while (XmlUtils.nextElementWithin(parser, outerDepth)) {
- if (!TAG_ASSISTANT.equals(parser.getName())) {
- continue;
- }
- final int impressionOuterDepth = parser.getDepth();
- while (XmlUtils.nextElementWithin(parser, impressionOuterDepth)) {
- if (!TAG_IMPRESSION.equals(parser.getName())) {
- continue;
- }
- String key = parser.getAttributeValue(null, ATT_KEY);
- ChannelImpressions ci = createChannelImpressionsWithThresholds();
- ci.populateFromXml(parser);
- synchronized (mkeyToImpressions) {
- ci.append(mkeyToImpressions.get(key));
- mkeyToImpressions.put(key, ci);
- }
- }
- }
- }
-
- private void saveFile() throws IOException {
- AsyncTask.execute(() -> {
- final FileOutputStream stream;
- try {
- stream = mFile.startWrite();
- } catch (IOException e) {
- Slog.w(TAG, "Failed to save policy file", e);
- return;
- }
- try {
- final XmlSerializer out = new FastXmlSerializer();
- out.setOutput(stream, StandardCharsets.UTF_8.name());
- writeXml(out);
- mFile.finishWrite(stream);
- } catch (IOException e) {
- Slog.w(TAG, "Failed to save impressions file, restoring backup", e);
- mFile.failWrite(stream);
- }
- });
- }
-
- protected void writeXml(XmlSerializer out) throws IOException {
- out.startDocument(null, true);
- out.startTag(null, TAG_ASSISTANT);
- out.attribute(null, ATTR_VERSION, Integer.toString(DB_VERSION));
- synchronized (mkeyToImpressions) {
- for (Map.Entry<String, ChannelImpressions> entry
- : mkeyToImpressions.entrySet()) {
- // TODO: ensure channel still exists
- out.startTag(null, TAG_IMPRESSION);
- out.attribute(null, ATT_KEY, entry.getKey());
- entry.getValue().writeXml(out);
- out.endTag(null, TAG_IMPRESSION);
- }
- }
- out.endTag(null, TAG_ASSISTANT);
- out.endDocument();
- }
-
- @Override
- public Adjustment onNotificationEnqueued(StatusBarNotification sbn) {
- if (DEBUG) Log.i(TAG, "ENQUEUED " + sbn.getKey());
- return null;
- }
-
- @Override
- public void onNotificationPosted(StatusBarNotification sbn, RankingMap rankingMap) {
- if (DEBUG) Log.i(TAG, "POSTED " + sbn.getKey());
- try {
- Ranking ranking = getRanking(sbn.getKey(), rankingMap);
- if (ranking != null && ranking.getChannel() != null) {
- String key = getKey(
- sbn.getPackageName(), sbn.getUserId(), ranking.getChannel().getId());
- ChannelImpressions ci = mkeyToImpressions.getOrDefault(key,
- createChannelImpressionsWithThresholds());
- if (ranking.getImportance() > IMPORTANCE_MIN && ci.shouldTriggerBlock()) {
- adjustNotification(createNegativeAdjustment(
- sbn.getPackageName(), sbn.getKey(), sbn.getUserId()));
- }
- mkeyToImpressions.put(key, ci);
- mLiveNotifications.put(sbn.getKey(), ranking.getChannel().getId());
- }
- } catch (Throwable e) {
- Log.e(TAG, "Error occurred processing post", e);
- }
- }
-
- @Override
- public void onNotificationRemoved(StatusBarNotification sbn, RankingMap rankingMap,
- NotificationStats stats, int reason) {
- try {
- boolean updatedImpressions = false;
- String channelId = mLiveNotifications.remove(sbn.getKey());
- String key = getKey(sbn.getPackageName(), sbn.getUserId(), channelId);
- synchronized (mkeyToImpressions) {
- ChannelImpressions ci = mkeyToImpressions.getOrDefault(key,
- createChannelImpressionsWithThresholds());
- if (stats.hasSeen()) {
- ci.incrementViews();
- updatedImpressions = true;
- }
- if (PREJUDICAL_DISMISSALS.contains(reason)) {
- if ((!sbn.isAppGroup() || sbn.getNotification().isGroupChild())
- && !stats.hasInteracted()
- && stats.getDismissalSurface() != NotificationStats.DISMISSAL_AOD
- && stats.getDismissalSurface() != NotificationStats.DISMISSAL_PEEK
- && stats.getDismissalSurface() != NotificationStats.DISMISSAL_OTHER) {
- if (DEBUG) Log.i(TAG, "increment dismissals " + key);
- ci.incrementDismissals();
- updatedImpressions = true;
- } else {
- if (DEBUG) Slog.i(TAG, "reset streak " + key);
- if (ci.getStreak() > 0) {
- updatedImpressions = true;
- }
- ci.resetStreak();
- }
- }
- mkeyToImpressions.put(key, ci);
- }
- if (updatedImpressions) {
- saveFile();
- }
- } catch (Throwable e) {
- Slog.e(TAG, "Error occurred processing removal", e);
- }
- }
-
- @Override
- public void onNotificationSnoozedUntilContext(StatusBarNotification sbn,
- String snoozeCriterionId) {
- }
-
- @Override
- public void onListenerConnected() {
- if (DEBUG) Log.i(TAG, "CONNECTED");
- try {
- mFile = new AtomicFile(new File(new File(
- Environment.getDataUserCePackageDirectory(
- StorageManager.UUID_PRIVATE_INTERNAL, getUserId(), getPackageName()),
- "assistant"), "blocking_helper_stats.xml"));
- loadFile();
- for (StatusBarNotification sbn : getActiveNotifications()) {
- onNotificationPosted(sbn);
- }
- } catch (Throwable e) {
- Log.e(TAG, "Error occurred on connection", e);
- }
- }
-
- protected String getKey(String pkg, int userId, String channelId) {
- return pkg + "|" + userId + "|" + channelId;
- }
-
- private Ranking getRanking(String key, RankingMap rankingMap) {
- if (mFakeRanking != null) {
- return mFakeRanking;
- }
- Ranking ranking = new Ranking();
- rankingMap.getRanking(key, ranking);
- return ranking;
- }
-
- private Adjustment createNegativeAdjustment(String packageName, String key, int user) {
- if (DEBUG) Log.d(TAG, "User probably doesn't want " + key);
- Bundle signals = new Bundle();
- signals.putInt(Adjustment.KEY_USER_SENTIMENT, USER_SENTIMENT_NEGATIVE);
- return new Adjustment(packageName, key, signals,
- getContext().getString(R.string.prompt_block_reason), user);
- }
-
- // for testing
-
- protected void setFile(AtomicFile file) {
- mFile = file;
- }
-
- protected void setFakeRanking(Ranking ranking) {
- mFakeRanking = ranking;
- }
-
- protected void setNoMan(INotificationManager noMan) {
- mNoMan = noMan;
- }
-
- protected void setContext(Context context) {
- mSystemContext = context;
- }
-
- protected ChannelImpressions getImpressions(String key) {
- synchronized (mkeyToImpressions) {
- return mkeyToImpressions.get(key);
- }
- }
-
- protected void insertImpressions(String key, ChannelImpressions ci) {
- synchronized (mkeyToImpressions) {
- mkeyToImpressions.put(key, ci);
- }
- }
-
- private ChannelImpressions createChannelImpressionsWithThresholds() {
- ChannelImpressions impressions = new ChannelImpressions();
- impressions.updateThresholds(mDismissToViewRatioLimit, mStreakLimit);
- return impressions;
- }
-
- /**
- * Observer for updates on blocking helper threshold values.
- */
- private final class SettingsObserver extends ContentObserver {
- private final Uri STREAK_LIMIT_URI =
- Settings.Global.getUriFor(Settings.Global.BLOCKING_HELPER_STREAK_LIMIT);
- private final Uri DISMISS_TO_VIEW_RATIO_LIMIT_URI =
- Settings.Global.getUriFor(
- Settings.Global.BLOCKING_HELPER_DISMISS_TO_VIEW_RATIO_LIMIT);
-
- public SettingsObserver(Handler handler) {
- super(handler);
- ContentResolver resolver = getApplicationContext().getContentResolver();
- resolver.registerContentObserver(
- DISMISS_TO_VIEW_RATIO_LIMIT_URI, false, this, getUserId());
- resolver.registerContentObserver(STREAK_LIMIT_URI, false, this, getUserId());
-
- // Update all uris on creation.
- update(null);
- }
-
- @Override
- public void onChange(boolean selfChange, Uri uri) {
- update(uri);
- }
-
- private void update(Uri uri) {
- ContentResolver resolver = getApplicationContext().getContentResolver();
- if (uri == null || DISMISS_TO_VIEW_RATIO_LIMIT_URI.equals(uri)) {
- mDismissToViewRatioLimit = Settings.Global.getFloat(
- resolver, Settings.Global.BLOCKING_HELPER_DISMISS_TO_VIEW_RATIO_LIMIT,
- ChannelImpressions.DEFAULT_DISMISS_TO_VIEW_RATIO_LIMIT);
- }
- if (uri == null || STREAK_LIMIT_URI.equals(uri)) {
- mStreakLimit = Settings.Global.getInt(
- resolver, Settings.Global.BLOCKING_HELPER_STREAK_LIMIT,
- ChannelImpressions.DEFAULT_STREAK_LIMIT);
- }
-
- // Update all existing channel impression objects with any new limits/thresholds.
- synchronized (mkeyToImpressions) {
- for (ChannelImpressions channelImpressions: mkeyToImpressions.values()) {
- channelImpressions.updateThresholds(mDismissToViewRatioLimit, mStreakLimit);
- }
- }
- }
- }
-} \ No newline at end of file
diff --git a/packages/ExtServices/src/android/ext/services/notification/ChannelImpressions.java b/packages/ExtServices/src/android/ext/services/notification/ChannelImpressions.java
deleted file mode 100644
index 29ee920d4dde..000000000000
--- a/packages/ExtServices/src/android/ext/services/notification/ChannelImpressions.java
+++ /dev/null
@@ -1,209 +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.ext.services.notification;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.text.TextUtils;
-import android.util.Log;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlSerializer;
-
-import java.io.IOException;
-
-public final class ChannelImpressions implements Parcelable {
- private static final String TAG = "ExtAssistant.CI";
- private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-
- static final float DEFAULT_DISMISS_TO_VIEW_RATIO_LIMIT = .8f;
- static final int DEFAULT_STREAK_LIMIT = 2;
- static final String ATT_DISMISSALS = "dismisses";
- static final String ATT_VIEWS = "views";
- static final String ATT_STREAK = "streak";
-
- private int mDismissals = 0;
- private int mViews = 0;
- private int mStreak = 0;
-
- private float mDismissToViewRatioLimit;
- private int mStreakLimit;
-
- public ChannelImpressions() {
- mDismissToViewRatioLimit = DEFAULT_DISMISS_TO_VIEW_RATIO_LIMIT;
- mStreakLimit = DEFAULT_STREAK_LIMIT;
- }
-
- protected ChannelImpressions(Parcel in) {
- mDismissals = in.readInt();
- mViews = in.readInt();
- mStreak = in.readInt();
- mDismissToViewRatioLimit = in.readFloat();
- mStreakLimit = in.readInt();
- }
-
- public int getStreak() {
- return mStreak;
- }
-
- public int getDismissals() {
- return mDismissals;
- }
-
- public int getViews() {
- return mViews;
- }
-
- public void incrementDismissals() {
- mDismissals++;
- mStreak++;
- }
-
- void updateThresholds(float dismissToViewRatioLimit, int streakLimit) {
- mDismissToViewRatioLimit = dismissToViewRatioLimit;
- mStreakLimit = streakLimit;
- }
-
- @VisibleForTesting
- float getDismissToViewRatioLimit() {
- return mDismissToViewRatioLimit;
- }
-
- @VisibleForTesting
- int getStreakLimit() {
- return mStreakLimit;
- }
-
- public void append(ChannelImpressions additionalImpressions) {
- if (additionalImpressions != null) {
- mViews += additionalImpressions.getViews();
- mStreak += additionalImpressions.getStreak();
- mDismissals += additionalImpressions.getDismissals();
- }
- }
-
- public void incrementViews() {
- mViews++;
- }
-
- public void resetStreak() {
- mStreak = 0;
- }
-
- public boolean shouldTriggerBlock() {
- if (getViews() == 0) {
- return false;
- }
- if (DEBUG) {
- Log.d(TAG, "should trigger? " + getDismissals() + " " + getViews() + " " + getStreak());
- }
- return ((float) getDismissals() / getViews()) > mDismissToViewRatioLimit
- && getStreak() > mStreakLimit;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(mDismissals);
- dest.writeInt(mViews);
- dest.writeInt(mStreak);
- dest.writeFloat(mDismissToViewRatioLimit);
- dest.writeInt(mStreakLimit);
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- public static final Creator<ChannelImpressions> CREATOR = new Creator<ChannelImpressions>() {
- @Override
- public ChannelImpressions createFromParcel(Parcel in) {
- return new ChannelImpressions(in);
- }
-
- @Override
- public ChannelImpressions[] newArray(int size) {
- return new ChannelImpressions[size];
- }
- };
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
-
- ChannelImpressions that = (ChannelImpressions) o;
-
- if (mDismissals != that.mDismissals) return false;
- if (mViews != that.mViews) return false;
- return mStreak == that.mStreak;
- }
-
- @Override
- public int hashCode() {
- int result = mDismissals;
- result = 31 * result + mViews;
- result = 31 * result + mStreak;
- return result;
- }
-
- @Override
- public String toString() {
- final StringBuilder sb = new StringBuilder("ChannelImpressions{");
- sb.append("mDismissals=").append(mDismissals);
- sb.append(", mViews=").append(mViews);
- sb.append(", mStreak=").append(mStreak);
- sb.append(", thresholds=(").append(mDismissToViewRatioLimit);
- sb.append(",").append(mStreakLimit);
- sb.append(")}");
- return sb.toString();
- }
-
- protected void populateFromXml(XmlPullParser parser) {
- mDismissals = safeInt(parser, ATT_DISMISSALS, 0);
- mStreak = safeInt(parser, ATT_STREAK, 0);
- mViews = safeInt(parser, ATT_VIEWS, 0);
- }
-
- protected void writeXml(XmlSerializer out) throws IOException {
- if (mDismissals != 0) {
- out.attribute(null, ATT_DISMISSALS, String.valueOf(mDismissals));
- }
- if (mStreak != 0) {
- out.attribute(null, ATT_STREAK, String.valueOf(mStreak));
- }
- if (mViews != 0) {
- out.attribute(null, ATT_VIEWS, String.valueOf(mViews));
- }
- }
-
- private static int safeInt(XmlPullParser parser, String att, int defValue) {
- final String val = parser.getAttributeValue(null, att);
- return tryParseInt(val, defValue);
- }
-
- private static int tryParseInt(String value, int defValue) {
- if (TextUtils.isEmpty(value)) return defValue;
- try {
- return Integer.parseInt(value);
- } catch (NumberFormatException e) {
- return defValue;
- }
- }
-}
diff --git a/packages/ExtServices/src/android/ext/services/resolver/LRResolverRankerService.java b/packages/ExtServices/src/android/ext/services/resolver/LRResolverRankerService.java
deleted file mode 100644
index 9d7a5689dcd1..000000000000
--- a/packages/ExtServices/src/android/ext/services/resolver/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 android.ext.services.resolver;
-
-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/packages/ExtServices/src/android/ext/services/storage/CacheQuotaServiceImpl.java b/packages/ExtServices/src/android/ext/services/storage/CacheQuotaServiceImpl.java
deleted file mode 100644
index 862f50b2b627..000000000000
--- a/packages/ExtServices/src/android/ext/services/storage/CacheQuotaServiceImpl.java
+++ /dev/null
@@ -1,143 +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.ext.services.storage;
-
-import android.app.usage.CacheQuotaHint;
-import android.app.usage.CacheQuotaService;
-import android.os.Environment;
-import android.os.storage.StorageManager;
-import android.os.storage.VolumeInfo;
-import android.util.ArrayMap;
-
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
-
-/**
- * CacheQuotaServiceImpl implements the CacheQuotaService with a strategy for populating the quota
- * of {@link CacheQuotaHint}.
- */
-public class CacheQuotaServiceImpl extends CacheQuotaService {
- private static final double CACHE_RESERVE_RATIO = 0.15;
-
- @Override
- public List<CacheQuotaHint> onComputeCacheQuotaHints(List<CacheQuotaHint> requests) {
- ArrayMap<String, List<CacheQuotaHint>> byUuid = new ArrayMap<>();
- final int requestCount = requests.size();
- for (int i = 0; i < requestCount; i++) {
- CacheQuotaHint request = requests.get(i);
- String uuid = request.getVolumeUuid();
- List<CacheQuotaHint> listForUuid = byUuid.get(uuid);
- if (listForUuid == null) {
- listForUuid = new ArrayList<>();
- byUuid.put(uuid, listForUuid);
- }
- listForUuid.add(request);
- }
-
- List<CacheQuotaHint> processed = new ArrayList<>();
- byUuid.entrySet().forEach(
- requestListEntry -> {
- // Collapse all usage stats to the same uid.
- Map<Integer, List<CacheQuotaHint>> byUid = requestListEntry.getValue()
- .stream()
- .collect(Collectors.groupingBy(CacheQuotaHint::getUid));
- byUid.values().forEach(uidGroupedList -> {
- int size = uidGroupedList.size();
- if (size < 2) {
- return;
- }
- CacheQuotaHint first = uidGroupedList.get(0);
- for (int i = 1; i < size; i++) {
- /* Note: We can't use the UsageStats built-in addition function because
- UIDs may span multiple packages and usage stats adding has
- matching package names as a precondition. */
- first.getUsageStats().mTotalTimeInForeground +=
- uidGroupedList.get(i).getUsageStats().mTotalTimeInForeground;
- }
- });
-
- // Because the foreground stats have been added to the first element, we need
- // a list of only the first values (which contain the merged foreground time).
- List<CacheQuotaHint> flattenedRequests =
- byUid.values()
- .stream()
- .map(entryList -> entryList.get(0))
- .filter(entry -> entry.getUsageStats().mTotalTimeInForeground != 0)
- .sorted(sCacheQuotaRequestComparator)
- .collect(Collectors.toList());
-
- // Because the elements are sorted, we can use the index to also be the sorted
- // index for cache quota calculation.
- double sum = getSumOfFairShares(flattenedRequests.size());
- String uuid = requestListEntry.getKey();
- long reservedSize = getReservedCacheSize(uuid);
- for (int count = 0; count < flattenedRequests.size(); count++) {
- double share = getFairShareForPosition(count) / sum;
- CacheQuotaHint entry = flattenedRequests.get(count);
- CacheQuotaHint.Builder builder = new CacheQuotaHint.Builder(entry);
- builder.setQuota(Math.round(share * reservedSize));
- processed.add(builder.build());
- }
- }
- );
-
- return processed.stream()
- .filter(request -> request.getQuota() > 0).collect(Collectors.toList());
- }
-
- private double getFairShareForPosition(int position) {
- double value = 1.0 / Math.log(position + 3) - 0.285;
- return (value > 0.01) ? value : 0.01;
- }
-
- private double getSumOfFairShares(int size) {
- double sum = 0;
- for (int i = 0; i < size; i++) {
- sum += getFairShareForPosition(i);
- }
- return sum;
- }
-
- private long getReservedCacheSize(String uuid) {
- // TODO: Revisit the cache size after running more storage tests.
- // TODO: Figure out how to ensure ExtServices has the permissions to call
- // StorageStatsManager, because this is ignoring the cache...
- StorageManager storageManager = getSystemService(StorageManager.class);
- long freeBytes = 0;
- if (uuid == StorageManager.UUID_PRIVATE_INTERNAL) { // regular equals because of null
- freeBytes = Environment.getDataDirectory().getUsableSpace();
- } else {
- final VolumeInfo vol = storageManager.findVolumeByUuid(uuid);
- freeBytes = vol.getPath().getUsableSpace();
- }
- return Math.round(freeBytes * CACHE_RESERVE_RATIO);
- }
-
- // Compares based upon foreground time.
- private static Comparator<CacheQuotaHint> sCacheQuotaRequestComparator =
- new Comparator<CacheQuotaHint>() {
- @Override
- public int compare(CacheQuotaHint o, CacheQuotaHint t1) {
- long x = t1.getUsageStats().getTotalTimeInForeground();
- long y = o.getUsageStats().getTotalTimeInForeground();
- return (x < y) ? -1 : ((x == y) ? 0 : 1);
- }
- };
-}