summaryrefslogtreecommitdiff
path: root/packages/ExtServices
diff options
context:
space:
mode:
Diffstat (limited to 'packages/ExtServices')
-rw-r--r--packages/ExtServices/Android.bp26
-rw-r--r--packages/ExtServices/AndroidManifest.xml70
-rw-r--r--packages/ExtServices/MODULE_LICENSE_APACHE20
-rw-r--r--packages/ExtServices/NOTICE190
-rw-r--r--packages/ExtServices/OWNERS2
-rw-r--r--packages/ExtServices/proguard.proguard7
-rw-r--r--packages/ExtServices/res/values/strings.xml27
-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
-rw-r--r--packages/ExtServices/tests/Android.bp19
-rw-r--r--packages/ExtServices/tests/AndroidManifest.xml31
-rw-r--r--packages/ExtServices/tests/AndroidTest.xml29
-rw-r--r--packages/ExtServices/tests/src/android/ext/services/autofill/AutofillFieldClassificationServiceImplTest.java59
-rw-r--r--packages/ExtServices/tests/src/android/ext/services/autofill/EditDistanceScorerTest.java121
-rw-r--r--packages/ExtServices/tests/src/android/ext/services/notification/AssistantTest.java447
-rw-r--r--packages/ExtServices/tests/src/android/ext/services/notification/ChannelImpressionsTest.java161
-rw-r--r--packages/ExtServices/tests/src/android/ext/services/storage/CacheQuotaServiceImplTest.java150
22 files changed, 0 insertions, 2508 deletions
diff --git a/packages/ExtServices/Android.bp b/packages/ExtServices/Android.bp
deleted file mode 100644
index db94eec17ce8..000000000000
--- a/packages/ExtServices/Android.bp
+++ /dev/null
@@ -1,26 +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.
-
-android_app {
- name: "ExtServices",
- srcs: ["src/**/*.java"],
- platform_apis: true,
- certificate: "platform",
- aaptflags: ["--shared-lib"],
- export_package_resources: true,
- optimize: {
- proguard_flags_files: ["proguard.proguard"],
- },
- privileged: true,
-}
diff --git a/packages/ExtServices/AndroidManifest.xml b/packages/ExtServices/AndroidManifest.xml
deleted file mode 100644
index 45e557c00333..000000000000
--- a/packages/ExtServices/AndroidManifest.xml
+++ /dev/null
@@ -1,70 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
- package="android.ext.services"
- android:versionCode="1"
- android:versionName="1"
- coreApp="true">
-
- <uses-permission android:name="android.permission.PROVIDE_RESOLVER_RANKER_SERVICE" />
-
- <application android:label="@string/app_name"
- android:defaultToDeviceProtectedStorage="true"
- android:directBootAware="true">
-
- <service android:name=".storage.CacheQuotaServiceImpl"
- android:permission="android.permission.BIND_CACHE_QUOTA_SERVICE">
- <intent-filter>
- <action android:name="android.app.usage.CacheQuotaService" />
- </intent-filter>
- </service>
-
- <service android:name=".resolver.LRResolverRankerService"
- android:permission="android.permission.BIND_RESOLVER_RANKER_SERVICE"
- android:priority="-1" >
- <intent-filter>
- <action android:name="android.service.resolver.ResolverRankerService" />
- </intent-filter>
- </service>
-
- <service android:name=".notification.Assistant"
- android:label="@string/notification_assistant"
- android:permission="android.permission.BIND_NOTIFICATION_ASSISTANT_SERVICE"
- android:exported="true">
- <intent-filter>
- <action android:name="android.service.notification.NotificationAssistantService" />
- </intent-filter>
- </service>
-
- <service android:name=".autofill.AutofillFieldClassificationServiceImpl"
- android:permission="android.permission.BIND_AUTOFILL_FIELD_CLASSIFICATION_SERVICE">
- <intent-filter>
- <action android:name="android.service.autofill.AutofillFieldClassificationService" />
- </intent-filter>
- <meta-data
- android:name="android.autofill.field_classification.default_algorithm"
- android:resource="@string/autofill_field_classification_default_algorithm" />
- <meta-data
- android:name="android.autofill.field_classification.available_algorithms"
- android:resource="@array/autofill_field_classification_available_algorithms" />
- </service>
-
- <library android:name="android.ext.services"/>
- </application>
-
-</manifest>
diff --git a/packages/ExtServices/MODULE_LICENSE_APACHE2 b/packages/ExtServices/MODULE_LICENSE_APACHE2
deleted file mode 100644
index e69de29bb2d1..000000000000
--- a/packages/ExtServices/MODULE_LICENSE_APACHE2
+++ /dev/null
diff --git a/packages/ExtServices/NOTICE b/packages/ExtServices/NOTICE
deleted file mode 100644
index c5b1efa7aac7..000000000000
--- a/packages/ExtServices/NOTICE
+++ /dev/null
@@ -1,190 +0,0 @@
-
- Copyright (c) 2005-2008, 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.
-
- 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.
-
-
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
diff --git a/packages/ExtServices/OWNERS b/packages/ExtServices/OWNERS
deleted file mode 100644
index 7640b919ca53..000000000000
--- a/packages/ExtServices/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-baligh@google.com
-delphij@google.com
diff --git a/packages/ExtServices/proguard.proguard b/packages/ExtServices/proguard.proguard
deleted file mode 100644
index e5dfbe1c453d..000000000000
--- a/packages/ExtServices/proguard.proguard
+++ /dev/null
@@ -1,7 +0,0 @@
--keepparameternames
--keepattributes Exceptions,InnerClasses,Signature,Deprecated,
- SourceFile,LineNumberTable,*Annotation*,EnclosingMethod
-
--keep public class * {
- public protected *;
-}
diff --git a/packages/ExtServices/res/values/strings.xml b/packages/ExtServices/res/values/strings.xml
deleted file mode 100644
index 72647ab8ae3f..000000000000
--- a/packages/ExtServices/res/values/strings.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name">Android Services Library</string>
-
- <string name="notification_assistant">Notification Assistant</string>
- <string name="prompt_block_reason">Too many dismissals:views</string>
-
- <string name="autofill_field_classification_default_algorithm">EDIT_DISTANCE</string>
- <string-array name="autofill_field_classification_available_algorithms">
- <item>EDIT_DISTANCE</item>
- </string-array>
-</resources>
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);
- }
- };
-}
diff --git a/packages/ExtServices/tests/Android.bp b/packages/ExtServices/tests/Android.bp
deleted file mode 100644
index db160277b82e..000000000000
--- a/packages/ExtServices/tests/Android.bp
+++ /dev/null
@@ -1,19 +0,0 @@
-android_test {
- name: "ExtServicesUnitTests",
- certificate: "platform",
- libs: [
- "android.test.runner",
- "android.test.base",
- ],
- static_libs: [
- "androidx.test.rules",
- "mockito-target-minus-junit4",
- "androidx.test.espresso.core",
- "truth-prebuilt",
- "testables",
- ],
- // Include all test java files.
- srcs: ["src/**/*.java"],
- platform_apis: true,
- instrumentation_for: "ExtServices",
-}
diff --git a/packages/ExtServices/tests/AndroidManifest.xml b/packages/ExtServices/tests/AndroidManifest.xml
deleted file mode 100644
index 42293b5a0b3e..000000000000
--- a/packages/ExtServices/tests/AndroidManifest.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.ext.services.tests.unit">
-
- <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
-
- <application>
- <uses-library android:name="android.test.runner" />
- </application>
-
- <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
- android:targetPackage="android.ext.services"
- android:label="ExtServices Test Cases">
- </instrumentation>
-
-</manifest> \ No newline at end of file
diff --git a/packages/ExtServices/tests/AndroidTest.xml b/packages/ExtServices/tests/AndroidTest.xml
deleted file mode 100644
index cd26ebc407c1..000000000000
--- a/packages/ExtServices/tests/AndroidTest.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-<configuration description="Runs Tests for ExtServices">
- <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
- <option name="test-file-name" value="ExtServicesUnitTests.apk" />
- </target_preparer>
-
- <option name="test-suite-tag" value="apct" />
- <option name="test-suite-tag" value="framework-base-presubmit" />
- <option name="test-tag" value="ExtServicesUnitTests" />
- <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
- <option name="package" value="android.ext.services.tests.unit" />
- <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
- <option name="hidden-api-checks" value="false"/>
- </test>
-</configuration> \ No newline at end of file
diff --git a/packages/ExtServices/tests/src/android/ext/services/autofill/AutofillFieldClassificationServiceImplTest.java b/packages/ExtServices/tests/src/android/ext/services/autofill/AutofillFieldClassificationServiceImplTest.java
deleted file mode 100644
index 48c076e67e78..000000000000
--- a/packages/ExtServices/tests/src/android/ext/services/autofill/AutofillFieldClassificationServiceImplTest.java
+++ /dev/null
@@ -1,59 +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 org.junit.Test;
-
-import java.util.Arrays;
-import java.util.Collections;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.view.autofill.AutofillValue;
-
-/**
- * Contains the base tests that does not rely on the specific algorithm implementation.
- */
-public class AutofillFieldClassificationServiceImplTest {
-
- private final AutofillFieldClassificationServiceImpl mService =
- new AutofillFieldClassificationServiceImpl();
-
- @Test
- public void testOnGetScores_nullActualValues() {
- assertThat(mService.onGetScores(null, null, null, Arrays.asList("whatever"))).isNull();
- }
-
- @Test
- public void testOnGetScores_emptyActualValues() {
- assertThat(mService.onGetScores(null, null, Collections.emptyList(),
- Arrays.asList("whatever"))).isNull();
- }
-
- @Test
- public void testOnGetScores_nullUserDataValues() {
- assertThat(mService.onGetScores(null, null,
- Arrays.asList(AutofillValue.forText("whatever")), null)).isNull();
- }
-
- @Test
- public void testOnGetScores_emptyUserDataValues() {
- assertThat(mService.onGetScores(null, null,
- Arrays.asList(AutofillValue.forText("whatever")), Collections.emptyList()))
- .isNull();
- }
-}
diff --git a/packages/ExtServices/tests/src/android/ext/services/autofill/EditDistanceScorerTest.java b/packages/ExtServices/tests/src/android/ext/services/autofill/EditDistanceScorerTest.java
deleted file mode 100644
index afe223641d37..000000000000
--- a/packages/ExtServices/tests/src/android/ext/services/autofill/EditDistanceScorerTest.java
+++ /dev/null
@@ -1,121 +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.getScore;
-import static android.ext.services.autofill.EditDistanceScorer.getScores;
-import static android.view.autofill.AutofillValue.forText;
-
-import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.Truth.assertWithMessage;
-
-import android.view.autofill.AutofillValue;
-
-import org.junit.Test;
-
-import java.util.Arrays;
-import java.util.List;
-
-public class EditDistanceScorerTest {
-
- @Test
- public void testGetScore_nullValue() {
- assertFloat(getScore(null, "D'OH!"), 0);
- }
-
- @Test
- public void testGetScore_nonTextValue() {
- assertFloat(getScore(AutofillValue.forToggle(true), "D'OH!"), 0);
- }
-
- @Test
- public void testGetScore_nullUserData() {
- assertFloat(getScore(AutofillValue.forText("D'OH!"), null), 0);
- }
-
- @Test
- public void testGetScore_fullMatch() {
- assertFloat(getScore(AutofillValue.forText("D'OH!"), "D'OH!"), 1);
- assertFloat(getScore(AutofillValue.forText(""), ""), 1);
- }
-
- @Test
- public void testGetScore_fullMatchMixedCase() {
- assertFloat(getScore(AutofillValue.forText("D'OH!"), "D'oH!"), 1);
- }
-
- @Test
- public void testGetScore_mismatchDifferentSizes() {
- assertFloat(getScore(AutofillValue.forText("X"), "Xy"), 0.50F);
- assertFloat(getScore(AutofillValue.forText("Xy"), "X"), 0.50F);
- assertFloat(getScore(AutofillValue.forText("One"), "MoreThanOne"), 0.27F);
- assertFloat(getScore(AutofillValue.forText("MoreThanOne"), "One"), 0.27F);
- assertFloat(getScore(AutofillValue.forText("1600 Amphitheatre Parkway"),
- "1600 Amphitheatre Pkwy"), 0.88F);
- assertFloat(getScore(AutofillValue.forText("1600 Amphitheatre Pkwy"),
- "1600 Amphitheatre Parkway"), 0.88F);
- }
-
- @Test
- public void testGetScore_partialMatch() {
- assertFloat(getScore(AutofillValue.forText("Dude"), "Dxxx"), 0.25F);
- assertFloat(getScore(AutofillValue.forText("Dude"), "DUxx"), 0.50F);
- assertFloat(getScore(AutofillValue.forText("Dude"), "DUDx"), 0.75F);
- assertFloat(getScore(AutofillValue.forText("Dxxx"), "Dude"), 0.25F);
- assertFloat(getScore(AutofillValue.forText("DUxx"), "Dude"), 0.50F);
- assertFloat(getScore(AutofillValue.forText("DUDx"), "Dude"), 0.75F);
- }
-
- @Test
- public void testGetScores() {
- final List<AutofillValue> actualValues = Arrays.asList(forText("A"), forText("b"));
- final List<String> userDataValues = Arrays.asList("a", "B", "ab", "c");
- final float[][] expectedScores = new float[][] {
- new float[] { 1F, 0F, 0.5F, 0F },
- new float[] { 0F, 1F, 0.5F, 0F }
- };
- final float[][] actualScores = getScores(actualValues, userDataValues);
-
- // Unfortunately, Truth does not have an easy way to compare float matrices and show useful
- // messages in case of error, so we need to check.
- assertWithMessage("actual=%s, expected=%s", toString(actualScores),
- toString(expectedScores)).that(actualScores.length).isEqualTo(2);
- assertWithMessage("actual=%s, expected=%s", toString(actualScores),
- toString(expectedScores)).that(actualScores[0].length).isEqualTo(4);
- assertWithMessage("actual=%s, expected=%s", toString(actualScores),
- toString(expectedScores)).that(actualScores[1].length).isEqualTo(4);
- for (int i = 0; i < actualScores.length; i++) {
- final float[] line = actualScores[i];
- for (int j = 0; j < line.length; j++) {
- float cell = line[j];
- assertWithMessage("wrong score at [%s, %s]", i, j).that(cell).isWithin(0.01F)
- .of(expectedScores[i][j]);
- }
- }
- }
-
- public static void assertFloat(float actualValue, float expectedValue) {
- assertThat(actualValue).isWithin(0.01F).of(expectedValue);
- }
-
- public static String toString(float[][] matrix) {
- final StringBuilder string = new StringBuilder("[ ");
- for (int i = 0; i < matrix.length; i++) {
- string.append(Arrays.toString(matrix[i])).append(" ");
- }
- return string.append(" ]").toString();
- }
-}
diff --git a/packages/ExtServices/tests/src/android/ext/services/notification/AssistantTest.java b/packages/ExtServices/tests/src/android/ext/services/notification/AssistantTest.java
deleted file mode 100644
index 6ef25e553204..000000000000
--- a/packages/ExtServices/tests/src/android/ext/services/notification/AssistantTest.java
+++ /dev/null
@@ -1,447 +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_DEFAULT;
-import static android.app.NotificationManager.IMPORTANCE_LOW;
-import static android.app.NotificationManager.IMPORTANCE_MIN;
-
-import static junit.framework.Assert.assertEquals;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.app.Application;
-import android.app.INotificationManager;
-import android.app.Notification;
-import android.app.NotificationChannel;
-import android.content.ContentResolver;
-import android.content.Intent;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.service.notification.Adjustment;
-import android.service.notification.NotificationListenerService;
-import android.service.notification.NotificationListenerService.Ranking;
-import android.service.notification.NotificationListenerService.RankingMap;
-import android.service.notification.NotificationStats;
-import android.service.notification.StatusBarNotification;
-import android.test.ServiceTestCase;
-import android.testing.TestableContext;
-import android.util.AtomicFile;
-
-import androidx.test.InstrumentationRegistry;
-
-import com.android.internal.util.FastXmlSerializer;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.xmlpull.v1.XmlSerializer;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.FileOutputStream;
-
-public class AssistantTest extends ServiceTestCase<Assistant> {
-
- private static final String PKG1 = "pkg1";
- private static final int UID1 = 1;
- private static final NotificationChannel P1C1 =
- new NotificationChannel("one", "", IMPORTANCE_LOW);
- private static final NotificationChannel P1C2 =
- new NotificationChannel("p1c2", "", IMPORTANCE_DEFAULT);
- private static final NotificationChannel P1C3 =
- new NotificationChannel("p1c3", "", IMPORTANCE_MIN);
- private static final String PKG2 = "pkg2";
-
- private static final int UID2 = 2;
- private static final NotificationChannel P2C1 =
- new NotificationChannel("one", "", IMPORTANCE_LOW);
-
- @Mock INotificationManager mNoMan;
- @Mock AtomicFile mFile;
-
- Assistant mAssistant;
- Application mApplication;
-
- @Rule
- public final TestableContext mContext =
- new TestableContext(InstrumentationRegistry.getContext(), null);
-
- public AssistantTest() {
- super(Assistant.class);
- }
-
- @Before
- public void setUp() throws Exception {
- MockitoAnnotations.initMocks(this);
-
- Intent startIntent =
- new Intent("android.service.notification.NotificationAssistantService");
- startIntent.setPackage("android.ext.services");
-
- // To bypass real calls to global settings values, set the Settings values here.
- Settings.Global.putFloat(mContext.getContentResolver(),
- Settings.Global.BLOCKING_HELPER_DISMISS_TO_VIEW_RATIO_LIMIT, 0.8f);
- Settings.Global.putInt(mContext.getContentResolver(),
- Settings.Global.BLOCKING_HELPER_STREAK_LIMIT, 2);
- mApplication = (Application) InstrumentationRegistry.getInstrumentation().
- getTargetContext().getApplicationContext();
- // Force the test to use the correct application instead of trying to use a mock application
- setApplication(mApplication);
- bindService(startIntent);
- mAssistant = getService();
- mAssistant.setNoMan(mNoMan);
- mAssistant.setFile(mFile);
- when(mFile.startWrite()).thenReturn(mock(FileOutputStream.class));
- }
-
- private StatusBarNotification generateSbn(String pkg, int uid, NotificationChannel channel,
- String tag, String groupKey) {
- Notification n = new Notification.Builder(mContext, channel.getId())
- .setContentTitle("foo")
- .setGroup(groupKey)
- .build();
-
- StatusBarNotification sbn = new StatusBarNotification(pkg, pkg, 0, tag, uid, uid, n,
- UserHandle.SYSTEM, null, 0);
-
- return sbn;
- }
-
- private Ranking generateRanking(StatusBarNotification sbn, NotificationChannel channel) {
- Ranking mockRanking = mock(Ranking.class);
- when(mockRanking.getChannel()).thenReturn(channel);
- when(mockRanking.getImportance()).thenReturn(channel.getImportance());
- when(mockRanking.getKey()).thenReturn(sbn.getKey());
- when(mockRanking.getOverrideGroupKey()).thenReturn(null);
- return mockRanking;
- }
-
- private void almostBlockChannel(String pkg, int uid, NotificationChannel channel) {
- for (int i = 0; i < ChannelImpressions.DEFAULT_STREAK_LIMIT; i++) {
- dismissBadNotification(pkg, uid, channel, String.valueOf(i));
- }
- }
-
- private void dismissBadNotification(String pkg, int uid, NotificationChannel channel,
- String tag) {
- StatusBarNotification sbn = generateSbn(pkg, uid, channel, tag, null);
- mAssistant.setFakeRanking(generateRanking(sbn, channel));
- mAssistant.onNotificationPosted(sbn, mock(RankingMap.class));
- mAssistant.setFakeRanking(mock(Ranking.class));
- NotificationStats stats = new NotificationStats();
- stats.setDismissalSurface(NotificationStats.DISMISSAL_SHADE);
- stats.setSeen();
- mAssistant.onNotificationRemoved(
- sbn, mock(RankingMap.class), stats, NotificationListenerService.REASON_CANCEL);
- }
-
- @Test
- public void testNoAdjustmentForInitialPost() throws Exception {
- StatusBarNotification sbn = generateSbn(PKG1, UID1, P1C1, null, null);
-
- mAssistant.setFakeRanking(generateRanking(sbn, P1C1));
- mAssistant.onNotificationPosted(sbn, mock(RankingMap.class));
-
- verify(mNoMan, never()).applyAdjustmentFromAssistant(any(), any());
- }
-
- @Test
- public void testTriggerAdjustment() throws Exception {
- almostBlockChannel(PKG1, UID1, P1C1);
- dismissBadNotification(PKG1, UID1, P1C1, "trigger!");
-
- StatusBarNotification sbn = generateSbn(PKG1, UID1, P1C1, "new one!", null);
- mAssistant.setFakeRanking(generateRanking(sbn, P1C1));
- mAssistant.onNotificationPosted(sbn, mock(RankingMap.class));
-
- ArgumentCaptor<Adjustment> captor = ArgumentCaptor.forClass(Adjustment.class);
- verify(mNoMan, times(1)).applyAdjustmentFromAssistant(any(), captor.capture());
- assertEquals(sbn.getKey(), captor.getValue().getKey());
- assertEquals(Ranking.USER_SENTIMENT_NEGATIVE,
- captor.getValue().getSignals().getInt(Adjustment.KEY_USER_SENTIMENT));
- }
-
- @Test
- public void testMinCannotTriggerAdjustment() throws Exception {
- almostBlockChannel(PKG1, UID1, P1C3);
- dismissBadNotification(PKG1, UID1, P1C3, "trigger!");
-
- StatusBarNotification sbn = generateSbn(PKG1, UID1, P1C3, "new one!", null);
- mAssistant.setFakeRanking(generateRanking(sbn, P1C3));
- mAssistant.onNotificationPosted(sbn, mock(RankingMap.class));
-
- verify(mNoMan, never()).applyAdjustmentFromAssistant(any(), any());
- }
-
- @Test
- public void testGroupChildCanTriggerAdjustment() throws Exception {
- almostBlockChannel(PKG1, UID1, P1C1);
-
- StatusBarNotification sbn = generateSbn(PKG1, UID1, P1C1, "no", "I HAVE A GROUP");
- mAssistant.setFakeRanking(generateRanking(sbn, P1C1));
- NotificationStats stats = new NotificationStats();
- stats.setDismissalSurface(NotificationStats.DISMISSAL_SHADE);
- stats.setSeen();
- mAssistant.onNotificationPosted(sbn, mock(RankingMap.class));
- mAssistant.onNotificationRemoved(
- sbn, mock(RankingMap.class), stats, NotificationListenerService.REASON_CANCEL);
-
- sbn = generateSbn(PKG1, UID1, P1C1, "new one!", "group");
- mAssistant.onNotificationPosted(sbn, mock(RankingMap.class));
-
- ArgumentCaptor<Adjustment> captor = ArgumentCaptor.forClass(Adjustment.class);
- verify(mNoMan, times(1)).applyAdjustmentFromAssistant(any(), captor.capture());
- assertEquals(sbn.getKey(), captor.getValue().getKey());
- assertEquals(Ranking.USER_SENTIMENT_NEGATIVE,
- captor.getValue().getSignals().getInt(Adjustment.KEY_USER_SENTIMENT));
- }
-
- @Test
- public void testGroupSummaryCannotTriggerAdjustment() throws Exception {
- almostBlockChannel(PKG1, UID1, P1C1);
-
- StatusBarNotification sbn = generateSbn(PKG1, UID1, P1C1, "no", "I HAVE A GROUP");
- sbn.getNotification().flags |= Notification.FLAG_GROUP_SUMMARY;
- mAssistant.setFakeRanking(generateRanking(sbn, P1C1));
- NotificationStats stats = new NotificationStats();
- stats.setDismissalSurface(NotificationStats.DISMISSAL_SHADE);
- stats.setSeen();
- mAssistant.onNotificationPosted(sbn, mock(RankingMap.class));
- mAssistant.onNotificationRemoved(
- sbn, mock(RankingMap.class), stats, NotificationListenerService.REASON_CANCEL);
-
- sbn = generateSbn(PKG1, UID1, P1C1, "new one!", "group");
- mAssistant.onNotificationPosted(sbn, mock(RankingMap.class));
-
- verify(mNoMan, never()).applyAdjustmentFromAssistant(any(), any());
- }
-
- @Test
- public void testAodCannotTriggerAdjustment() throws Exception {
- almostBlockChannel(PKG1, UID1, P1C1);
-
- StatusBarNotification sbn = generateSbn(PKG1, UID1, P1C1, "no", null);
- mAssistant.setFakeRanking(generateRanking(sbn, P1C1));
- NotificationStats stats = new NotificationStats();
- stats.setDismissalSurface(NotificationStats.DISMISSAL_AOD);
- stats.setSeen();
- mAssistant.onNotificationPosted(sbn, mock(RankingMap.class));
- mAssistant.onNotificationRemoved(
- sbn, mock(RankingMap.class), stats, NotificationListenerService.REASON_CANCEL);
-
- sbn = generateSbn(PKG1, UID1, P1C1, "new one!", null);
- mAssistant.onNotificationPosted(sbn, mock(RankingMap.class));
-
- verify(mNoMan, never()).applyAdjustmentFromAssistant(any(), any());
- }
-
- @Test
- public void testInteractedCannotTriggerAdjustment() throws Exception {
- almostBlockChannel(PKG1, UID1, P1C1);
- StatusBarNotification sbn = generateSbn(PKG1, UID1, P1C1, "no", null);
- mAssistant.setFakeRanking(generateRanking(sbn, P1C1));
- NotificationStats stats = new NotificationStats();
- stats.setDismissalSurface(NotificationStats.DISMISSAL_SHADE);
- stats.setSeen();
- stats.setExpanded();
- mAssistant.onNotificationPosted(sbn, mock(RankingMap.class));
- mAssistant.onNotificationRemoved(
- sbn, mock(RankingMap.class), stats, NotificationListenerService.REASON_CANCEL);
-
- sbn = generateSbn(PKG1, UID1, P1C1, "new one!", null);
- mAssistant.onNotificationPosted(sbn, mock(RankingMap.class));
-
- verify(mNoMan, never()).applyAdjustmentFromAssistant(any(), any());
- }
-
- @Test
- public void testAppDismissedCannotTriggerAdjustment() throws Exception {
- almostBlockChannel(PKG1, UID1, P1C1);
-
- StatusBarNotification sbn = generateSbn(PKG1, UID1, P1C1, "no", null);
- mAssistant.setFakeRanking(generateRanking(sbn, P1C1));
- NotificationStats stats = new NotificationStats();
- stats.setDismissalSurface(NotificationStats.DISMISSAL_SHADE);
- stats.setSeen();
- mAssistant.onNotificationPosted(sbn, mock(RankingMap.class));
- mAssistant.onNotificationRemoved(
- sbn, mock(RankingMap.class), stats, NotificationListenerService.REASON_APP_CANCEL);
-
- sbn = generateSbn(PKG1, UID1, P1C1, "new one!", null);
- mAssistant.onNotificationPosted(sbn, mock(RankingMap.class));
-
- verify(mNoMan, never()).applyAdjustmentFromAssistant(any(), any());
- }
-
- @Test
- public void testAppSeparation() throws Exception {
- almostBlockChannel(PKG1, UID1, P1C1);
- dismissBadNotification(PKG1, UID1, P1C1, "trigger!");
-
- StatusBarNotification sbn = generateSbn(PKG2, UID2, P2C1, "new app!", null);
- mAssistant.setFakeRanking(generateRanking(sbn, P2C1));
- mAssistant.onNotificationPosted(sbn, mock(RankingMap.class));
-
- verify(mNoMan, never()).applyAdjustmentFromAssistant(any(), any());
- }
-
- @Test
- public void testChannelSeparation() throws Exception {
- almostBlockChannel(PKG1, UID1, P1C1);
- dismissBadNotification(PKG1, UID1, P1C1, "trigger!");
-
- StatusBarNotification sbn = generateSbn(PKG1, UID1, P1C2, "new app!", null);
- mAssistant.setFakeRanking(generateRanking(sbn, P1C2));
- mAssistant.onNotificationPosted(sbn, mock(RankingMap.class));
-
- verify(mNoMan, never()).applyAdjustmentFromAssistant(any(), any());
- }
-
- @Test
- public void testReadXml() throws Exception {
- String key1 = mAssistant.getKey("pkg1", 1, "channel1");
- int streak1 = 2;
- int views1 = 5;
- int dismiss1 = 9;
-
- int streak1a = 3;
- int views1a = 10;
- int dismiss1a = 99;
- String key1a = mAssistant.getKey("pkg1", 1, "channel1a");
-
- int streak2 = 7;
- int views2 = 77;
- int dismiss2 = 777;
- String key2 = mAssistant.getKey("pkg2", 2, "channel2");
-
- String xml = "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>"
- + "<assistant version=\"1\">\n"
- + "<impression-set key=\"" + key1 + "\" "
- + "dismisses=\"" + dismiss1 + "\" views=\"" + views1
- + "\" streak=\"" + streak1 + "\"/>\n"
- + "<impression-set key=\"" + key1a + "\" "
- + "dismisses=\"" + dismiss1a + "\" views=\"" + views1a
- + "\" streak=\"" + streak1a + "\"/>\n"
- + "<impression-set key=\"" + key2 + "\" "
- + "dismisses=\"" + dismiss2 + "\" views=\"" + views2
- + "\" streak=\"" + streak2 + "\"/>\n"
- + "</assistant>\n";
- mAssistant.readXml(new BufferedInputStream(new ByteArrayInputStream(xml.getBytes())));
-
- ChannelImpressions c1 = mAssistant.getImpressions(key1);
- assertEquals(2, c1.getStreak());
- assertEquals(5, c1.getViews());
- assertEquals(9, c1.getDismissals());
-
- ChannelImpressions c1a = mAssistant.getImpressions(key1a);
- assertEquals(3, c1a.getStreak());
- assertEquals(10, c1a.getViews());
- assertEquals(99, c1a.getDismissals());
-
- ChannelImpressions c2 = mAssistant.getImpressions(key2);
- assertEquals(7, c2.getStreak());
- assertEquals(77, c2.getViews());
- assertEquals(777, c2.getDismissals());
- }
-
- @Test
- public void testRoundTripXml() throws Exception {
- String key1 = mAssistant.getKey("pkg1", 1, "channel1");
- ChannelImpressions ci1 = new ChannelImpressions();
- String key2 = mAssistant.getKey("pkg1", 1, "channel2");
- ChannelImpressions ci2 = new ChannelImpressions();
- for (int i = 0; i < 3; i++) {
- ci2.incrementViews();
- ci2.incrementDismissals();
- }
- ChannelImpressions ci3 = new ChannelImpressions();
- String key3 = mAssistant.getKey("pkg3", 3, "channel2");
- for (int i = 0; i < 9; i++) {
- ci3.incrementViews();
- if (i % 3 == 0) {
- ci3.incrementDismissals();
- }
- }
-
- mAssistant.insertImpressions(key1, ci1);
- mAssistant.insertImpressions(key2, ci2);
- mAssistant.insertImpressions(key3, ci3);
-
- XmlSerializer serializer = new FastXmlSerializer();
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
- mAssistant.writeXml(serializer);
-
- Assistant assistant = new Assistant();
- assistant.readXml(new BufferedInputStream(new ByteArrayInputStream(baos.toByteArray())));
-
- assertEquals(ci1, assistant.getImpressions(key1));
- assertEquals(ci2, assistant.getImpressions(key2));
- assertEquals(ci3, assistant.getImpressions(key3));
- }
-
- @Test
- public void testSettingsProviderUpdate() {
- ContentResolver resolver = mApplication.getContentResolver();
-
- // Set up channels
- String key = mAssistant.getKey("pkg1", 1, "channel1");
- ChannelImpressions ci = new ChannelImpressions();
- for (int i = 0; i < 3; i++) {
- ci.incrementViews();
- if (i % 2 == 0) {
- ci.incrementDismissals();
- }
- }
-
- mAssistant.insertImpressions(key, ci);
-
- // With default values, the blocking helper shouldn't be triggered.
- assertEquals(false, ci.shouldTriggerBlock());
-
- // Update settings values.
- float newDismissToViewRatioLimit = 0f;
- int newStreakLimit = 0;
- Settings.Global.putFloat(resolver,
- Settings.Global.BLOCKING_HELPER_DISMISS_TO_VIEW_RATIO_LIMIT,
- newDismissToViewRatioLimit);
- Settings.Global.putInt(resolver,
- Settings.Global.BLOCKING_HELPER_STREAK_LIMIT, newStreakLimit);
-
- // Notify for the settings values we updated.
- resolver.notifyChange(
- Settings.Global.getUriFor(Settings.Global.BLOCKING_HELPER_STREAK_LIMIT), null);
- resolver.notifyChange(
- Settings.Global.getUriFor(
- Settings.Global.BLOCKING_HELPER_DISMISS_TO_VIEW_RATIO_LIMIT),
- null);
-
- // With the new threshold, the blocking helper should be triggered.
- assertEquals(true, ci.shouldTriggerBlock());
- }
-}
diff --git a/packages/ExtServices/tests/src/android/ext/services/notification/ChannelImpressionsTest.java b/packages/ExtServices/tests/src/android/ext/services/notification/ChannelImpressionsTest.java
deleted file mode 100644
index 3253802bec03..000000000000
--- a/packages/ExtServices/tests/src/android/ext/services/notification/ChannelImpressionsTest.java
+++ /dev/null
@@ -1,161 +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.ext.services.notification.ChannelImpressions.DEFAULT_DISMISS_TO_VIEW_RATIO_LIMIT;
-import static android.ext.services.notification.ChannelImpressions.DEFAULT_STREAK_LIMIT;
-
-import static junit.framework.Assert.assertFalse;
-import static junit.framework.Assert.assertTrue;
-
-import static org.junit.Assert.assertEquals;
-
-import org.junit.Test;
-
-public class ChannelImpressionsTest {
-
- @Test
- public void testNoResultNoBlock() {
- ChannelImpressions ci = new ChannelImpressions();
- assertFalse(ci.shouldTriggerBlock());
- }
-
- @Test
- public void testNoStreakNoBlock() {
- ChannelImpressions ci = new ChannelImpressions();
-
- for (int i = 0; i < DEFAULT_STREAK_LIMIT - 1; i++) {
- ci.incrementViews();
- ci.incrementDismissals();
- }
-
- assertFalse(ci.shouldTriggerBlock());
- }
-
- @Test
- public void testNoStreakNoBlock_breakStreak() {
- ChannelImpressions ci = new ChannelImpressions();
-
- for (int i = 0; i < DEFAULT_STREAK_LIMIT; i++) {
- ci.incrementViews();
- ci.incrementDismissals();
- if (i == DEFAULT_STREAK_LIMIT - 1) {
- ci.resetStreak();
- }
- }
-
- assertFalse(ci.shouldTriggerBlock());
- }
-
- @Test
- public void testStreakBlock() {
- ChannelImpressions ci = new ChannelImpressions();
-
- for (int i = 0; i <= DEFAULT_STREAK_LIMIT; i++) {
- ci.incrementViews();
- ci.incrementDismissals();
- }
-
- assertTrue(ci.shouldTriggerBlock());
- }
-
- @Test
- public void testRatio_NoBlockEvenWithStreak() {
- ChannelImpressions ci = new ChannelImpressions();
-
- for (int i = 0; i < DEFAULT_STREAK_LIMIT; i++) {
- ci.incrementViews();
- ci.incrementDismissals();
- ci.incrementViews();
- }
-
- assertFalse(ci.shouldTriggerBlock());
- }
-
- @Test
- public void testAppend() {
- ChannelImpressions ci = new ChannelImpressions();
- ci.incrementViews();
- ci.incrementDismissals();
-
- ChannelImpressions ci2 = new ChannelImpressions();
- ci2.incrementViews();
- ci2.incrementDismissals();
- ci2.incrementViews();
-
- ci.append(ci2);
- assertEquals(3, ci.getViews());
- assertEquals(2, ci.getDismissals());
- assertEquals(2, ci.getStreak());
-
- assertEquals(2, ci2.getViews());
- assertEquals(1, ci2.getDismissals());
- assertEquals(1, ci2.getStreak());
-
- // no crash
- ci.append(null);
- }
-
- @Test
- public void testUpdateThresholds_streakLimitsCorrectlyApplied() {
- int updatedStreakLimit = DEFAULT_STREAK_LIMIT + 3;
- ChannelImpressions ci = new ChannelImpressions();
- ci.updateThresholds(DEFAULT_DISMISS_TO_VIEW_RATIO_LIMIT, updatedStreakLimit);
-
- for (int i = 0; i <= updatedStreakLimit; i++) {
- ci.incrementViews();
- ci.incrementDismissals();
- }
-
- ChannelImpressions ci2 = new ChannelImpressions();
- ci2.updateThresholds(DEFAULT_DISMISS_TO_VIEW_RATIO_LIMIT, updatedStreakLimit);
-
- for (int i = 0; i < updatedStreakLimit; i++) {
- ci2.incrementViews();
- ci2.incrementDismissals();
- }
-
- assertTrue(ci.shouldTriggerBlock());
- assertFalse(ci2.shouldTriggerBlock());
- }
-
- @Test
- public void testUpdateThresholds_ratioLimitsCorrectlyApplied() {
- float updatedDismissRatio = .99f;
- ChannelImpressions ci = new ChannelImpressions();
- ci.updateThresholds(updatedDismissRatio, DEFAULT_STREAK_LIMIT);
-
- // N views, N-1 dismissals, which doesn't satisfy the ratio = 1 criteria.
- for (int i = 0; i <= DEFAULT_STREAK_LIMIT; i++) {
- ci.incrementViews();
- if (i != DEFAULT_STREAK_LIMIT) {
- ci.incrementDismissals();
- }
- }
-
- ChannelImpressions ci2 = new ChannelImpressions();
- ci2.updateThresholds(updatedDismissRatio, DEFAULT_STREAK_LIMIT);
-
- for (int i = 0; i <= DEFAULT_STREAK_LIMIT; i++) {
- ci2.incrementViews();
- ci2.incrementDismissals();
- }
-
- assertFalse(ci.shouldTriggerBlock());
- assertTrue(ci2.shouldTriggerBlock());
- }
-}
diff --git a/packages/ExtServices/tests/src/android/ext/services/storage/CacheQuotaServiceImplTest.java b/packages/ExtServices/tests/src/android/ext/services/storage/CacheQuotaServiceImplTest.java
deleted file mode 100644
index df4738ff1948..000000000000
--- a/packages/ExtServices/tests/src/android/ext/services/storage/CacheQuotaServiceImplTest.java
+++ /dev/null
@@ -1,150 +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 static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.when;
-
-import android.app.usage.CacheQuotaHint;
-import android.app.usage.UsageStats;
-import android.content.Context;
-import android.content.ContextWrapper;
-import android.content.Intent;
-import android.os.storage.StorageManager;
-import android.os.storage.VolumeInfo;
-import android.test.ServiceTestCase;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.Answers;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.List;
-
-public class CacheQuotaServiceImplTest extends ServiceTestCase<CacheQuotaServiceImpl> {
- private static final String sTestVolUuid = "uuid";
- private static final String sSecondTestVolUuid = "otherUuid";
-
- @Mock private Context mContext;
- @Mock private File mFile;
- @Mock private VolumeInfo mVolume;
- @Mock(answer = Answers.RETURNS_DEEP_STUBS) private StorageManager mStorageManager;
-
- public CacheQuotaServiceImplTest() {
- super(CacheQuotaServiceImpl.class);
- }
-
- @Before
- public void setUp() throws Exception {
- super.setUp();
- MockitoAnnotations.initMocks(this);
- mContext = Mockito.spy(new ContextWrapper(getSystemContext()));
- setContext(mContext);
- when(mContext.getSystemService(Context.STORAGE_SERVICE)).thenReturn(mStorageManager);
-
- when(mFile.getUsableSpace()).thenReturn(10000L);
- when(mVolume.getPath()).thenReturn(mFile);
- when(mStorageManager.findVolumeByUuid(sTestVolUuid)).thenReturn(mVolume);
- when(mStorageManager.findVolumeByUuid(sSecondTestVolUuid)).thenReturn(mVolume);
-
- Intent intent = new Intent(getContext(), CacheQuotaServiceImpl.class);
- startService(intent);
- }
-
- @Test
- public void testNoApps() {
- CacheQuotaServiceImpl service = getService();
- assertEquals(service.onComputeCacheQuotaHints(new ArrayList()).size(), 0);
- }
-
- @Test
- public void testOneApp() throws Exception {
- ArrayList<CacheQuotaHint> requests = new ArrayList<>();
- CacheQuotaHint request = makeNewRequest("com.test", sTestVolUuid, 1001, 100L);
- requests.add(request);
-
- List<CacheQuotaHint> output = getService().onComputeCacheQuotaHints(requests);
-
- assertThat(output).hasSize(1);
- assertThat(output.get(0).getQuota()).isEqualTo(1500L);
- }
-
- @Test
- public void testTwoAppsOneVolume() throws Exception {
- ArrayList<CacheQuotaHint> requests = new ArrayList<>();
- requests.add(makeNewRequest("com.test", sTestVolUuid, 1001, 100L));
- requests.add(makeNewRequest("com.test2", sTestVolUuid, 1002, 99L));
-
- List<CacheQuotaHint> output = getService().onComputeCacheQuotaHints(requests);
-
- // Note that the sizes are just the cache area split up.
- assertThat(output).hasSize(2);
- assertThat(output.get(0).getQuota()).isEqualTo(883);
- assertThat(output.get(1).getQuota()).isEqualTo(1500 - 883);
- }
-
- @Test
- public void testTwoAppsTwoVolumes() throws Exception {
- ArrayList<CacheQuotaHint> requests = new ArrayList<>();
- requests.add(makeNewRequest("com.test", sTestVolUuid, 1001, 100L));
- requests.add(makeNewRequest("com.test2", sSecondTestVolUuid, 1002, 99L));
-
- List<CacheQuotaHint> output = getService().onComputeCacheQuotaHints(requests);
-
- assertThat(output).hasSize(2);
- assertThat(output.get(0).getQuota()).isEqualTo(1500);
- assertThat(output.get(1).getQuota()).isEqualTo(1500);
- }
-
- @Test
- public void testMultipleAppsPerUidIsCollated() throws Exception {
- ArrayList<CacheQuotaHint> requests = new ArrayList<>();
- requests.add(makeNewRequest("com.test", sTestVolUuid, 1001, 100L));
- requests.add(makeNewRequest("com.test2", sTestVolUuid, 1001, 99L));
-
- List<CacheQuotaHint> output = getService().onComputeCacheQuotaHints(requests);
-
- assertThat(output).hasSize(1);
- assertThat(output.get(0).getQuota()).isEqualTo(1500);
- }
-
- @Test
- public void testTwoAppsTwoVolumesTwoUuidsShouldBESeparate() throws Exception {
- ArrayList<CacheQuotaHint> requests = new ArrayList<>();
- requests.add(makeNewRequest("com.test", sTestVolUuid, 1001, 100L));
- requests.add(makeNewRequest("com.test2", sSecondTestVolUuid, 1001, 99L));
-
- List<CacheQuotaHint> output = getService().onComputeCacheQuotaHints(requests);
-
- assertThat(output).hasSize(2);
- assertThat(output.get(0).getQuota()).isEqualTo(1500);
- assertThat(output.get(1).getQuota()).isEqualTo(1500);
- }
-
- private CacheQuotaHint makeNewRequest(String packageName, String uuid, int uid, long foregroundTime) {
- UsageStats stats = new UsageStats();
- stats.mPackageName = packageName;
- stats.mTotalTimeInForeground = foregroundTime;
- return new CacheQuotaHint.Builder()
- .setVolumeUuid(uuid).setUid(uid).setUsageStats(stats).setQuota(-1).build();
- }
-}