summaryrefslogtreecommitdiff
path: root/android/app
diff options
context:
space:
mode:
authorJason Monk <jmonk@google.com>2017-10-19 18:17:25 +0000
committerJason Monk <jmonk@google.com>2017-10-19 18:17:25 +0000
commit07f9f65561c2b81bcd189b895b31bb2ad0438d74 (patch)
tree49f76f879a89c256a4f65b674086be50760bdffb /android/app
parentd439404c9988df6001e4ff8bce31537e2692660e (diff)
downloadandroid-28-07f9f65561c2b81bcd189b895b31bb2ad0438d74.tar.gz
Revert "Import Android SDK Platform P [4402356]"
This reverts commit d439404c9988df6001e4ff8bce31537e2692660e. Change-Id: I825790bdf38523800388bc1bb531cecfcd7e60bd
Diffstat (limited to 'android/app')
-rw-r--r--android/app/Activity.java8
-rw-r--r--android/app/ActivityManager.java294
-rw-r--r--android/app/ActivityOptions.java43
-rw-r--r--android/app/KeyguardManager.java2
-rw-r--r--android/app/NotificationChannel.java2
-rw-r--r--android/app/NotificationManager.java9
-rw-r--r--android/app/StatusBarManager.java5
-rw-r--r--android/app/TaskStackListener.java7
-rw-r--r--android/app/WallpaperManager.java31
-rw-r--r--android/app/WindowConfiguration.java3
-rw-r--r--android/app/assist/AssistStructure.java57
-rw-r--r--android/app/job/JobScheduler.java41
-rw-r--r--android/app/job/JobService.java102
-rw-r--r--android/app/slice/Slice.java417
-rw-r--r--android/app/slice/SliceItem.java346
-rw-r--r--android/app/slice/SliceProvider.java182
-rw-r--r--android/app/slice/SliceQuery.java150
-rw-r--r--android/app/slice/views/ActionRow.java201
-rw-r--r--android/app/slice/views/GridView.java186
-rw-r--r--android/app/slice/views/LargeSliceAdapter.java224
-rw-r--r--android/app/slice/views/LargeTemplateView.java115
-rw-r--r--android/app/slice/views/MessageView.java77
-rw-r--r--android/app/slice/views/RemoteInputView.java445
-rw-r--r--android/app/slice/views/ShortcutView.java110
-rw-r--r--android/app/slice/views/SliceView.java251
-rw-r--r--android/app/slice/views/SliceViewUtil.java182
-rw-r--r--android/app/slice/views/SmallTemplateView.java211
-rw-r--r--android/app/usage/UsageStatsManager.java19
28 files changed, 311 insertions, 3409 deletions
diff --git a/android/app/Activity.java b/android/app/Activity.java
index 85f73bb7..e0ac9113 100644
--- a/android/app/Activity.java
+++ b/android/app/Activity.java
@@ -542,9 +542,9 @@ import java.util.List;
* <ul>
* <li> <p>When creating a new document, the backing database entry or file for
* it is created immediately. For example, if the user chooses to write
- * a new email, a new entry for that email is created as soon as they
+ * a new e-mail, a new entry for that e-mail is created as soon as they
* start entering data, so that if they go to any other activity after
- * that point this email will now appear in the list of drafts.</p>
+ * that point this e-mail will now appear in the list of drafts.</p>
* <li> <p>When an activity's <code>onPause()</code> method is called, it should
* commit to the backing content provider or file any changes the user
* has made. This ensures that those changes will be seen by any other
@@ -1879,7 +1879,7 @@ public class Activity extends ContextThemeWrapper
if (isFinishing()) {
if (mAutoFillResetNeeded) {
- getAutofillManager().onActivityFinished();
+ getAutofillManager().commit();
} else if (mIntent != null
&& mIntent.hasExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN)) {
// Activity was launched when user tapped a link in the Autofill Save UI - since
@@ -6259,8 +6259,6 @@ public class Activity extends ContextThemeWrapper
final AutofillManager afm = getAutofillManager();
if (afm != null) {
afm.dump(prefix, writer);
- } else {
- writer.print(prefix); writer.println("No AutofillManager");
}
}
diff --git a/android/app/ActivityManager.java b/android/app/ActivityManager.java
index fc4c8d7f..5e61727f 100644
--- a/android/app/ActivityManager.java
+++ b/android/app/ActivityManager.java
@@ -16,8 +16,14 @@
package android.app;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+
import android.Manifest;
-import android.annotation.DrawableRes;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -664,6 +670,138 @@ public class ActivityManager {
/** Invalid stack ID. */
public static final int INVALID_STACK_ID = -1;
+ /** First static stack ID.
+ * @hide */
+ private static final int FIRST_STATIC_STACK_ID = 0;
+
+ /** ID of stack where fullscreen activities are normally launched into.
+ * @hide */
+ public static final int FULLSCREEN_WORKSPACE_STACK_ID = 1;
+
+ /** ID of stack where freeform/resized activities are normally launched into.
+ * @hide */
+ public static final int FREEFORM_WORKSPACE_STACK_ID = FULLSCREEN_WORKSPACE_STACK_ID + 1;
+
+ /** ID of stack that occupies a dedicated region of the screen.
+ * @hide */
+ public static final int DOCKED_STACK_ID = FREEFORM_WORKSPACE_STACK_ID + 1;
+
+ /** ID of stack that always on top (always visible) when it exist.
+ * @hide */
+ public static final int PINNED_STACK_ID = DOCKED_STACK_ID + 1;
+
+ /** Last static stack stack ID.
+ * @hide */
+ private static final int LAST_STATIC_STACK_ID = PINNED_STACK_ID;
+
+ /** Start of ID range used by stacks that are created dynamically.
+ * @hide */
+ public static final int FIRST_DYNAMIC_STACK_ID = LAST_STATIC_STACK_ID + 1;
+
+ // TODO: Figure-out a way to remove this.
+ /** @hide */
+ public static boolean isStaticStack(int stackId) {
+ return stackId >= FIRST_STATIC_STACK_ID && stackId <= LAST_STATIC_STACK_ID;
+ }
+
+ // TODO: It seems this mostly means a stack on a secondary display now. Need to see if
+ // there are other meanings. If not why not just use information from the display?
+ /** @hide */
+ public static boolean isDynamicStack(int stackId) {
+ return stackId >= FIRST_DYNAMIC_STACK_ID;
+ }
+
+ /**
+ * Returns true if we try to maintain focus in the current stack when the top activity
+ * finishes.
+ * @hide
+ */
+ // TODO: Figure-out a way to remove. Probably isn't needed in the new world...
+ public static boolean keepFocusInStackIfPossible(int stackId) {
+ return stackId == FREEFORM_WORKSPACE_STACK_ID
+ || stackId == DOCKED_STACK_ID || stackId == PINNED_STACK_ID;
+ }
+
+ /**
+ * Returns true if the windows of tasks being moved to the target stack from the source
+ * stack should be replaced, meaning that window manager will keep the old window around
+ * until the new is ready.
+ * @hide
+ */
+ public static boolean replaceWindowsOnTaskMove(int sourceStackId, int targetStackId) {
+ return sourceStackId == FREEFORM_WORKSPACE_STACK_ID
+ || targetStackId == FREEFORM_WORKSPACE_STACK_ID;
+ }
+
+ /**
+ * Returns true if the top task in the task is allowed to return home when finished and
+ * there are other tasks in the stack.
+ * @hide
+ */
+ public static boolean allowTopTaskToReturnHome(int stackId) {
+ return stackId != PINNED_STACK_ID;
+ }
+
+ /**
+ * Returns true if the stack should be resized to match the bounds specified by
+ * {@link ActivityOptions#setLaunchBounds} when launching an activity into the stack.
+ * @hide
+ */
+ public static boolean resizeStackWithLaunchBounds(int stackId) {
+ return stackId == PINNED_STACK_ID;
+ }
+
+ /**
+ * Returns true if a window from the specified stack with {@param stackId} are normally
+ * fullscreen, i. e. they can become the top opaque fullscreen window, meaning that it
+ * controls system bars, lockscreen occluded/dismissing state, screen rotation animation,
+ * etc.
+ * @hide
+ */
+ // TODO: What about the other side of docked stack if we move this to WindowConfiguration?
+ public static boolean normallyFullscreenWindows(int stackId) {
+ return stackId != PINNED_STACK_ID && stackId != FREEFORM_WORKSPACE_STACK_ID
+ && stackId != DOCKED_STACK_ID;
+ }
+
+ /** Returns the stack id for the input windowing mode.
+ * @hide */
+ // TODO: To be removed once we are not using stack id for stuff...
+ public static int getStackIdForWindowingMode(int windowingMode) {
+ switch (windowingMode) {
+ case WINDOWING_MODE_PINNED: return PINNED_STACK_ID;
+ case WINDOWING_MODE_FREEFORM: return FREEFORM_WORKSPACE_STACK_ID;
+ case WINDOWING_MODE_SPLIT_SCREEN_PRIMARY: return DOCKED_STACK_ID;
+ case WINDOWING_MODE_SPLIT_SCREEN_SECONDARY: return FULLSCREEN_WORKSPACE_STACK_ID;
+ case WINDOWING_MODE_FULLSCREEN: return FULLSCREEN_WORKSPACE_STACK_ID;
+ default: return INVALID_STACK_ID;
+ }
+ }
+
+ /** Returns the windowing mode that should be used for this input stack id.
+ * @hide */
+ // TODO: To be removed once we are not using stack id for stuff...
+ public static int getWindowingModeForStackId(int stackId, boolean inSplitScreenMode) {
+ final int windowingMode;
+ switch (stackId) {
+ case FULLSCREEN_WORKSPACE_STACK_ID:
+ windowingMode = inSplitScreenMode
+ ? WINDOWING_MODE_SPLIT_SCREEN_SECONDARY : WINDOWING_MODE_FULLSCREEN;
+ break;
+ case PINNED_STACK_ID:
+ windowingMode = WINDOWING_MODE_PINNED;
+ break;
+ case DOCKED_STACK_ID:
+ windowingMode = WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+ break;
+ case FREEFORM_WORKSPACE_STACK_ID:
+ windowingMode = WINDOWING_MODE_FREEFORM;
+ break;
+ default :
+ windowingMode = WINDOWING_MODE_UNDEFINED;
+ }
+ return windowingMode;
+ }
}
/**
@@ -942,14 +1080,11 @@ public class ActivityManager {
ATTR_TASKDESCRIPTION_PREFIX + "color";
private static final String ATTR_TASKDESCRIPTIONCOLOR_BACKGROUND =
ATTR_TASKDESCRIPTION_PREFIX + "colorBackground";
- private static final String ATTR_TASKDESCRIPTIONICON_FILENAME =
+ private static final String ATTR_TASKDESCRIPTIONICONFILENAME =
ATTR_TASKDESCRIPTION_PREFIX + "icon_filename";
- private static final String ATTR_TASKDESCRIPTIONICON_RESOURCE =
- ATTR_TASKDESCRIPTION_PREFIX + "icon_resource";
private String mLabel;
private Bitmap mIcon;
- private int mIconRes;
private String mIconFilename;
private int mColorPrimary;
private int mColorBackground;
@@ -963,27 +1098,9 @@ public class ActivityManager {
* @param icon An icon that represents the current state of this task.
* @param colorPrimary A color to override the theme's primary color. This color must be
* opaque.
- * @deprecated use TaskDescription constructor with icon resource instead
*/
- @Deprecated
public TaskDescription(String label, Bitmap icon, int colorPrimary) {
- this(label, icon, 0, null, colorPrimary, 0, 0, 0);
- if ((colorPrimary != 0) && (Color.alpha(colorPrimary) != 255)) {
- throw new RuntimeException("A TaskDescription's primary color should be opaque");
- }
- }
-
- /**
- * Creates the TaskDescription to the specified values.
- *
- * @param label A label and description of the current state of this task.
- * @param iconRes A drawable resource of an icon that represents the current state of this
- * activity.
- * @param colorPrimary A color to override the theme's primary color. This color must be
- * opaque.
- */
- public TaskDescription(String label, @DrawableRes int iconRes, int colorPrimary) {
- this(label, null, iconRes, null, colorPrimary, 0, 0, 0);
+ this(label, icon, null, colorPrimary, 0, 0, 0);
if ((colorPrimary != 0) && (Color.alpha(colorPrimary) != 255)) {
throw new RuntimeException("A TaskDescription's primary color should be opaque");
}
@@ -994,22 +1111,9 @@ public class ActivityManager {
*
* @param label A label and description of the current state of this activity.
* @param icon An icon that represents the current state of this activity.
- * @deprecated use TaskDescription constructor with icon resource instead
*/
- @Deprecated
public TaskDescription(String label, Bitmap icon) {
- this(label, icon, 0, null, 0, 0, 0, 0);
- }
-
- /**
- * Creates the TaskDescription to the specified values.
- *
- * @param label A label and description of the current state of this activity.
- * @param iconRes A drawable resource of an icon that represents the current state of this
- * activity.
- */
- public TaskDescription(String label, @DrawableRes int iconRes) {
- this(label, null, iconRes, null, 0, 0, 0, 0);
+ this(label, icon, null, 0, 0, 0, 0);
}
/**
@@ -1018,22 +1122,21 @@ public class ActivityManager {
* @param label A label and description of the current state of this activity.
*/
public TaskDescription(String label) {
- this(label, null, 0, null, 0, 0, 0, 0);
+ this(label, null, null, 0, 0, 0, 0);
}
/**
* Creates an empty TaskDescription.
*/
public TaskDescription() {
- this(null, null, 0, null, 0, 0, 0, 0);
+ this(null, null, null, 0, 0, 0, 0);
}
/** @hide */
- public TaskDescription(String label, Bitmap bitmap, int iconRes, String iconFilename,
- int colorPrimary, int colorBackground, int statusBarColor, int navigationBarColor) {
+ public TaskDescription(String label, Bitmap icon, String iconFilename, int colorPrimary,
+ int colorBackground, int statusBarColor, int navigationBarColor) {
mLabel = label;
- mIcon = bitmap;
- mIconRes = iconRes;
+ mIcon = icon;
mIconFilename = iconFilename;
mColorPrimary = colorPrimary;
mColorBackground = colorBackground;
@@ -1055,7 +1158,6 @@ public class ActivityManager {
public void copyFrom(TaskDescription other) {
mLabel = other.mLabel;
mIcon = other.mIcon;
- mIconRes = other.mIconRes;
mIconFilename = other.mIconFilename;
mColorPrimary = other.mColorPrimary;
mColorBackground = other.mColorBackground;
@@ -1071,7 +1173,6 @@ public class ActivityManager {
public void copyFromPreserveHiddenFields(TaskDescription other) {
mLabel = other.mLabel;
mIcon = other.mIcon;
- mIconRes = other.mIconRes;
mIconFilename = other.mIconFilename;
mColorPrimary = other.mColorPrimary;
if (other.mColorBackground != 0) {
@@ -1144,14 +1245,6 @@ public class ActivityManager {
}
/**
- * Sets the icon resource for this task description.
- * @hide
- */
- public void setIcon(int iconRes) {
- mIconRes = iconRes;
- }
-
- /**
* Moves the icon bitmap reference from an actual Bitmap to a file containing the
* bitmap.
* @hide
@@ -1179,13 +1272,6 @@ public class ActivityManager {
}
/** @hide */
- @TestApi
- public int getIconResource() {
- return mIconRes;
- }
-
- /** @hide */
- @TestApi
public String getIconFilename() {
return mIconFilename;
}
@@ -1251,10 +1337,7 @@ public class ActivityManager {
Integer.toHexString(mColorBackground));
}
if (mIconFilename != null) {
- out.attribute(null, ATTR_TASKDESCRIPTIONICON_FILENAME, mIconFilename);
- }
- if (mIconRes != 0) {
- out.attribute(null, ATTR_TASKDESCRIPTIONICON_RESOURCE, Integer.toString(mIconRes));
+ out.attribute(null, ATTR_TASKDESCRIPTIONICONFILENAME, mIconFilename);
}
}
@@ -1266,10 +1349,8 @@ public class ActivityManager {
setPrimaryColor((int) Long.parseLong(attrValue, 16));
} else if (ATTR_TASKDESCRIPTIONCOLOR_BACKGROUND.equals(attrName)) {
setBackgroundColor((int) Long.parseLong(attrValue, 16));
- } else if (ATTR_TASKDESCRIPTIONICON_FILENAME.equals(attrName)) {
+ } else if (ATTR_TASKDESCRIPTIONICONFILENAME.equals(attrName)) {
setIconFilename(attrValue);
- } else if (ATTR_TASKDESCRIPTIONICON_RESOURCE.equals(attrName)) {
- setIcon(Integer.parseInt(attrValue, 10));
}
}
@@ -1292,7 +1373,6 @@ public class ActivityManager {
dest.writeInt(1);
mIcon.writeToParcel(dest, 0);
}
- dest.writeInt(mIconRes);
dest.writeInt(mColorPrimary);
dest.writeInt(mColorBackground);
dest.writeInt(mStatusBarColor);
@@ -1308,7 +1388,6 @@ public class ActivityManager {
public void readFromParcel(Parcel source) {
mLabel = source.readInt() > 0 ? source.readString() : null;
mIcon = source.readInt() > 0 ? Bitmap.CREATOR.createFromParcel(source) : null;
- mIconRes = source.readInt();
mColorPrimary = source.readInt();
mColorBackground = source.readInt();
mStatusBarColor = source.readInt();
@@ -1329,8 +1408,8 @@ public class ActivityManager {
@Override
public String toString() {
return "TaskDescription Label: " + mLabel + " Icon: " + mIcon +
- " IconRes: " + mIconRes + " IconFilename: " + mIconFilename +
- " colorPrimary: " + mColorPrimary + " colorBackground: " + mColorBackground +
+ " IconFilename: " + mIconFilename + " colorPrimary: " + mColorPrimary +
+ " colorBackground: " + mColorBackground +
" statusBarColor: " + mColorBackground +
" navigationBarColor: " + mNavigationBarColor;
}
@@ -1492,6 +1571,7 @@ public class ActivityManager {
}
dest.writeInt(stackId);
dest.writeInt(userId);
+ dest.writeLong(firstActiveTime);
dest.writeLong(lastActiveTime);
dest.writeInt(affiliatedTaskId);
dest.writeInt(affiliatedTaskColor);
@@ -1520,6 +1600,7 @@ public class ActivityManager {
TaskDescription.CREATOR.createFromParcel(source) : null;
stackId = source.readInt();
userId = source.readInt();
+ firstActiveTime = source.readLong();
lastActiveTime = source.readLong();
affiliatedTaskId = source.readInt();
affiliatedTaskColor = source.readInt();
@@ -1562,6 +1643,31 @@ public class ActivityManager {
public static final int RECENT_IGNORE_UNAVAILABLE = 0x0002;
/**
+ * Provides a list that contains recent tasks for all
+ * profiles of a user.
+ * @hide
+ */
+ public static final int RECENT_INCLUDE_PROFILES = 0x0004;
+
+ /**
+ * Ignores all tasks that are on the home stack.
+ * @hide
+ */
+ public static final int RECENT_IGNORE_HOME_AND_RECENTS_STACK_TASKS = 0x0008;
+
+ /**
+ * Ignores the top task in the docked stack.
+ * @hide
+ */
+ public static final int RECENT_INGORE_DOCKED_STACK_TOP_TASK = 0x0010;
+
+ /**
+ * Ignores all tasks that are on the pinned stack.
+ * @hide
+ */
+ public static final int RECENT_INGORE_PINNED_STACK_TASKS = 0x0020;
+
+ /**
* <p></p>Return a list of the tasks that the user has recently launched, with
* the most recent being first and older ones after in order.
*
@@ -1596,7 +1702,33 @@ public class ActivityManager {
public List<RecentTaskInfo> getRecentTasks(int maxNum, int flags)
throws SecurityException {
try {
- return getService().getRecentTasks(maxNum, flags, UserHandle.myUserId()).getList();
+ return getService().getRecentTasks(maxNum,
+ flags, UserHandle.myUserId()).getList();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Same as {@link #getRecentTasks(int, int)} but returns the recent tasks for a
+ * specific user. It requires holding
+ * the {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} permission.
+ * @param maxNum The maximum number of entries to return in the list. The
+ * actual number returned may be smaller, depending on how many tasks the
+ * user has started and the maximum number the system can remember.
+ * @param flags Information about what to return. May be any combination
+ * of {@link #RECENT_WITH_EXCLUDED} and {@link #RECENT_IGNORE_UNAVAILABLE}.
+ *
+ * @return Returns a list of RecentTaskInfo records describing each of
+ * the recent tasks. Most recently activated tasks go first.
+ *
+ * @hide
+ */
+ public List<RecentTaskInfo> getRecentTasksForUser(int maxNum, int flags, int userId)
+ throws SecurityException {
+ try {
+ return getService().getRecentTasks(maxNum,
+ flags, userId).getList();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1889,6 +2021,22 @@ public class ActivityManager {
}
/**
+ * Completely remove the given task.
+ *
+ * @param taskId Identifier of the task to be removed.
+ * @return Returns true if the given task was found and removed.
+ *
+ * @hide
+ */
+ public boolean removeTask(int taskId) throws SecurityException {
+ try {
+ return getService().removeTask(taskId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Sets the windowing mode for a specific task. Only works on tasks of type
* {@link WindowConfiguration#ACTIVITY_TYPE_STANDARD}
* @param taskId The id of the task to set the windowing mode for.
diff --git a/android/app/ActivityOptions.java b/android/app/ActivityOptions.java
index b62e4c2d..a68c3a5c 100644
--- a/android/app/ActivityOptions.java
+++ b/android/app/ActivityOptions.java
@@ -17,13 +17,13 @@
package android.app;
import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
+import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.view.Display.INVALID_DISPLAY;
import android.annotation.Nullable;
import android.annotation.TestApi;
-import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
@@ -159,12 +159,6 @@ public class ActivityOptions {
private static final String KEY_ANIM_SPECS = "android:activity.animSpecs";
/**
- * Whether the activity should be launched into LockTask mode.
- * @see #setLockTaskMode(boolean)
- */
- private static final String KEY_LOCK_TASK_MODE = "android:activity.lockTaskMode";
-
- /**
* The display id the activity should be launched into.
* @see #setLaunchDisplayId(int)
* @hide
@@ -285,7 +279,6 @@ public class ActivityOptions {
private int mResultCode;
private int mExitCoordinatorIndex;
private PendingIntent mUsageTimeReport;
- private boolean mLockTaskMode = false;
private int mLaunchDisplayId = INVALID_DISPLAY;
@WindowConfiguration.WindowingMode
private int mLaunchWindowingMode = WINDOWING_MODE_UNDEFINED;
@@ -877,7 +870,6 @@ public class ActivityOptions {
mExitCoordinatorIndex = opts.getInt(KEY_EXIT_COORDINATOR_INDEX);
break;
}
- mLockTaskMode = opts.getBoolean(KEY_LOCK_TASK_MODE, false);
mLaunchDisplayId = opts.getInt(KEY_LAUNCH_DISPLAY_ID, INVALID_DISPLAY);
mLaunchWindowingMode = opts.getInt(KEY_LAUNCH_WINDOWING_MODE, WINDOWING_MODE_UNDEFINED);
mLaunchActivityType = opts.getInt(KEY_LAUNCH_ACTIVITY_TYPE, ACTIVITY_TYPE_UNDEFINED);
@@ -1064,37 +1056,6 @@ public class ActivityOptions {
}
/**
- * Gets whether the activity is to be launched into LockTask mode.
- * @return {@code true} if the activity is to be launched into LockTask mode.
- * @see Activity#startLockTask()
- * @see android.app.admin.DevicePolicyManager#setLockTaskPackages(ComponentName, String[])
- */
- public boolean getLockTaskMode() {
- return mLockTaskMode;
- }
-
- /**
- * Sets whether the activity is to be launched into LockTask mode.
- *
- * Use this option to start an activity in LockTask mode. Note that only apps permitted by
- * {@link android.app.admin.DevicePolicyManager} can run in LockTask mode. Therefore, if
- * {@link android.app.admin.DevicePolicyManager#isLockTaskPermitted(String)} returns
- * {@code false} for the package of the target activity, a {@link SecurityException} will be
- * thrown during {@link Context#startActivity(Intent, Bundle)}.
- *
- * Defaults to {@code false} if not set.
- *
- * @param lockTaskMode {@code true} if the activity is to be launched into LockTask mode.
- * @return {@code this} {@link ActivityOptions} instance.
- * @see Activity#startLockTask()
- * @see android.app.admin.DevicePolicyManager#setLockTaskPackages(ComponentName, String[])
- */
- public ActivityOptions setLockTaskMode(boolean lockTaskMode) {
- mLockTaskMode = lockTaskMode;
- return this;
- }
-
- /**
* Gets the id of the display where activity should be launched.
* @return The id of the display where activity should be launched,
* {@link android.view.Display#INVALID_DISPLAY} if not set.
@@ -1287,7 +1248,6 @@ public class ActivityOptions {
mExitCoordinatorIndex = otherOptions.mExitCoordinatorIndex;
break;
}
- mLockTaskMode = otherOptions.mLockTaskMode;
mAnimSpecs = otherOptions.mAnimSpecs;
mAnimationFinishedListener = otherOptions.mAnimationFinishedListener;
mSpecsFuture = otherOptions.mSpecsFuture;
@@ -1362,7 +1322,6 @@ public class ActivityOptions {
b.putInt(KEY_EXIT_COORDINATOR_INDEX, mExitCoordinatorIndex);
break;
}
- b.putBoolean(KEY_LOCK_TASK_MODE, mLockTaskMode);
b.putInt(KEY_LAUNCH_DISPLAY_ID, mLaunchDisplayId);
b.putInt(KEY_LAUNCH_WINDOWING_MODE, mLaunchWindowingMode);
b.putInt(KEY_LAUNCH_ACTIVITY_TYPE, mLaunchActivityType);
diff --git a/android/app/KeyguardManager.java b/android/app/KeyguardManager.java
index 1fe29004..54f74b15 100644
--- a/android/app/KeyguardManager.java
+++ b/android/app/KeyguardManager.java
@@ -387,6 +387,8 @@ public class KeyguardManager {
* such as the Home key and the right soft keys, don't work.
*
* @return true if in keyguard restricted input mode.
+ *
+ * @see android.view.WindowManagerPolicy#inKeyguardRestrictedKeyInputMode
*/
public boolean inKeyguardRestrictedInputMode() {
try {
diff --git a/android/app/NotificationChannel.java b/android/app/NotificationChannel.java
index c06ad3f3..47063f08 100644
--- a/android/app/NotificationChannel.java
+++ b/android/app/NotificationChannel.java
@@ -32,8 +32,6 @@ import android.util.proto.ProtoOutputStream;
import com.android.internal.util.Preconditions;
-import com.android.internal.util.Preconditions;
-
import org.json.JSONException;
import org.json.JSONObject;
import org.xmlpull.v1.XmlPullParser;
diff --git a/android/app/NotificationManager.java b/android/app/NotificationManager.java
index a52dc1e4..eb52cb7f 100644
--- a/android/app/NotificationManager.java
+++ b/android/app/NotificationManager.java
@@ -934,14 +934,8 @@ public class NotificationManager {
public static final int PRIORITY_CATEGORY_CALLS = 1 << 3;
/** Calls from repeat callers are prioritized. */
public static final int PRIORITY_CATEGORY_REPEAT_CALLERS = 1 << 4;
- /** Alarms are prioritized */
- public static final int PRIORITY_CATEGORY_ALARMS = 1 << 5;
- /** Media, system, game (catch-all for non-never suppressible sounds) are prioritized */
- public static final int PRIORITY_CATEGORY_MEDIA_SYSTEM_OTHER = 1 << 6;
private static final int[] ALL_PRIORITY_CATEGORIES = {
- PRIORITY_CATEGORY_ALARMS,
- PRIORITY_CATEGORY_MEDIA_SYSTEM_OTHER,
PRIORITY_CATEGORY_REMINDERS,
PRIORITY_CATEGORY_EVENTS,
PRIORITY_CATEGORY_MESSAGES,
@@ -1141,9 +1135,6 @@ public class NotificationManager {
case PRIORITY_CATEGORY_MESSAGES: return "PRIORITY_CATEGORY_MESSAGES";
case PRIORITY_CATEGORY_CALLS: return "PRIORITY_CATEGORY_CALLS";
case PRIORITY_CATEGORY_REPEAT_CALLERS: return "PRIORITY_CATEGORY_REPEAT_CALLERS";
- case PRIORITY_CATEGORY_ALARMS: return "PRIORITY_CATEGORY_ALARMS";
- case PRIORITY_CATEGORY_MEDIA_SYSTEM_OTHER:
- return "PRIORITY_CATEGORY_MEDIA_SYSTEM_OTHER";
default: return "PRIORITY_CATEGORY_UNKNOWN_" + priorityCategory;
}
}
diff --git a/android/app/StatusBarManager.java b/android/app/StatusBarManager.java
index 23c4166d..8987bc02 100644
--- a/android/app/StatusBarManager.java
+++ b/android/app/StatusBarManager.java
@@ -73,16 +73,15 @@ public class StatusBarManager {
public static final int DISABLE2_QUICK_SETTINGS = 1;
public static final int DISABLE2_SYSTEM_ICONS = 1 << 1;
public static final int DISABLE2_NOTIFICATION_SHADE = 1 << 2;
- public static final int DISABLE2_GLOBAL_ACTIONS = 1 << 3;
public static final int DISABLE2_NONE = 0x00000000;
public static final int DISABLE2_MASK = DISABLE2_QUICK_SETTINGS | DISABLE2_SYSTEM_ICONS
- | DISABLE2_NOTIFICATION_SHADE | DISABLE2_GLOBAL_ACTIONS;
+ | DISABLE2_NOTIFICATION_SHADE;
@IntDef(flag = true,
value = {DISABLE2_NONE, DISABLE2_MASK, DISABLE2_QUICK_SETTINGS, DISABLE2_SYSTEM_ICONS,
- DISABLE2_NOTIFICATION_SHADE, DISABLE2_GLOBAL_ACTIONS})
+ DISABLE2_NOTIFICATION_SHADE})
@Retention(RetentionPolicy.SOURCE)
public @interface Disable2Flags {}
diff --git a/android/app/TaskStackListener.java b/android/app/TaskStackListener.java
index 895d12a7..402e2095 100644
--- a/android/app/TaskStackListener.java
+++ b/android/app/TaskStackListener.java
@@ -77,7 +77,7 @@ public abstract class TaskStackListener extends ITaskStackListener.Stub {
}
@Override
- public void onTaskRemovalStarted(int taskId) throws RemoteException {
+ public void onTaskRemovalStarted(int taskId) {
}
@Override
@@ -91,10 +91,11 @@ public abstract class TaskStackListener extends ITaskStackListener.Stub {
}
@Override
- public void onTaskProfileLocked(int taskId, int userId) throws RemoteException {
+ public void onTaskProfileLocked(int taskId, int userId) {
}
@Override
- public void onTaskSnapshotChanged(int taskId, TaskSnapshot snapshot) throws RemoteException {
+ public void onTaskSnapshotChanged(int taskId, TaskSnapshot snapshot)
+ throws RemoteException {
}
}
diff --git a/android/app/WallpaperManager.java b/android/app/WallpaperManager.java
index 081bd814..942cc995 100644
--- a/android/app/WallpaperManager.java
+++ b/android/app/WallpaperManager.java
@@ -388,12 +388,11 @@ public class WallpaperManager {
public Bitmap peekWallpaperBitmap(Context context, boolean returnDefault,
@SetWallpaperFlags int which) {
- return peekWallpaperBitmap(context, returnDefault, which, context.getUserId(),
- false /* hardware */);
+ return peekWallpaperBitmap(context, returnDefault, which, context.getUserId());
}
public Bitmap peekWallpaperBitmap(Context context, boolean returnDefault,
- @SetWallpaperFlags int which, int userId, boolean hardware) {
+ @SetWallpaperFlags int which, int userId) {
if (mService != null) {
try {
if (!mService.isWallpaperSupported(context.getOpPackageName())) {
@@ -410,7 +409,7 @@ public class WallpaperManager {
mCachedWallpaper = null;
mCachedWallpaperUserId = 0;
try {
- mCachedWallpaper = getCurrentWallpaperLocked(context, userId, hardware);
+ mCachedWallpaper = getCurrentWallpaperLocked(context, userId);
mCachedWallpaperUserId = userId;
} catch (OutOfMemoryError e) {
Log.w(TAG, "Out of memory loading the current wallpaper: " + e);
@@ -448,7 +447,7 @@ public class WallpaperManager {
}
}
- private Bitmap getCurrentWallpaperLocked(Context context, int userId, boolean hardware) {
+ private Bitmap getCurrentWallpaperLocked(Context context, int userId) {
if (mService == null) {
Log.w(TAG, "WallpaperService not running");
return null;
@@ -461,9 +460,6 @@ public class WallpaperManager {
if (fd != null) {
try {
BitmapFactory.Options options = new BitmapFactory.Options();
- if (hardware) {
- options.inPreferredConfig = Bitmap.Config.HARDWARE;
- }
return BitmapFactory.decodeFileDescriptor(
fd.getFileDescriptor(), null, options);
} catch (OutOfMemoryError e) {
@@ -818,23 +814,12 @@ public class WallpaperManager {
}
/**
- * Like {@link #getDrawable()} but returns a Bitmap with default {@link Bitmap.Config}.
- *
- * @hide
- */
- public Bitmap getBitmap() {
- return getBitmap(false);
- }
-
- /**
* Like {@link #getDrawable()} but returns a Bitmap.
*
- * @param hardware Asks for a hardware backed bitmap.
- * @see Bitmap.Config#HARDWARE
* @hide
*/
- public Bitmap getBitmap(boolean hardware) {
- return getBitmapAsUser(mContext.getUserId(), hardware);
+ public Bitmap getBitmap() {
+ return getBitmapAsUser(mContext.getUserId());
}
/**
@@ -842,8 +827,8 @@ public class WallpaperManager {
*
* @hide
*/
- public Bitmap getBitmapAsUser(int userId, boolean hardware) {
- return sGlobals.peekWallpaperBitmap(mContext, true, FLAG_SYSTEM, userId, hardware);
+ public Bitmap getBitmapAsUser(int userId) {
+ return sGlobals.peekWallpaperBitmap(mContext, true, FLAG_SYSTEM, userId);
}
/**
diff --git a/android/app/WindowConfiguration.java b/android/app/WindowConfiguration.java
index 251863ca..6b405384 100644
--- a/android/app/WindowConfiguration.java
+++ b/android/app/WindowConfiguration.java
@@ -511,8 +511,7 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu
return windowingMode != WINDOWING_MODE_FREEFORM && windowingMode != WINDOWING_MODE_PINNED;
}
- /** @hide */
- public static String windowingModeToString(@WindowingMode int windowingMode) {
+ private static String windowingModeToString(@WindowingMode int windowingMode) {
switch (windowingMode) {
case WINDOWING_MODE_UNDEFINED: return "undefined";
case WINDOWING_MODE_FULLSCREEN: return "fullscreen";
diff --git a/android/app/assist/AssistStructure.java b/android/app/assist/AssistStructure.java
index e491a4f9..d9b7cd7e 100644
--- a/android/app/assist/AssistStructure.java
+++ b/android/app/assist/AssistStructure.java
@@ -616,9 +616,6 @@ public class AssistStructure implements Parcelable {
CharSequence[] mAutofillOptions;
boolean mSanitized;
HtmlInfo mHtmlInfo;
- int mMinEms = -1;
- int mMaxEms = -1;
- int mMaxLength = -1;
// POJO used to override some autofill-related values when the node is parcelized.
// Not written to parcel.
@@ -716,9 +713,6 @@ public class AssistStructure implements Parcelable {
if (p instanceof HtmlInfo) {
mHtmlInfo = (HtmlInfo) p;
}
- mMinEms = in.readInt();
- mMaxEms = in.readInt();
- mMaxLength = in.readInt();
}
if ((flags&FLAGS_HAS_LARGE_COORDS) != 0) {
mX = in.readInt();
@@ -882,9 +876,6 @@ public class AssistStructure implements Parcelable {
} else {
out.writeParcelable(null, 0);
}
- out.writeInt(mMinEms);
- out.writeInt(mMaxEms);
- out.writeInt(mMaxLength);
}
if ((flags&FLAGS_HAS_LARGE_COORDS) != 0) {
out.writeInt(mX);
@@ -1453,39 +1444,6 @@ public class AssistStructure implements Parcelable {
public ViewNode getChildAt(int index) {
return mChildren[index];
}
-
- /**
- * Returns the minimum width in ems of the text associated with this node, or {@code -1}
- * if not supported by the node.
- *
- * <p>It's only relevant when the {@link AssistStructure} is used for autofill purposes,
- * not for assist purposes.
- */
- public int getMinTextEms() {
- return mMinEms;
- }
-
- /**
- * Returns the maximum width in ems of the text associated with this node, or {@code -1}
- * if not supported by the node.
- *
- * <p>It's only relevant when the {@link AssistStructure} is used for autofill purposes,
- * not for assist purposes.
- */
- public int getMaxTextEms() {
- return mMaxEms;
- }
-
- /**
- * Returns the maximum length of the text associated with this node node, or {@code -1}
- * if not supported by the node or not set.
- *
- * <p>It's only relevant when the {@link AssistStructure} is used for autofill purposes,
- * not for assist purposes.
- */
- public int getMaxTextLength() {
- return mMaxLength;
- }
}
/**
@@ -1818,21 +1776,6 @@ public class AssistStructure implements Parcelable {
}
@Override
- public void setMinTextEms(int minEms) {
- mNode.mMinEms = minEms;
- }
-
- @Override
- public void setMaxTextEms(int maxEms) {
- mNode.mMaxEms = maxEms;
- }
-
- @Override
- public void setMaxTextLength(int maxLength) {
- mNode.mMaxLength = maxLength;
- }
-
- @Override
public void setDataIsSensitive(boolean sensitive) {
mNode.mSanitized = !sensitive;
}
diff --git a/android/app/job/JobScheduler.java b/android/app/job/JobScheduler.java
index 0deb2e13..3868439f 100644
--- a/android/app/job/JobScheduler.java
+++ b/android/app/job/JobScheduler.java
@@ -24,6 +24,7 @@ import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.content.ClipData;
import android.content.Context;
+import android.content.Intent;
import android.os.Bundle;
import android.os.PersistableBundle;
@@ -39,18 +40,16 @@ import java.util.List;
* and how to construct them. You will construct these JobInfo objects and pass them to the
* JobScheduler with {@link #schedule(JobInfo)}. When the criteria declared are met, the
* system will execute this job on your application's {@link android.app.job.JobService}.
- * You identify the service component that implements the logic for your job when you
- * construct the JobInfo using
+ * You identify which JobService is meant to execute the logic for your job when you create the
+ * JobInfo with
* {@link android.app.job.JobInfo.Builder#JobInfo.Builder(int,android.content.ComponentName)}.
* </p>
* <p>
- * The framework will be intelligent about when it executes jobs, and attempt to batch
- * and defer them as much as possible. Typically if you don't specify a deadline on a job, it
- * can be run at any moment depending on the current state of the JobScheduler's internal queue.
- * <p>
- * While a job is running, the system holds a wakelock on behalf of your app. For this reason,
- * you do not need to take any action to guarantee that the device stays awake for the
- * duration of the job.
+ * The framework will be intelligent about when you receive your callbacks, and attempt to batch
+ * and defer them as much as possible. Typically if you don't specify a deadline on your job, it
+ * can be run at any moment depending on the current state of the JobScheduler's internal queue,
+ * however it might be deferred as long as until the next time the device is connected to a power
+ * source.
* </p>
* <p>You do not
* instantiate this class directly; instead, retrieve it through
@@ -142,34 +141,30 @@ public abstract class JobScheduler {
int userId, String tag);
/**
- * Cancel the specified job. If the job is currently executing, it is stopped
- * immediately and the return value from its {@link JobService#onStopJob(JobParameters)}
- * method is ignored.
- *
- * @param jobId unique identifier for the job to be canceled, as supplied to
- * {@link JobInfo.Builder#JobInfo.Builder(int, android.content.ComponentName)
- * JobInfo.Builder(int, android.content.ComponentName)}.
+ * Cancel a job that is pending in the JobScheduler.
+ * @param jobId unique identifier for this job. Obtain this value from the jobs returned by
+ * {@link #getAllPendingJobs()}.
*/
public abstract void cancel(int jobId);
/**
- * Cancel <em>all</em> jobs that have been scheduled by the calling application.
+ * Cancel all jobs that have been registered with the JobScheduler by this package.
*/
public abstract void cancelAll();
/**
- * Retrieve all jobs that have been scheduled by the calling application.
+ * Retrieve all jobs for this package that are pending in the JobScheduler.
*
- * @return a list of all of the app's scheduled jobs. This includes jobs that are
- * currently started as well as those that are still waiting to run.
+ * @return a list of all the jobs registered by this package that have not
+ * yet been executed.
*/
public abstract @NonNull List<JobInfo> getAllPendingJobs();
/**
- * Look up the description of a scheduled job.
+ * Retrieve a specific job for this package that is pending in the
+ * JobScheduler.
*
- * @return The {@link JobInfo} description of the given scheduled job, or {@code null}
- * if the supplied job ID does not correspond to any job.
+ * @return job registered by this package that has not yet been executed.
*/
public abstract @Nullable JobInfo getPendingJob(int jobId);
}
diff --git a/android/app/job/JobService.java b/android/app/job/JobService.java
index 69afed20..9096b47b 100644
--- a/android/app/job/JobService.java
+++ b/android/app/job/JobService.java
@@ -18,7 +18,16 @@ package android.app.job;
import android.app.Service;
import android.content.Intent;
+import android.os.Handler;
import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+import android.util.Log;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.lang.ref.WeakReference;
/**
* <p>Entry point for the callback from the {@link android.app.job.JobScheduler}.</p>
@@ -46,7 +55,7 @@ public abstract class JobService extends Service {
* </pre>
*
* <p>If a job service is declared in the manifest but not protected with this
- * permission, that service will be ignored by the system.
+ * permission, that service will be ignored by the OS.
*/
public static final String PERMISSION_BIND =
"android.permission.BIND_JOB_SERVICE";
@@ -72,36 +81,14 @@ public abstract class JobService extends Service {
}
/**
- * Called to indicate that the job has begun executing. Override this method with the
- * logic for your job. Like all other component lifecycle callbacks, this method executes
- * on your application's main thread.
- * <p>
- * Return {@code true} from this method if your job needs to continue running. If you
- * do this, the job remains active until you call
- * {@link #jobFinished(JobParameters, boolean)} to tell the system that it has completed
- * its work, or until the job's required constraints are no longer satisfied. For
- * example, if the job was scheduled using
- * {@link JobInfo.Builder#setRequiresCharging(boolean) setRequiresCharging(true)},
- * it will be immediately halted by the system if the user unplugs the device from power,
- * the job's {@link #onStopJob(JobParameters)} callback will be invoked, and the app
- * will be expected to shut down all ongoing work connected with that job.
- * <p>
- * The system holds a wakelock on behalf of your app as long as your job is executing.
- * This wakelock is acquired before this method is invoked, and is not released until either
- * you call {@link #jobFinished(JobParameters, boolean)}, or after the system invokes
- * {@link #onStopJob(JobParameters)} to notify your job that it is being shut down
- * prematurely.
- * <p>
- * Returning {@code false} from this method means your job is already finished. The
- * system's wakelock for the job will be released, and {@link #onStopJob(JobParameters)}
- * will not be invoked.
+ * Override this method with the callback logic for your job. Any such logic needs to be
+ * performed on a separate thread, as this function is executed on your application's main
+ * thread.
*
- * @param params Parameters specifying info about this job, including the optional
- * extras configured with {@link JobInfo.Builder#setExtras(android.os.PersistableBundle).
- * This object serves to identify this specific running job instance when calling
- * {@link #jobFinished(JobParameters, boolean)}.
- * @return {@code true} if your service will continue running, using a separate thread
- * when appropriate. {@code false} means that this job has completed its work.
+ * @param params Parameters specifying info about this job, including the extras bundle you
+ * optionally provided at job-creation time.
+ * @return True if your service needs to process the work (on a separate thread). False if
+ * there's no more work to be done for this job.
*/
public abstract boolean onStartJob(JobParameters params);
@@ -114,44 +101,37 @@ public abstract class JobService extends Service {
* {@link android.app.job.JobInfo.Builder#setRequiredNetworkType(int)}, yet while your
* job was executing the user toggled WiFi. Another example is if you had specified
* {@link android.app.job.JobInfo.Builder#setRequiresDeviceIdle(boolean)}, and the phone left its
- * idle maintenance window. You are solely responsible for the behavior of your application
- * upon receipt of this message; your app will likely start to misbehave if you ignore it.
- * <p>
- * Once this method returns, the system releases the wakelock that it is holding on
- * behalf of the job.</p>
+ * idle maintenance window. You are solely responsible for the behaviour of your application
+ * upon receipt of this message; your app will likely start to misbehave if you ignore it. One
+ * immediate repercussion is that the system will cease holding a wakelock for you.</p>
*
- * @param params The parameters identifying this job, as supplied to
- * the job in the {@link #onStartJob(JobParameters)} callback.
- * @return {@code true} to indicate to the JobManager whether you'd like to reschedule
- * this job based on the retry criteria provided at job creation-time; or {@code false}
- * to end the job entirely. Regardless of the value returned, your job must stop executing.
+ * @param params Parameters specifying info about this job.
+ * @return True to indicate to the JobManager whether you'd like to reschedule this job based
+ * on the retry criteria provided at job creation-time. False to drop the job. Regardless of
+ * the value returned, your job must stop executing.
*/
public abstract boolean onStopJob(JobParameters params);
/**
- * Call this to inform the JobScheduler that the job has finished its work. When the
- * system receives this message, it releases the wakelock being held for the job.
+ * Call this to inform the JobManager you've finished executing. This can be called from any
+ * thread, as it will ultimately be run on your application's main thread. When the system
+ * receives this message it will release the wakelock being held.
* <p>
- * You can request that the job be scheduled again by passing {@code true} as
- * the <code>wantsReschedule</code> parameter. This will apply back-off policy
- * for the job; this policy can be adjusted through the
- * {@link android.app.job.JobInfo.Builder#setBackoffCriteria(long, int)} method
- * when the job is originally scheduled. The job's initial
- * requirements are preserved when jobs are rescheduled, regardless of backed-off
- * policy.
- * <p class="note">
- * A job running while the device is dozing will not be rescheduled with the normal back-off
- * policy. Instead, the job will be re-added to the queue and executed again during
- * a future idle maintenance window.
+ * You can specify post-execution behaviour to the scheduler here with
+ * <code>needsReschedule </code>. This will apply a back-off timer to your job based on
+ * the default, or what was set with
+ * {@link android.app.job.JobInfo.Builder#setBackoffCriteria(long, int)}. The original
+ * requirements are always honoured even for a backed-off job. Note that a job running in
+ * idle mode will not be backed-off. Instead what will happen is the job will be re-added
+ * to the queue and re-executed within a future idle maintenance window.
* </p>
*
- * @param params The parameters identifying this job, as supplied to
- * the job in the {@link #onStartJob(JobParameters)} callback.
- * @param wantsReschedule {@code true} if this job should be rescheduled according
- * to the back-off criteria specified when it was first scheduled; {@code false}
- * otherwise.
+ * @param params Parameters specifying system-provided info about this job, this was given to
+ * your application in {@link #onStartJob(JobParameters)}.
+ * @param needsReschedule True if this job should be rescheduled according to the back-off
+ * criteria specified at schedule-time. False otherwise.
*/
- public final void jobFinished(JobParameters params, boolean wantsReschedule) {
- mEngine.jobFinished(params, wantsReschedule);
+ public final void jobFinished(JobParameters params, boolean needsReschedule) {
+ mEngine.jobFinished(params, needsReschedule);
}
-}
+} \ No newline at end of file
diff --git a/android/app/slice/Slice.java b/android/app/slice/Slice.java
deleted file mode 100644
index 7f9f74b4..00000000
--- a/android/app/slice/Slice.java
+++ /dev/null
@@ -1,417 +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.app.slice;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.StringDef;
-import android.app.PendingIntent;
-import android.app.RemoteInput;
-import android.content.ContentResolver;
-import android.content.IContentProvider;
-import android.graphics.drawable.Icon;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.os.RemoteException;
-import android.widget.RemoteViews;
-
-import com.android.internal.util.ArrayUtils;
-import com.android.internal.util.Preconditions;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * A slice is a piece of app content and actions that can be surfaced outside of the app.
- *
- * <p>They are constructed using {@link Builder} in a tree structure
- * that provides the OS some information about how the content should be displayed.
- */
-public final class Slice implements Parcelable {
-
- /**
- * @hide
- */
- @StringDef({HINT_TITLE, HINT_LIST, HINT_LIST_ITEM, HINT_LARGE, HINT_ACTIONS, HINT_SELECTED,
- HINT_SOURCE, HINT_MESSAGE, HINT_HORIZONTAL, HINT_NO_TINT, HINT_PARTIAL})
- public @interface SliceHint{ }
-
- /**
- * Hint that this content is a title of other content in the slice.
- */
- public static final String HINT_TITLE = "title";
- /**
- * Hint that all sub-items/sub-slices within this content should be considered
- * to have {@link #HINT_LIST_ITEM}.
- */
- public static final String HINT_LIST = "list";
- /**
- * Hint that this item is part of a list and should be formatted as if is part
- * of a list.
- */
- public static final String HINT_LIST_ITEM = "list_item";
- /**
- * Hint that this content is important and should be larger when displayed if
- * possible.
- */
- public static final String HINT_LARGE = "large";
- /**
- * Hint that this slice contains a number of actions that can be grouped together
- * in a sort of controls area of the UI.
- */
- public static final String HINT_ACTIONS = "actions";
- /**
- * Hint indicating that this item (and its sub-items) are the current selection.
- */
- public static final String HINT_SELECTED = "selected";
- /**
- * Hint to indicate that this is a message as part of a communication
- * sequence in this slice.
- */
- public static final String HINT_MESSAGE = "message";
- /**
- * Hint to tag the source (i.e. sender) of a {@link #HINT_MESSAGE}.
- */
- public static final String HINT_SOURCE = "source";
- /**
- * Hint that list items within this slice or subslice would appear better
- * if organized horizontally.
- */
- public static final String HINT_HORIZONTAL = "horizontal";
- /**
- * Hint to indicate that this content should not be tinted.
- */
- public static final String HINT_NO_TINT = "no_tint";
- /**
- * Hint to indicate that this slice is incomplete and an update will be sent once
- * loading is complete. Slices which contain HINT_PARTIAL will not be cached by the
- * OS and should not be cached by apps.
- */
- public static final String HINT_PARTIAL = "partial";
-
- // These two are coming over from prototyping, but we probably don't want in
- // public API, at least not right now.
- /**
- * @hide
- */
- public static final String HINT_ALT = "alt";
-
- private final SliceItem[] mItems;
- private final @SliceHint String[] mHints;
- private Uri mUri;
-
- Slice(ArrayList<SliceItem> items, @SliceHint String[] hints, Uri uri) {
- mHints = hints;
- mItems = items.toArray(new SliceItem[items.size()]);
- mUri = uri;
- }
-
- protected Slice(Parcel in) {
- mHints = in.readStringArray();
- int n = in.readInt();
- mItems = new SliceItem[n];
- for (int i = 0; i < n; i++) {
- mItems[i] = SliceItem.CREATOR.createFromParcel(in);
- }
- mUri = Uri.CREATOR.createFromParcel(in);
- }
-
- /**
- * @return The Uri that this Slice represents.
- */
- public Uri getUri() {
- return mUri;
- }
-
- /**
- * @return All child {@link SliceItem}s that this Slice contains.
- */
- public List<SliceItem> getItems() {
- return Arrays.asList(mItems);
- }
-
- /**
- * @return All hints associated with this Slice.
- */
- public @SliceHint List<String> getHints() {
- return Arrays.asList(mHints);
- }
-
- /**
- * @hide
- */
- public SliceItem getPrimaryIcon() {
- for (SliceItem item : getItems()) {
- if (item.getType() == SliceItem.TYPE_IMAGE) {
- return item;
- }
- if (!(item.getType() == SliceItem.TYPE_SLICE && item.hasHint(Slice.HINT_LIST))
- && !item.hasHint(Slice.HINT_ACTIONS)
- && !item.hasHint(Slice.HINT_LIST_ITEM)
- && (item.getType() != SliceItem.TYPE_ACTION)) {
- SliceItem icon = SliceQuery.find(item, SliceItem.TYPE_IMAGE);
- if (icon != null) return icon;
- }
- }
- return null;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeStringArray(mHints);
- dest.writeInt(mItems.length);
- for (int i = 0; i < mItems.length; i++) {
- mItems[i].writeToParcel(dest, flags);
- }
- mUri.writeToParcel(dest, 0);
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- /**
- * @hide
- */
- public boolean hasHint(@SliceHint String hint) {
- return ArrayUtils.contains(mHints, hint);
- }
-
- /**
- * A Builder used to construct {@link Slice}s
- */
- public static class Builder {
-
- private final Uri mUri;
- private ArrayList<SliceItem> mItems = new ArrayList<>();
- private @SliceHint ArrayList<String> mHints = new ArrayList<>();
-
- /**
- * Create a builder which will construct a {@link Slice} for the Given Uri.
- * @param uri Uri to tag for this slice.
- */
- public Builder(@NonNull Uri uri) {
- mUri = uri;
- }
-
- /**
- * Create a builder for a {@link Slice} that is a sub-slice of the slice
- * being constructed by the provided builder.
- * @param parent The builder constructing the parent slice
- */
- public Builder(@NonNull Slice.Builder parent) {
- mUri = parent.mUri.buildUpon().appendPath("_gen")
- .appendPath(String.valueOf(mItems.size())).build();
- }
-
- /**
- * Add hints to the Slice being constructed
- */
- public Builder addHints(@SliceHint String... hints) {
- mHints.addAll(Arrays.asList(hints));
- return this;
- }
-
- /**
- * Add hints to the Slice being constructed
- */
- public Builder addHints(@SliceHint List<String> hints) {
- return addHints(hints.toArray(new String[hints.size()]));
- }
-
- /**
- * Add a sub-slice to the slice being constructed
- */
- public Builder addSubSlice(@NonNull Slice slice) {
- mItems.add(new SliceItem(slice, SliceItem.TYPE_SLICE, slice.getHints().toArray(
- new String[slice.getHints().size()])));
- return this;
- }
-
- /**
- * Add an action to the slice being constructed
- */
- public Slice.Builder addAction(@NonNull PendingIntent action, @NonNull Slice s) {
- mItems.add(new SliceItem(action, s, SliceItem.TYPE_ACTION, new String[0]));
- return this;
- }
-
- /**
- * Add text to the slice being constructed
- */
- public Builder addText(CharSequence text, @SliceHint String... hints) {
- mItems.add(new SliceItem(text, SliceItem.TYPE_TEXT, hints));
- return this;
- }
-
- /**
- * Add text to the slice being constructed
- */
- public Builder addText(CharSequence text, @SliceHint List<String> hints) {
- return addText(text, hints.toArray(new String[hints.size()]));
- }
-
- /**
- * Add an image to the slice being constructed
- */
- public Builder addIcon(Icon icon, @SliceHint String... hints) {
- mItems.add(new SliceItem(icon, SliceItem.TYPE_IMAGE, hints));
- return this;
- }
-
- /**
- * Add an image to the slice being constructed
- */
- public Builder addIcon(Icon icon, @SliceHint List<String> hints) {
- return addIcon(icon, hints.toArray(new String[hints.size()]));
- }
-
- /**
- * @hide This isn't final
- */
- public Builder addRemoteView(RemoteViews remoteView, @SliceHint String... hints) {
- mItems.add(new SliceItem(remoteView, SliceItem.TYPE_REMOTE_VIEW, hints));
- return this;
- }
-
- /**
- * Add remote input to the slice being constructed
- */
- public Slice.Builder addRemoteInput(RemoteInput remoteInput,
- @SliceHint List<String> hints) {
- return addRemoteInput(remoteInput, hints.toArray(new String[hints.size()]));
- }
-
- /**
- * Add remote input to the slice being constructed
- */
- public Slice.Builder addRemoteInput(RemoteInput remoteInput, @SliceHint String... hints) {
- mItems.add(new SliceItem(remoteInput, SliceItem.TYPE_REMOTE_INPUT, hints));
- return this;
- }
-
- /**
- * Add a color to the slice being constructed
- */
- public Builder addColor(int color, @SliceHint String... hints) {
- mItems.add(new SliceItem(color, SliceItem.TYPE_COLOR, hints));
- return this;
- }
-
- /**
- * Add a color to the slice being constructed
- */
- public Builder addColor(int color, @SliceHint List<String> hints) {
- return addColor(color, hints.toArray(new String[hints.size()]));
- }
-
- /**
- * Add a timestamp to the slice being constructed
- */
- public Slice.Builder addTimestamp(long time, @SliceHint String... hints) {
- mItems.add(new SliceItem(time, SliceItem.TYPE_TIMESTAMP, hints));
- return this;
- }
-
- /**
- * Add a timestamp to the slice being constructed
- */
- public Slice.Builder addTimestamp(long time, @SliceHint List<String> hints) {
- return addTimestamp(time, hints.toArray(new String[hints.size()]));
- }
-
- /**
- * Construct the slice.
- */
- public Slice build() {
- return new Slice(mItems, mHints.toArray(new String[mHints.size()]), mUri);
- }
- }
-
- public static final Creator<Slice> CREATOR = new Creator<Slice>() {
- @Override
- public Slice createFromParcel(Parcel in) {
- return new Slice(in);
- }
-
- @Override
- public Slice[] newArray(int size) {
- return new Slice[size];
- }
- };
-
- /**
- * @hide
- * @return A string representation of this slice.
- */
- public String toString() {
- return toString("");
- }
-
- private String toString(String indent) {
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < mItems.length; i++) {
- sb.append(indent);
- if (mItems[i].getType() == SliceItem.TYPE_SLICE) {
- sb.append("slice:\n");
- sb.append(mItems[i].getSlice().toString(indent + " "));
- } else if (mItems[i].getType() == SliceItem.TYPE_TEXT) {
- sb.append("text: ");
- sb.append(mItems[i].getText());
- sb.append("\n");
- } else {
- sb.append(SliceItem.typeToString(mItems[i].getType()));
- sb.append("\n");
- }
- }
- return sb.toString();
- }
-
- /**
- * Turns a slice Uri into slice content.
- *
- * @param resolver ContentResolver to be used.
- * @param uri The URI to a slice provider
- * @return The Slice provided by the app or null if none is given.
- * @see Slice
- */
- public static @Nullable Slice bindSlice(ContentResolver resolver, @NonNull Uri uri) {
- Preconditions.checkNotNull(uri, "uri");
- IContentProvider provider = resolver.acquireProvider(uri);
- if (provider == null) {
- throw new IllegalArgumentException("Unknown URI " + uri);
- }
- try {
- Bundle extras = new Bundle();
- extras.putParcelable(SliceProvider.EXTRA_BIND_URI, uri);
- final Bundle res = provider.call(resolver.getPackageName(), SliceProvider.METHOD_SLICE,
- null, extras);
- Bundle.setDefusable(res, true);
- return res.getParcelable(SliceProvider.EXTRA_SLICE);
- } catch (RemoteException e) {
- // Arbitrary and not worth documenting, as Activity
- // Manager will kill this process shortly anyway.
- return null;
- } finally {
- resolver.releaseProvider(provider);
- }
- }
-}
diff --git a/android/app/slice/SliceItem.java b/android/app/slice/SliceItem.java
deleted file mode 100644
index 6e69b051..00000000
--- a/android/app/slice/SliceItem.java
+++ /dev/null
@@ -1,346 +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.app.slice;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.app.PendingIntent;
-import android.app.RemoteInput;
-import android.graphics.drawable.Icon;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.text.TextUtils;
-import android.util.Pair;
-import android.widget.RemoteViews;
-
-import com.android.internal.util.ArrayUtils;
-
-import java.util.Arrays;
-import java.util.List;
-
-
-/**
- * A SliceItem is a single unit in the tree structure of a {@link Slice}.
- *
- * A SliceItem a piece of content and some hints about what that content
- * means or how it should be displayed. The types of content can be:
- * <li>{@link #TYPE_SLICE}</li>
- * <li>{@link #TYPE_TEXT}</li>
- * <li>{@link #TYPE_IMAGE}</li>
- * <li>{@link #TYPE_ACTION}</li>
- * <li>{@link #TYPE_COLOR}</li>
- * <li>{@link #TYPE_TIMESTAMP}</li>
- * <li>{@link #TYPE_REMOTE_INPUT}</li>
- *
- * The hints that a {@link SliceItem} are a set of strings which annotate
- * the content. The hints that are guaranteed to be understood by the system
- * are defined on {@link Slice}.
- */
-public final class SliceItem implements Parcelable {
-
- /**
- * @hide
- */
- @IntDef({TYPE_SLICE, TYPE_TEXT, TYPE_IMAGE, TYPE_ACTION, TYPE_COLOR,
- TYPE_TIMESTAMP, TYPE_REMOTE_INPUT})
- public @interface SliceType {}
-
- /**
- * A {@link SliceItem} that contains a {@link Slice}
- */
- public static final int TYPE_SLICE = 1;
- /**
- * A {@link SliceItem} that contains a {@link CharSequence}
- */
- public static final int TYPE_TEXT = 2;
- /**
- * A {@link SliceItem} that contains an {@link Icon}
- */
- public static final int TYPE_IMAGE = 3;
- /**
- * A {@link SliceItem} that contains a {@link PendingIntent}
- *
- * Note: Actions contain 2 pieces of data, In addition to the pending intent, the
- * item contains a {@link Slice} that the action applies to.
- */
- public static final int TYPE_ACTION = 4;
- /**
- * @hide This isn't final
- */
- public static final int TYPE_REMOTE_VIEW = 5;
- /**
- * A {@link SliceItem} that contains a Color int.
- */
- public static final int TYPE_COLOR = 6;
- /**
- * A {@link SliceItem} that contains a timestamp.
- */
- public static final int TYPE_TIMESTAMP = 8;
- /**
- * A {@link SliceItem} that contains a {@link RemoteInput}.
- */
- public static final int TYPE_REMOTE_INPUT = 9;
-
- /**
- * @hide
- */
- protected @Slice.SliceHint
- String[] mHints;
- private final int mType;
- private final Object mObj;
-
- /**
- * @hide
- */
- public SliceItem(Object obj, @SliceType int type, @Slice.SliceHint String[] hints) {
- mHints = hints;
- mType = type;
- mObj = obj;
- }
-
- /**
- * @hide
- */
- public SliceItem(PendingIntent intent, Slice slice, int type, @Slice.SliceHint String[] hints) {
- this(new Pair<>(intent, slice), type, hints);
- }
-
- /**
- * Gets all hints associated with this SliceItem.
- * @return Array of hints.
- */
- public @NonNull @Slice.SliceHint List<String> getHints() {
- return Arrays.asList(mHints);
- }
-
- /**
- * @hide
- */
- public void addHint(@Slice.SliceHint String hint) {
- mHints = ArrayUtils.appendElement(String.class, mHints, hint);
- }
-
- /**
- * @hide
- */
- public void removeHint(String hint) {
- ArrayUtils.removeElement(String.class, mHints, hint);
- }
-
- public @SliceType int getType() {
- return mType;
- }
-
- /**
- * @return The text held by this {@link #TYPE_TEXT} SliceItem
- */
- public CharSequence getText() {
- return (CharSequence) mObj;
- }
-
- /**
- * @return The icon held by this {@link #TYPE_IMAGE} SliceItem
- */
- public Icon getIcon() {
- return (Icon) mObj;
- }
-
- /**
- * @return The pending intent held by this {@link #TYPE_ACTION} SliceItem
- */
- public PendingIntent getAction() {
- return ((Pair<PendingIntent, Slice>) mObj).first;
- }
-
- /**
- * @hide This isn't final
- */
- public RemoteViews getRemoteView() {
- return (RemoteViews) mObj;
- }
-
- /**
- * @return The remote input held by this {@link #TYPE_REMOTE_INPUT} SliceItem
- */
- public RemoteInput getRemoteInput() {
- return (RemoteInput) mObj;
- }
-
- /**
- * @return The color held by this {@link #TYPE_COLOR} SliceItem
- */
- public int getColor() {
- return (Integer) mObj;
- }
-
- /**
- * @return The slice held by this {@link #TYPE_ACTION} or {@link #TYPE_SLICE} SliceItem
- */
- public Slice getSlice() {
- if (getType() == TYPE_ACTION) {
- return ((Pair<PendingIntent, Slice>) mObj).second;
- }
- return (Slice) mObj;
- }
-
- /**
- * @return The timestamp held by this {@link #TYPE_TIMESTAMP} SliceItem
- */
- public long getTimestamp() {
- return (Long) mObj;
- }
-
- /**
- * @param hint The hint to check for
- * @return true if this item contains the given hint
- */
- public boolean hasHint(@Slice.SliceHint String hint) {
- return ArrayUtils.contains(mHints, hint);
- }
-
- /**
- * @hide
- */
- public SliceItem(Parcel in) {
- mHints = in.readStringArray();
- mType = in.readInt();
- mObj = readObj(mType, in);
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeStringArray(mHints);
- dest.writeInt(mType);
- writeObj(dest, flags, mObj, mType);
- }
-
- /**
- * @hide
- */
- public boolean hasHints(@Slice.SliceHint String[] hints) {
- if (hints == null) return true;
- for (String hint : hints) {
- if (!TextUtils.isEmpty(hint) && !ArrayUtils.contains(mHints, hint)) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * @hide
- */
- public boolean hasAnyHints(@Slice.SliceHint String[] hints) {
- if (hints == null) return false;
- for (String hint : hints) {
- if (ArrayUtils.contains(mHints, hint)) {
- return true;
- }
- }
- return false;
- }
-
- private void writeObj(Parcel dest, int flags, Object obj, int type) {
- switch (type) {
- case TYPE_SLICE:
- case TYPE_REMOTE_VIEW:
- case TYPE_IMAGE:
- case TYPE_REMOTE_INPUT:
- ((Parcelable) obj).writeToParcel(dest, flags);
- break;
- case TYPE_ACTION:
- ((Pair<PendingIntent, Slice>) obj).first.writeToParcel(dest, flags);
- ((Pair<PendingIntent, Slice>) obj).second.writeToParcel(dest, flags);
- break;
- case TYPE_TEXT:
- TextUtils.writeToParcel((CharSequence) mObj, dest, flags);
- break;
- case TYPE_COLOR:
- dest.writeInt((Integer) mObj);
- break;
- case TYPE_TIMESTAMP:
- dest.writeLong((Long) mObj);
- break;
- }
- }
-
- private static Object readObj(int type, Parcel in) {
- switch (type) {
- case TYPE_SLICE:
- return Slice.CREATOR.createFromParcel(in);
- case TYPE_TEXT:
- return TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
- case TYPE_IMAGE:
- return Icon.CREATOR.createFromParcel(in);
- case TYPE_ACTION:
- return new Pair<PendingIntent, Slice>(
- PendingIntent.CREATOR.createFromParcel(in),
- Slice.CREATOR.createFromParcel(in));
- case TYPE_REMOTE_VIEW:
- return RemoteViews.CREATOR.createFromParcel(in);
- case TYPE_COLOR:
- return in.readInt();
- case TYPE_TIMESTAMP:
- return in.readLong();
- case TYPE_REMOTE_INPUT:
- return RemoteInput.CREATOR.createFromParcel(in);
- }
- throw new RuntimeException("Unsupported type " + type);
- }
-
- public static final Creator<SliceItem> CREATOR = new Creator<SliceItem>() {
- @Override
- public SliceItem createFromParcel(Parcel in) {
- return new SliceItem(in);
- }
-
- @Override
- public SliceItem[] newArray(int size) {
- return new SliceItem[size];
- }
- };
-
- /**
- * @hide
- */
- public static String typeToString(int type) {
- switch (type) {
- case TYPE_SLICE:
- return "Slice";
- case TYPE_TEXT:
- return "Text";
- case TYPE_IMAGE:
- return "Image";
- case TYPE_ACTION:
- return "Action";
- case TYPE_REMOTE_VIEW:
- return "RemoteView";
- case TYPE_COLOR:
- return "Color";
- case TYPE_TIMESTAMP:
- return "Timestamp";
- case TYPE_REMOTE_INPUT:
- return "RemoteInput";
- }
- return "Unrecognized type: " + type;
- }
-}
diff --git a/android/app/slice/SliceProvider.java b/android/app/slice/SliceProvider.java
deleted file mode 100644
index df87b455..00000000
--- a/android/app/slice/SliceProvider.java
+++ /dev/null
@@ -1,182 +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.app.slice;
-
-import android.Manifest.permission;
-import android.content.ContentProvider;
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.database.ContentObserver;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.CancellationSignal;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.StrictMode;
-import android.os.StrictMode.ThreadPolicy;
-import android.util.Log;
-
-import java.util.concurrent.CountDownLatch;
-
-/**
- * A SliceProvider allows app to provide content to be displayed in system
- * spaces. This content is templated and can contain actions, and the behavior
- * of how it is surfaced is specific to the system surface.
- *
- * <p>Slices are not currently live content. They are bound once and shown to the
- * user. If the content changes due to a callback from user interaction, then
- * {@link ContentResolver#notifyChange(Uri, ContentObserver)}
- * should be used to notify the system.</p>
- *
- * <p>The provider needs to be declared in the manifest to provide the authority
- * for the app. The authority for most slices is expected to match the package
- * of the application.</p>
- * <pre class="prettyprint">
- * {@literal
- * <provider
- * android:name="com.android.mypkg.MySliceProvider"
- * android:authorities="com.android.mypkg" />}
- * </pre>
- *
- * @see Slice
- */
-public abstract class SliceProvider extends ContentProvider {
-
- /**
- * This is the Android platform's MIME type for a slice: URI
- * containing a slice implemented through {@link SliceProvider}.
- */
- public static final String SLICE_TYPE = "vnd.android.slice";
-
- private static final String TAG = "SliceProvider";
- /**
- * @hide
- */
- public static final String EXTRA_BIND_URI = "slice_uri";
- /**
- * @hide
- */
- public static final String METHOD_SLICE = "bind_slice";
- /**
- * @hide
- */
- public static final String EXTRA_SLICE = "slice";
-
- private static final boolean DEBUG = false;
-
- /**
- * Implemented to create a slice. Will be called on the main thread.
- * <p>
- * onBindSlice should return as quickly as possible so that the UI tied
- * to this slice can be responsive. No network or other IO will be allowed
- * during onBindSlice. Any loading that needs to be done should happen
- * off the main thread with a call to {@link ContentResolver#notifyChange(Uri, ContentObserver)}
- * when the app is ready to provide the complete data in onBindSlice.
- * <p>
- *
- * @see {@link Slice}.
- * @see {@link Slice#HINT_PARTIAL}
- */
- // TODO: Provide alternate notifyChange that takes in the slice (i.e. notifyChange(Uri, Slice)).
- public abstract Slice onBindSlice(Uri sliceUri);
-
- @Override
- public final int update(Uri uri, ContentValues values, String selection,
- String[] selectionArgs) {
- if (DEBUG) Log.d(TAG, "update " + uri);
- return 0;
- }
-
- @Override
- public final int delete(Uri uri, String selection, String[] selectionArgs) {
- if (DEBUG) Log.d(TAG, "delete " + uri);
- return 0;
- }
-
- @Override
- public final Cursor query(Uri uri, String[] projection, String selection,
- String[] selectionArgs, String sortOrder) {
- if (DEBUG) Log.d(TAG, "query " + uri);
- return null;
- }
-
- @Override
- public final Cursor query(Uri uri, String[] projection, String selection, String[]
- selectionArgs, String sortOrder, CancellationSignal cancellationSignal) {
- if (DEBUG) Log.d(TAG, "query " + uri);
- return null;
- }
-
- @Override
- public final Cursor query(Uri uri, String[] projection, Bundle queryArgs,
- CancellationSignal cancellationSignal) {
- if (DEBUG) Log.d(TAG, "query " + uri);
- return null;
- }
-
- @Override
- public final Uri insert(Uri uri, ContentValues values) {
- if (DEBUG) Log.d(TAG, "insert " + uri);
- return null;
- }
-
- @Override
- public final String getType(Uri uri) {
- if (DEBUG) Log.d(TAG, "getType " + uri);
- return SLICE_TYPE;
- }
-
- @Override
- public Bundle call(String method, String arg, Bundle extras) {
- if (method.equals(METHOD_SLICE)) {
- getContext().enforceCallingPermission(permission.BIND_SLICE,
- "Slice binding requires the permission BIND_SLICE");
- Uri uri = extras.getParcelable(EXTRA_BIND_URI);
-
- Slice s = handleBindSlice(uri);
- Bundle b = new Bundle();
- b.putParcelable(EXTRA_SLICE, s);
- return b;
- }
- return super.call(method, arg, extras);
- }
-
- private Slice handleBindSlice(Uri sliceUri) {
- Slice[] output = new Slice[1];
- CountDownLatch latch = new CountDownLatch(1);
- Handler mainHandler = new Handler(Looper.getMainLooper());
- mainHandler.post(() -> {
- ThreadPolicy oldPolicy = StrictMode.getThreadPolicy();
- try {
- StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
- .detectAll()
- .penaltyDeath()
- .build());
- output[0] = onBindSlice(sliceUri);
- } finally {
- StrictMode.setThreadPolicy(oldPolicy);
- latch.countDown();
- }
- });
- try {
- latch.await();
- return output[0];
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
- }
-}
diff --git a/android/app/slice/SliceQuery.java b/android/app/slice/SliceQuery.java
deleted file mode 100644
index d1fe2c90..00000000
--- a/android/app/slice/SliceQuery.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.app.slice;
-
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Queue;
-import java.util.Spliterators;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-import java.util.stream.StreamSupport;
-
-/**
- * A bunch of utilities for searching the contents of a slice.
- * @hide
- */
-public class SliceQuery {
- private static final String TAG = "SliceQuery";
-
- /**
- * @hide
- */
- public static SliceItem findNotContaining(SliceItem container, List<SliceItem> list) {
- SliceItem ret = null;
- while (ret == null && list.size() != 0) {
- SliceItem remove = list.remove(0);
- if (!contains(container, remove)) {
- ret = remove;
- }
- }
- return ret;
- }
-
- /**
- * @hide
- */
- private static boolean contains(SliceItem container, SliceItem item) {
- if (container == null || item == null) return false;
- return stream(container).filter(s -> (s == item)).findAny().isPresent();
- }
-
- /**
- * @hide
- */
- public static List<SliceItem> findAll(SliceItem s, int type) {
- return findAll(s, type, (String[]) null, null);
- }
-
- /**
- * @hide
- */
- public static List<SliceItem> findAll(SliceItem s, int type, String hints, String nonHints) {
- return findAll(s, type, new String[]{ hints }, new String[]{ nonHints });
- }
-
- /**
- * @hide
- */
- public static List<SliceItem> findAll(SliceItem s, int type, String[] hints,
- String[] nonHints) {
- return stream(s).filter(item -> (type == -1 || item.getType() == type)
- && (item.hasHints(hints) && !item.hasAnyHints(nonHints)))
- .collect(Collectors.toList());
- }
-
- /**
- * @hide
- */
- public static SliceItem find(Slice s, int type, String hints, String nonHints) {
- return find(s, type, new String[]{ hints }, new String[]{ nonHints });
- }
-
- /**
- * @hide
- */
- public static SliceItem find(Slice s, int type) {
- return find(s, type, (String[]) null, null);
- }
-
- /**
- * @hide
- */
- public static SliceItem find(SliceItem s, int type) {
- return find(s, type, (String[]) null, null);
- }
-
- /**
- * @hide
- */
- public static SliceItem find(SliceItem s, int type, String hints, String nonHints) {
- return find(s, type, new String[]{ hints }, new String[]{ nonHints });
- }
-
- /**
- * @hide
- */
- public static SliceItem find(Slice s, int type, String[] hints, String[] nonHints) {
- List<String> h = s.getHints();
- return find(new SliceItem(s, SliceItem.TYPE_SLICE, h.toArray(new String[h.size()])), type,
- hints, nonHints);
- }
-
- /**
- * @hide
- */
- public static SliceItem find(SliceItem s, int type, String[] hints, String[] nonHints) {
- return stream(s).filter(item -> (item.getType() == type || type == -1)
- && (item.hasHints(hints) && !item.hasAnyHints(nonHints))).findFirst().orElse(null);
- }
-
- /**
- * @hide
- */
- public static Stream<SliceItem> stream(SliceItem slice) {
- Queue<SliceItem> items = new LinkedList();
- items.add(slice);
- Iterator<SliceItem> iterator = new Iterator<SliceItem>() {
- @Override
- public boolean hasNext() {
- return items.size() != 0;
- }
-
- @Override
- public SliceItem next() {
- SliceItem item = items.poll();
- if (item.getType() == SliceItem.TYPE_SLICE
- || item.getType() == SliceItem.TYPE_ACTION) {
- items.addAll(item.getSlice().getItems());
- }
- return item;
- }
- };
- return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, 0), false);
- }
-}
diff --git a/android/app/slice/views/ActionRow.java b/android/app/slice/views/ActionRow.java
deleted file mode 100644
index c7d99f7f..00000000
--- a/android/app/slice/views/ActionRow.java
+++ /dev/null
@@ -1,201 +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.app.slice.views;
-
-import android.app.PendingIntent;
-import android.app.PendingIntent.CanceledException;
-import android.app.RemoteInput;
-import android.app.slice.Slice;
-import android.app.slice.SliceItem;
-import android.app.slice.SliceQuery;
-import android.content.Context;
-import android.content.res.ColorStateList;
-import android.graphics.Color;
-import android.graphics.drawable.Icon;
-import android.os.AsyncTask;
-import android.util.TypedValue;
-import android.view.View;
-import android.view.ViewParent;
-import android.widget.FrameLayout;
-import android.widget.ImageView;
-import android.widget.ImageView.ScaleType;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-/**
- * @hide
- */
-public class ActionRow extends FrameLayout {
-
- private static final int MAX_ACTIONS = 5;
- private final int mSize;
- private final int mIconPadding;
- private final LinearLayout mActionsGroup;
- private final boolean mFullActions;
- private int mColor = Color.BLACK;
-
- public ActionRow(Context context, boolean fullActions) {
- super(context);
- mFullActions = fullActions;
- mSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 48,
- context.getResources().getDisplayMetrics());
- mIconPadding = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 12,
- context.getResources().getDisplayMetrics());
- mActionsGroup = new LinearLayout(context);
- mActionsGroup.setOrientation(LinearLayout.HORIZONTAL);
- mActionsGroup.setLayoutParams(
- new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
- addView(mActionsGroup);
- }
-
- private void setColor(int color) {
- mColor = color;
- for (int i = 0; i < mActionsGroup.getChildCount(); i++) {
- View view = mActionsGroup.getChildAt(i);
- SliceItem item = (SliceItem) view.getTag();
- boolean tint = !item.hasHint(Slice.HINT_NO_TINT);
- if (tint) {
- ((ImageView) view).setImageTintList(ColorStateList.valueOf(mColor));
- }
- }
- }
-
- private ImageView addAction(Icon icon, boolean allowTint, SliceItem image) {
- ImageView imageView = new ImageView(getContext());
- imageView.setPadding(mIconPadding, mIconPadding, mIconPadding, mIconPadding);
- imageView.setScaleType(ScaleType.FIT_CENTER);
- imageView.setImageIcon(icon);
- if (allowTint) {
- imageView.setImageTintList(ColorStateList.valueOf(mColor));
- }
- imageView.setBackground(SliceViewUtil.getDrawable(getContext(),
- android.R.attr.selectableItemBackground));
- imageView.setTag(image);
- addAction(imageView);
- return imageView;
- }
-
- /**
- * Set the actions and color for this action row.
- */
- public void setActions(SliceItem actionRow, SliceItem defColor) {
- removeAllViews();
- mActionsGroup.removeAllViews();
- addView(mActionsGroup);
-
- SliceItem color = SliceQuery.find(actionRow, SliceItem.TYPE_COLOR);
- if (color == null) {
- color = defColor;
- }
- if (color != null) {
- setColor(color.getColor());
- }
- SliceQuery.findAll(actionRow, SliceItem.TYPE_ACTION).forEach(action -> {
- if (mActionsGroup.getChildCount() >= MAX_ACTIONS) {
- return;
- }
- SliceItem image = SliceQuery.find(action, SliceItem.TYPE_IMAGE);
- if (image == null) {
- return;
- }
- boolean tint = !image.hasHint(Slice.HINT_NO_TINT);
- SliceItem input = SliceQuery.find(action, SliceItem.TYPE_REMOTE_INPUT);
- if (input != null && input.getRemoteInput().getAllowFreeFormInput()) {
- addAction(image.getIcon(), tint, image).setOnClickListener(
- v -> handleRemoteInputClick(v, action.getAction(), input.getRemoteInput()));
- createRemoteInputView(mColor, getContext());
- } else {
- addAction(image.getIcon(), tint, image).setOnClickListener(v -> AsyncTask.execute(
- () -> {
- try {
- action.getAction().send();
- } catch (CanceledException e) {
- e.printStackTrace();
- }
- }));
- }
- });
- setVisibility(getChildCount() != 0 ? View.VISIBLE : View.GONE);
- }
-
- private void addAction(View child) {
- mActionsGroup.addView(child, new LinearLayout.LayoutParams(mSize, mSize, 1));
- }
-
- private void createRemoteInputView(int color, Context context) {
- View riv = RemoteInputView.inflate(context, this);
- riv.setVisibility(View.INVISIBLE);
- addView(riv, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
- riv.setBackgroundColor(color);
- }
-
- private boolean handleRemoteInputClick(View view, PendingIntent pendingIntent,
- RemoteInput input) {
- if (input == null) {
- return false;
- }
-
- ViewParent p = view.getParent().getParent();
- RemoteInputView riv = null;
- while (p != null) {
- if (p instanceof View) {
- View pv = (View) p;
- riv = findRemoteInputView(pv);
- if (riv != null) {
- break;
- }
- }
- p = p.getParent();
- }
- if (riv == null) {
- return false;
- }
-
- int width = view.getWidth();
- if (view instanceof TextView) {
- // Center the reveal on the text which might be off-center from the TextView
- TextView tv = (TextView) view;
- if (tv.getLayout() != null) {
- int innerWidth = (int) tv.getLayout().getLineWidth(0);
- innerWidth += tv.getCompoundPaddingLeft() + tv.getCompoundPaddingRight();
- width = Math.min(width, innerWidth);
- }
- }
- int cx = view.getLeft() + width / 2;
- int cy = view.getTop() + view.getHeight() / 2;
- int w = riv.getWidth();
- int h = riv.getHeight();
- int r = Math.max(
- Math.max(cx + cy, cx + (h - cy)),
- Math.max((w - cx) + cy, (w - cx) + (h - cy)));
-
- riv.setRevealParameters(cx, cy, r);
- riv.setPendingIntent(pendingIntent);
- riv.setRemoteInput(new RemoteInput[] {
- input
- }, input);
- riv.focusAnimated();
- return true;
- }
-
- private RemoteInputView findRemoteInputView(View v) {
- if (v == null) {
- return null;
- }
- return (RemoteInputView) v.findViewWithTag(RemoteInputView.VIEW_TAG);
- }
-}
diff --git a/android/app/slice/views/GridView.java b/android/app/slice/views/GridView.java
deleted file mode 100644
index 6f30c507..00000000
--- a/android/app/slice/views/GridView.java
+++ /dev/null
@@ -1,186 +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.app.slice.views;
-
-import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
-import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
-
-import android.app.slice.Slice;
-import android.app.slice.SliceItem;
-import android.app.slice.views.LargeSliceAdapter.SliceListView;
-import android.content.Context;
-import android.graphics.Color;
-import android.util.AttributeSet;
-import android.util.TypedValue;
-import android.view.Gravity;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.FrameLayout;
-import android.widget.ImageView;
-import android.widget.ImageView.ScaleType;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-import com.android.internal.R;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @hide
- */
-public class GridView extends LinearLayout implements SliceListView {
-
- private static final String TAG = "GridView";
-
- private static final int MAX_IMAGES = 3;
- private static final int MAX_ALL = 5;
- private boolean mIsAllImages;
-
- public GridView(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- if (mIsAllImages) {
- int width = MeasureSpec.getSize(widthMeasureSpec);
- int height = width / getChildCount();
- heightMeasureSpec = MeasureSpec.makeMeasureSpec(MeasureSpec.EXACTLY,
- height);
- getLayoutParams().height = height;
- for (int i = 0; i < getChildCount(); i++) {
- getChildAt(i).getLayoutParams().height = height;
- }
- }
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- }
-
- @Override
- public void setSliceItem(SliceItem slice) {
- mIsAllImages = true;
- removeAllViews();
- int total = 1;
- if (slice.getType() == SliceItem.TYPE_SLICE) {
- List<SliceItem> items = slice.getSlice().getItems();
- total = items.size();
- for (int i = 0; i < total; i++) {
- SliceItem item = items.get(i);
- if (isFull()) {
- continue;
- }
- if (!addItem(item)) {
- mIsAllImages = false;
- }
- }
- } else {
- if (!isFull()) {
- if (!addItem(slice)) {
- mIsAllImages = false;
- }
- }
- }
- if (total > getChildCount() && mIsAllImages) {
- addExtraCount(total - getChildCount());
- }
- }
-
- private void addExtraCount(int numExtra) {
- View last = getChildAt(getChildCount() - 1);
- FrameLayout frame = new FrameLayout(getContext());
- frame.setLayoutParams(last.getLayoutParams());
-
- removeView(last);
- frame.addView(last, new LayoutParams(MATCH_PARENT, MATCH_PARENT));
-
- TextView v = new TextView(getContext());
- v.setTextColor(Color.WHITE);
- v.setBackgroundColor(0x4d000000);
- v.setText(getResources().getString(R.string.slice_more_content, numExtra));
- v.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18);
- v.setGravity(Gravity.CENTER);
- frame.addView(v, new LayoutParams(MATCH_PARENT, MATCH_PARENT));
-
- addView(frame);
- }
-
- private boolean isFull() {
- return getChildCount() >= (mIsAllImages ? MAX_IMAGES : MAX_ALL);
- }
-
- /**
- * Returns true if this item is just an image.
- */
- private boolean addItem(SliceItem item) {
- if (item.getType() == SliceItem.TYPE_IMAGE) {
- ImageView v = new ImageView(getContext());
- v.setImageIcon(item.getIcon());
- v.setScaleType(ScaleType.CENTER_CROP);
- addView(v, new LayoutParams(0, MATCH_PARENT, 1));
- return true;
- } else {
- LinearLayout v = new LinearLayout(getContext());
- int s = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
- 12, getContext().getResources().getDisplayMetrics());
- v.setPadding(0, s, 0, 0);
- v.setOrientation(LinearLayout.VERTICAL);
- v.setGravity(Gravity.CENTER_HORIZONTAL);
- // TODO: Unify sporadic inflates that happen throughout the code.
- ArrayList<SliceItem> items = new ArrayList<>();
- if (item.getType() == SliceItem.TYPE_SLICE) {
- items.addAll(item.getSlice().getItems());
- }
- items.forEach(i -> {
- Context context = getContext();
- switch (i.getType()) {
- case SliceItem.TYPE_TEXT:
- boolean title = false;
- if ((item.hasAnyHints(new String[] {
- Slice.HINT_LARGE, Slice.HINT_TITLE
- }))) {
- title = true;
- }
- TextView tv = (TextView) LayoutInflater.from(context).inflate(
- title ? R.layout.slice_title : R.layout.slice_secondary_text, null);
- tv.setText(i.getText());
- v.addView(tv);
- break;
- case SliceItem.TYPE_IMAGE:
- ImageView iv = new ImageView(context);
- iv.setImageIcon(i.getIcon());
- if (item.hasHint(Slice.HINT_LARGE)) {
- iv.setLayoutParams(new LayoutParams(WRAP_CONTENT, WRAP_CONTENT));
- } else {
- int size = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
- 48, context.getResources().getDisplayMetrics());
- iv.setLayoutParams(new LayoutParams(size, size));
- }
- v.addView(iv);
- break;
- case SliceItem.TYPE_REMOTE_VIEW:
- v.addView(i.getRemoteView().apply(context, v));
- break;
- case SliceItem.TYPE_COLOR:
- // TODO: Support color to tint stuff here.
- break;
- }
- });
- addView(v, new LayoutParams(0, WRAP_CONTENT, 1));
- return false;
- }
- }
-}
diff --git a/android/app/slice/views/LargeSliceAdapter.java b/android/app/slice/views/LargeSliceAdapter.java
deleted file mode 100644
index 6794ff98..00000000
--- a/android/app/slice/views/LargeSliceAdapter.java
+++ /dev/null
@@ -1,224 +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.app.slice.views;
-
-import android.app.slice.Slice;
-import android.app.slice.SliceItem;
-import android.app.slice.SliceQuery;
-import android.app.slice.views.LargeSliceAdapter.SliceViewHolder;
-import android.content.Context;
-import android.util.ArrayMap;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewGroup.LayoutParams;
-import android.widget.FrameLayout;
-
-import com.android.internal.R;
-import com.android.internal.widget.RecyclerView;
-import com.android.internal.widget.RecyclerView.ViewHolder;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.stream.Collectors;
-
-/**
- * @hide
- */
-public class LargeSliceAdapter extends RecyclerView.Adapter<SliceViewHolder> {
-
- public static final int TYPE_DEFAULT = 1;
- public static final int TYPE_HEADER = 2;
- public static final int TYPE_GRID = 3;
- public static final int TYPE_MESSAGE = 4;
- public static final int TYPE_MESSAGE_LOCAL = 5;
- public static final int TYPE_REMOTE_VIEWS = 6;
-
- private final IdGenerator mIdGen = new IdGenerator();
- private final Context mContext;
- private List<SliceWrapper> mSlices = new ArrayList<>();
- private SliceItem mColor;
-
- public LargeSliceAdapter(Context context) {
- mContext = context;
- setHasStableIds(true);
- }
-
- /**
- * Set the {@link SliceItem}'s to be displayed in the adapter and the accent color.
- */
- public void setSliceItems(List<SliceItem> slices, SliceItem color) {
- mColor = color;
- mIdGen.resetUsage();
- mSlices = slices.stream().map(s -> new SliceWrapper(s, mIdGen))
- .collect(Collectors.toList());
- notifyDataSetChanged();
- }
-
- @Override
- public SliceViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
- View v = inflateforType(viewType);
- v.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
- return new SliceViewHolder(v);
- }
-
- @Override
- public int getItemViewType(int position) {
- return mSlices.get(position).mType;
- }
-
- @Override
- public long getItemId(int position) {
- return mSlices.get(position).mId;
- }
-
- @Override
- public int getItemCount() {
- return mSlices.size();
- }
-
- @Override
- public void onBindViewHolder(SliceViewHolder holder, int position) {
- SliceWrapper slice = mSlices.get(position);
- if (holder.mSliceView != null) {
- holder.mSliceView.setColor(mColor);
- holder.mSliceView.setSliceItem(slice.mItem);
- } else if (slice.mType == TYPE_REMOTE_VIEWS) {
- FrameLayout frame = (FrameLayout) holder.itemView;
- frame.removeAllViews();
- frame.addView(slice.mItem.getRemoteView().apply(mContext, frame));
- }
- }
-
- private View inflateforType(int viewType) {
- switch (viewType) {
- case TYPE_REMOTE_VIEWS:
- return new FrameLayout(mContext);
- case TYPE_GRID:
- return LayoutInflater.from(mContext).inflate(R.layout.slice_grid, null);
- case TYPE_MESSAGE:
- return LayoutInflater.from(mContext).inflate(R.layout.slice_message, null);
- case TYPE_MESSAGE_LOCAL:
- return LayoutInflater.from(mContext).inflate(R.layout.slice_message_local, null);
- }
- return new SmallTemplateView(mContext);
- }
-
- protected static class SliceWrapper {
- private final SliceItem mItem;
- private final int mType;
- private final long mId;
-
- public SliceWrapper(SliceItem item, IdGenerator idGen) {
- mItem = item;
- mType = getType(item);
- mId = idGen.getId(item);
- }
-
- public static int getType(SliceItem item) {
- if (item.getType() == SliceItem.TYPE_REMOTE_VIEW) {
- return TYPE_REMOTE_VIEWS;
- }
- if (item.hasHint(Slice.HINT_MESSAGE)) {
- // TODO: Better way to determine me or not? Something more like Messaging style.
- if (SliceQuery.find(item, -1, Slice.HINT_SOURCE, null) != null) {
- return TYPE_MESSAGE;
- } else {
- return TYPE_MESSAGE_LOCAL;
- }
- }
- if (item.hasHint(Slice.HINT_HORIZONTAL)) {
- return TYPE_GRID;
- }
- return TYPE_DEFAULT;
- }
- }
-
- /**
- * A {@link ViewHolder} for presenting slices in {@link LargeSliceAdapter}.
- */
- public static class SliceViewHolder extends ViewHolder {
- public final SliceListView mSliceView;
-
- public SliceViewHolder(View itemView) {
- super(itemView);
- mSliceView = itemView instanceof SliceListView ? (SliceListView) itemView : null;
- }
- }
-
- /**
- * View slices being displayed in {@link LargeSliceAdapter}.
- */
- public interface SliceListView {
- /**
- * Set the slice item for this view.
- */
- void setSliceItem(SliceItem slice);
-
- /**
- * Set the color for the items in this view.
- */
- default void setColor(SliceItem color) {
-
- }
- }
-
- private static class IdGenerator {
- private long mNextLong = 0;
- private final ArrayMap<String, Long> mCurrentIds = new ArrayMap<>();
- private final ArrayMap<String, Integer> mUsedIds = new ArrayMap<>();
-
- public long getId(SliceItem item) {
- String str = genString(item);
- if (!mCurrentIds.containsKey(str)) {
- mCurrentIds.put(str, mNextLong++);
- }
- long id = mCurrentIds.get(str);
- int index = mUsedIds.getOrDefault(str, 0);
- mUsedIds.put(str, index + 1);
- return id + index * 10000;
- }
-
- private String genString(SliceItem item) {
- StringBuilder builder = new StringBuilder();
- SliceQuery.stream(item).forEach(i -> {
- builder.append(i.getType());
- i.removeHint(Slice.HINT_SELECTED);
- builder.append(i.getHints());
- switch (i.getType()) {
- case SliceItem.TYPE_REMOTE_VIEW:
- builder.append(i.getRemoteView());
- break;
- case SliceItem.TYPE_IMAGE:
- builder.append(i.getIcon());
- break;
- case SliceItem.TYPE_TEXT:
- builder.append(i.getText());
- break;
- case SliceItem.TYPE_COLOR:
- builder.append(i.getColor());
- break;
- }
- });
- return builder.toString();
- }
-
- public void resetUsage() {
- mUsedIds.clear();
- }
- }
-}
diff --git a/android/app/slice/views/LargeTemplateView.java b/android/app/slice/views/LargeTemplateView.java
deleted file mode 100644
index 9e225162..00000000
--- a/android/app/slice/views/LargeTemplateView.java
+++ /dev/null
@@ -1,115 +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.app.slice.views;
-
-import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
-
-import android.app.slice.Slice;
-import android.app.slice.SliceItem;
-import android.app.slice.SliceQuery;
-import android.app.slice.views.SliceView.SliceModeView;
-import android.content.Context;
-import android.util.TypedValue;
-
-import com.android.internal.widget.LinearLayoutManager;
-import com.android.internal.widget.RecyclerView;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @hide
- */
-public class LargeTemplateView extends SliceModeView {
- private final LargeSliceAdapter mAdapter;
- private final RecyclerView mRecyclerView;
- private final int mDefaultHeight;
- private final int mMaxHeight;
- private Slice mSlice;
-
- public LargeTemplateView(Context context) {
- super(context);
-
- mRecyclerView = new RecyclerView(getContext());
- mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
- mAdapter = new LargeSliceAdapter(context);
- mRecyclerView.setAdapter(mAdapter);
- addView(mRecyclerView);
- int width = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 300,
- getResources().getDisplayMetrics());
- setLayoutParams(new LayoutParams(width, WRAP_CONTENT));
- mDefaultHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 200,
- getResources().getDisplayMetrics());
- mMaxHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 200,
- getResources().getDisplayMetrics());
- }
-
- @Override
- public String getMode() {
- return SliceView.MODE_LARGE;
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- mRecyclerView.getLayoutParams().height = WRAP_CONTENT;
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- if (mRecyclerView.getMeasuredHeight() > mMaxHeight
- || mSlice.hasHint(Slice.HINT_PARTIAL)) {
- mRecyclerView.getLayoutParams().height = mDefaultHeight;
- } else {
- mRecyclerView.getLayoutParams().height = mRecyclerView.getMeasuredHeight();
- }
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- }
-
- @Override
- public void setSlice(Slice slice) {
- SliceItem color = SliceQuery.find(slice, SliceItem.TYPE_COLOR);
- mSlice = slice;
- List<SliceItem> items = new ArrayList<>();
- boolean[] hasHeader = new boolean[1];
- if (slice.hasHint(Slice.HINT_LIST)) {
- addList(slice, items);
- } else {
- slice.getItems().forEach(item -> {
- if (item.hasHint(Slice.HINT_ACTIONS)) {
- return;
- } else if (item.getType() == SliceItem.TYPE_COLOR) {
- return;
- } else if (item.getType() == SliceItem.TYPE_SLICE
- && item.hasHint(Slice.HINT_LIST)) {
- addList(item.getSlice(), items);
- } else if (item.hasHint(Slice.HINT_LIST_ITEM)) {
- items.add(item);
- } else if (!hasHeader[0]) {
- hasHeader[0] = true;
- items.add(0, item);
- } else {
- item.addHint(Slice.HINT_LIST_ITEM);
- items.add(item);
- }
- });
- }
- mAdapter.setSliceItems(items, color);
- }
-
- private void addList(Slice slice, List<SliceItem> items) {
- List<SliceItem> sliceItems = slice.getItems();
- sliceItems.forEach(i -> i.addHint(Slice.HINT_LIST_ITEM));
- items.addAll(sliceItems);
- }
-}
diff --git a/android/app/slice/views/MessageView.java b/android/app/slice/views/MessageView.java
deleted file mode 100644
index 77252bf2..00000000
--- a/android/app/slice/views/MessageView.java
+++ /dev/null
@@ -1,77 +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.app.slice.views;
-
-import android.app.slice.Slice;
-import android.app.slice.SliceItem;
-import android.app.slice.SliceQuery;
-import android.app.slice.views.LargeSliceAdapter.SliceListView;
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.drawable.Drawable;
-import android.text.SpannableStringBuilder;
-import android.util.AttributeSet;
-import android.util.TypedValue;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-/**
- * @hide
- */
-public class MessageView extends LinearLayout implements SliceListView {
-
- private TextView mDetails;
- private ImageView mIcon;
-
- public MessageView(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
- mDetails = findViewById(android.R.id.summary);
- mIcon = findViewById(android.R.id.icon);
- }
-
- @Override
- public void setSliceItem(SliceItem slice) {
- SliceItem source = SliceQuery.find(slice, SliceItem.TYPE_IMAGE, Slice.HINT_SOURCE, null);
- if (source != null) {
- final int iconSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
- 24, getContext().getResources().getDisplayMetrics());
- // TODO try and turn this into a drawable
- Bitmap iconBm = Bitmap.createBitmap(iconSize, iconSize, Bitmap.Config.ARGB_8888);
- Canvas iconCanvas = new Canvas(iconBm);
- Drawable d = source.getIcon().loadDrawable(getContext());
- d.setBounds(0, 0, iconSize, iconSize);
- d.draw(iconCanvas);
- mIcon.setImageBitmap(SliceViewUtil.getCircularBitmap(iconBm));
- }
- SpannableStringBuilder builder = new SpannableStringBuilder();
- SliceQuery.findAll(slice, SliceItem.TYPE_TEXT).forEach(text -> {
- if (builder.length() != 0) {
- builder.append('\n');
- }
- builder.append(text.getText());
- });
- mDetails.setText(builder.toString());
- }
-
-}
diff --git a/android/app/slice/views/RemoteInputView.java b/android/app/slice/views/RemoteInputView.java
deleted file mode 100644
index e53cb1ea..00000000
--- a/android/app/slice/views/RemoteInputView.java
+++ /dev/null
@@ -1,445 +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.app.slice.views;
-
-import android.animation.Animator;
-import android.app.Notification;
-import android.app.PendingIntent;
-import android.app.RemoteInput;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.ShortcutManager;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.os.Bundle;
-import android.text.Editable;
-import android.text.TextWatcher;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewAnimationUtils;
-import android.view.ViewGroup;
-import android.view.accessibility.AccessibilityEvent;
-import android.view.inputmethod.CompletionInfo;
-import android.view.inputmethod.EditorInfo;
-import android.view.inputmethod.InputConnection;
-import android.view.inputmethod.InputMethodManager;
-import android.widget.EditText;
-import android.widget.ImageButton;
-import android.widget.LinearLayout;
-import android.widget.ProgressBar;
-import android.widget.TextView;
-import android.widget.Toast;
-
-import com.android.internal.R;
-
-/**
- * Host for the remote input.
- *
- * @hide
- */
-// TODO this should be unified with SystemUI RemoteInputView (b/67527720)
-public class RemoteInputView extends LinearLayout implements View.OnClickListener, TextWatcher {
-
- private static final String TAG = "RemoteInput";
-
- /**
- * A marker object that let's us easily find views of this class.
- */
- public static final Object VIEW_TAG = new Object();
-
- private RemoteEditText mEditText;
- private ImageButton mSendButton;
- private ProgressBar mProgressBar;
- private PendingIntent mPendingIntent;
- private RemoteInput[] mRemoteInputs;
- private RemoteInput mRemoteInput;
-
- private int mRevealCx;
- private int mRevealCy;
- private int mRevealR;
- private boolean mResetting;
-
- public RemoteInputView(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
-
- mProgressBar = findViewById(R.id.remote_input_progress);
- mSendButton = findViewById(R.id.remote_input_send);
- mSendButton.setOnClickListener(this);
-
- mEditText = (RemoteEditText) getChildAt(0);
- mEditText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
- @Override
- public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
- final boolean isSoftImeEvent = event == null
- && (actionId == EditorInfo.IME_ACTION_DONE
- || actionId == EditorInfo.IME_ACTION_NEXT
- || actionId == EditorInfo.IME_ACTION_SEND);
- final boolean isKeyboardEnterKey = event != null
- && KeyEvent.isConfirmKey(event.getKeyCode())
- && event.getAction() == KeyEvent.ACTION_DOWN;
-
- if (isSoftImeEvent || isKeyboardEnterKey) {
- if (mEditText.length() > 0) {
- sendRemoteInput();
- }
- // Consume action to prevent IME from closing.
- return true;
- }
- return false;
- }
- });
- mEditText.addTextChangedListener(this);
- mEditText.setInnerFocusable(false);
- mEditText.mRemoteInputView = this;
- }
-
- private void sendRemoteInput() {
- Bundle results = new Bundle();
- results.putString(mRemoteInput.getResultKey(), mEditText.getText().toString());
- Intent fillInIntent = new Intent().addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
- RemoteInput.addResultsToIntent(mRemoteInputs, fillInIntent,
- results);
-
- mEditText.setEnabled(false);
- mSendButton.setVisibility(INVISIBLE);
- mProgressBar.setVisibility(VISIBLE);
- mEditText.mShowImeOnInputConnection = false;
-
- // Tell ShortcutManager that this package has been "activated". ShortcutManager
- // will reset the throttling for this package.
- // Strictly speaking, the intent receiver may be different from the intent creator,
- // but that's an edge case, and also because we can't always know which package will receive
- // an intent, so we just reset for the creator.
- getContext().getSystemService(ShortcutManager.class).onApplicationActive(
- mPendingIntent.getCreatorPackage(),
- getContext().getUserId());
-
- try {
- mPendingIntent.send(mContext, 0, fillInIntent);
- reset();
- } catch (PendingIntent.CanceledException e) {
- Log.i(TAG, "Unable to send remote input result", e);
- Toast.makeText(mContext, "Failure sending pending intent for inline reply :(",
- Toast.LENGTH_SHORT).show();
- reset();
- }
- }
-
- /**
- * Creates a remote input view.
- */
- public static RemoteInputView inflate(Context context, ViewGroup root) {
- RemoteInputView v = (RemoteInputView) LayoutInflater.from(context).inflate(
- R.layout.slice_remote_input, root, false);
- v.setTag(VIEW_TAG);
- return v;
- }
-
- @Override
- public void onClick(View v) {
- if (v == mSendButton) {
- sendRemoteInput();
- }
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- super.onTouchEvent(event);
-
- // We never want for a touch to escape to an outer view or one we covered.
- return true;
- }
-
- private void onDefocus() {
- setVisibility(INVISIBLE);
- }
-
- /**
- * Set the pending intent for remote input.
- */
- public void setPendingIntent(PendingIntent pendingIntent) {
- mPendingIntent = pendingIntent;
- }
-
- /**
- * Set the remote inputs for this view.
- */
- public void setRemoteInput(RemoteInput[] remoteInputs, RemoteInput remoteInput) {
- mRemoteInputs = remoteInputs;
- mRemoteInput = remoteInput;
- mEditText.setHint(mRemoteInput.getLabel());
- }
-
- /**
- * Focuses the remote input view.
- */
- public void focusAnimated() {
- if (getVisibility() != VISIBLE) {
- Animator animator = ViewAnimationUtils.createCircularReveal(
- this, mRevealCx, mRevealCy, 0, mRevealR);
- animator.setDuration(200);
- animator.start();
- }
- focus();
- }
-
- private void focus() {
- setVisibility(VISIBLE);
- mEditText.setInnerFocusable(true);
- mEditText.mShowImeOnInputConnection = true;
- mEditText.setSelection(mEditText.getText().length());
- mEditText.requestFocus();
- updateSendButton();
- }
-
- private void reset() {
- mResetting = true;
-
- mEditText.getText().clear();
- mEditText.setEnabled(true);
- mSendButton.setVisibility(VISIBLE);
- mProgressBar.setVisibility(INVISIBLE);
- updateSendButton();
- onDefocus();
-
- mResetting = false;
- }
-
- @Override
- public boolean onRequestSendAccessibilityEvent(View child, AccessibilityEvent event) {
- if (mResetting && child == mEditText) {
- // Suppress text events if it happens during resetting. Ideally this would be
- // suppressed by the text view not being shown, but that doesn't work here because it
- // needs to stay visible for the animation.
- return false;
- }
- return super.onRequestSendAccessibilityEvent(child, event);
- }
-
- private void updateSendButton() {
- mSendButton.setEnabled(mEditText.getText().length() != 0);
- }
-
- @Override
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {
- }
-
- @Override
- public void onTextChanged(CharSequence s, int start, int before, int count) {
- }
-
- @Override
- public void afterTextChanged(Editable s) {
- updateSendButton();
- }
-
- /**
- * Tries to find an action that matches the current pending intent of this view and updates its
- * state to that of the found action
- *
- * @return true if a matching action was found, false otherwise
- */
- public boolean updatePendingIntentFromActions(Notification.Action[] actions) {
- if (mPendingIntent == null || actions == null) {
- return false;
- }
- Intent current = mPendingIntent.getIntent();
- if (current == null) {
- return false;
- }
-
- for (Notification.Action a : actions) {
- RemoteInput[] inputs = a.getRemoteInputs();
- if (a.actionIntent == null || inputs == null) {
- continue;
- }
- Intent candidate = a.actionIntent.getIntent();
- if (!current.filterEquals(candidate)) {
- continue;
- }
-
- RemoteInput input = null;
- for (RemoteInput i : inputs) {
- if (i.getAllowFreeFormInput()) {
- input = i;
- }
- }
- if (input == null) {
- continue;
- }
- setPendingIntent(a.actionIntent);
- setRemoteInput(inputs, input);
- return true;
- }
- return false;
- }
-
- /**
- * @hide
- */
- public void setRevealParameters(int cx, int cy, int r) {
- mRevealCx = cx;
- mRevealCy = cy;
- mRevealR = r;
- }
-
- @Override
- public void dispatchStartTemporaryDetach() {
- super.dispatchStartTemporaryDetach();
- // Detach the EditText temporarily such that it doesn't get onDetachedFromWindow and
- // won't lose IME focus.
- detachViewFromParent(mEditText);
- }
-
- @Override
- public void dispatchFinishTemporaryDetach() {
- if (isAttachedToWindow()) {
- attachViewToParent(mEditText, 0, mEditText.getLayoutParams());
- } else {
- removeDetachedView(mEditText, false /* animate */);
- }
- super.dispatchFinishTemporaryDetach();
- }
-
- /**
- * An EditText that changes appearance based on whether it's focusable and becomes un-focusable
- * whenever the user navigates away from it or it becomes invisible.
- */
- public static class RemoteEditText extends EditText {
-
- private final Drawable mBackground;
- private RemoteInputView mRemoteInputView;
- boolean mShowImeOnInputConnection;
-
- public RemoteEditText(Context context, AttributeSet attrs) {
- super(context, attrs);
- mBackground = getBackground();
- }
-
- private void defocusIfNeeded(boolean animate) {
- if (mRemoteInputView != null || isTemporarilyDetached()) {
- if (isTemporarilyDetached()) {
- // We might get reattached but then the other one of HUN / expanded might steal
- // our focus, so we'll need to save our text here.
- }
- return;
- }
- if (isFocusable() && isEnabled()) {
- setInnerFocusable(false);
- if (mRemoteInputView != null) {
- mRemoteInputView.onDefocus();
- }
- mShowImeOnInputConnection = false;
- }
- }
-
- @Override
- protected void onVisibilityChanged(View changedView, int visibility) {
- super.onVisibilityChanged(changedView, visibility);
-
- if (!isShown()) {
- defocusIfNeeded(false /* animate */);
- }
- }
-
- @Override
- protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
- super.onFocusChanged(focused, direction, previouslyFocusedRect);
- if (!focused) {
- defocusIfNeeded(true /* animate */);
- }
- }
-
- @Override
- public void getFocusedRect(Rect r) {
- super.getFocusedRect(r);
- r.top = mScrollY;
- r.bottom = mScrollY + (mBottom - mTop);
- }
-
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- if (keyCode == KeyEvent.KEYCODE_BACK) {
- // Eat the DOWN event here to prevent any default behavior.
- return true;
- }
- return super.onKeyDown(keyCode, event);
- }
-
- @Override
- public boolean onKeyUp(int keyCode, KeyEvent event) {
- if (keyCode == KeyEvent.KEYCODE_BACK) {
- defocusIfNeeded(true /* animate */);
- return true;
- }
- return super.onKeyUp(keyCode, event);
- }
-
- @Override
- public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
- final InputConnection inputConnection = super.onCreateInputConnection(outAttrs);
-
- if (mShowImeOnInputConnection && inputConnection != null) {
- final InputMethodManager imm = InputMethodManager.getInstance();
- if (imm != null) {
- // onCreateInputConnection is called by InputMethodManager in the middle of
- // setting up the connection to the IME; wait with requesting the IME until that
- // work has completed.
- post(new Runnable() {
- @Override
- public void run() {
- imm.viewClicked(RemoteEditText.this);
- imm.showSoftInput(RemoteEditText.this, 0);
- }
- });
- }
- }
-
- return inputConnection;
- }
-
- @Override
- public void onCommitCompletion(CompletionInfo text) {
- clearComposingText();
- setText(text.getText());
- setSelection(getText().length());
- }
-
- void setInnerFocusable(boolean focusable) {
- setFocusableInTouchMode(focusable);
- setFocusable(focusable);
- setCursorVisible(focusable);
-
- if (focusable) {
- requestFocus();
- setBackground(mBackground);
- } else {
- setBackground(null);
- }
-
- }
- }
-}
diff --git a/android/app/slice/views/ShortcutView.java b/android/app/slice/views/ShortcutView.java
deleted file mode 100644
index b6790c7d..00000000
--- a/android/app/slice/views/ShortcutView.java
+++ /dev/null
@@ -1,110 +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.app.slice.views;
-
-import android.app.PendingIntent;
-import android.app.PendingIntent.CanceledException;
-import android.app.slice.Slice;
-import android.app.slice.SliceItem;
-import android.app.slice.SliceQuery;
-import android.app.slice.views.SliceView.SliceModeView;
-import android.content.Context;
-import android.content.Intent;
-import android.graphics.Color;
-import android.graphics.drawable.ShapeDrawable;
-import android.graphics.drawable.shapes.OvalShape;
-import android.net.Uri;
-import android.view.ViewGroup;
-
-import com.android.internal.R;
-
-/**
- * @hide
- */
-public class ShortcutView extends SliceModeView {
-
- private static final String TAG = "ShortcutView";
-
- private PendingIntent mAction;
- private Uri mUri;
- private int mLargeIconSize;
- private int mSmallIconSize;
-
- public ShortcutView(Context context) {
- super(context);
- mLargeIconSize = getContext().getResources()
- .getDimensionPixelSize(R.dimen.slice_shortcut_size);
- mSmallIconSize = getContext().getResources().getDimensionPixelSize(R.dimen.slice_icon_size);
- setLayoutParams(new ViewGroup.LayoutParams(mLargeIconSize, mLargeIconSize));
- }
-
- @Override
- public void setSlice(Slice slice) {
- removeAllViews();
- SliceItem sliceItem = SliceQuery.find(slice, SliceItem.TYPE_ACTION);
- SliceItem iconItem = slice.getPrimaryIcon();
- SliceItem textItem = sliceItem != null
- ? SliceQuery.find(sliceItem, SliceItem.TYPE_TEXT)
- : SliceQuery.find(slice, SliceItem.TYPE_TEXT);
- SliceItem colorItem = sliceItem != null
- ? SliceQuery.find(sliceItem, SliceItem.TYPE_COLOR)
- : SliceQuery.find(slice, SliceItem.TYPE_COLOR);
- if (colorItem == null) {
- colorItem = SliceQuery.find(slice, SliceItem.TYPE_COLOR);
- }
- // TODO: pick better default colour
- final int color = colorItem != null ? colorItem.getColor() : Color.GRAY;
- ShapeDrawable circle = new ShapeDrawable(new OvalShape());
- circle.setTint(color);
- setBackground(circle);
- if (iconItem != null) {
- final boolean isLarge = iconItem.hasHint(Slice.HINT_LARGE);
- final int iconSize = isLarge ? mLargeIconSize : mSmallIconSize;
- SliceViewUtil.createCircledIcon(getContext(), color, iconSize, iconItem.getIcon(),
- isLarge, this /* parent */);
- mAction = sliceItem != null ? sliceItem.getAction()
- : null;
- mUri = slice.getUri();
- setClickable(true);
- } else {
- setClickable(false);
- }
- }
-
- @Override
- public String getMode() {
- return SliceView.MODE_SHORTCUT;
- }
-
- @Override
- public boolean performClick() {
- if (!callOnClick()) {
- try {
- if (mAction != null) {
- mAction.send();
- } else {
- Intent intent = new Intent(Intent.ACTION_VIEW).setData(mUri);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- getContext().startActivity(intent);
- }
- } catch (CanceledException e) {
- e.printStackTrace();
- }
- }
- return true;
- }
-}
diff --git a/android/app/slice/views/SliceView.java b/android/app/slice/views/SliceView.java
deleted file mode 100644
index 32484fca..00000000
--- a/android/app/slice/views/SliceView.java
+++ /dev/null
@@ -1,251 +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.app.slice.views;
-
-import android.annotation.StringDef;
-import android.app.slice.Slice;
-import android.app.slice.SliceItem;
-import android.app.slice.SliceQuery;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.graphics.drawable.ColorDrawable;
-import android.net.Uri;
-import android.util.Log;
-import android.view.MotionEvent;
-import android.view.View;
-import android.widget.FrameLayout;
-import android.widget.LinearLayout;
-
-import java.util.List;
-
-/**
- * A view that can display a {@link Slice} in different {@link SliceMode}'s.
- *
- * @hide
- */
-public class SliceView extends LinearLayout {
-
- private static final String TAG = "SliceView";
-
- /**
- * @hide
- */
- public abstract static class SliceModeView extends FrameLayout {
-
- public SliceModeView(Context context) {
- super(context);
- }
-
- /**
- * @return the {@link SliceMode} of the slice being presented.
- */
- public abstract String getMode();
-
- /**
- * @param slice the slice to show in this view.
- */
- public abstract void setSlice(Slice slice);
- }
-
- /**
- * @hide
- */
- @StringDef({
- MODE_SMALL, MODE_LARGE, MODE_SHORTCUT
- })
- public @interface SliceMode {}
-
- /**
- * Mode indicating this slice should be presented in small template format.
- */
- public static final String MODE_SMALL = "SLICE_SMALL";
- /**
- * Mode indicating this slice should be presented in large template format.
- */
- public static final String MODE_LARGE = "SLICE_LARGE";
- /**
- * Mode indicating this slice should be presented as an icon.
- */
- public static final String MODE_SHORTCUT = "SLICE_ICON";
-
- /**
- * Will select the type of slice binding based on size of the View. TODO: Put in some info about
- * that selection.
- */
- private static final String MODE_AUTO = "auto";
-
- private String mMode = MODE_AUTO;
- private SliceModeView mCurrentView;
- private final ActionRow mActions;
- private Slice mCurrentSlice;
- private boolean mShowActions = true;
-
- /**
- * Simple constructor to create a slice view from code.
- *
- * @param context The context the view is running in.
- */
- public SliceView(Context context) {
- super(context);
- setOrientation(LinearLayout.VERTICAL);
- mActions = new ActionRow(mContext, true);
- mActions.setBackground(new ColorDrawable(0xffeeeeee));
- mCurrentView = new LargeTemplateView(mContext);
- addView(mCurrentView);
- addView(mActions);
- }
-
- /**
- * @hide
- */
- public void bindSlice(Intent intent) {
- // TODO
- }
-
- /**
- * Binds this view to the {@link Slice} associated with the provided {@link Uri}.
- */
- public void bindSlice(Uri sliceUri) {
- validate(sliceUri);
- Slice s = Slice.bindSlice(mContext.getContentResolver(), sliceUri);
- bindSlice(s);
- }
-
- /**
- * Binds this view to the provided {@link Slice}.
- */
- public void bindSlice(Slice slice) {
- mCurrentSlice = slice;
- if (mCurrentSlice != null) {
- reinflate();
- }
- }
-
- /**
- * Call to clean up the view.
- */
- public void unbindSlice() {
- mCurrentSlice = null;
- }
-
- /**
- * Set the {@link SliceMode} this view should present in.
- */
- public void setMode(@SliceMode String mode) {
- setMode(mode, false /* animate */);
- }
-
- /**
- * @hide
- */
- public void setMode(@SliceMode String mode, boolean animate) {
- if (animate) {
- Log.e(TAG, "Animation not supported yet");
- }
- mMode = mode;
- reinflate();
- }
-
- /**
- * @return the {@link SliceMode} this view is presenting in.
- */
- public @SliceMode String getMode() {
- if (mMode.equals(MODE_AUTO)) {
- return MODE_LARGE;
- }
- return mMode;
- }
-
- /**
- * @hide
- *
- * Whether this view should show a row of actions with it.
- */
- public void setShowActionRow(boolean show) {
- mShowActions = show;
- reinflate();
- }
-
- private SliceModeView createView(String mode) {
- switch (mode) {
- case MODE_SHORTCUT:
- return new ShortcutView(getContext());
- case MODE_SMALL:
- return new SmallTemplateView(getContext());
- }
- return new LargeTemplateView(getContext());
- }
-
- @Override
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
- unbindSlice();
- }
-
- private void reinflate() {
- if (mCurrentSlice == null) {
- return;
- }
- // TODO: Smarter mapping here from one state to the next.
- SliceItem color = SliceQuery.find(mCurrentSlice, SliceItem.TYPE_COLOR);
- List<SliceItem> items = mCurrentSlice.getItems();
- SliceItem actionRow = SliceQuery.find(mCurrentSlice, SliceItem.TYPE_SLICE,
- Slice.HINT_ACTIONS,
- Slice.HINT_ALT);
- String mode = getMode();
- if (!mode.equals(mCurrentView.getMode())) {
- removeAllViews();
- mCurrentView = createView(mode);
- addView(mCurrentView);
- addView(mActions);
- }
- if (items.size() > 1 || (items.size() != 0 && items.get(0) != actionRow)) {
- mCurrentView.setVisibility(View.VISIBLE);
- mCurrentView.setSlice(mCurrentSlice);
- } else {
- mCurrentView.setVisibility(View.GONE);
- }
-
- boolean showActions = mShowActions && actionRow != null
- && !mode.equals(MODE_SHORTCUT);
- if (showActions) {
- mActions.setActions(actionRow, color);
- mActions.setVisibility(View.VISIBLE);
- } else {
- mActions.setVisibility(View.GONE);
- }
- }
-
- @Override
- public boolean onInterceptTouchEvent(MotionEvent ev) {
- // TODO -- may need to rethink for AGSA
- if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) {
- requestDisallowInterceptTouchEvent(true);
- }
- return super.onInterceptTouchEvent(ev);
- }
-
- private static void validate(Uri sliceUri) {
- if (!ContentResolver.SCHEME_CONTENT.equals(sliceUri.getScheme())) {
- throw new RuntimeException("Invalid uri " + sliceUri);
- }
- if (sliceUri.getPathSegments().size() == 0) {
- throw new RuntimeException("Invalid uri " + sliceUri);
- }
- }
-}
diff --git a/android/app/slice/views/SliceViewUtil.java b/android/app/slice/views/SliceViewUtil.java
deleted file mode 100644
index 19e8e7c9..00000000
--- a/android/app/slice/views/SliceViewUtil.java
+++ /dev/null
@@ -1,182 +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.app.slice.views;
-
-import android.annotation.ColorInt;
-import android.content.Context;
-import android.content.res.ColorStateList;
-import android.content.res.TypedArray;
-import android.graphics.Bitmap;
-import android.graphics.Bitmap.Config;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.PorterDuff.Mode;
-import android.graphics.PorterDuffXfermode;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.Icon;
-import android.view.Gravity;
-import android.view.ViewGroup;
-import android.widget.FrameLayout;
-import android.widget.ImageView;
-
-/**
- * A bunch of utilities for slice UI.
- *
- * @hide
- */
-public class SliceViewUtil {
-
- /**
- * @hide
- */
- @ColorInt
- public static int getColorAccent(Context context) {
- return getColorAttr(context, android.R.attr.colorAccent);
- }
-
- /**
- * @hide
- */
- @ColorInt
- public static int getColorError(Context context) {
- return getColorAttr(context, android.R.attr.colorError);
- }
-
- /**
- * @hide
- */
- @ColorInt
- public static int getDefaultColor(Context context, int resId) {
- final ColorStateList list = context.getResources().getColorStateList(resId,
- context.getTheme());
-
- return list.getDefaultColor();
- }
-
- /**
- * @hide
- */
- @ColorInt
- public static int getDisabled(Context context, int inputColor) {
- return applyAlphaAttr(context, android.R.attr.disabledAlpha, inputColor);
- }
-
- /**
- * @hide
- */
- @ColorInt
- public static int applyAlphaAttr(Context context, int attr, int inputColor) {
- TypedArray ta = context.obtainStyledAttributes(new int[] {
- attr
- });
- float alpha = ta.getFloat(0, 0);
- ta.recycle();
- return applyAlpha(alpha, inputColor);
- }
-
- /**
- * @hide
- */
- @ColorInt
- public static int applyAlpha(float alpha, int inputColor) {
- alpha *= Color.alpha(inputColor);
- return Color.argb((int) (alpha), Color.red(inputColor), Color.green(inputColor),
- Color.blue(inputColor));
- }
-
- /**
- * @hide
- */
- @ColorInt
- public static int getColorAttr(Context context, int attr) {
- TypedArray ta = context.obtainStyledAttributes(new int[] {
- attr
- });
- @ColorInt
- int colorAccent = ta.getColor(0, 0);
- ta.recycle();
- return colorAccent;
- }
-
- /**
- * @hide
- */
- public static int getThemeAttr(Context context, int attr) {
- TypedArray ta = context.obtainStyledAttributes(new int[] {
- attr
- });
- int theme = ta.getResourceId(0, 0);
- ta.recycle();
- return theme;
- }
-
- /**
- * @hide
- */
- public static Drawable getDrawable(Context context, int attr) {
- TypedArray ta = context.obtainStyledAttributes(new int[] {
- attr
- });
- Drawable drawable = ta.getDrawable(0);
- ta.recycle();
- return drawable;
- }
-
- /**
- * @hide
- */
- public static void createCircledIcon(Context context, int color, int iconSize, Icon icon,
- boolean isLarge, ViewGroup parent) {
- ImageView v = new ImageView(context);
- v.setImageIcon(icon);
- parent.addView(v);
- FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) v.getLayoutParams();
- if (isLarge) {
- // XXX better way to convert from icon -> bitmap or crop an icon (?)
- Bitmap iconBm = Bitmap.createBitmap(iconSize, iconSize, Bitmap.Config.ARGB_8888);
- Canvas iconCanvas = new Canvas(iconBm);
- v.layout(0, 0, iconSize, iconSize);
- v.draw(iconCanvas);
- v.setImageBitmap(getCircularBitmap(iconBm));
- } else {
- v.setColorFilter(Color.WHITE);
- }
- lp.width = iconSize;
- lp.height = iconSize;
- lp.gravity = Gravity.CENTER;
- }
-
- /**
- * @hide
- */
- public static Bitmap getCircularBitmap(Bitmap bitmap) {
- Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
- bitmap.getHeight(), Config.ARGB_8888);
- Canvas canvas = new Canvas(output);
- final Paint paint = new Paint();
- final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
- paint.setAntiAlias(true);
- canvas.drawARGB(0, 0, 0, 0);
- canvas.drawCircle(bitmap.getWidth() / 2, bitmap.getHeight() / 2,
- bitmap.getWidth() / 2, paint);
- paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
- canvas.drawBitmap(bitmap, rect, rect, paint);
- return output;
- }
-}
diff --git a/android/app/slice/views/SmallTemplateView.java b/android/app/slice/views/SmallTemplateView.java
deleted file mode 100644
index 42b2d213..00000000
--- a/android/app/slice/views/SmallTemplateView.java
+++ /dev/null
@@ -1,211 +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.app.slice.views;
-
-import android.app.PendingIntent.CanceledException;
-import android.app.slice.Slice;
-import android.app.slice.SliceItem;
-import android.app.slice.SliceQuery;
-import android.app.slice.views.LargeSliceAdapter.SliceListView;
-import android.app.slice.views.SliceView.SliceModeView;
-import android.content.Context;
-import android.os.AsyncTask;
-import android.view.View;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-import com.android.internal.R;
-
-import java.text.Format;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-
-/**
- * Small template is also used to construct list items for use with {@link LargeTemplateView}.
- *
- * @hide
- */
-public class SmallTemplateView extends SliceModeView implements SliceListView {
-
- private static final String TAG = "SmallTemplateView";
-
- private int mIconSize;
- private int mPadding;
-
- private LinearLayout mStartContainer;
- private TextView mTitleText;
- private TextView mSecondaryText;
- private LinearLayout mEndContainer;
-
- public SmallTemplateView(Context context) {
- super(context);
- inflate(context, R.layout.slice_small_template, this);
- mIconSize = getContext().getResources().getDimensionPixelSize(R.dimen.slice_icon_size);
- mPadding = getContext().getResources().getDimensionPixelSize(R.dimen.slice_padding);
-
- mStartContainer = (LinearLayout) findViewById(android.R.id.icon_frame);
- mTitleText = (TextView) findViewById(android.R.id.title);
- mSecondaryText = (TextView) findViewById(android.R.id.summary);
- mEndContainer = (LinearLayout) findViewById(android.R.id.widget_frame);
- }
-
- @Override
- public String getMode() {
- return SliceView.MODE_SMALL;
- }
-
- @Override
- public void setSliceItem(SliceItem slice) {
- resetViews();
- SliceItem colorItem = SliceQuery.find(slice, SliceItem.TYPE_COLOR);
- int color = colorItem != null ? colorItem.getColor() : -1;
-
- // Look for any title elements
- List<SliceItem> titleItems = SliceQuery.findAll(slice, -1, Slice.HINT_TITLE,
- null);
- boolean hasTitleText = false;
- boolean hasTitleItem = false;
- for (int i = 0; i < titleItems.size(); i++) {
- SliceItem item = titleItems.get(i);
- if (!hasTitleItem) {
- // icon, action icon, or timestamp
- if (item.getType() == SliceItem.TYPE_ACTION) {
- hasTitleItem = addIcon(item, color, mStartContainer);
- } else if (item.getType() == SliceItem.TYPE_IMAGE) {
- addIcon(item, color, mStartContainer);
- hasTitleItem = true;
- } else if (item.getType() == SliceItem.TYPE_TIMESTAMP) {
- TextView tv = new TextView(getContext());
- tv.setText(convertTimeToString(item.getTimestamp()));
- hasTitleItem = true;
- }
- }
- if (!hasTitleText && item.getType() == SliceItem.TYPE_TEXT) {
- mTitleText.setText(item.getText());
- hasTitleText = true;
- }
- if (hasTitleText && hasTitleItem) {
- break;
- }
- }
- mTitleText.setVisibility(hasTitleText ? View.VISIBLE : View.GONE);
- mStartContainer.setVisibility(hasTitleItem ? View.VISIBLE : View.GONE);
-
- if (slice.getType() != SliceItem.TYPE_SLICE) {
- return;
- }
-
- // Deal with remaining items
- int itemCount = 0;
- boolean hasSummary = false;
- ArrayList<SliceItem> sliceItems = new ArrayList<SliceItem>(
- slice.getSlice().getItems());
- for (int i = 0; i < sliceItems.size(); i++) {
- SliceItem item = sliceItems.get(i);
- if (!hasSummary && item.getType() == SliceItem.TYPE_TEXT
- && !item.hasHint(Slice.HINT_TITLE)) {
- // TODO -- Should combine all text items?
- mSecondaryText.setText(item.getText());
- hasSummary = true;
- }
- if (itemCount <= 3) {
- if (item.getType() == SliceItem.TYPE_ACTION) {
- if (addIcon(item, color, mEndContainer)) {
- itemCount++;
- }
- } else if (item.getType() == SliceItem.TYPE_IMAGE) {
- addIcon(item, color, mEndContainer);
- itemCount++;
- } else if (item.getType() == SliceItem.TYPE_TIMESTAMP) {
- TextView tv = new TextView(getContext());
- tv.setText(convertTimeToString(item.getTimestamp()));
- mEndContainer.addView(tv);
- itemCount++;
- } else if (item.getType() == SliceItem.TYPE_SLICE) {
- List<SliceItem> subItems = item.getSlice().getItems();
- for (int j = 0; j < subItems.size(); j++) {
- sliceItems.add(subItems.get(j));
- }
- }
- }
- }
- }
-
- @Override
- public void setSlice(Slice slice) {
- setSliceItem(new SliceItem(slice, SliceItem.TYPE_SLICE,
- slice.getHints().toArray(new String[slice.getHints().size()])));
- }
-
- /**
- * @return Whether an icon was added.
- */
- private boolean addIcon(SliceItem sliceItem, int color, LinearLayout container) {
- SliceItem image = null;
- SliceItem action = null;
- if (sliceItem.getType() == SliceItem.TYPE_ACTION) {
- image = SliceQuery.find(sliceItem.getSlice(), SliceItem.TYPE_IMAGE);
- action = sliceItem;
- } else if (sliceItem.getType() == SliceItem.TYPE_IMAGE) {
- image = sliceItem;
- }
- if (image != null) {
- ImageView iv = new ImageView(getContext());
- iv.setImageIcon(image.getIcon());
- if (action != null) {
- final SliceItem sliceAction = action;
- iv.setOnClickListener(v -> AsyncTask.execute(
- () -> {
- try {
- sliceAction.getAction().send();
- } catch (CanceledException e) {
- e.printStackTrace();
- }
- }));
- iv.setBackground(SliceViewUtil.getDrawable(getContext(),
- android.R.attr.selectableItemBackground));
- }
- if (color != -1 && !sliceItem.hasHint(Slice.HINT_NO_TINT)) {
- iv.setColorFilter(color);
- }
- container.addView(iv);
- LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) iv.getLayoutParams();
- lp.width = mIconSize;
- lp.height = mIconSize;
- lp.setMarginStart(mPadding);
- return true;
- }
- return false;
- }
-
- private String convertTimeToString(long time) {
- // TODO -- figure out what format(s) we support
- Date date = new Date(time);
- Format format = new SimpleDateFormat("MM dd yyyy HH:mm:ss");
- return format.format(date);
- }
-
- private void resetViews() {
- mStartContainer.removeAllViews();
- mEndContainer.removeAllViews();
- mTitleText.setText(null);
- mSecondaryText.setText(null);
- }
-}
diff --git a/android/app/usage/UsageStatsManager.java b/android/app/usage/UsageStatsManager.java
index fd579fce..051dccbd 100644
--- a/android/app/usage/UsageStatsManager.java
+++ b/android/app/usage/UsageStatsManager.java
@@ -48,10 +48,10 @@ import java.util.Map;
* </pre>
* A request for data in the middle of a time interval will include that interval.
* <p/>
- * <b>NOTE:</b> This API requires the permission android.permission.PACKAGE_USAGE_STATS.
- * However, declaring the permission implies intention to use the API and the user of the device
- * still needs to grant permission through the Settings application.
- * See {@link android.provider.Settings#ACTION_USAGE_ACCESS_SETTINGS}
+ * <b>NOTE:</b> This API requires the permission android.permission.PACKAGE_USAGE_STATS, which
+ * is a system-level permission and will not be granted to third-party apps. However, declaring
+ * the permission implies intention to use the API and the user of the device can grant permission
+ * through the Settings application.
*/
@SystemService(Context.USAGE_STATS_SERVICE)
public final class UsageStatsManager {
@@ -122,7 +122,7 @@ public final class UsageStatsManager {
* @param intervalType The time interval by which the stats are aggregated.
* @param beginTime The inclusive beginning of the range of stats to include in the results.
* @param endTime The exclusive end of the range of stats to include in the results.
- * @return A list of {@link UsageStats}
+ * @return A list of {@link UsageStats} or null if none are available.
*
* @see #INTERVAL_DAILY
* @see #INTERVAL_WEEKLY
@@ -139,7 +139,7 @@ public final class UsageStatsManager {
return slice.getList();
}
} catch (RemoteException e) {
- // fallthrough and return the empty list.
+ // fallthrough and return null.
}
return Collections.emptyList();
}
@@ -152,7 +152,7 @@ public final class UsageStatsManager {
* @param intervalType The time interval by which the stats are aggregated.
* @param beginTime The inclusive beginning of the range of stats to include in the results.
* @param endTime The exclusive end of the range of stats to include in the results.
- * @return A list of {@link ConfigurationStats}
+ * @return A list of {@link ConfigurationStats} or null if none are available.
*/
public List<ConfigurationStats> queryConfigurations(int intervalType, long beginTime,
long endTime) {
@@ -185,7 +185,7 @@ public final class UsageStatsManager {
return iter;
}
} catch (RemoteException e) {
- // fallthrough and return empty result.
+ // fallthrough and return null
}
return sEmptyResults;
}
@@ -197,7 +197,8 @@ public final class UsageStatsManager {
*
* @param beginTime The inclusive beginning of the range of stats to include in the results.
* @param endTime The exclusive end of the range of stats to include in the results.
- * @return A {@link java.util.Map} keyed by package name
+ * @return A {@link java.util.Map} keyed by package name, or null if no stats are
+ * available.
*/
public Map<String, UsageStats> queryAndAggregateUsageStats(long beginTime, long endTime) {
List<UsageStats> stats = queryUsageStats(INTERVAL_BEST, beginTime, endTime);