API for notification listener for Companioon apps
Test: 1. Trigger the confitrmation dialog.
Ensure it looks exactly like the one from settings.
2. Call an API without associating the appa first
Ensure exception is thrown with a message mentioning the need to associate 1st
Change-Id: I94d4116e1988db869ed445ae3fd018c50590e3f4
diff --git a/core/java/com/android/internal/app/AlertActivity.java b/core/java/com/android/internal/app/AlertActivity.java
index 35ffa71..999a908 100644
--- a/core/java/com/android/internal/app/AlertActivity.java
+++ b/core/java/com/android/internal/app/AlertActivity.java
@@ -67,10 +67,15 @@
@Override
public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
- event.setClassName(Dialog.class.getName());
- event.setPackageName(getPackageName());
+ return dispatchPopulateAccessibilityEvent(this, event);
+ }
- ViewGroup.LayoutParams params = getWindow().getAttributes();
+ public static boolean dispatchPopulateAccessibilityEvent(Activity act,
+ AccessibilityEvent event) {
+ event.setClassName(Dialog.class.getName());
+ event.setPackageName(act.getPackageName());
+
+ ViewGroup.LayoutParams params = act.getWindow().getAttributes();
boolean isFullScreen = (params.width == ViewGroup.LayoutParams.MATCH_PARENT) &&
(params.height == ViewGroup.LayoutParams.MATCH_PARENT);
event.setFullScreen(isFullScreen);
@@ -86,8 +91,7 @@
* @see #mAlertParams
*/
protected void setupAlert() {
- mAlertParams.apply(mAlert);
- mAlert.installContent();
+ mAlert.installContent(mAlertParams);
}
@Override
diff --git a/core/java/com/android/internal/app/AlertController.java b/core/java/com/android/internal/app/AlertController.java
index 95c291a..46cb546 100644
--- a/core/java/com/android/internal/app/AlertController.java
+++ b/core/java/com/android/internal/app/AlertController.java
@@ -247,6 +247,11 @@
return false;
}
+ public void installContent(AlertParams params) {
+ params.apply(this);
+ installContent();
+ }
+
public void installContent() {
int contentView = selectContentView();
mWindow.setContentView(contentView);
diff --git a/core/java/com/android/internal/notification/NotificationAccessConfirmationActivityContract.java b/core/java/com/android/internal/notification/NotificationAccessConfirmationActivityContract.java
new file mode 100644
index 0000000..4ce6f60
--- /dev/null
+++ b/core/java/com/android/internal/notification/NotificationAccessConfirmationActivityContract.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.notification;
+
+import android.content.ComponentName;
+import android.content.Intent;
+
+public final class NotificationAccessConfirmationActivityContract {
+ private static final ComponentName COMPONENT_NAME = new ComponentName(
+ "com.android.settings",
+ "com.android.settings.notification.NotificationAccessConfirmationActivity");
+ public static final String EXTRA_USER_ID = "user_id";
+ public static final String EXTRA_COMPONENT_NAME = "component_name";
+ public static final String EXTRA_PACKAGE_TITLE = "package_title";
+
+ public static Intent launcherIntent(int userId, ComponentName component, String packageTitle) {
+ return new Intent()
+ .setComponent(COMPONENT_NAME)
+ .putExtra(EXTRA_USER_ID, userId)
+ .putExtra(EXTRA_COMPONENT_NAME, component)
+ .putExtra(EXTRA_PACKAGE_TITLE, packageTitle);
+ }
+}
diff --git a/core/java/com/android/internal/util/CollectionUtils.java b/core/java/com/android/internal/util/CollectionUtils.java
index 183945c..96b443d 100644
--- a/core/java/com/android/internal/util/CollectionUtils.java
+++ b/core/java/com/android/internal/util/CollectionUtils.java
@@ -16,6 +16,8 @@
package com.android.internal.util;
+import static com.android.internal.util.ArrayUtils.isEmpty;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -64,7 +66,7 @@
*/
public static @NonNull <I, O> List<O> map(@Nullable List<I> cur,
Function<? super I, ? extends O> f) {
- if (cur == null || cur.isEmpty()) return Collections.emptyList();
+ if (isEmpty(cur)) return Collections.emptyList();
final ArrayList<O> result = new ArrayList<>();
for (int i = 0; i < cur.size(); i++) {
result.add(f.apply(cur.get(i)));
@@ -73,6 +75,30 @@
}
/**
+ * {@link #map(List, Function)} + {@link #filter(List, java.util.function.Predicate)}
+ *
+ * Calling this is equivalent (but more memory efficient) to:
+ *
+ * {@code
+ * filter(
+ * map(cur, f),
+ * i -> { i != null })
+ * }
+ */
+ public static @NonNull <I, O> List<O> mapNotNull(@Nullable List<I> cur,
+ Function<? super I, ? extends O> f) {
+ if (isEmpty(cur)) return Collections.emptyList();
+ final ArrayList<O> result = new ArrayList<>();
+ for (int i = 0; i < cur.size(); i++) {
+ O transformed = f.apply(cur.get(i));
+ if (transformed != null) {
+ result.add(transformed);
+ }
+ }
+ return result;
+ }
+
+ /**
* Returns the given list, or an immutable empty list if the provided list is null
*
* This can be used to guaranty null-safety without paying the price of extra allocations
@@ -94,7 +120,7 @@
* Returns the elements of the given list that are of type {@code c}
*/
public static @NonNull <T> List<T> filter(@Nullable List<?> list, Class<T> c) {
- if (ArrayUtils.isEmpty(list)) return Collections.emptyList();
+ if (isEmpty(list)) return Collections.emptyList();
ArrayList<T> result = null;
for (int i = 0; i < list.size(); i++) {
final Object item = list.get(i);
@@ -120,7 +146,7 @@
*/
public static @Nullable <T> T find(@Nullable List<T> items,
java.util.function.Predicate<T> predicate) {
- if (ArrayUtils.isEmpty(items)) return null;
+ if (isEmpty(items)) return null;
for (int i = 0; i < items.size(); i++) {
final T item = items.get(i);
if (predicate.test(item)) return item;
@@ -145,11 +171,17 @@
* {@link Collections#emptyList}
*/
public static @NonNull <T> List<T> remove(@Nullable List<T> cur, T val) {
- if (cur == null || cur == Collections.emptyList()) {
- return Collections.emptyList();
+ if (isEmpty(cur)) {
+ return emptyIfNull(cur);
}
cur.remove(val);
return cur;
}
+ /**
+ * @return a list that will not be affected by mutations to the given original list.
+ */
+ public static @NonNull <T> List<T> copyOf(@Nullable List<T> cur) {
+ return isEmpty(cur) ? Collections.emptyList() : new ArrayList<>(cur);
+ }
}
diff --git a/core/java/com/android/internal/util/FunctionalUtils.java b/core/java/com/android/internal/util/FunctionalUtils.java
new file mode 100644
index 0000000..9aeb041
--- /dev/null
+++ b/core/java/com/android/internal/util/FunctionalUtils.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.util;
+
+import java.util.function.Supplier;
+
+/**
+ * Utilities specific to functional programming
+ */
+public class FunctionalUtils {
+ private FunctionalUtils() {}
+
+ /**
+ * An equivalent of {@link Runnable} that allows throwing checked exceptions
+ *
+ * This can be used to specify a lambda argument without forcing all the checked exceptions
+ * to be handled within it
+ */
+ @FunctionalInterface
+ public interface ThrowingRunnable {
+ void run() throws Exception;
+ }
+
+ /**
+ * An equivalent of {@link Supplier} that allows throwing checked exceptions
+ *
+ * This can be used to specify a lambda argument without forcing all the checked exceptions
+ * to be handled within it
+ */
+ @FunctionalInterface
+ public interface ThrowingSupplier<T> {
+ T get() throws Exception;
+ }
+}
diff --git a/core/java/com/android/internal/util/Preconditions.java b/core/java/com/android/internal/util/Preconditions.java
index 4e6857a..e5d5716 100644
--- a/core/java/com/android/internal/util/Preconditions.java
+++ b/core/java/com/android/internal/util/Preconditions.java
@@ -49,6 +49,23 @@
}
/**
+ * Ensures that an expression checking an argument is true.
+ *
+ * @param expression the expression to check
+ * @param messageTemplate a printf-style message template to use if the check fails; will
+ * be converted to a string using {@link String#format(String, Object...)}
+ * @param messageArgs arguments for {@code messageTemplate}
+ * @throws IllegalArgumentException if {@code expression} is false
+ */
+ public static void checkArgument(boolean expression,
+ final String messageTemplate,
+ final Object... messageArgs) {
+ if (!expression) {
+ throw new IllegalArgumentException(String.format(messageTemplate, messageArgs));
+ }
+ }
+
+ /**
* Ensures that an string reference passed as a parameter to the calling
* method is not empty.
*