Merge "Provide some compatibility story for devs in the past"
diff --git a/apct-tests/perftests/core/res/layout/test_autosize_textview_10.xml b/apct-tests/perftests/core/res/layout/test_autosize_textview_10.xml
index a8d3de0..4a4b3b4 100644
--- a/apct-tests/perftests/core/res/layout/test_autosize_textview_10.xml
+++ b/apct-tests/perftests/core/res/layout/test_autosize_textview_10.xml
@@ -35,7 +35,7 @@
android:layout_width="400dp"
android:layout_height="600dp"
android:text="@string/long_text"
- android:autoSizeText="uniform"
+ android:autoSizeTextType="uniform"
android:autoSizeMinTextSize="10px"
android:textSize="20px"
android:autoSizeStepGranularity="1px"/>
diff --git a/apct-tests/perftests/core/res/layout/test_autosize_textview_100.xml b/apct-tests/perftests/core/res/layout/test_autosize_textview_100.xml
index d991862..0b326e8 100644
--- a/apct-tests/perftests/core/res/layout/test_autosize_textview_100.xml
+++ b/apct-tests/perftests/core/res/layout/test_autosize_textview_100.xml
@@ -19,7 +19,7 @@
android:layout_width="400dp"
android:layout_height="600dp"
android:text="@string/long_text"
- android:autoSizeText="uniform"
+ android:autoSizeTextType="uniform"
android:autoSizeMinTextSize="10px"
android:textSize="110px"
android:autoSizeStepGranularity="1px"/>
diff --git a/apct-tests/perftests/core/res/layout/test_autosize_textview_1000.xml b/apct-tests/perftests/core/res/layout/test_autosize_textview_1000.xml
index 3b55b6c..2f4239d 100644
--- a/apct-tests/perftests/core/res/layout/test_autosize_textview_1000.xml
+++ b/apct-tests/perftests/core/res/layout/test_autosize_textview_1000.xml
@@ -19,7 +19,7 @@
android:layout_width="400dp"
android:layout_height="600dp"
android:text="@string/long_text"
- android:autoSizeText="uniform"
+ android:autoSizeTextType="uniform"
android:autoSizeMinTextSize="10px"
android:textSize="1010px"
android:autoSizeStepGranularity="1px"/>
diff --git a/apct-tests/perftests/core/res/layout/test_autosize_textview_10000.xml b/apct-tests/perftests/core/res/layout/test_autosize_textview_10000.xml
index 64a25c2..b6be10a 100644
--- a/apct-tests/perftests/core/res/layout/test_autosize_textview_10000.xml
+++ b/apct-tests/perftests/core/res/layout/test_autosize_textview_10000.xml
@@ -19,7 +19,7 @@
android:layout_width="400dp"
android:layout_height="600dp"
android:text="@string/long_text"
- android:autoSizeText="uniform"
+ android:autoSizeTextType="uniform"
android:autoSizeMinTextSize="10px"
android:textSize="10010px"
android:autoSizeStepGranularity="1px"/>
diff --git a/apct-tests/perftests/core/res/layout/test_autosize_textview_100000.xml b/apct-tests/perftests/core/res/layout/test_autosize_textview_100000.xml
index 1f60783..aed339c 100644
--- a/apct-tests/perftests/core/res/layout/test_autosize_textview_100000.xml
+++ b/apct-tests/perftests/core/res/layout/test_autosize_textview_100000.xml
@@ -19,7 +19,7 @@
android:layout_width="400dp"
android:layout_height="600dp"
android:text="@string/long_text"
- android:autoSizeText="uniform"
+ android:autoSizeTextType="uniform"
android:autoSizeMinTextSize="10px"
android:textSize="100010px"
android:autoSizeStepGranularity="1px"/>
diff --git a/apct-tests/perftests/core/res/layout/test_autosize_textview_300.xml b/apct-tests/perftests/core/res/layout/test_autosize_textview_300.xml
index 54c7e71..62522ba 100644
--- a/apct-tests/perftests/core/res/layout/test_autosize_textview_300.xml
+++ b/apct-tests/perftests/core/res/layout/test_autosize_textview_300.xml
@@ -19,7 +19,7 @@
android:layout_width="400dp"
android:layout_height="600dp"
android:text="@string/long_text"
- android:autoSizeText="uniform"
+ android:autoSizeTextType="uniform"
android:autoSizeMinTextSize="10px"
android:textSize="310px"
android:autoSizeStepGranularity="1px"/>
diff --git a/apct-tests/perftests/core/res/layout/test_autosize_textview_5.xml b/apct-tests/perftests/core/res/layout/test_autosize_textview_5.xml
index 525b2c8..f383fa4 100644
--- a/apct-tests/perftests/core/res/layout/test_autosize_textview_5.xml
+++ b/apct-tests/perftests/core/res/layout/test_autosize_textview_5.xml
@@ -35,7 +35,7 @@
android:layout_width="400dp"
android:layout_height="600dp"
android:text="@string/long_text"
- android:autoSizeText="uniform"
+ android:autoSizeTextType="uniform"
android:autoSizeMinTextSize="10px"
android:textSize="15px"
android:autoSizeStepGranularity="1px"/>
diff --git a/apct-tests/perftests/core/res/layout/test_autosize_textview_50.xml b/apct-tests/perftests/core/res/layout/test_autosize_textview_50.xml
index 470c4da..04dd6c2 100644
--- a/apct-tests/perftests/core/res/layout/test_autosize_textview_50.xml
+++ b/apct-tests/perftests/core/res/layout/test_autosize_textview_50.xml
@@ -19,7 +19,7 @@
android:layout_width="400dp"
android:layout_height="600dp"
android:text="@string/long_text"
- android:autoSizeText="uniform"
+ android:autoSizeTextType="uniform"
android:autoSizeMinTextSize="10px"
android:textSize="60px"
android:autoSizeStepGranularity="1px"/>
diff --git a/apct-tests/perftests/core/res/layout/test_autosize_textview_500.xml b/apct-tests/perftests/core/res/layout/test_autosize_textview_500.xml
index b8a6e0a..a8e2b38 100644
--- a/apct-tests/perftests/core/res/layout/test_autosize_textview_500.xml
+++ b/apct-tests/perftests/core/res/layout/test_autosize_textview_500.xml
@@ -19,7 +19,7 @@
android:layout_width="400dp"
android:layout_height="600dp"
android:text="@string/long_text"
- android:autoSizeText="uniform"
+ android:autoSizeTextType="uniform"
android:autoSizeMinTextSize="10px"
android:textSize="510px"
android:autoSizeStepGranularity="1px"/>
diff --git a/apct-tests/perftests/core/src/android/widget/TextViewAutoSizeLayoutPerfTest.java b/apct-tests/perftests/core/src/android/widget/TextViewAutoSizeLayoutPerfTest.java
index 6ee6f70..c310166 100644
--- a/apct-tests/perftests/core/src/android/widget/TextViewAutoSizeLayoutPerfTest.java
+++ b/apct-tests/perftests/core/src/android/widget/TextViewAutoSizeLayoutPerfTest.java
@@ -89,7 +89,7 @@
while (state.keepRunning()) {
TextView textView = new TextView(activity);
- // TextView#onMeasure() gets called, which triggers TextView#autoSizeText()
+ // TextView#onLayout() gets called, which triggers TextView#autoSizeText()
// which is the method we want to benchmark.
textView.requestLayout();
}
diff --git a/api/current.txt b/api/current.txt
index d53a4b8..df31f2c 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -305,7 +305,7 @@
field public static final int autoSizeMinTextSize = 16844088; // 0x1010538
field public static final int autoSizePresetSizes = 16844087; // 0x1010537
field public static final int autoSizeStepGranularity = 16844086; // 0x1010536
- field public static final int autoSizeText = 16844085; // 0x1010535
+ field public static final int autoSizeTextType = 16844085; // 0x1010535
field public static final int autoStart = 16843445; // 0x10102b5
field public static final deprecated int autoText = 16843114; // 0x101016a
field public static final int autoUrlDetect = 16843404; // 0x101028c
@@ -10103,10 +10103,12 @@
ctor public LauncherApps.ShortcutQuery();
method public android.content.pm.LauncherApps.ShortcutQuery setActivity(android.content.ComponentName);
method public android.content.pm.LauncherApps.ShortcutQuery setChangedSince(long);
+ method public android.content.pm.LauncherApps.ShortcutQuery setIntent(android.content.Intent);
method public android.content.pm.LauncherApps.ShortcutQuery setPackage(java.lang.String);
method public android.content.pm.LauncherApps.ShortcutQuery setQueryFlags(int);
method public android.content.pm.LauncherApps.ShortcutQuery setShortcutIds(java.util.List<java.lang.String>);
field public static final int FLAG_GET_KEY_FIELDS_ONLY = 4; // 0x4
+ field public static final int FLAG_MATCH_CHOOSER = 16; // 0x10
field public static final int FLAG_MATCH_DYNAMIC = 1; // 0x1
field public static final int FLAG_MATCH_MANIFEST = 8; // 0x8
field public static final int FLAG_MATCH_PINNED = 2; // 0x2
@@ -10645,6 +10647,9 @@
method public int describeContents();
method public android.content.ComponentName getActivity();
method public java.util.Set<java.lang.String> getCategories();
+ method public android.content.ComponentName[] getChooserComponentNames();
+ method public android.os.PersistableBundle getChooserExtras();
+ method public android.content.IntentFilter[] getChooserIntentFilters();
method public java.lang.CharSequence getDisabledMessage();
method public android.os.PersistableBundle getExtras();
method public java.lang.String getId();
@@ -10657,6 +10662,7 @@
method public java.lang.CharSequence getShortLabel();
method public android.os.UserHandle getUserHandle();
method public boolean hasKeyFieldsOnly();
+ method public boolean isChooser();
method public boolean isDeclaredInManifest();
method public boolean isDynamic();
method public boolean isEnabled();
@@ -10669,9 +10675,11 @@
public static class ShortcutInfo.Builder {
ctor public ShortcutInfo.Builder(android.content.Context, java.lang.String);
+ method public android.content.pm.ShortcutInfo.Builder addChooserIntentFilter(android.content.IntentFilter, android.content.ComponentName);
method public android.content.pm.ShortcutInfo build();
method public android.content.pm.ShortcutInfo.Builder setActivity(android.content.ComponentName);
method public android.content.pm.ShortcutInfo.Builder setCategories(java.util.Set<java.lang.String>);
+ method public android.content.pm.ShortcutInfo.Builder setChooserExtras(android.os.PersistableBundle);
method public android.content.pm.ShortcutInfo.Builder setDisabledMessage(java.lang.CharSequence);
method public android.content.pm.ShortcutInfo.Builder setExtras(android.os.PersistableBundle);
method public android.content.pm.ShortcutInfo.Builder setIcon(android.graphics.drawable.Icon);
@@ -14013,6 +14021,8 @@
public class ArcShape extends android.graphics.drawable.shapes.RectShape {
ctor public ArcShape(float, float);
+ method public final float getStartAngle();
+ method public final float getSweepAngle();
}
public class OvalShape extends android.graphics.drawable.shapes.RectShape {
@@ -22164,6 +22174,7 @@
field public static final java.lang.String KEY_IS_FORCED_SUBTITLE = "is-forced-subtitle";
field public static final java.lang.String KEY_I_FRAME_INTERVAL = "i-frame-interval";
field public static final java.lang.String KEY_LANGUAGE = "language";
+ field public static final java.lang.String KEY_LATENCY = "latency";
field public static final java.lang.String KEY_LEVEL = "level";
field public static final java.lang.String KEY_MAX_HEIGHT = "max-height";
field public static final java.lang.String KEY_MAX_INPUT_SIZE = "max-input-size";
@@ -26130,8 +26141,6 @@
public class DiscoverySession {
method public java.lang.String createNetworkSpecifier(android.net.wifi.aware.PeerHandle, byte[]);
method public void destroy();
- method public static int getMaxSendRetryCount();
- method public void sendMessage(android.net.wifi.aware.PeerHandle, int, byte[], int);
method public void sendMessage(android.net.wifi.aware.PeerHandle, int, byte[]);
}
@@ -36391,16 +36400,17 @@
method public int describeContents();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.service.autofill.SaveInfo> CREATOR;
- field public static final int SAVE_UI_TYPE_ADDRESS = 2; // 0x2
- field public static final int SAVE_UI_TYPE_CREDENTIALS = 1; // 0x1
- field public static final int SAVE_UI_TYPE_GENERIC = 0; // 0x0
- field public static final int SAVE_UI_TYPE_PAYMENT = 3; // 0x3
+ field public static final int SAVE_DATA_TYPE_ADDRESS = 2; // 0x2
+ field public static final int SAVE_DATA_TYPE_CREDIT_CARD = 3; // 0x3
+ field public static final int SAVE_DATA_TYPE_GENERIC = 0; // 0x0
+ field public static final int SAVE_DATA_TYPE_PASSWORD = 1; // 0x1
}
public static final class SaveInfo.Builder {
ctor public SaveInfo.Builder(int);
method public android.service.autofill.SaveInfo.Builder addSavableIds(android.view.autofill.AutoFillId...);
method public android.service.autofill.SaveInfo build();
+ method public android.service.autofill.SaveInfo.Builder setDescription(java.lang.CharSequence);
}
}
@@ -42518,30 +42528,51 @@
method public abstract void setValue(T, float);
}
- public final class Half {
+ public final class Half extends java.lang.Number implements java.lang.Comparable {
+ ctor public Half(short);
+ ctor public Half(float);
+ ctor public Half(double);
+ ctor public Half(java.lang.String) throws java.lang.NumberFormatException;
method public static short abs(short);
method public static short ceil(short);
+ method public static int compare(short, short);
+ method public int compareTo(android.util.Half);
method public static short copySign(short, short);
+ method public double doubleValue();
method public static boolean equals(short, short);
+ method public float floatValue();
method public static short floor(short);
method public static int getExponent(short);
method public static int getSign(short);
method public static int getSignificand(short);
method public static boolean greater(short, short);
method public static boolean greaterEquals(short, short);
+ method public static int halfToIntBits(short);
+ method public static int halfToRawIntBits(short);
+ method public static short halfToShortBits(short);
+ method public short halfValue();
+ method public static int hashCode(short);
+ method public static short intBitsToHalf(int);
+ method public int intValue();
method public static boolean isInfinite(short);
+ method public boolean isNaN();
method public static boolean isNaN(short);
method public static boolean isNormalized(short);
method public static boolean less(short, short);
method public static boolean lessEquals(short, short);
+ method public long longValue();
method public static short max(short, short);
method public static short min(short, short);
+ method public static short parseHalf(java.lang.String) throws java.lang.NumberFormatException;
method public static short round(short);
method public static float toFloat(short);
+ method public static short toHalf(float);
method public static java.lang.String toHexString(short);
method public static java.lang.String toString(short);
method public static short trunc(short);
- method public static short valueOf(float);
+ method public static android.util.Half valueOf(short);
+ method public static android.util.Half valueOf(float);
+ method public static android.util.Half valueOf(java.lang.String);
field public static final short EPSILON = 5120; // 0x1400
field public static final short LOWEST_VALUE = -1025; // 0xfffffbff
field public static final int MAX_EXPONENT = 15; // 0xf
@@ -44645,8 +44676,8 @@
method public void drawableHotspotChanged(float, float);
method protected void drawableStateChanged();
method public android.view.View findFocus();
- method public final android.view.View findViewById(int);
- method public final android.view.View findViewWithTag(java.lang.Object);
+ method public final <T extends android.view.View> T findViewById(int);
+ method public final <T extends android.view.View> T findViewWithTag(java.lang.Object);
method public void findViewsWithText(java.util.ArrayList<android.view.View>, java.lang.CharSequence, int);
method protected deprecated boolean fitSystemWindows(android.graphics.Rect);
method public android.view.View focusSearch(int);
diff --git a/api/system-current.txt b/api/system-current.txt
index e5de7dc..dcf62cd 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -418,7 +418,7 @@
field public static final int autoSizeMinTextSize = 16844088; // 0x1010538
field public static final int autoSizePresetSizes = 16844087; // 0x1010537
field public static final int autoSizeStepGranularity = 16844086; // 0x1010536
- field public static final int autoSizeText = 16844085; // 0x1010535
+ field public static final int autoSizeTextType = 16844085; // 0x1010535
field public static final int autoStart = 16843445; // 0x10102b5
field public static final deprecated int autoText = 16843114; // 0x101016a
field public static final int autoUrlDetect = 16843404; // 0x101028c
@@ -10640,10 +10640,12 @@
ctor public LauncherApps.ShortcutQuery();
method public android.content.pm.LauncherApps.ShortcutQuery setActivity(android.content.ComponentName);
method public android.content.pm.LauncherApps.ShortcutQuery setChangedSince(long);
+ method public android.content.pm.LauncherApps.ShortcutQuery setIntent(android.content.Intent);
method public android.content.pm.LauncherApps.ShortcutQuery setPackage(java.lang.String);
method public android.content.pm.LauncherApps.ShortcutQuery setQueryFlags(int);
method public android.content.pm.LauncherApps.ShortcutQuery setShortcutIds(java.util.List<java.lang.String>);
field public static final int FLAG_GET_KEY_FIELDS_ONLY = 4; // 0x4
+ field public static final int FLAG_MATCH_CHOOSER = 16; // 0x10
field public static final int FLAG_MATCH_DYNAMIC = 1; // 0x1
field public static final int FLAG_MATCH_MANIFEST = 8; // 0x8
field public static final int FLAG_MATCH_PINNED = 2; // 0x2
@@ -11267,6 +11269,9 @@
method public int describeContents();
method public android.content.ComponentName getActivity();
method public java.util.Set<java.lang.String> getCategories();
+ method public android.content.ComponentName[] getChooserComponentNames();
+ method public android.os.PersistableBundle getChooserExtras();
+ method public android.content.IntentFilter[] getChooserIntentFilters();
method public java.lang.CharSequence getDisabledMessage();
method public android.os.PersistableBundle getExtras();
method public java.lang.String getId();
@@ -11279,6 +11284,7 @@
method public java.lang.CharSequence getShortLabel();
method public android.os.UserHandle getUserHandle();
method public boolean hasKeyFieldsOnly();
+ method public boolean isChooser();
method public boolean isDeclaredInManifest();
method public boolean isDynamic();
method public boolean isEnabled();
@@ -11291,9 +11297,11 @@
public static class ShortcutInfo.Builder {
ctor public ShortcutInfo.Builder(android.content.Context, java.lang.String);
+ method public android.content.pm.ShortcutInfo.Builder addChooserIntentFilter(android.content.IntentFilter, android.content.ComponentName);
method public android.content.pm.ShortcutInfo build();
method public android.content.pm.ShortcutInfo.Builder setActivity(android.content.ComponentName);
method public android.content.pm.ShortcutInfo.Builder setCategories(java.util.Set<java.lang.String>);
+ method public android.content.pm.ShortcutInfo.Builder setChooserExtras(android.os.PersistableBundle);
method public android.content.pm.ShortcutInfo.Builder setDisabledMessage(java.lang.CharSequence);
method public android.content.pm.ShortcutInfo.Builder setExtras(android.os.PersistableBundle);
method public android.content.pm.ShortcutInfo.Builder setIcon(android.graphics.drawable.Icon);
@@ -14649,6 +14657,8 @@
public class ArcShape extends android.graphics.drawable.shapes.RectShape {
ctor public ArcShape(float, float);
+ method public final float getStartAngle();
+ method public final float getSweepAngle();
}
public class OvalShape extends android.graphics.drawable.shapes.RectShape {
@@ -23852,6 +23862,7 @@
field public static final java.lang.String KEY_IS_FORCED_SUBTITLE = "is-forced-subtitle";
field public static final java.lang.String KEY_I_FRAME_INTERVAL = "i-frame-interval";
field public static final java.lang.String KEY_LANGUAGE = "language";
+ field public static final java.lang.String KEY_LATENCY = "latency";
field public static final java.lang.String KEY_LEVEL = "level";
field public static final java.lang.String KEY_MAX_HEIGHT = "max-height";
field public static final java.lang.String KEY_MAX_INPUT_SIZE = "max-input-size";
@@ -25932,9 +25943,9 @@
method public static final boolean isProgramUri(android.net.Uri);
field public static final java.lang.String AUTHORITY = "android.media.tv";
field public static final java.lang.String EXTRA_COLUMN_NAME = "android.media.tv.extra.COLUMN_NAME";
- field public static final java.lang.String EXTRA_EXISTING_COLUMN_NAMES = "android.media.tv.extra.EXISTING_COLUMN_NAMES";
field public static final java.lang.String EXTRA_DATA_TYPE = "android.media.tv.extra.DATA_TYPE";
field public static final java.lang.String EXTRA_DEFAULT_VALUE = "android.media.tv.extra.DEFAULT_VALUE";
+ field public static final java.lang.String EXTRA_EXISTING_COLUMN_NAMES = "android.media.tv.extra.EXISTING_COLUMN_NAMES";
field public static final java.lang.String METHOD_ADD_COLUMN = "add_column";
field public static final java.lang.String METHOD_GET_COLUMNS = "get_columns";
}
@@ -28715,8 +28726,6 @@
public class DiscoverySession {
method public java.lang.String createNetworkSpecifier(android.net.wifi.aware.PeerHandle, byte[]);
method public void destroy();
- method public static int getMaxSendRetryCount();
- method public void sendMessage(android.net.wifi.aware.PeerHandle, int, byte[], int);
method public void sendMessage(android.net.wifi.aware.PeerHandle, int, byte[]);
}
@@ -39311,16 +39320,17 @@
method public int describeContents();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.service.autofill.SaveInfo> CREATOR;
- field public static final int SAVE_UI_TYPE_ADDRESS = 2; // 0x2
- field public static final int SAVE_UI_TYPE_CREDENTIALS = 1; // 0x1
- field public static final int SAVE_UI_TYPE_GENERIC = 0; // 0x0
- field public static final int SAVE_UI_TYPE_PAYMENT = 3; // 0x3
+ field public static final int SAVE_DATA_TYPE_ADDRESS = 2; // 0x2
+ field public static final int SAVE_DATA_TYPE_CREDIT_CARD = 3; // 0x3
+ field public static final int SAVE_DATA_TYPE_GENERIC = 0; // 0x0
+ field public static final int SAVE_DATA_TYPE_PASSWORD = 1; // 0x1
}
public static final class SaveInfo.Builder {
ctor public SaveInfo.Builder(int);
method public android.service.autofill.SaveInfo.Builder addSavableIds(android.view.autofill.AutoFillId...);
method public android.service.autofill.SaveInfo build();
+ method public android.service.autofill.SaveInfo.Builder setDescription(java.lang.CharSequence);
}
}
@@ -45863,30 +45873,51 @@
method public abstract void setValue(T, float);
}
- public final class Half {
+ public final class Half extends java.lang.Number implements java.lang.Comparable {
+ ctor public Half(short);
+ ctor public Half(float);
+ ctor public Half(double);
+ ctor public Half(java.lang.String) throws java.lang.NumberFormatException;
method public static short abs(short);
method public static short ceil(short);
+ method public static int compare(short, short);
+ method public int compareTo(android.util.Half);
method public static short copySign(short, short);
+ method public double doubleValue();
method public static boolean equals(short, short);
+ method public float floatValue();
method public static short floor(short);
method public static int getExponent(short);
method public static int getSign(short);
method public static int getSignificand(short);
method public static boolean greater(short, short);
method public static boolean greaterEquals(short, short);
+ method public static int halfToIntBits(short);
+ method public static int halfToRawIntBits(short);
+ method public static short halfToShortBits(short);
+ method public short halfValue();
+ method public static int hashCode(short);
+ method public static short intBitsToHalf(int);
+ method public int intValue();
method public static boolean isInfinite(short);
+ method public boolean isNaN();
method public static boolean isNaN(short);
method public static boolean isNormalized(short);
method public static boolean less(short, short);
method public static boolean lessEquals(short, short);
+ method public long longValue();
method public static short max(short, short);
method public static short min(short, short);
+ method public static short parseHalf(java.lang.String) throws java.lang.NumberFormatException;
method public static short round(short);
method public static float toFloat(short);
+ method public static short toHalf(float);
method public static java.lang.String toHexString(short);
method public static java.lang.String toString(short);
method public static short trunc(short);
- method public static short valueOf(float);
+ method public static android.util.Half valueOf(short);
+ method public static android.util.Half valueOf(float);
+ method public static android.util.Half valueOf(java.lang.String);
field public static final short EPSILON = 5120; // 0x1400
field public static final short LOWEST_VALUE = -1025; // 0xfffffbff
field public static final int MAX_EXPONENT = 15; // 0xf
@@ -47990,8 +48021,8 @@
method public void drawableHotspotChanged(float, float);
method protected void drawableStateChanged();
method public android.view.View findFocus();
- method public final android.view.View findViewById(int);
- method public final android.view.View findViewWithTag(java.lang.Object);
+ method public final <T extends android.view.View> T findViewById(int);
+ method public final <T extends android.view.View> T findViewWithTag(java.lang.Object);
method public void findViewsWithText(java.util.ArrayList<android.view.View>, java.lang.CharSequence, int);
method protected deprecated boolean fitSystemWindows(android.graphics.Rect);
method public android.view.View focusSearch(int);
diff --git a/api/test-current.txt b/api/test-current.txt
index cff6ffe..d90b5f0 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -305,7 +305,7 @@
field public static final int autoSizeMinTextSize = 16844088; // 0x1010538
field public static final int autoSizePresetSizes = 16844087; // 0x1010537
field public static final int autoSizeStepGranularity = 16844086; // 0x1010536
- field public static final int autoSizeText = 16844085; // 0x1010535
+ field public static final int autoSizeTextType = 16844085; // 0x1010535
field public static final int autoStart = 16843445; // 0x10102b5
field public static final deprecated int autoText = 16843114; // 0x101016a
field public static final int autoUrlDetect = 16843404; // 0x101028c
@@ -10135,10 +10135,12 @@
ctor public LauncherApps.ShortcutQuery();
method public android.content.pm.LauncherApps.ShortcutQuery setActivity(android.content.ComponentName);
method public android.content.pm.LauncherApps.ShortcutQuery setChangedSince(long);
+ method public android.content.pm.LauncherApps.ShortcutQuery setIntent(android.content.Intent);
method public android.content.pm.LauncherApps.ShortcutQuery setPackage(java.lang.String);
method public android.content.pm.LauncherApps.ShortcutQuery setQueryFlags(int);
method public android.content.pm.LauncherApps.ShortcutQuery setShortcutIds(java.util.List<java.lang.String>);
field public static final int FLAG_GET_KEY_FIELDS_ONLY = 4; // 0x4
+ field public static final int FLAG_MATCH_CHOOSER = 16; // 0x10
field public static final int FLAG_MATCH_DYNAMIC = 1; // 0x1
field public static final int FLAG_MATCH_MANIFEST = 8; // 0x8
field public static final int FLAG_MATCH_PINNED = 2; // 0x2
@@ -10681,6 +10683,9 @@
method public int describeContents();
method public android.content.ComponentName getActivity();
method public java.util.Set<java.lang.String> getCategories();
+ method public android.content.ComponentName[] getChooserComponentNames();
+ method public android.os.PersistableBundle getChooserExtras();
+ method public android.content.IntentFilter[] getChooserIntentFilters();
method public java.lang.CharSequence getDisabledMessage();
method public android.os.PersistableBundle getExtras();
method public java.lang.String getId();
@@ -10693,6 +10698,7 @@
method public java.lang.CharSequence getShortLabel();
method public android.os.UserHandle getUserHandle();
method public boolean hasKeyFieldsOnly();
+ method public boolean isChooser();
method public boolean isDeclaredInManifest();
method public boolean isDynamic();
method public boolean isEnabled();
@@ -10705,9 +10711,11 @@
public static class ShortcutInfo.Builder {
ctor public ShortcutInfo.Builder(android.content.Context, java.lang.String);
+ method public android.content.pm.ShortcutInfo.Builder addChooserIntentFilter(android.content.IntentFilter, android.content.ComponentName);
method public android.content.pm.ShortcutInfo build();
method public android.content.pm.ShortcutInfo.Builder setActivity(android.content.ComponentName);
method public android.content.pm.ShortcutInfo.Builder setCategories(java.util.Set<java.lang.String>);
+ method public android.content.pm.ShortcutInfo.Builder setChooserExtras(android.os.PersistableBundle);
method public android.content.pm.ShortcutInfo.Builder setDisabledMessage(java.lang.CharSequence);
method public android.content.pm.ShortcutInfo.Builder setExtras(android.os.PersistableBundle);
method public android.content.pm.ShortcutInfo.Builder setIcon(android.graphics.drawable.Icon);
@@ -14051,6 +14059,8 @@
public class ArcShape extends android.graphics.drawable.shapes.RectShape {
ctor public ArcShape(float, float);
+ method public final float getStartAngle();
+ method public final float getSweepAngle();
}
public class OvalShape extends android.graphics.drawable.shapes.RectShape {
@@ -22260,6 +22270,7 @@
field public static final java.lang.String KEY_IS_FORCED_SUBTITLE = "is-forced-subtitle";
field public static final java.lang.String KEY_I_FRAME_INTERVAL = "i-frame-interval";
field public static final java.lang.String KEY_LANGUAGE = "language";
+ field public static final java.lang.String KEY_LATENCY = "latency";
field public static final java.lang.String KEY_LEVEL = "level";
field public static final java.lang.String KEY_MAX_HEIGHT = "max-height";
field public static final java.lang.String KEY_MAX_INPUT_SIZE = "max-input-size";
@@ -26226,8 +26237,6 @@
public class DiscoverySession {
method public java.lang.String createNetworkSpecifier(android.net.wifi.aware.PeerHandle, byte[]);
method public void destroy();
- method public static int getMaxSendRetryCount();
- method public void sendMessage(android.net.wifi.aware.PeerHandle, int, byte[], int);
method public void sendMessage(android.net.wifi.aware.PeerHandle, int, byte[]);
}
@@ -36530,16 +36539,17 @@
method public int describeContents();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.service.autofill.SaveInfo> CREATOR;
- field public static final int SAVE_UI_TYPE_ADDRESS = 2; // 0x2
- field public static final int SAVE_UI_TYPE_CREDENTIALS = 1; // 0x1
- field public static final int SAVE_UI_TYPE_GENERIC = 0; // 0x0
- field public static final int SAVE_UI_TYPE_PAYMENT = 3; // 0x3
+ field public static final int SAVE_DATA_TYPE_ADDRESS = 2; // 0x2
+ field public static final int SAVE_DATA_TYPE_CREDIT_CARD = 3; // 0x3
+ field public static final int SAVE_DATA_TYPE_GENERIC = 0; // 0x0
+ field public static final int SAVE_DATA_TYPE_PASSWORD = 1; // 0x1
}
public static final class SaveInfo.Builder {
ctor public SaveInfo.Builder(int);
method public android.service.autofill.SaveInfo.Builder addSavableIds(android.view.autofill.AutoFillId...);
method public android.service.autofill.SaveInfo build();
+ method public android.service.autofill.SaveInfo.Builder setDescription(java.lang.CharSequence);
}
}
@@ -42707,30 +42717,51 @@
method public abstract void setValue(T, float);
}
- public final class Half {
+ public final class Half extends java.lang.Number implements java.lang.Comparable {
+ ctor public Half(short);
+ ctor public Half(float);
+ ctor public Half(double);
+ ctor public Half(java.lang.String) throws java.lang.NumberFormatException;
method public static short abs(short);
method public static short ceil(short);
+ method public static int compare(short, short);
+ method public int compareTo(android.util.Half);
method public static short copySign(short, short);
+ method public double doubleValue();
method public static boolean equals(short, short);
+ method public float floatValue();
method public static short floor(short);
method public static int getExponent(short);
method public static int getSign(short);
method public static int getSignificand(short);
method public static boolean greater(short, short);
method public static boolean greaterEquals(short, short);
+ method public static int halfToIntBits(short);
+ method public static int halfToRawIntBits(short);
+ method public static short halfToShortBits(short);
+ method public short halfValue();
+ method public static int hashCode(short);
+ method public static short intBitsToHalf(int);
+ method public int intValue();
method public static boolean isInfinite(short);
+ method public boolean isNaN();
method public static boolean isNaN(short);
method public static boolean isNormalized(short);
method public static boolean less(short, short);
method public static boolean lessEquals(short, short);
+ method public long longValue();
method public static short max(short, short);
method public static short min(short, short);
+ method public static short parseHalf(java.lang.String) throws java.lang.NumberFormatException;
method public static short round(short);
method public static float toFloat(short);
+ method public static short toHalf(float);
method public static java.lang.String toHexString(short);
method public static java.lang.String toString(short);
method public static short trunc(short);
- method public static short valueOf(float);
+ method public static android.util.Half valueOf(short);
+ method public static android.util.Half valueOf(float);
+ method public static android.util.Half valueOf(java.lang.String);
field public static final short EPSILON = 5120; // 0x1400
field public static final short LOWEST_VALUE = -1025; // 0xfffffbff
field public static final int MAX_EXPONENT = 15; // 0xf
@@ -45000,8 +45031,8 @@
method public void drawableHotspotChanged(float, float);
method protected void drawableStateChanged();
method public android.view.View findFocus();
- method public final android.view.View findViewById(int);
- method public final android.view.View findViewWithTag(java.lang.Object);
+ method public final <T extends android.view.View> T findViewById(int);
+ method public final <T extends android.view.View> T findViewWithTag(java.lang.Object);
method public void findViewsWithText(java.util.ArrayList<android.view.View>, java.lang.CharSequence, int);
method protected deprecated boolean fitSystemWindows(android.graphics.Rect);
method public android.view.View focusSearch(int);
diff --git a/core/java/android/annotation/HalfFloat.java b/core/java/android/annotation/HalfFloat.java
index d3e9f08..256008c 100644
--- a/core/java/android/annotation/HalfFloat.java
+++ b/core/java/android/annotation/HalfFloat.java
@@ -37,7 +37,7 @@
* }</pre>
*
* @see android.util.Half
- * @see android.util.Half#valueOf(float)
+ * @see android.util.Half#toHalf(float)
* @see android.util.Half#toFloat(short)
*
* @hide
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 1652299..0608acb 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -1024,12 +1024,18 @@
}
@Override
- @SuppressWarnings("unchecked")
public List<ProviderInfo> queryContentProviders(String processName,
int uid, int flags) {
+ return queryContentProviders(processName, uid, flags, null);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public List<ProviderInfo> queryContentProviders(String processName,
+ int uid, int flags, String metaDataKey) {
try {
ParceledListSlice<ProviderInfo> slice =
- mPM.queryContentProviders(processName, uid, flags);
+ mPM.queryContentProviders(processName, uid, flags, metaDataKey);
return slice != null ? slice.getList() : Collections.<ProviderInfo>emptyList();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
diff --git a/core/java/android/content/pm/ILauncherApps.aidl b/core/java/android/content/pm/ILauncherApps.aidl
index c08bd1d..41311eb 100644
--- a/core/java/android/content/pm/ILauncherApps.aidl
+++ b/core/java/android/content/pm/ILauncherApps.aidl
@@ -55,7 +55,8 @@
String callingPackage, String packageName, int flags, in UserHandle user);
ParceledListSlice getShortcuts(String callingPackage, long changedSince, String packageName,
- in List shortcutIds, in ComponentName componentName, int flags, in UserHandle user);
+ in List shortcutIds, in ComponentName componentName, in Intent intent, int flags,
+ in UserHandle user);
void pinShortcuts(String callingPackage, String packageName, in List<String> shortcutIds,
in UserHandle user);
boolean startShortcut(String callingPackage, String packageName, String id,
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 11948dbc..147b3e1 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -211,7 +211,7 @@
inout List<ProviderInfo> outInfo);
ParceledListSlice queryContentProviders(
- String processName, int uid, int flags);
+ String processName, int uid, int flags, String metaDataKey);
InstrumentationInfo getInstrumentationInfo(
in ComponentName className, int flags);
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index d76d824..776492a 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -275,7 +275,18 @@
@Deprecated
public static final int FLAG_GET_MANIFEST = FLAG_MATCH_MANIFEST;
- /** @hide */
+ /**
+ * Include chooser shortcuts in the result.
+ * STOPSHIP TODO: Unless explicitly requesting chooser fields, we should strip out chooser
+ * relevant fields from the Shortcut. This should also be adequately documented.
+ */
+ public static final int FLAG_MATCH_CHOOSER = 1 << 4;
+
+ /**
+ * Does not retrieve CHOOSER only shortcuts.
+ * TODO: Add another flag for MATCH_ALL_PINNED
+ * @hide
+ */
public static final int FLAG_MATCH_ALL_KINDS =
FLAG_GET_DYNAMIC | FLAG_GET_PINNED | FLAG_GET_MANIFEST;
@@ -308,6 +319,7 @@
FLAG_MATCH_DYNAMIC,
FLAG_MATCH_PINNED,
FLAG_MATCH_MANIFEST,
+ FLAG_MATCH_CHOOSER,
FLAG_GET_KEY_FIELDS_ONLY,
})
@Retention(RetentionPolicy.SOURCE)
@@ -324,6 +336,9 @@
@Nullable
ComponentName mActivity;
+ @Nullable
+ Intent mIntent;
+
@QueryFlags
int mQueryFlags;
@@ -368,6 +383,14 @@
}
/**
+ * If non-null, returns only shortcuts with intent filters that match this intent.
+ */
+ public ShortcutQuery setIntent(@Nullable Intent intent) {
+ mIntent = intent;
+ return this;
+ }
+
+ /**
* Set query options. At least one of the {@code MATCH} flags should be set. Otherwise,
* no shortcuts will be returned.
*
@@ -681,7 +704,7 @@
try {
return mService.getShortcuts(mContext.getPackageName(),
query.mChangedSince, query.mPackage, query.mShortcutIds, query.mActivity,
- query.mQueryFlags, user)
+ query.mIntent, query.mQueryFlags, user)
.getList();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index ddbb5da..0482f51 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -4462,6 +4462,27 @@
String processName, int uid, @ComponentInfoFlags int flags);
/**
+ * Same as {@link #queryContentProviders}, except when {@code metaDataKey} is not null,
+ * it only returns providers which have metadata with the {@code metaDataKey} key.
+ *
+ * <p>DO NOT USE the {@code metaDataKey} parameter, unless you're the contacts provider.
+ * You really shouldn't need it. Other apps should use {@link #queryIntentContentProviders}
+ * instead.
+ *
+ * <p>The {@code metaDataKey} parameter was added to allow the contacts provider to quickly
+ * scan the GAL providers on the device. Unfortunately the discovery protocol used metadata
+ * to mark GAL providers, rather than intent filters, so we can't use
+ * {@link #queryIntentContentProviders} for that.
+ *
+ * @hide
+ */
+ public List<ProviderInfo> queryContentProviders(
+ String processName, int uid, @ComponentInfoFlags int flags, String metaDataKey) {
+ // Provide the default implementation for mocks.
+ return queryContentProviders(processName, uid, flags);
+ }
+
+ /**
* Retrieve all of the information we know about a particular
* instrumentation class.
*
diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java
index f1f2683..d3d3c66 100644
--- a/core/java/android/content/pm/ShortcutInfo.java
+++ b/core/java/android/content/pm/ShortcutInfo.java
@@ -21,8 +21,10 @@
import android.annotation.UserIdInt;
import android.app.TaskStackBuilder;
import android.content.ComponentName;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.pm.LauncherApps.ShortcutQuery;
import android.content.res.Resources;
import android.content.res.Resources.NotFoundException;
@@ -38,10 +40,12 @@
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.MemInfoReader;
import com.android.internal.util.Preconditions;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
import java.util.List;
import java.util.Set;
@@ -95,6 +99,14 @@
public static final int FLAG_MASKABLE_BITMAP = 1 << 9;
/** @hide */
+ public static final int FLAG_CHOOSER = 1 << 10;
+
+ /**
+ * TODO: Add FLAG_CHOOSER_INFO_OMITTED to reflect that chooser info was omitted in the Shortcut
+ * due to the context in which it was retrieved.
+ * TODO: Add a FLAG_LAUNCHABLE to reflect whether or not the Shortcut has a launchable intent
+ * @hide
+ */
@IntDef(flag = true,
value = {
FLAG_DYNAMIC,
@@ -107,6 +119,7 @@
FLAG_STRINGS_RESOLVED,
FLAG_IMMUTABLE,
FLAG_MASKABLE_BITMAP,
+ FLAG_CHOOSER,
})
@Retention(RetentionPolicy.SOURCE)
public @interface ShortcutFlags {}
@@ -201,6 +214,24 @@
@Nullable
private PersistableBundle[] mIntentPersistableExtrases;
+ /**
+ * If used in a chooser, extras that should be added into the intent passed through.
+ */
+ @Nullable
+ private PersistableBundle mChooserExtras;
+
+ /**
+ * Intent filters to be used if the shortcut is to be used in a chooser context.
+ */
+ @Nullable
+ private IntentFilter[] mChooserIntentFilters;
+
+ /**
+ * Component names corresponding to the above intent filters.
+ */
+ @Nullable
+ private ComponentName[] mChooserComponentNames;
+
private int mRank;
/**
@@ -250,6 +281,13 @@
mDisabledMessageResId = b.mDisabledMessageResId;
mCategories = cloneCategories(b.mCategories);
mIntents = cloneIntents(b.mIntents);
+ if (b.mChooserIntentFilters != null) {
+ mChooserIntentFilters = b.mChooserIntentFilters.toArray(new IntentFilter[0]);
+ }
+ if (b.mChooserComponentNames != null) {
+ mChooserComponentNames = b.mChooserComponentNames.toArray(new ComponentName[0]);
+ }
+ mChooserExtras = b.mChooserExtras;
fixUpIntentExtras();
mRank = b.mRank;
mExtras = b.mExtras;
@@ -330,8 +368,28 @@
if (mTitle == null && mTitleResId == 0) {
throw new IllegalArgumentException("Short label must be provided");
}
- Preconditions.checkNotNull(mIntents, "Shortcut Intent must be provided");
- Preconditions.checkArgument(mIntents.length > 0, "Shortcut Intent must be provided");
+
+ // For a shortcut to be valid, there should either be an Intent, or a non-empty set of
+ // intent filters.
+ if (mIntents == null || mIntents.length == 0) {
+ Preconditions.checkNotNull(mChooserIntentFilters,
+ "Intent must be provided if not a chooser target");
+ Preconditions.checkNotNull(mChooserComponentNames,
+ "Intent must be provided if not a chooser target");
+ }
+
+ // If ChooserIntentFilter are provided, they should match the length of the provided
+ // component names.
+ if (mChooserIntentFilters != null) {
+ if (mChooserComponentNames == null
+ || mChooserIntentFilters.length != mChooserComponentNames.length) {
+ throw new IllegalArgumentException("Inconsistent intent filters and "
+ + "component names given");
+ }
+ if (mChooserIntentFilters.length == 0 || mChooserComponentNames.length == 0) {
+ throw new IllegalArgumentException("Empty intent filter and component names given");
+ }
+ }
}
/**
@@ -376,6 +434,10 @@
mDisabledMessageResName = source.mDisabledMessageResName;
mIconResName = source.mIconResName;
}
+ // TODO: Omit these by default and add a new clone flag.
+ mChooserIntentFilters = source.mChooserIntentFilters;
+ mChooserComponentNames = source.mChooserComponentNames;
+ mChooserExtras = source.mChooserExtras;
} else {
// Set this bit.
mFlags |= FLAG_KEY_FIELDS_ONLY;
@@ -503,6 +565,25 @@
}
/**
+ * Whether the shortcut has any intentFilter matching the passed in one.
+ * @hide
+ */
+ @VisibleForTesting
+ public boolean hasMatchingFilter(ContentResolver resolver, Intent intent) {
+ if (mChooserIntentFilters == null) {
+ return false;
+ }
+ for (IntentFilter filter : mChooserIntentFilters) {
+ int match = filter.match(resolver, intent, false, TAG);
+ if (match > 0) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+ /**
* Extract the entry name from a fully-donated resource name.
* e.g. "com.android.app1:drawable/icon1" -> "icon1"
* @hide
@@ -685,6 +766,15 @@
if (source.mExtras != null) {
mExtras = source.mExtras;
}
+ if (source.mChooserExtras != null) {
+ mChooserExtras = source.mChooserExtras;
+ }
+ if (source.mChooserIntentFilters != null) {
+ mChooserIntentFilters = source.mChooserIntentFilters;
+ }
+ if (source.mChooserComponentNames != null) {
+ mChooserComponentNames = source.mChooserComponentNames;
+ }
}
/**
@@ -746,6 +836,12 @@
private PersistableBundle mExtras;
+ private PersistableBundle mChooserExtras;
+
+ private List<IntentFilter> mChooserIntentFilters;
+
+ private List<ComponentName> mChooserComponentNames;
+
/**
* Old style constructor.
* @hide
@@ -1032,6 +1128,40 @@
}
/**
+ * Extras that can be added which will be added to the Intent used to launch the app if
+ * launched from a chooser context.
+ */
+ @NonNull
+ public Builder setChooserExtras(@NonNull PersistableBundle extras) {
+ mChooserExtras = extras;
+ return this;
+ }
+
+ /**
+ * IntentFilters and the components that should resolve a match for a given chooser target.
+ * If multiple matches are found, the component corresponding to the closest match will be
+ * used.
+ *
+ * @param filter IntendFilter that if matched will have the intent forwarded to the given
+ * component
+ * @param name The component that an intent that passes this filter will resolve to.
+ */
+ public Builder addChooserIntentFilter(@NonNull IntentFilter filter,
+ @NonNull ComponentName name) {
+ Preconditions.checkNotNull(filter, "intent filter cannot be null");
+ Preconditions.checkNotNull(name, "component name cannot be null");
+
+ if (mChooserIntentFilters == null || mChooserComponentNames == null) {
+ mChooserIntentFilters = new ArrayList<>();
+ mChooserComponentNames = new ArrayList<>();
+ }
+
+ mChooserIntentFilters.add(filter);
+ mChooserComponentNames.add(name);
+ return this;
+ }
+
+ /**
* Creates a {@link ShortcutInfo} instance.
*/
@NonNull
@@ -1232,6 +1362,30 @@
}
/**
+ * Retrieve the extras that will be added in to any intent launched through the chooser.
+ */
+ @NonNull
+ public PersistableBundle getChooserExtras() {
+ return mChooserExtras;
+ }
+
+ /**
+ * Retrieve the list of intent filters for chooser targets.
+ */
+ @NonNull
+ public IntentFilter[] getChooserIntentFilters() {
+ return mChooserIntentFilters;
+ }
+
+ /**
+ * Retrieve the list of component names corresponding to the above intent filters.
+ */
+ @NonNull
+ public ComponentName[] getChooserComponentNames() {
+ return mChooserComponentNames;
+ }
+
+ /**
* "Rank" of a shortcut, which is a non-negative, sequential value that's unique for each
* {@link #getActivity} for each of the two types of shortcuts (static and dynamic).
*
@@ -1352,6 +1506,11 @@
return hasFlags(FLAG_PINNED);
}
+ /** Return whether a shortcut can be shown in the chooser. */
+ public boolean isChooser() {
+ return hasFlags(FLAG_CHOOSER);
+ }
+
/**
* Return whether a shortcut is static; that is, whether a shortcut is
* published from AndroidManifest.xml. If {@code true}, the shortcut is
@@ -1380,6 +1539,14 @@
return isPinned() && !(isDynamic() || isManifestShortcut());
}
+ /**
+ * @return true if pinned but neither static nor dynamic.
+ * @hide
+ */
+ public boolean isDynamicOrChooser() {
+ return hasFlags(FLAG_DYNAMIC) || hasFlags(FLAG_CHOOSER);
+ }
+
/** @hide */
public boolean isOriginallyFromManifest() {
return hasFlags(FLAG_IMMUTABLE);
@@ -1661,6 +1828,19 @@
mCategories.add(source.readString().intern());
}
}
+
+ // We put a placeholder empty array in to keep the parcelable order, but can do away with
+ // them at this point if they're empty.
+ mChooserComponentNames = source.readParcelableArray(cl, ComponentName.class);
+ if (mChooserComponentNames.length == 0) {
+ mChooserComponentNames = null;
+ }
+
+ mChooserIntentFilters = source.readParcelableArray(cl, IntentFilter.class);
+ if (mChooserIntentFilters.length == 0) {
+ mChooserIntentFilters = null;
+ }
+ mChooserExtras = source.readPersistableBundle(cl);
}
@Override
@@ -1707,6 +1887,17 @@
} else {
dest.writeInt(0);
}
+ if (mChooserComponentNames != null) {
+ dest.writeParcelableArray(mChooserComponentNames, flags);
+ } else {
+ dest.writeParcelableArray(new ComponentName[0], flags);
+ }
+ if (mChooserIntentFilters != null) {
+ dest.writeParcelableArray(mChooserIntentFilters, flags);
+ } else {
+ dest.writeParcelableArray(new IntentFilter[0], flags);
+ }
+ dest.writePersistableBundle(mChooserExtras);
}
public static final Creator<ShortcutInfo> CREATOR =
diff --git a/core/java/android/content/pm/ShortcutServiceInternal.java b/core/java/android/content/pm/ShortcutServiceInternal.java
index 87a6d4a..696fe81 100644
--- a/core/java/android/content/pm/ShortcutServiceInternal.java
+++ b/core/java/android/content/pm/ShortcutServiceInternal.java
@@ -44,8 +44,8 @@
getShortcuts(int launcherUserId,
@NonNull String callingPackage, long changedSince,
@Nullable String packageName, @Nullable List<String> shortcutIds,
- @Nullable ComponentName componentName, @ShortcutQuery.QueryFlags int flags,
- int userId);
+ @Nullable ComponentName componentName, @Nullable Intent intent,
+ @ShortcutQuery.QueryFlags int flags, int userId);
public abstract boolean
isPinnedByCaller(int launcherUserId, @NonNull String callingPackage,
diff --git a/core/java/android/service/autofill/FillResponse.java b/core/java/android/service/autofill/FillResponse.java
index a241d1f..ba75c8b 100644
--- a/core/java/android/service/autofill/FillResponse.java
+++ b/core/java/android/service/autofill/FillResponse.java
@@ -188,7 +188,7 @@
// Handle the the case where service didn't call setSavableIds() because it would
// contain just the ids from the datasets.
if (saveInfo == null && mDatasets != null) {
- saveInfo = new SaveInfo.Builder(SaveInfo.SAVE_UI_TYPE_GENERIC).build();
+ saveInfo = new SaveInfo.Builder(SaveInfo.SAVE_DATA_TYPE_GENERIC).build();
}
if (saveInfo != null) {
saveInfo.addSavableIds(mDatasets);
@@ -324,7 +324,7 @@
throw new IllegalStateException("setSaveInfo() already called");
}
if (mSaveInfoBuilder == null) {
- mSaveInfoBuilder = new SaveInfo.Builder(SaveInfo.SAVE_UI_TYPE_GENERIC);
+ mSaveInfoBuilder = new SaveInfo.Builder(SaveInfo.SAVE_DATA_TYPE_GENERIC);
}
mSaveInfoBuilder.addSavableIds(ids);
diff --git a/core/java/android/service/autofill/SaveInfo.java b/core/java/android/service/autofill/SaveInfo.java
index 148bd24..096f28b 100644
--- a/core/java/android/service/autofill/SaveInfo.java
+++ b/core/java/android/service/autofill/SaveInfo.java
@@ -52,43 +52,44 @@
* Type used on when the service can save the contents of an activity, but cannot describe what
* the content is for.
*/
- public static final int SAVE_UI_TYPE_GENERIC = 0;
+ public static final int SAVE_DATA_TYPE_GENERIC = 0;
/**
- * Type used when the {@link FillResponse} represents user credentials (such as username and
- * password).
+ * Type used when the {@link FillResponse} represents user credentials that have a password.
*/
- public static final int SAVE_UI_TYPE_CREDENTIALS = 1;
+ public static final int SAVE_DATA_TYPE_PASSWORD = 1;
+
/**
* Type used on when the {@link FillResponse} represents a physical address (such as street,
* city, state, etc).
*/
- public static final int SAVE_UI_TYPE_ADDRESS = 2;
+ public static final int SAVE_DATA_TYPE_ADDRESS = 2;
/**
- * Type used when the {@link FillResponse} represents a payment (such as credit card number
- * and expiration date).
+ * Type used when the {@link FillResponse} represents a credit card.
*/
- public static final int SAVE_UI_TYPE_PAYMENT = 3;
+ public static final int SAVE_DATA_TYPE_CREDIT_CARD = 3;
- private final @SaveUiType int mType;
+ private final @SaveDataType int mType;
private ArraySet<AutoFillId> mSavableIds;
+ private final CharSequence mDescription;
/** @hide */
@IntDef({
- SAVE_UI_TYPE_GENERIC,
- SAVE_UI_TYPE_CREDENTIALS,
- SAVE_UI_TYPE_ADDRESS,
- SAVE_UI_TYPE_PAYMENT
+ SAVE_DATA_TYPE_GENERIC,
+ SAVE_DATA_TYPE_PASSWORD,
+ SAVE_DATA_TYPE_ADDRESS,
+ SAVE_DATA_TYPE_CREDIT_CARD
})
@Retention(RetentionPolicy.SOURCE)
- public @interface SaveUiType {
+ public @interface SaveDataType {
}
private SaveInfo(Builder builder) {
mType = builder.mType;
mSavableIds = builder.mSavableIds;
+ mDescription = builder.mDescription;
}
/** @hide */
@@ -97,6 +98,16 @@
}
/** @hide */
+ public int getType() {
+ return mType;
+ }
+
+ /** @hide */
+ public CharSequence getDescription() {
+ return mDescription;
+ }
+
+ /** @hide */
public void addSavableIds(@Nullable ArrayList<Dataset> datasets) {
if (datasets != null) {
for (Dataset dataset : datasets) {
@@ -120,27 +131,28 @@
*/
public static final class Builder {
- private final @SaveUiType int mType;
+ private final @SaveDataType int mType;
private ArraySet<AutoFillId> mSavableIds;
+ private CharSequence mDescription;
private boolean mDestroyed;
/**
* Creates a new builder.
*
* @param type the type of information the associated {@link FillResponse} represents. Must
- * be {@link SaveInfo#SAVE_UI_TYPE_GENERIC}, {@link SaveInfo#SAVE_UI_TYPE_CREDENTIALS},
- * {@link SaveInfo#SAVE_UI_TYPE_ADDRESS}, or {@link SaveInfo#SAVE_UI_TYPE_PAYMENT};
- * otherwise it will assume {@link SaveInfo#SAVE_UI_TYPE_GENERIC}.
+ * be {@link SaveInfo#SAVE_DATA_TYPE_GENERIC}, {@link SaveInfo#SAVE_DATA_TYPE_PASSWORD},
+ * {@link SaveInfo#SAVE_DATA_TYPE_ADDRESS}, or {@link SaveInfo#SAVE_DATA_TYPE_CREDIT_CARD};
+ * otherwise it will assume {@link SaveInfo#SAVE_DATA_TYPE_GENERIC}.
*/
- public Builder(@SaveUiType int type) {
+ public Builder(@SaveDataType int type) {
switch (type) {
- case SAVE_UI_TYPE_CREDENTIALS:
- case SAVE_UI_TYPE_ADDRESS:
- case SAVE_UI_TYPE_PAYMENT:
+ case SAVE_DATA_TYPE_PASSWORD:
+ case SAVE_DATA_TYPE_ADDRESS:
+ case SAVE_DATA_TYPE_CREDIT_CARD:
mType = type;
break;
default:
- mType = SAVE_UI_TYPE_GENERIC;
+ mType = SAVE_DATA_TYPE_GENERIC;
}
}
@@ -169,6 +181,20 @@
}
/**
+ * Sets an optional description to be shown in the UI when the user is asked to save.
+ *
+ * <p>Typically, it describes how the data will be stored by the service, so it can help
+ * users to decide whether they can trust the service to save their data.
+ *
+ * @param description a succint description.
+ * @return This Builder.
+ */
+ public @NonNull Builder setDescription(@Nullable CharSequence description) {
+ mDescription = description;
+ return this;
+ }
+
+ /**
* Builds a new {@link SaveInfo} instance.
*/
public SaveInfo build() {
@@ -210,6 +236,7 @@
public void writeToParcel(Parcel parcel, int flags) {
parcel.writeInt(mType);
parcel.writeTypedArraySet(mSavableIds, flags);
+ parcel.writeCharSequence(mDescription);
}
public static final Parcelable.Creator<SaveInfo> CREATOR = new Parcelable.Creator<SaveInfo>() {
@@ -224,7 +251,7 @@
for (int i = 0; i < savableIdsCount; i++) {
builder.addSavableIds(savableIds.valueAt(i));
}
-
+ builder.setDescription(parcel.readCharSequence());
return builder.build();
}
diff --git a/core/java/android/util/Half.java b/core/java/android/util/Half.java
index e4f8dd1..84c2e83 100644
--- a/core/java/android/util/Half.java
+++ b/core/java/android/util/Half.java
@@ -17,9 +17,13 @@
package android.util;
import android.annotation.HalfFloat;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+import sun.misc.FloatingDecimal;
/**
- * <p>Half is a utility class to manipulate half-precision 16-bit
+ * <p>The {@code Half} class is a wrapper and a utility class to manipulate half-precision 16-bit
* <a href="https://en.wikipedia.org/wiki/Half-precision_floating-point_format">IEEE 754</a>
* floating point data types (also called fp16 or binary16). A half-precision float can be
* created from or converted to single-precision floats, and is stored in a short data type.
@@ -88,7 +92,7 @@
* <p>This table shows that numbers higher than 1024 lose all fractional precision.</p>
*/
@SuppressWarnings("SimplifiableIfStatement")
-public final class Half {
+public final class Half extends Number implements Comparable<Half> {
/**
* The number of bits used to represent a half-precision float value.
*/
@@ -164,7 +168,332 @@
private static final int FP32_DENORMAL_MAGIC = 126 << 23;
private static final float FP32_DENORMAL_FLOAT = Float.intBitsToFloat(FP32_DENORMAL_MAGIC);
- private Half() {
+ private final @HalfFloat short mValue;
+
+ /**
+ * Constructs a newly allocated {@code Half} object that represents the
+ * half-precision float type argument.
+ *
+ * @param value The value to be represented by the {@code Half}
+ */
+ public Half(@HalfFloat short value) {
+ mValue = value;
+ }
+
+ /**
+ * Constructs a newly allocated {@code Half} object that represents the
+ * argument converted to a half-precision float.
+ *
+ * @param value The value to be represented by the {@code Half}
+ *
+ * @see #toHalf(float)
+ */
+ public Half(float value) {
+ mValue = toHalf(value);
+ }
+
+ /**
+ * Constructs a newly allocated {@code Half} object that
+ * represents the argument converted to a half-precision float.
+ *
+ * @param value The value to be represented by the {@code Half}
+ *
+ * @see #toHalf(float)
+ */
+ public Half(double value) {
+ mValue = toHalf((float) value);
+ }
+
+ /**
+ * <p>Constructs a newly allocated {@code Half} object that represents the
+ * half-precision float value represented by the string.
+ * The string is converted to a half-precision float value as if by the
+ * {@link #valueOf(String)} method.</p>
+ *
+ * <p>Calling this constructor is equivalent to calling:</p>
+ * <pre>
+ * new Half(Float.parseFloat(value))
+ * </pre>
+ *
+ * @param value A string to be converted to a {@code Half}
+ * @throws NumberFormatException if the string does not contain a parsable number
+ *
+ * @see Float#valueOf(java.lang.String)
+ * @see #toHalf(float)
+ */
+ public Half(@NonNull String value) throws NumberFormatException {
+ mValue = toHalf(Float.parseFloat(value));
+ }
+
+ /**
+ * Returns the half-precision value of this {@code Half} as a {@code short}
+ * containing the bit representation described in {@link Half}.
+ *
+ * @return The half-precision float value represented by this object
+ */
+ public @HalfFloat short halfValue() {
+ return mValue;
+ }
+
+ /**
+ * Returns the value of this {@code Half} as a {@code byte} after
+ * a narrowing primitive conversion.
+ *
+ * @return The half-precision float value represented by this object
+ * converted to type {@code byte}
+ */
+ @Override
+ public byte byteValue() {
+ return (byte) toFloat(mValue);
+ }
+
+ /**
+ * Returns the value of this {@code Half} as a {@code short} after
+ * a narrowing primitive conversion.
+ *
+ * @return The half-precision float value represented by this object
+ * converted to type {@code short}
+ */
+ @Override
+ public short shortValue() {
+ return (short) toFloat(mValue);
+ }
+
+ /**
+ * Returns the value of this {@code Half} as a {@code int} after
+ * a narrowing primitive conversion.
+ *
+ * @return The half-precision float value represented by this object
+ * converted to type {@code int}
+ */
+ @Override
+ public int intValue() {
+ return (int) toFloat(mValue);
+ }
+
+ /**
+ * Returns the value of this {@code Half} as a {@code long} after
+ * a narrowing primitive conversion.
+ *
+ * @return The half-precision float value represented by this object
+ * converted to type {@code long}
+ */
+ @Override
+ public long longValue() {
+ return (long) toFloat(mValue);
+ }
+
+ /**
+ * Returns the value of this {@code Half} as a {@code float} after
+ * a widening primitive conversion.
+ *
+ * @return The half-precision float value represented by this object
+ * converted to type {@code float}
+ */
+ @Override
+ public float floatValue() {
+ return toFloat(mValue);
+ }
+
+ /**
+ * Returns the value of this {@code Half} as a {@code double} after
+ * a widening primitive conversion.
+ *
+ * @return The half-precision float value represented by this object
+ * converted to type {@code double}
+ */
+ @Override
+ public double doubleValue() {
+ return toFloat(mValue);
+ }
+
+ /**
+ * Returns true if this {@code Half} value represents a Not-a-Number,
+ * false otherwise.
+ *
+ * @return True if the value is a NaN, false otherwise
+ */
+ public boolean isNaN() {
+ return isNaN(mValue);
+ }
+
+ /**
+ * Compares this object against the specified object. The result is {@code true}
+ * if and only if the argument is not {@code null} and is a {@code Half} object
+ * that represents the same half-precision value as the this object. Two
+ * half-precision values are considered to be the same if and only if the method
+ * {@link #halfToIntBits(short)} returns an identical {@code int} value for both.
+ *
+ * @param o The object to compare
+ * @return True if the objects are the same, false otherwise
+ *
+ * @see #halfToIntBits(short)
+ */
+ @Override
+ public boolean equals(@Nullable Object o) {
+ return (o instanceof Half) &&
+ (halfToIntBits(((Half) o).mValue) == halfToIntBits(mValue));
+ }
+
+ /**
+ * Returns a hash code for this {@code Half} object. The result is the
+ * integer bit representation, exactly as produced by the method
+ * {@link #halfToIntBits(short)}, of the primitive half-precision float
+ * value represented by this {@code Half} object.
+ *
+ * @return A hash code value for this object
+ */
+ @Override
+ public int hashCode() {
+ return hashCode(mValue);
+ }
+
+ /**
+ * Returns a string representation of the specified half-precision
+ * float value. See {@link #toString(short)} for more information.
+ *
+ * @return A string representation of this {@code Half} object
+ */
+ @NonNull
+ @Override
+ public String toString() {
+ return toString(mValue);
+ }
+
+ /**
+ * <p>Compares the two specified half-precision float values. The following
+ * conditions apply during the comparison:</p>
+ *
+ * <ul>
+ * <li>{@link #NaN} is considered by this method to be equal to itself and greater
+ * than all other half-precision float values (including {@code #POSITIVE_INFINITY})</li>
+ * <li>{@link #POSITIVE_ZERO} is considered by this method to be greater than
+ * {@link #NEGATIVE_ZERO}.</li>
+ * </ul>
+ *
+ * @param h The half-precision float value to compare to the half-precision value
+ * represented by this {@code Half} object
+ *
+ * @return The value {@code 0} if {@code x} is numerically equal to {@code y}; a
+ * value less than {@code 0} if {@code x} is numerically less than {@code y};
+ * and a value greater than {@code 0} if {@code x} is numerically greater
+ * than {@code y}
+ */
+ @Override
+ public int compareTo(@NonNull Half h) {
+ return compare(mValue, h.mValue);
+ }
+
+ /**
+ * Returns a hash code for a half-precision float value.
+ *
+ * @param h The value to hash
+ *
+ * @return A hash code value for a half-precision float value
+ */
+ public static int hashCode(@HalfFloat short h) {
+ return halfToIntBits(h);
+ }
+
+ /**
+ * <p>Compares the two specified half-precision float values. The following
+ * conditions apply during the comparison:</p>
+ *
+ * <ul>
+ * <li>{@link #NaN} is considered by this method to be equal to itself and greater
+ * than all other half-precision float values (including {@code #POSITIVE_INFINITY})</li>
+ * <li>{@link #POSITIVE_ZERO} is considered by this method to be greater than
+ * {@link #NEGATIVE_ZERO}.</li>
+ * </ul>
+ *
+ * @param x The first half-precision float value to compare.
+ * @param y The second half-precision float value to compare
+ *
+ * @return The value {@code 0} if {@code x} is numerically equal to {@code y}, a
+ * value less than {@code 0} if {@code x} is numerically less than {@code y},
+ * and a value greater than {@code 0} if {@code x} is numerically greater
+ * than {@code y}
+ */
+ public static int compare(@HalfFloat short x, @HalfFloat short y) {
+ if (less(x, y)) return -1;
+ if (greater(x, y)) return 1;
+
+ // Collapse NaNs, akin to halfToIntBits(), but we want to keep
+ // (signed) short value types to preserve the ordering of -0.0
+ // and +0.0
+ short xBits = (x & FP16_COMBINED) > FP16_EXPONENT_MAX ? NaN : x;
+ short yBits = (y & FP16_COMBINED) > FP16_EXPONENT_MAX ? NaN : y;
+
+ return (xBits == yBits ? 0 : (xBits < yBits ? -1 : 1));
+ }
+
+ /**
+ * <p>Returns a representation of the specified half-precision float value
+ * according to the bit layout described in {@link Half}.</p>
+ *
+ * <p>Similar to {@link #halfToIntBits(short)}, this method collapses all
+ * possible Not-a-Number values to a single canonical Not-a-Number value
+ * defined by {@link #NaN}.</p>
+ *
+ * @param h A half-precision float value
+ * @return The bits that represent the half-precision float value
+ *
+ * @see #halfToIntBits(short)
+ */
+ public static @HalfFloat short halfToShortBits(@HalfFloat short h) {
+ return (h & FP16_COMBINED) > FP16_EXPONENT_MAX ? NaN : h;
+ }
+
+ /**
+ * <p>Returns a representation of the specified half-precision float value
+ * according to the bit layout described in {@link Half}.</p>
+ *
+ * <p>Unlike {@link #halfToRawIntBits(short)}, this method collapses all
+ * possible Not-a-Number values to a single canonical Not-a-Number value
+ * defined by {@link #NaN}.</p>
+ *
+ * @param h A half-precision float value
+ * @return The bits that represent the half-precision float value
+ *
+ * @see #halfToRawIntBits(short)
+ * @see #halfToShortBits(short)
+ * @see #intBitsToHalf(int)
+ */
+ public static int halfToIntBits(@HalfFloat short h) {
+ return (h & FP16_COMBINED) > FP16_EXPONENT_MAX ? NaN : h & 0xffff;
+ }
+
+ /**
+ * <p>Returns a representation of the specified half-precision float value
+ * according to the bit layout described in {@link Half}.</p>
+ *
+ * <p>The argument is considered to be a representation of a half-precision
+ * float value according to the bit layout described in {@link Half}. The 16
+ * most significant bits of the returned value are set to 0.</p>
+ *
+ * @param h A half-precision float value
+ * @return The bits that represent the half-precision float value
+ *
+ * @see #halfToIntBits(short)
+ * @see #intBitsToHalf(int)
+ */
+ public static int halfToRawIntBits(@HalfFloat short h) {
+ return h & 0xffff;
+ }
+
+ /**
+ * <p>Returns the half-precision float value corresponding to a given
+ * bit representation.</p>
+ *
+ * <p>The argument is considered to be a representation of a half-precision
+ * float value according to the bit layout described in {@link Half}. The 16
+ * most significant bits of the argument are ignored.</p>
+ *
+ * @param bits An integer
+ * @return The half-precision float value with the same bit pattern
+ */
+ public static @HalfFloat short intBitsToHalf(int bits) {
+ return (short) (bits & 0xffff);
}
/**
@@ -509,7 +838,7 @@
* infinity, false otherwise.
*
* @param h A half-precision float value
- * @return true if the value is positive infinity or negative infinity,
+ * @return True if the value is positive infinity or negative infinity,
* false otherwise
*/
public static boolean isInfinite(@HalfFloat short h) {
@@ -521,7 +850,7 @@
* a Not-a-Number, false otherwise.
*
* @param h A half-precision float value
- * @return true if the value is a NaN, false otherwise
+ * @return True if the value is a NaN, false otherwise
*/
public static boolean isNaN(@HalfFloat short h) {
return (h & FP16_COMBINED) > FP16_EXPONENT_MAX;
@@ -535,7 +864,7 @@
* number, this method returns false.
*
* @param h A half-precision float value
- * @return true if the value is normalized, false otherwise
+ * @return True if the value is normalized, false otherwise
*/
public static boolean isNormalized(@HalfFloat short h) {
return (h & FP16_EXPONENT_MAX) != 0 && (h & FP16_EXPONENT_MAX) != FP16_EXPONENT_MAX;
@@ -608,7 +937,7 @@
* @return A half-precision float value
*/
@SuppressWarnings("StatementWithEmptyBody")
- public static @HalfFloat short valueOf(float f) {
+ public static @HalfFloat short toHalf(float f) {
int bits = Float.floatToRawIntBits(f);
int s = (bits >>> FP32_SIGN_SHIFT );
int e = (bits >>> FP32_EXPONENT_SHIFT) & FP32_EXPONENT_MASK;
@@ -650,6 +979,57 @@
}
/**
+ * Returns a {@code Half} instance representing the specified
+ * half-precision float value.
+ *
+ * @param h A half-precision float value
+ * @return a {@code Half} instance representing {@code h}
+ */
+ public static @NonNull Half valueOf(@HalfFloat short h) {
+ return new Half(h);
+ }
+
+ /**
+ * Returns a {@code Half} instance representing the specified float value.
+ *
+ * @param f A float value
+ * @return a {@code Half} instance representing {@code f}
+ */
+ public static @NonNull Half valueOf(float f) {
+ return new Half(f);
+ }
+
+ /**
+ * Returns a {@code Half} instance representing the specified string value.
+ * Calling this method is equivalent to calling
+ * <code>toHalf(Float.parseString(h))</code>. See {@link Float#valueOf(String)}
+ * for more information on the format of the string representation.
+ *
+ * @param s The string to be parsed
+ * @return a {@code Half} instance representing {@code h}
+ * @throws NumberFormatException if the string does not contain a parsable
+ * half-precision float value
+ */
+ public static @NonNull Half valueOf(@NonNull String s) {
+ return new Half(s);
+ }
+
+ /**
+ * Returns the half-precision float value represented by the specified string.
+ * Calling this method is equivalent to calling
+ * <code>toHalf(Float.parseString(h))</code>. See {@link Float#valueOf(String)}
+ * for more information on the format of the string representation.
+ *
+ * @param s The string to be parsed
+ * @return A half-precision float value represented by the string
+ * @throws NumberFormatException if the string does not contain a parsable
+ * half-precision float value
+ */
+ public static @HalfFloat short parseHalf(@NonNull String s) throws NumberFormatException {
+ return toHalf(FloatingDecimal.parseFloat(s));
+ }
+
+ /**
* Returns a string representation of the specified half-precision
* float value. Calling this method is equivalent to calling
* <code>Float.toString(toFloat(h))</code>. See {@link Float#toString(float)}
@@ -658,6 +1038,7 @@
* @param h A half-precision float value
* @return A string representation of the specified value
*/
+ @NonNull
public static String toString(@HalfFloat short h) {
return Float.toString(toFloat(h));
}
@@ -688,6 +1069,7 @@
* @param h A half-precision float value
* @return A hexadecimal string representation of the specified value
*/
+ @NonNull
public static String toHexString(@HalfFloat short h) {
StringBuilder o = new StringBuilder();
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index a880842..1338b05 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -20260,9 +20260,9 @@
* @return the view of the specified id, null if cannot be found
* @hide
*/
- protected View findViewTraversal(@IdRes int id) {
+ protected <T extends View> T findViewTraversal(@IdRes int id) {
if (id == mID) {
- return this;
+ return (T) this;
}
return null;
}
@@ -20272,9 +20272,9 @@
* @return the view of specified tag, null if cannot be found
* @hide
*/
- protected View findViewWithTagTraversal(Object tag) {
+ protected <T extends View> T findViewWithTagTraversal(Object tag) {
if (tag != null && tag.equals(mTag)) {
- return this;
+ return (T) this;
}
return null;
}
@@ -20285,9 +20285,10 @@
* @return The first view that matches the predicate or null.
* @hide
*/
- protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
+ protected <T extends View> T findViewByPredicateTraversal(Predicate<View> predicate,
+ View childToSkip) {
if (predicate.test(this)) {
- return this;
+ return (T) this;
}
return null;
}
@@ -20300,7 +20301,7 @@
* @return The view that has the given id in the hierarchy or null
*/
@Nullable
- public final View findViewById(@IdRes int id) {
+ public final <T extends View> T findViewById(@IdRes int id) {
if (id < 0) {
return null;
}
@@ -20313,11 +20314,11 @@
* @param accessibilityId The searched accessibility id.
* @return The found view.
*/
- final View findViewByAccessibilityId(int accessibilityId) {
+ final <T extends View> T findViewByAccessibilityId(int accessibilityId) {
if (accessibilityId < 0) {
return null;
}
- View view = findViewByAccessibilityIdTraversal(accessibilityId);
+ T view = findViewByAccessibilityIdTraversal(accessibilityId);
if (view != null) {
return view.includeForAccessibility() ? view : null;
}
@@ -20336,12 +20337,11 @@
*
* @param accessibilityId The accessibility id.
* @return The found view.
- *
* @hide
*/
- public View findViewByAccessibilityIdTraversal(int accessibilityId) {
+ public <T extends View> T findViewByAccessibilityIdTraversal(int accessibilityId) {
if (getAccessibilityViewId() == accessibilityId) {
- return this;
+ return (T) this;
}
return null;
}
@@ -20353,7 +20353,7 @@
* @param tag The tag to search for, using "tag.equals(getTag())".
* @return The View that has the given tag in the hierarchy or null
*/
- public final View findViewWithTag(Object tag) {
+ public final <T extends View> T findViewWithTag(Object tag) {
if (tag == null) {
return null;
}
@@ -20368,7 +20368,7 @@
* @return The first view that matches the predicate or null.
* @hide
*/
- public final View findViewByPredicate(Predicate<View> predicate) {
+ public final <T extends View> T findViewByPredicate(Predicate<View> predicate) {
return findViewByPredicateTraversal(predicate, null);
}
@@ -20388,10 +20388,11 @@
* @return The first view that matches the predicate or null.
* @hide
*/
- public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) {
+ public final <T extends View> T findViewByPredicateInsideOut(
+ View start, Predicate<View> predicate) {
View childToSkip = null;
for (;;) {
- View view = start.findViewByPredicateTraversal(predicate, childToSkip);
+ T view = start.findViewByPredicateTraversal(predicate, childToSkip);
if (view != null || start == this) {
return view;
}
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 7aa2168..ffa79bd 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -4324,9 +4324,9 @@
* {@hide}
*/
@Override
- protected View findViewTraversal(@IdRes int id) {
+ protected <T extends View> T findViewTraversal(@IdRes int id) {
if (id == mID) {
- return this;
+ return (T) this;
}
final View[] where = mChildren;
@@ -4339,7 +4339,7 @@
v = v.findViewById(id);
if (v != null) {
- return v;
+ return (T) v;
}
}
}
@@ -4351,9 +4351,9 @@
* {@hide}
*/
@Override
- protected View findViewWithTagTraversal(Object tag) {
+ protected <T extends View> T findViewWithTagTraversal(Object tag) {
if (tag != null && tag.equals(mTag)) {
- return this;
+ return (T) this;
}
final View[] where = mChildren;
@@ -4366,7 +4366,7 @@
v = v.findViewWithTag(tag);
if (v != null) {
- return v;
+ return (T) v;
}
}
}
@@ -4378,9 +4378,10 @@
* {@hide}
*/
@Override
- protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
+ protected <T extends View> T findViewByPredicateTraversal(Predicate<View> predicate,
+ View childToSkip) {
if (predicate.test(this)) {
- return this;
+ return (T) this;
}
final View[] where = mChildren;
@@ -4393,7 +4394,7 @@
v = v.findViewByPredicate(predicate);
if (v != null) {
- return v;
+ return (T) v;
}
}
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index b79f22f..20d960f 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -4305,11 +4305,11 @@
mTranslator.translateEventInScreenToAppWindow(event);
}
- // Enter touch mode on down or scroll.
+ // Enter touch mode on down or scroll, if it is coming from a touch screen device,
+ // exit otherwise.
final int action = event.getAction();
- if (event.isFromSource(InputDevice.SOURCE_TOUCHSCREEN)
- && (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_SCROLL)) {
- ensureTouchMode(true);
+ if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_SCROLL) {
+ ensureTouchMode(event.isFromSource(InputDevice.SOURCE_TOUCHSCREEN));
}
if (action == MotionEvent.ACTION_DOWN && mAttachInfo.mTooltipHost != null) {
diff --git a/core/java/android/widget/ActivityChooserView.java b/core/java/android/widget/ActivityChooserView.java
index 51587a7..9a39a17 100644
--- a/core/java/android/widget/ActivityChooserView.java
+++ b/core/java/android/widget/ActivityChooserView.java
@@ -250,7 +250,7 @@
mDefaultActivityButton = (FrameLayout) findViewById(R.id.default_activity_button);
mDefaultActivityButton.setOnClickListener(mCallbacks);
mDefaultActivityButton.setOnLongClickListener(mCallbacks);
- mDefaultActivityButtonImage = (ImageView) mDefaultActivityButton.findViewById(R.id.image);
+ mDefaultActivityButtonImage = mDefaultActivityButton.findViewById(R.id.image);
final FrameLayout expandButton = (FrameLayout) findViewById(R.id.expand_activities_button);
expandButton.setOnClickListener(mCallbacks);
@@ -282,7 +282,7 @@
mExpandActivityOverflowButton = expandButton;
mExpandActivityOverflowButtonImage =
- (ImageView) expandButton.findViewById(R.id.image);
+ expandButton.findViewById(R.id.image);
mExpandActivityOverflowButtonImage.setImageDrawable(expandActivityOverflowButtonDrawable);
mAdapter = new ActivityChooserViewAdapter();
@@ -760,7 +760,7 @@
convertView = LayoutInflater.from(getContext()).inflate(
R.layout.activity_chooser_view_list_item, parent, false);
convertView.setId(ITEM_VIEW_TYPE_FOOTER);
- TextView titleView = (TextView) convertView.findViewById(R.id.title);
+ TextView titleView = convertView.findViewById(R.id.title);
titleView.setText(mContext.getString(
R.string.activity_chooser_view_see_all));
}
@@ -772,11 +772,11 @@
}
PackageManager packageManager = mContext.getPackageManager();
// Set the icon
- ImageView iconView = (ImageView) convertView.findViewById(R.id.icon);
+ ImageView iconView = convertView.findViewById(R.id.icon);
ResolveInfo activity = (ResolveInfo) getItem(position);
iconView.setImageDrawable(activity.loadIcon(packageManager));
// Set the title.
- TextView titleView = (TextView) convertView.findViewById(R.id.title);
+ TextView titleView = convertView.findViewById(R.id.title);
titleView.setText(activity.loadLabel(packageManager));
// Highlight the default.
if (mShowDefaultActivity && position == 0 && mHighlightDefaultActivity) {
diff --git a/core/java/android/widget/AppSecurityPermissions.java b/core/java/android/widget/AppSecurityPermissions.java
index 68e6809..06d4868 100644
--- a/core/java/android/widget/AppSecurityPermissions.java
+++ b/core/java/android/widget/AppSecurityPermissions.java
@@ -451,7 +451,7 @@
private View getPermissionsView(int which, boolean showRevokeUI) {
LinearLayout permsView = (LinearLayout) mInflater.inflate(R.layout.app_perms_summary, null);
- LinearLayout displayList = (LinearLayout) permsView.findViewById(R.id.perms_list);
+ LinearLayout displayList = permsView.findViewById(R.id.perms_list);
View noPermsView = permsView.findViewById(R.id.no_permissions);
displayPermissions(mPermGroupsList, displayList, which, showRevokeUI);
@@ -517,8 +517,8 @@
CharSequence grpName, CharSequence permList, boolean dangerous, Drawable icon) {
View permView = inflater.inflate(R.layout.app_permission_item_old, null);
- TextView permGrpView = (TextView) permView.findViewById(R.id.permission_group);
- TextView permDescView = (TextView) permView.findViewById(R.id.permission_list);
+ TextView permGrpView = permView.findViewById(R.id.permission_group);
+ TextView permDescView = permView.findViewById(R.id.permission_list);
ImageView imgView = (ImageView)permView.findViewById(R.id.perm_icon);
imgView.setImageDrawable(icon);
diff --git a/core/java/android/widget/ArrayAdapter.java b/core/java/android/widget/ArrayAdapter.java
index bbc50da..81f0d3d 100644
--- a/core/java/android/widget/ArrayAdapter.java
+++ b/core/java/android/widget/ArrayAdapter.java
@@ -388,7 +388,7 @@
text = (TextView) view;
} else {
// Otherwise, find the TextView field within the layout
- text = (TextView) view.findViewById(mFieldId);
+ text = view.findViewById(mFieldId);
if (text == null) {
throw new RuntimeException("Failed to find view with ID "
diff --git a/core/java/android/widget/CalendarViewLegacyDelegate.java b/core/java/android/widget/CalendarViewLegacyDelegate.java
index 557d411..1b899db 100644
--- a/core/java/android/widget/CalendarViewLegacyDelegate.java
+++ b/core/java/android/widget/CalendarViewLegacyDelegate.java
@@ -316,9 +316,9 @@
View content = layoutInflater.inflate(R.layout.calendar_view, null, false);
mDelegator.addView(content);
- mListView = (ListView) mDelegator.findViewById(R.id.list);
- mDayNamesHeader = (ViewGroup) content.findViewById(R.id.day_names);
- mMonthName = (TextView) content.findViewById(R.id.month_name);
+ mListView = mDelegator.findViewById(R.id.list);
+ mDayNamesHeader = content.findViewById(R.id.day_names);
+ mMonthName = content.findViewById(R.id.month_name);
setUpHeader();
setUpListView();
diff --git a/core/java/android/widget/DatePickerCalendarDelegate.java b/core/java/android/widget/DatePickerCalendarDelegate.java
index f712685..907250a 100755
--- a/core/java/android/widget/DatePickerCalendarDelegate.java
+++ b/core/java/android/widget/DatePickerCalendarDelegate.java
@@ -115,10 +115,10 @@
mDelegator.addView(mContainer);
// Set up header views.
- final ViewGroup header = (ViewGroup) mContainer.findViewById(R.id.date_picker_header);
- mHeaderYear = (TextView) header.findViewById(R.id.date_picker_header_year);
+ final ViewGroup header = mContainer.findViewById(R.id.date_picker_header);
+ mHeaderYear = header.findViewById(R.id.date_picker_header_year);
mHeaderYear.setOnClickListener(mOnHeaderClickListener);
- mHeaderMonthDay = (TextView) header.findViewById(R.id.date_picker_header_date);
+ mHeaderMonthDay = header.findViewById(R.id.date_picker_header_date);
mHeaderMonthDay.setOnClickListener(mOnHeaderClickListener);
// For the sake of backwards compatibility, attempt to extract the text
@@ -154,10 +154,10 @@
a.recycle();
// Set up picker container.
- mAnimator = (ViewAnimator) mContainer.findViewById(R.id.animator);
+ mAnimator = mContainer.findViewById(R.id.animator);
// Set up day picker view.
- mDayPickerView = (DayPickerView) mAnimator.findViewById(R.id.date_picker_day_picker);
+ mDayPickerView = mAnimator.findViewById(R.id.date_picker_day_picker);
mDayPickerView.setFirstDayOfWeek(mFirstDayOfWeek);
mDayPickerView.setMinDate(mMinDate.getTimeInMillis());
mDayPickerView.setMaxDate(mMaxDate.getTimeInMillis());
@@ -165,7 +165,7 @@
mDayPickerView.setOnDaySelectedListener(mOnDaySelectedListener);
// Set up year picker view.
- mYearPickerView = (YearPickerView) mAnimator.findViewById(R.id.date_picker_year_picker);
+ mYearPickerView = mAnimator.findViewById(R.id.date_picker_year_picker);
mYearPickerView.setRange(mMinDate, mMaxDate);
mYearPickerView.setYear(mCurrentDate.get(Calendar.YEAR));
mYearPickerView.setOnYearSelectedListener(mOnYearSelectedListener);
diff --git a/core/java/android/widget/DayPickerPagerAdapter.java b/core/java/android/widget/DayPickerPagerAdapter.java
index 8d5bf8f..63621e1 100644
--- a/core/java/android/widget/DayPickerPagerAdapter.java
+++ b/core/java/android/widget/DayPickerPagerAdapter.java
@@ -225,7 +225,7 @@
public Object instantiateItem(ViewGroup container, int position) {
final View itemView = mInflater.inflate(mLayoutResId, container, false);
- final SimpleMonthView v = (SimpleMonthView) itemView.findViewById(mCalendarViewId);
+ final SimpleMonthView v = itemView.findViewById(mCalendarViewId);
v.setOnDayClickListener(mOnDayClickListener);
v.setMonthTextAppearance(mMonthTextAppearance);
v.setDayOfWeekTextAppearance(mDayOfWeekTextAppearance);
diff --git a/core/java/android/widget/DayPickerViewPager.java b/core/java/android/widget/DayPickerViewPager.java
index a27e022..1704ed7 100644
--- a/core/java/android/widget/DayPickerViewPager.java
+++ b/core/java/android/widget/DayPickerViewPager.java
@@ -137,9 +137,10 @@
}
@Override
- protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
+ protected <T extends View> T findViewByPredicateTraversal(Predicate<View> predicate,
+ View childToSkip) {
if (predicate.test(this)) {
- return this;
+ return (T) this;
}
// Always try the selected view first.
@@ -148,7 +149,7 @@
if (current != childToSkip && current != null) {
final View v = current.findViewByPredicate(predicate);
if (v != null) {
- return v;
+ return (T) v;
}
}
@@ -160,7 +161,7 @@
final View v = child.findViewByPredicate(predicate);
if (v != null) {
- return v;
+ return (T) v;
}
}
}
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index 46e998a..1c0c4ef 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -3740,20 +3740,21 @@
* @removed For internal use only. This should have been hidden.
*/
@Override
- protected View findViewTraversal(@IdRes int id) {
- View v;
- v = super.findViewTraversal(id);
+ protected <T extends View> T findViewTraversal(@IdRes int id) {
+ // First look in our children, then in any header and footer views that
+ // may be scrolled off.
+ View v = super.findViewTraversal(id);
if (v == null) {
v = findViewInHeadersOrFooters(mHeaderViewInfos, id);
if (v != null) {
- return v;
+ return (T) v;
}
v = findViewInHeadersOrFooters(mFooterViewInfos, id);
if (v != null) {
- return v;
+ return (T) v;
}
}
- return v;
+ return (T) v;
}
View findViewInHeadersOrFooters(ArrayList<FixedViewInfo> where, int id) {
@@ -3782,21 +3783,22 @@
* @removed For internal use only. This should have been hidden.
*/
@Override
- protected View findViewWithTagTraversal(Object tag) {
- View v;
- v = super.findViewWithTagTraversal(tag);
+ protected <T extends View> T findViewWithTagTraversal(Object tag) {
+ // First look in our children, then in any header and footer views that
+ // may be scrolled off.
+ View v = super.findViewWithTagTraversal(tag);
if (v == null) {
v = findViewWithTagInHeadersOrFooters(mHeaderViewInfos, tag);
if (v != null) {
- return v;
+ return (T) v;
}
v = findViewWithTagInHeadersOrFooters(mFooterViewInfos, tag);
if (v != null) {
- return v;
+ return (T) v;
}
}
- return v;
+ return (T) v;
}
View findViewWithTagInHeadersOrFooters(ArrayList<FixedViewInfo> where, Object tag) {
@@ -3829,21 +3831,21 @@
* @hide
*/
@Override
- protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
- View v;
- v = super.findViewByPredicateTraversal(predicate, childToSkip);
+ protected <T extends View> T findViewByPredicateTraversal(
+ Predicate<View> predicate, View childToSkip) {
+ View v = super.findViewByPredicateTraversal(predicate, childToSkip);
if (v == null) {
v = findViewByPredicateInHeadersOrFooters(mHeaderViewInfos, predicate, childToSkip);
if (v != null) {
- return v;
+ return (T) v;
}
v = findViewByPredicateInHeadersOrFooters(mFooterViewInfos, predicate, childToSkip);
if (v != null) {
- return v;
+ return (T) v;
}
}
- return v;
+ return (T) v;
}
/**
diff --git a/core/java/android/widget/MediaController.java b/core/java/android/widget/MediaController.java
index 8008637..8e04f1c 100644
--- a/core/java/android/widget/MediaController.java
+++ b/core/java/android/widget/MediaController.java
@@ -257,13 +257,13 @@
.getText(com.android.internal.R.string.lockscreen_transport_play_description);
mPauseDescription = res
.getText(com.android.internal.R.string.lockscreen_transport_pause_description);
- mPauseButton = (ImageButton) v.findViewById(com.android.internal.R.id.pause);
+ mPauseButton = v.findViewById(com.android.internal.R.id.pause);
if (mPauseButton != null) {
mPauseButton.requestFocus();
mPauseButton.setOnClickListener(mPauseListener);
}
- mFfwdButton = (ImageButton) v.findViewById(com.android.internal.R.id.ffwd);
+ mFfwdButton = v.findViewById(com.android.internal.R.id.ffwd);
if (mFfwdButton != null) {
mFfwdButton.setOnClickListener(mFfwdListener);
if (!mFromXml) {
@@ -271,7 +271,7 @@
}
}
- mRewButton = (ImageButton) v.findViewById(com.android.internal.R.id.rew);
+ mRewButton = v.findViewById(com.android.internal.R.id.rew);
if (mRewButton != null) {
mRewButton.setOnClickListener(mRewListener);
if (!mFromXml) {
@@ -280,16 +280,16 @@
}
// By default these are hidden. They will be enabled when setPrevNextListeners() is called
- mNextButton = (ImageButton) v.findViewById(com.android.internal.R.id.next);
+ mNextButton = v.findViewById(com.android.internal.R.id.next);
if (mNextButton != null && !mFromXml && !mListenersSet) {
mNextButton.setVisibility(View.GONE);
}
- mPrevButton = (ImageButton) v.findViewById(com.android.internal.R.id.prev);
+ mPrevButton = v.findViewById(com.android.internal.R.id.prev);
if (mPrevButton != null && !mFromXml && !mListenersSet) {
mPrevButton.setVisibility(View.GONE);
}
- mProgress = (ProgressBar) v.findViewById(com.android.internal.R.id.mediacontroller_progress);
+ mProgress = v.findViewById(com.android.internal.R.id.mediacontroller_progress);
if (mProgress != null) {
if (mProgress instanceof SeekBar) {
SeekBar seeker = (SeekBar) mProgress;
@@ -298,8 +298,8 @@
mProgress.setMax(1000);
}
- mEndTime = (TextView) v.findViewById(com.android.internal.R.id.time);
- mCurrentTime = (TextView) v.findViewById(com.android.internal.R.id.time_current);
+ mEndTime = v.findViewById(com.android.internal.R.id.time);
+ mCurrentTime = v.findViewById(com.android.internal.R.id.time_current);
mFormatBuilder = new StringBuilder();
mFormatter = new Formatter(mFormatBuilder, Locale.getDefault());
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 359d04e..5505f2f 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -1578,7 +1578,7 @@
@Override
public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
final Context context = root.getContext();
- final ViewGroup target = (ViewGroup) root.findViewById(viewId);
+ final ViewGroup target = root.findViewById(viewId);
if (target == null) return;
if (nestedViews != null) {
// Inflate nested views and add as children
@@ -1757,7 +1757,7 @@
@Override
public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
- final TextView target = (TextView) root.findViewById(viewId);
+ final TextView target = root.findViewById(viewId);
if (target == null) return;
if (drawablesLoaded) {
if (isRelative) {
@@ -1857,7 +1857,7 @@
@Override
public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
- final TextView target = (TextView) root.findViewById(viewId);
+ final TextView target = root.findViewById(viewId);
if (target == null) return;
target.setTextSize(units, size);
}
@@ -2045,7 +2045,7 @@
@Override
public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
- final TextView target = (TextView) root.findViewById(viewId);
+ final TextView target = root.findViewById(viewId);
if (target == null) return;
Drawable[] drawables = isRelative
? target.getCompoundDrawablesRelative()
diff --git a/core/java/android/widget/SuggestionsAdapter.java b/core/java/android/widget/SuggestionsAdapter.java
index f833d1b..fbb8993 100644
--- a/core/java/android/widget/SuggestionsAdapter.java
+++ b/core/java/android/widget/SuggestionsAdapter.java
@@ -286,7 +286,7 @@
v.setTag(new ChildViewCache(v));
// Set up icon.
- final ImageView iconRefine = (ImageView) v.findViewById(R.id.edit_query);
+ final ImageView iconRefine = v.findViewById(R.id.edit_query);
iconRefine.setImageResource(mCommitIconResId);
return v;
@@ -304,11 +304,11 @@
public final ImageView mIconRefine;
public ChildViewCache(View v) {
- mText1 = (TextView) v.findViewById(com.android.internal.R.id.text1);
- mText2 = (TextView) v.findViewById(com.android.internal.R.id.text2);
- mIcon1 = (ImageView) v.findViewById(com.android.internal.R.id.icon1);
- mIcon2 = (ImageView) v.findViewById(com.android.internal.R.id.icon2);
- mIconRefine = (ImageView) v.findViewById(com.android.internal.R.id.edit_query);
+ mText1 = v.findViewById(com.android.internal.R.id.text1);
+ mText2 = v.findViewById(com.android.internal.R.id.text2);
+ mIcon1 = v.findViewById(com.android.internal.R.id.icon1);
+ mIcon2 = v.findViewById(com.android.internal.R.id.icon2);
+ mIconRefine = v.findViewById(com.android.internal.R.id.edit_query);
}
}
diff --git a/core/java/android/widget/TabHost.java b/core/java/android/widget/TabHost.java
index 32418cd..7e2cadf 100644
--- a/core/java/android/widget/TabHost.java
+++ b/core/java/android/widget/TabHost.java
@@ -619,7 +619,7 @@
mTabWidget, // tab widget is the parent
false); // no inflate params
- final TextView tv = (TextView) tabIndicator.findViewById(R.id.title);
+ final TextView tv = tabIndicator.findViewById(R.id.title);
tv.setText(mLabel);
if (context.getApplicationInfo().targetSdkVersion <= Build.VERSION_CODES.DONUT) {
@@ -653,8 +653,8 @@
mTabWidget, // tab widget is the parent
false); // no inflate params
- final TextView tv = (TextView) tabIndicator.findViewById(R.id.title);
- final ImageView iconView = (ImageView) tabIndicator.findViewById(R.id.icon);
+ final TextView tv = tabIndicator.findViewById(R.id.title);
+ final ImageView iconView = tabIndicator.findViewById(R.id.icon);
// when icon is gone by default, we're in exclusive mode
final boolean exclusive = iconView.getVisibility() == View.GONE;
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 9078e61..adc6f72 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -266,7 +266,7 @@
* @attr ref android.R.styleable#TextView_fontFeatureSettings
* @attr ref android.R.styleable#TextView_breakStrategy
* @attr ref android.R.styleable#TextView_hyphenationFrequency
- * @attr ref android.R.styleable#TextView_autoSizeText
+ * @attr ref android.R.styleable#TextView_autoSizeTextType
* @attr ref android.R.styleable#TextView_autoSizeMinTextSize
* @attr ref android.R.styleable#TextView_autoSizeMaxTextSize
* @attr ref android.R.styleable#TextView_autoSizeStepGranularity
@@ -691,18 +691,24 @@
*/
private int mDeviceProvisionedState = DEVICE_PROVISIONED_UNKNOWN;
- // The TextView does not auto-size text (default).
+ /**
+ * The TextView does not auto-size text (default).
+ */
public static final int AUTO_SIZE_TEXT_TYPE_NONE = 0;
- // The TextView performs uniform horizontal and vertical text size scaling to fit within the
- // container.
+
+ /**
+ * The TextView scales text size both horizontally and vertically to fit within the
+ * container.
+ */
public static final int AUTO_SIZE_TEXT_TYPE_UNIFORM = 1;
+
/** @hide */
@IntDef({AUTO_SIZE_TEXT_TYPE_NONE, AUTO_SIZE_TEXT_TYPE_UNIFORM})
@Retention(RetentionPolicy.SOURCE)
public @interface AutoSizeTextType {}
- // Default minimum size for auto-sizing text in scaled pixels. {@see #setAutoSizeMinTextSize}.
+ // Default minimum size for auto-sizing text in scaled pixels.
private static final int DEFAULT_AUTO_SIZE_MIN_TEXT_SIZE_IN_SP = 12;
- // Default maximum size for auto-sizing text in scaled pixels. {@see #setAutoSizeMaxTextSize}.
+ // Default maximum size for auto-sizing text in scaled pixels.
private static final int DEFAULT_AUTO_SIZE_MAX_TEXT_SIZE_IN_SP = 112;
// Default value for the step size in pixels.
private static final int DEFAULT_AUTO_SIZE_GRANULARITY_IN_PX = 1;
@@ -1308,7 +1314,7 @@
mHyphenationFrequency = a.getInt(attr, Layout.HYPHENATION_FREQUENCY_NONE);
break;
- case com.android.internal.R.styleable.TextView_autoSizeText:
+ case com.android.internal.R.styleable.TextView_autoSizeTextType:
mAutoSizeTextType = a.getInt(attr, AUTO_SIZE_TEXT_TYPE_NONE);
break;
@@ -1660,7 +1666,7 @@
* {@link TextView#AUTO_SIZE_TEXT_TYPE_NONE} or
* {@link TextView#AUTO_SIZE_TEXT_TYPE_UNIFORM}
*
- * @attr ref android.R.styleable#TextView_autoSizeText
+ * @attr ref android.R.styleable#TextView_autoSizeTextType
*
* @see #getAutoSizeTextType()
*/
@@ -1709,7 +1715,7 @@
*
* @throws IllegalArgumentException if any of the configuration params are invalid.
*
- * @attr ref android.R.styleable#TextView_autoSizeText
+ * @attr ref android.R.styleable#TextView_autoSizeTextType
* @attr ref android.R.styleable#TextView_autoSizeMinTextSize
* @attr ref android.R.styleable#TextView_autoSizeMaxTextSize
* @attr ref android.R.styleable#TextView_autoSizeStepGranularity
@@ -1753,7 +1759,7 @@
*
* @throws IllegalArgumentException if all of the <code>presetSizes</code> are invalid.
*
- * @attr ref android.R.styleable#TextView_autoSizeText
+ * @attr ref android.R.styleable#TextView_autoSizeTextType
* @attr ref android.R.styleable#TextView_autoSizePresetSizes
*
* @see #setAutoSizeTextTypeWithDefaults(int)
@@ -1806,7 +1812,7 @@
* {@link TextView#AUTO_SIZE_TEXT_TYPE_NONE} or
* {@link TextView#AUTO_SIZE_TEXT_TYPE_UNIFORM}
*
- * @attr ref android.R.styleable#TextView_autoSizeText
+ * @attr ref android.R.styleable#TextView_autoSizeTextType
*
* @see #setAutoSizeTextTypeWithDefaults(int)
* @see #setAutoSizeTextTypeUniformWithConfiguration(int, int, int, int)
diff --git a/core/java/android/widget/TimePickerSpinnerDelegate.java b/core/java/android/widget/TimePickerSpinnerDelegate.java
index 7ef54a5..20a5512 100644
--- a/core/java/android/widget/TimePickerSpinnerDelegate.java
+++ b/core/java/android/widget/TimePickerSpinnerDelegate.java
@@ -86,7 +86,7 @@
inflater.inflate(layoutResourceId, mDelegator, true);
// hour
- mHourSpinner = (NumberPicker) delegator.findViewById(R.id.hour);
+ mHourSpinner = delegator.findViewById(R.id.hour);
mHourSpinner.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
public void onValueChange(NumberPicker spinner, int oldVal, int newVal) {
updateInputState();
@@ -100,17 +100,17 @@
onTimeChanged();
}
});
- mHourSpinnerInput = (EditText) mHourSpinner.findViewById(R.id.numberpicker_input);
+ mHourSpinnerInput = mHourSpinner.findViewById(R.id.numberpicker_input);
mHourSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_NEXT);
// divider (only for the new widget style)
- mDivider = (TextView) mDelegator.findViewById(R.id.divider);
+ mDivider = mDelegator.findViewById(R.id.divider);
if (mDivider != null) {
setDividerText();
}
// minute
- mMinuteSpinner = (NumberPicker) mDelegator.findViewById(R.id.minute);
+ mMinuteSpinner = mDelegator.findViewById(R.id.minute);
mMinuteSpinner.setMinValue(0);
mMinuteSpinner.setMaxValue(59);
mMinuteSpinner.setOnLongPressUpdateInterval(100);
@@ -138,7 +138,7 @@
onTimeChanged();
}
});
- mMinuteSpinnerInput = (EditText) mMinuteSpinner.findViewById(R.id.numberpicker_input);
+ mMinuteSpinnerInput = mMinuteSpinner.findViewById(R.id.numberpicker_input);
mMinuteSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_NEXT);
// Get the localized am/pm strings and use them in the spinner.
@@ -173,13 +173,13 @@
onTimeChanged();
}
});
- mAmPmSpinnerInput = (EditText) mAmPmSpinner.findViewById(R.id.numberpicker_input);
+ mAmPmSpinnerInput = mAmPmSpinner.findViewById(R.id.numberpicker_input);
mAmPmSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_DONE);
}
if (isAmPmAtStart()) {
// Move the am/pm view to the beginning
- ViewGroup amPmParent = (ViewGroup) delegator.findViewById(R.id.timePickerLayout);
+ ViewGroup amPmParent = delegator.findViewById(R.id.timePickerLayout);
amPmParent.removeView(amPmView);
amPmParent.addView(amPmView, 0);
// Swap layout margins if needed. They may be not symmetrical (Old Standard Theme
diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java
index 789e60b..bf0601d 100644
--- a/core/java/android/widget/Toast.java
+++ b/core/java/android/widget/Toast.java
@@ -299,7 +299,7 @@
if (mNextView == null) {
throw new RuntimeException("This Toast was not created with Toast.makeText()");
}
- TextView tv = (TextView) mNextView.findViewById(com.android.internal.R.id.message);
+ TextView tv = mNextView.findViewById(com.android.internal.R.id.message);
if (tv == null) {
throw new RuntimeException("This Toast was not created with Toast.makeText()");
}
diff --git a/core/java/android/widget/ZoomButtonsController.java b/core/java/android/widget/ZoomButtonsController.java
index 69b79971..1a3ca86 100644
--- a/core/java/android/widget/ZoomButtonsController.java
+++ b/core/java/android/widget/ZoomButtonsController.java
@@ -264,7 +264,7 @@
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(com.android.internal.R.layout.zoom_container, container);
- mControls = (ZoomControls) container.findViewById(com.android.internal.R.id.zoomControls);
+ mControls = container.findViewById(com.android.internal.R.id.zoomControls);
mControls.setOnZoomInClickListener(new OnClickListener() {
public void onClick(View v) {
dismissControlsDelayed(ZOOM_CONTROLS_TIMEOUT);
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 84c8f7a..79301aa 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -23,15 +23,21 @@
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.IntentSender;
import android.content.IntentSender.SendIntentException;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
import android.content.pm.LabeledIntent;
+import android.content.pm.LauncherApps;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ParceledListSlice;
import android.content.pm.ResolveInfo;
+import android.content.pm.ShortcutInfo;
+import android.content.pm.ShortcutManager;
import android.database.DataSetObserver;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
@@ -84,6 +90,14 @@
public class ChooserActivity extends ResolverActivity {
private static final String TAG = "ChooserActivity";
+ /**
+ * Boolean extra to change the following behavior: Normally, ChooserActivity finishes itself
+ * in onStop when launched in a new task. If this extra is set to true, we do not finish
+ * ourselves when onStop gets called.
+ */
+ public static final String EXTRA_PRIVATE_RETAIN_IN_ON_STOP
+ = "com.android.internal.app.ChooserActivity.EXTRA_PRIVATE_RETAIN_IN_ON_STOP";
+
private static final boolean DEBUG = false;
private static final int QUERY_TARGET_SERVICE_LIMIT = 5;
@@ -260,6 +274,7 @@
}
mPinnedSharedPrefs = getPinnedSharedPrefs(this);
+ setRetainInOnStop(intent.getBooleanExtra(EXTRA_PRIVATE_RETAIN_IN_ON_STOP, false));
super.onCreate(savedInstanceState, target, title, defaultTitleRes, initialIntents,
null, false);
@@ -347,6 +362,7 @@
mChooserListAdapter.addServiceResults(null, Lists.newArrayList(mCallerChooserTargets));
}
mChooserRowAdapter = new ChooserRowAdapter(mChooserListAdapter);
+ mChooserRowAdapter.updateRowScales();
mChooserRowAdapter.registerDataSetObserver(new OffsetDataSetObserver(adapterView));
adapterView.setAdapter(mChooserRowAdapter);
if (listView != null) {
@@ -833,7 +849,9 @@
return false;
}
intent.setComponent(mChooserTarget.getComponentName());
- intent.putExtras(mChooserTarget.getIntentExtras());
+ if (mChooserTarget.getIntentExtras() != null) {
+ intent.putExtras(mChooserTarget.getIntentExtras());
+ }
// Important: we will ignore the target security checks in ActivityManager
// if and only if the ChooserTarget's target package is the same package
@@ -916,6 +934,8 @@
private static final int MAX_SERVICE_TARGETS = 8;
private static final int MAX_TARGETS_PER_SERVICE = 4;
+ private boolean mAreChooserShortcutsRetrieved;
+
private final List<ChooserTargetInfo> mServiceTargets = new ArrayList<>();
private final List<TargetInfo> mCallerTargets = new ArrayList<>();
private boolean mShowServiceTargets;
@@ -1007,6 +1027,20 @@
if (mServiceTargets != null) {
pruneServiceTargets();
}
+
+ if (DEBUG) Log.d(TAG, "Adding pushed chooser targets");
+
+ if (!mAreChooserShortcutsRetrieved) {
+ LauncherApps launcherApps = getLauncherApps();
+ LauncherApps.ShortcutQuery query = new LauncherApps.ShortcutQuery();
+ query.setIntent(getTargetIntent());
+ query.setQueryFlags(LauncherApps.ShortcutQuery.FLAG_MATCH_CHOOSER);
+ List<ShortcutInfo> shortcuts = launcherApps.getShortcuts(query, UserHandle.SYSTEM);
+ if (DEBUG) Log.d(TAG, "Adding " + shortcuts.size() + " chooser shortcuts");
+ addShortcuts(shortcuts);
+ mAreChooserShortcutsRetrieved = true;
+ }
+
if (DEBUG) Log.d(TAG, "List built querying services");
queryTargetServices(this);
}
@@ -1032,6 +1066,7 @@
public int getServiceTargetCount() {
if (!mShowServiceTargets) {
+ if (DEBUG) Log.d("TAG", "Hiding service targets");
return 0;
}
return Math.min(mServiceTargets.size(), MAX_SERVICE_TARGETS);
@@ -1123,6 +1158,71 @@
notifyDataSetChanged();
}
+ // TODO: Pushed targets need to be scored correctly
+ public void addShortcuts(List<ShortcutInfo> infos) {
+ for (ShortcutInfo info : infos) {
+ List<ChooserTarget> newTargets = new ArrayList<>();
+ final ComponentName cn = info.getActivity();
+ ActivityInfo ai;
+ ResolveInfo ri = new ResolveInfo();
+ if (cn != null) {
+ try {
+ ai = getPackageManager().getActivityInfo(cn, 0);
+ ri.activityInfo = ai;
+ UserManager userManager =
+ (UserManager) getSystemService(Context.USER_SERVICE);
+ ri.iconResourceId = ai.icon;
+ ri.labelRes = ai.labelRes;
+ ri.resolvePackageName = ai.packageName;
+ ri.activityInfo.applicationInfo = new ApplicationInfo(
+ ri.activityInfo.applicationInfo);
+ ri.activityInfo.applicationInfo = ai.applicationInfo;
+ ri.activityInfo.applicationInfo.uid = getUserId();
+ } catch (PackageManager.NameNotFoundException ignored) {
+ if (DEBUG) Log.d(TAG, "Package not found, skipping this shortcut");
+ continue;
+ }
+ }
+
+ DisplayResolveInfo resolveInfo = new DisplayResolveInfo(getTargetIntent(),
+ ri,
+ info.getShortLabel(),
+ info.getLongLabel(),
+ getTargetIntent());
+
+ int bestMatch = 0;
+ ComponentName bestComponent = null;
+ for (int i = 0; i < info.getChooserIntentFilters().length; i++) {
+ int newMatch = info.getChooserIntentFilters()[i]
+ .match(getContentResolver(), getTargetIntent(), false, TAG);
+ if (DEBUG) Log.d(TAG, "A match was found with value: " + newMatch);
+ if (newMatch > bestMatch) {
+ bestMatch = newMatch;
+ bestComponent = info.getChooserComponentNames()[i];
+ }
+ }
+ if (bestMatch == 0) {
+ Log.e(TAG, "Unexpectedly, no match was found for the provided chooser intent");
+ return;
+ }
+
+ Bundle extrasToAdd =
+ info.getChooserExtras() == null ? null: new Bundle(info.getChooserExtras());
+ if (DEBUG) Log.d(TAG, "Adding service target " + info.getShortLabel());
+ newTargets.add(new ChooserTarget(
+ info.getShortLabel(),
+ info.getIcon(),
+ 1,
+ bestComponent,
+ extrasToAdd));
+ addServiceResults(resolveInfo, newTargets);
+ }
+ if (mChooserRowAdapter != null) {
+ mChooserRowAdapter.updateRowScales();
+ }
+ setShowServiceTargets(true);
+ }
+
/**
* Set to true to reveal all service targets at once.
*/
@@ -1237,37 +1337,7 @@
@Override
public void onChanged() {
super.onChanged();
- final int rcount = getServiceTargetRowCount();
- if (mServiceTargetScale == null
- || mServiceTargetScale.length != rcount) {
- RowScale[] old = mServiceTargetScale;
- int oldRCount = old != null ? old.length : 0;
- mServiceTargetScale = new RowScale[rcount];
- if (old != null && rcount > 0) {
- System.arraycopy(old, 0, mServiceTargetScale, 0,
- Math.min(old.length, rcount));
- }
-
- for (int i = rcount; i < oldRCount; i++) {
- old[i].cancelAnimation();
- }
-
- for (int i = oldRCount; i < rcount; i++) {
- final RowScale rs = new RowScale(ChooserRowAdapter.this, 0.f, 1.f)
- .setInterpolator(mInterpolator);
- mServiceTargetScale[i] = rs;
- }
-
- // Start the animations in a separate loop.
- // The process of starting animations will result in
- // binding views to set up initial values, and we must
- // have ALL of the new RowScale objects created above before
- // we get started.
- for (int i = oldRCount; i < rcount; i++) {
- mServiceTargetScale[i].startAnimation();
- }
- }
-
+ updateRowScales();
notifyDataSetChanged();
}
@@ -1284,6 +1354,40 @@
});
}
+ void updateRowScales() {
+ final int rcount = getServiceTargetRowCount();
+ if (mServiceTargetScale == null
+ || mServiceTargetScale.length != rcount) {
+ if (DEBUG) Log.d(TAG, "Row scales need adjusting to " + rcount + " rows.");
+ RowScale[] old = mServiceTargetScale;
+ int oldRCount = old != null ? old.length : 0;
+ mServiceTargetScale = new RowScale[rcount];
+ if (old != null && rcount > 0) {
+ System.arraycopy(old, 0, mServiceTargetScale, 0,
+ Math.min(old.length, rcount));
+ }
+
+ for (int i = rcount; i < oldRCount; i++) {
+ old[i].cancelAnimation();
+ }
+
+ for (int i = oldRCount; i < rcount; i++) {
+ final RowScale rs = new RowScale(ChooserRowAdapter.this, 0.f, 1.f)
+ .setInterpolator(mInterpolator);
+ mServiceTargetScale[i] = rs;
+ }
+
+ // Start the animations in a separate loop.
+ // The process of starting animations will result in
+ // binding views to set up initial values, and we must
+ // have ALL of the new RowScale objects created above before
+ // we get started.
+ for (int i = oldRCount; i < rcount; i++) {
+ mServiceTargetScale[i].startAnimation();
+ }
+ }
+ }
+
private float getRowScale(int rowPosition) {
final int start = getCallerTargetRowCount();
final int end = start + getServiceTargetRowCount();
@@ -1554,6 +1658,10 @@
}
}
+ public LauncherApps getLauncherApps() {
+ return (LauncherApps) getSystemService(Context.LAUNCHER_APPS_SERVICE);
+ }
+
static class ServiceResultInfo {
public final DisplayResolveInfo originalTarget;
public final List<ChooserTarget> resultTargets;
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 0b1f0aa..9fb9cb6 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -116,6 +116,10 @@
private Runnable mPostListReadyRunnable;
private boolean mRegistered;
+
+ /** See {@link #setRetainInOnStop}. */
+ private boolean mRetainInOnStop;
+
private final PackageMonitor mPackageMonitor = new PackageMonitor() {
@Override public void onSomePackagesChanged() {
mAdapter.handlePackagesChanged();
@@ -502,7 +506,7 @@
}
final Intent intent = getIntent();
if ((intent.getFlags() & FLAG_ACTIVITY_NEW_TASK) != 0 && !isVoiceInteraction()
- && !mResolvingHome) {
+ && !mResolvingHome && !mRetainInOnStop) {
// This resolver is in the unusual situation where it has been
// launched at the top of a new task. We don't let it be added
// to the recent tasks shown to the user, and we need to make sure
@@ -1029,6 +1033,14 @@
}
/**
+ * If {@code retainInOnStop} is set to true, we will not finish ourselves when onStop gets
+ * called and we are launched in a new task.
+ */
+ protected void setRetainInOnStop(boolean retainInOnStop) {
+ mRetainInOnStop = retainInOnStop;
+ }
+
+ /**
* Check a simple match for the component of two ResolveInfos.
*/
static boolean resolveInfoMatch(ResolveInfo lhs, ResolveInfo rhs) {
diff --git a/core/java/com/android/internal/widget/WatchHeaderListView.java b/core/java/com/android/internal/widget/WatchHeaderListView.java
index 7e91537..0654454 100644
--- a/core/java/com/android/internal/widget/WatchHeaderListView.java
+++ b/core/java/com/android/internal/widget/WatchHeaderListView.java
@@ -91,13 +91,14 @@
}
@Override
- protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
+ protected <T extends View> T findViewByPredicateTraversal(
+ Predicate<View> predicate, View childToSkip) {
View v = super.findViewByPredicateTraversal(predicate, childToSkip);
if (v == null && mTopPanel != null && mTopPanel != childToSkip
&& !mTopPanel.isRootNamespace()) {
- return mTopPanel.findViewByPredicate(predicate);
+ return (T) mTopPanel.findViewByPredicate(predicate);
}
- return v;
+ return (T) v;
}
@Override
diff --git a/core/res/res/layout/autofill_dataset_picker.xml b/core/res/res/layout/autofill_dataset_picker.xml
index 40cce7b..9b90de6 100644
--- a/core/res/res/layout/autofill_dataset_picker.xml
+++ b/core/res/res/layout/autofill_dataset_picker.xml
@@ -15,7 +15,7 @@
-->
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/list"
+ android:id="@+id/autofill_dataset_picker"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:divider="?android:attr/listDivider"
diff --git a/core/res/res/layout/autofill_save.xml b/core/res/res/layout/autofill_save.xml
index 8453cd35..dad9aad 100644
--- a/core/res/res/layout/autofill_save.xml
+++ b/core/res/res/layout/autofill_save.xml
@@ -16,6 +16,7 @@
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/autofill_save"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingStart="16dip"
@@ -39,6 +40,13 @@
android:singleLine="true">
</TextView>
+ <TextView
+ android:id="@+id/autofill_save_subtitle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:visibility="invisible">
+ </TextView>
+
<Space
android:layout_width="0dp"
android:layout_height="0dp"
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index f55538f..be77603 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -4721,18 +4721,19 @@
</attr>
<!-- Specify the type of auto-size. Note that this feature is not supported by EditText,
works only for TextView -->
- <attr name="autoSizeText" format="enum">
+ <attr name="autoSizeTextType" format="enum">
<!-- No auto-sizing (default). -->
<enum name="none" value="0" />
- <!-- Uniform horizontal and vertical scaling. -->
+ <!-- Uniform horizontal and vertical text size scaling to fit within the
+ container -->
<enum name="uniform" value="1" />
</attr>
- <!-- Specify the auto-size step size if <code>autoSizeText</code> is set to
- <code>xy</code>. The default is 1px. Overwrites
+ <!-- Specify the auto-size step size if <code>autoSizeTextType</code> is set to
+ <code>uniform</code>. The default is 1px. Overwrites
<code>autoSizePresetSizes</code> if set. -->
<attr name="autoSizeStepGranularity" format="dimension" />
- <!-- Array of dimensions to be used in conjunction with
- <code>autoSizeText</code> set to <code>xy</code>. Overwrites
+ <!-- Resource array of dimensions to be used in conjunction with
+ <code>autoSizeTextType</code> set to <code>uniform</code>. Overrides
<code>autoSizeStepGranularity</code> if set. -->
<attr name="autoSizePresetSizes"/>
<!-- The minimum text size constraint to be used when auto-sizing text -->
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index e5660b5..01737e7 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2765,7 +2765,7 @@
<public name="font" />
<public name="fontWeight" />
<public name="tooltipText" />
- <public name="autoSizeText" />
+ <public name="autoSizeTextType" />
<public name="autoSizeStepGranularity" />
<public name="autoSizePresetSizes" />
<public name="autoSizeMinTextSize" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 6abc009..b0c532c 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4510,11 +4510,22 @@
<!-- Accessibility string used for describing the button in time picker that changes the dialog to circular clock mode. [CHAR LIMIT=NONE] -->
<string name="time_picker_radial_mode_description">Switch to clock mode for the time input.</string>
- <!-- Title for the auto-fill save dialog shown when the user entered savable text [CHAR LIMIT=NONE] -->
+ <!-- Title for the auto-fill save dialog shown when the the contents of the activity can be saved
+ by an auto-fill service, but the service does not know what the activity represents [CHAR LIMIT=NONE] -->
<string name="autofill_save_title">Save to <xliff:g id="label" example="MyPass">%1$s</xliff:g>?</string>
+ <!-- Title for the auto-fill save dialog shown when the the contents of the activity can be saved
+ by an auto-fill service, and the service does knows what the activity represents (for example, credit card info) [CHAR LIMIT=NONE] -->
+ <string name="autofill_save_title_with_type">Save <xliff:g id="type" example="Credit Card">%1$s</xliff:g> to <xliff:g id="label" example="MyPass">%2$s</xliff:g>?</string>
<!-- Label for the auto-fill save button [CHAR LIMIT=NONE] -->
<string name="autofill_save_yes">Save</string>
<!-- Label for the auto-fill cancel button [CHAR LIMIT=NONE] -->
<string name="autofill_save_no">No thanks</string>
+ <!-- Label for the type of data being saved for auto-fill when it represent user credentials with a password [CHAR LIMIT=NONE] -->
+ <string name="autofill_save_type_password">password</string>
+ <!-- Label for the type of data being saved for auto-fill when it represent an address (street, city, etc.) [CHAR LIMIT=NONE] -->
+ <string name="autofill_save_type_address">address</string>
+ <!-- Label for the type of data being saved for auto-fill when it represents a credit card [CHAR LIMIT=NONE] -->
+ <string name="autofill_save_type_credit_card">credit card</string>
+
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 49216d9..6995d9a 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2838,12 +2838,17 @@
<java-symbol type="layout" name="autofill_save"/>
<java-symbol type="layout" name="autofill_dataset_picker"/>
<java-symbol type="id" name="autofill_save_title" />
+ <java-symbol type="id" name="autofill_save_subtitle" />
<java-symbol type="id" name="autofill_save_no" />
<java-symbol type="id" name="autofill_save_yes" />
<java-symbol type="id" name="autofill_save_close" />
<java-symbol type="string" name="autofill_save_title" />
+ <java-symbol type="string" name="autofill_save_title_with_type" />
<java-symbol type="string" name="autofill_save_yes" />
<java-symbol type="string" name="autofill_save_no" />
+ <java-symbol type="string" name="autofill_save_type_password" />
+ <java-symbol type="string" name="autofill_save_type_address" />
+ <java-symbol type="string" name="autofill_save_type_credit_card" />
<!-- Accessibility fingerprint gestures -->
<java-symbol type="string" name="capability_title_canCaptureFingerprintGestures" />
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
index 1080a9f..3dfecc6 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
@@ -16,6 +16,17 @@
package com.android.internal.app;
+import android.app.Instrumentation;
+import android.content.ComponentName;
+import android.content.IntentFilter;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.LauncherApps;
+import android.content.pm.PackageManager;
+import android.content.pm.ShortcutInfo;
+import android.content.pm.ShortcutManager;
+import android.graphics.drawable.Icon;
+import android.os.SystemClock;
import com.android.internal.R;
import com.android.internal.app.ResolverActivity.ResolvedComponentInfo;
@@ -48,25 +59,31 @@
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
-import static org.mockito.Mockito.when;
-import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.isA;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
/**
* Chooser activity instrumentation tests
*/
@RunWith(AndroidJUnit4.class)
public class ChooserActivityTest {
+ private Instrumentation instrumentation;
+
+ @Before
+ public void setUp() {
+ instrumentation = InstrumentationRegistry.getInstrumentation();
+ sOverrides.reset();
+ }
+
@Rule
public ActivityTestRule<ChooserWrapperActivity> mActivityRule =
new ActivityTestRule<>(ChooserWrapperActivity.class, false,
false);
- @Before
- public void cleanOverrideData() {
- sOverrides.reset();
- }
-
@Test
public void customTitle() throws InterruptedException {
Intent sendIntent = createSendImageIntent();
@@ -235,7 +252,6 @@
chosen[0] = targetInfo.getResolveInfo();
return true;
};
-
// Make a stable copy of the components as the original list may be modified
List<ResolvedComponentInfo> stableCopy =
createResolvedComponentsForTestWithOtherProfile(2);
@@ -324,6 +340,32 @@
assertThat(chosen[0], is(toChoose));
}
+ public void pushedChooserTarget() {
+ ResolveInfo[] chosen = new ResolveInfo[1];
+ sOverrides.onSafelyStartCallback = targetInfo -> {
+ chosen[0] = targetInfo.getResolveInfo();
+ return true;
+ };
+
+ setChooserShortcuts(1);
+ List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
+ when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
+ Mockito.anyBoolean(),
+ Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
+
+ Intent sendIntent = createSendImageIntent();
+ final ChooserWrapperActivity activity = mActivityRule
+ .launchActivity(Intent.createChooser(sendIntent, null));
+
+ waitForIdle();
+
+ onView(withText("short chooser label 0"))
+ .perform(click());
+ waitForIdle();
+ assertThat(chosen[0].resolvePackageName,
+ is(ResolverDataProvider.createActivityInfo(0).packageName));
+ }
+
private Intent createSendImageIntent() {
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
@@ -371,4 +413,48 @@
}
return packageStats.mChooserCounts.get(action).getOrDefault(annotation, 0);
}
+
+ private void setChooserShortcuts(int numShortcuts) {
+ ArrayList<ShortcutInfo> shortcuts = new ArrayList<>();
+ for (int i = 0; i < numShortcuts; i++) {
+ shortcuts.add(makeShortcut(i));
+ }
+ when(sOverrides.launcherApps.getShortcuts(
+ Mockito.isA(LauncherApps.ShortcutQuery.class),
+ Mockito.eq(UserHandle.SYSTEM)))
+ .thenReturn(shortcuts);
+ }
+
+ private ShortcutInfo makeShortcut(int i) {
+ try {
+ IntentFilter filter = new IntentFilter(Intent.ACTION_SEND, "image/jpeg");
+
+ ComponentName component = new ComponentName("foo.bar", "foo.bar" + ".MainActivity");
+ ShortcutInfo.Builder b = new ShortcutInfo.Builder(instrumentation.getContext(), "" + i)
+ .setActivity(component)
+ .setShortLabel("short chooser label " + i)
+ .setLongLabel("long chooser label" + i)
+ .setRank(i)
+ .setIntent(createSendImageIntent())
+ .setIcon(Icon.createWithResource(instrumentation.getContext(),
+ android.R.drawable.ic_menu_add))
+ .addChooserIntentFilter(
+ filter,
+ component);
+
+ sOverrides.createPackageManager = pm -> {
+ final PackageManager spied = spy(pm);
+ try {
+ doAnswer(invocation -> ResolverDataProvider.createActivityInfo(i))
+ .when(spied).getActivityInfo(
+ Mockito.isA(ComponentName.class), Mockito.anyInt());
+ } catch (Exception e) {
+ // this is ok, just not found
+ e.printStackTrace();
+ }
+ return spied;
+ };
+ return b.build();
+ } catch (Exception e) {return null;}
+ }
}
\ No newline at end of file
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
index c446f3c..0dac260 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
@@ -18,6 +18,7 @@
import android.app.usage.UsageStatsManager;
import android.content.Context;
+import android.content.pm.LauncherApps;
import android.content.pm.PackageManager;
import java.util.function.Function;
@@ -74,6 +75,11 @@
return super.getPackageManager();
}
+ @Override
+ public LauncherApps getLauncherApps() {
+ return sOverrides.launcherApps;
+ }
+
/**
* We cannot directly mock the activity created since instrumentation creates it.
* <p>
@@ -82,6 +88,7 @@
static class OverrideData {
@SuppressWarnings("Since15")
public Function<PackageManager, PackageManager> createPackageManager;
+ public LauncherApps launcherApps;
public Function<TargetInfo, Boolean> onSafelyStartCallback;
public ResolverListController resolverListController;
public Boolean isVoiceInteraction;
@@ -90,6 +97,7 @@
onSafelyStartCallback = null;
isVoiceInteraction = null;
createPackageManager = null;
+ launcherApps = mock(LauncherApps.class);
resolverListController = mock(ResolverListController.class);
}
}
diff --git a/graphics/java/android/graphics/Color.java b/graphics/java/android/graphics/Color.java
index ff21cac..33d19d4 100644
--- a/graphics/java/android/graphics/Color.java
+++ b/graphics/java/android/graphics/Color.java
@@ -1023,9 +1023,9 @@
"The color space must use a color model with at most 3 components");
}
- @HalfFloat short r = Half.valueOf(red);
- @HalfFloat short g = Half.valueOf(green);
- @HalfFloat short b = Half.valueOf(blue);
+ @HalfFloat short r = Half.toHalf(red);
+ @HalfFloat short g = Half.toHalf(green);
+ @HalfFloat short b = Half.toHalf(blue);
int a = (int) (Math.max(0.0f, Math.min(alpha, 1.0f)) * 1023.0f + 0.5f);
diff --git a/graphics/java/android/graphics/drawable/ShapeDrawable.java b/graphics/java/android/graphics/drawable/ShapeDrawable.java
index fe82a93..a24b970 100644
--- a/graphics/java/android/graphics/drawable/ShapeDrawable.java
+++ b/graphics/java/android/graphics/drawable/ShapeDrawable.java
@@ -16,9 +16,11 @@
package android.graphics.drawable;
+import android.annotation.NonNull;
import android.content.pm.ActivityInfo.Config;
import android.content.res.ColorStateList;
import android.content.res.Resources;
+import android.content.res.Resources.Theme;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
@@ -31,10 +33,10 @@
import android.graphics.Rect;
import android.graphics.Shader;
import android.graphics.drawable.shapes.Shape;
-import android.content.res.Resources.Theme;
import android.util.AttributeSet;
import com.android.internal.R;
+
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -69,7 +71,7 @@
* @attr ref android.R.styleable#ShapeDrawable_height
*/
public class ShapeDrawable extends Drawable {
- private ShapeState mShapeState;
+ private @NonNull ShapeState mShapeState;
private PorterDuffColorFilter mTintFilter;
private boolean mMutated;
@@ -77,7 +79,7 @@
* ShapeDrawable constructor.
*/
public ShapeDrawable() {
- this(new ShapeState(null), null);
+ this(new ShapeState(), null);
}
/**
@@ -86,7 +88,7 @@
* @param s the Shape that this ShapeDrawable should be
*/
public ShapeDrawable(Shape s) {
- this(new ShapeState(null), null);
+ this(new ShapeState(), null);
mShapeState.mShape = s;
}
@@ -402,7 +404,7 @@
}
// Update local properties.
- updateLocalState(r);
+ updateLocalState();
}
@Override
@@ -426,7 +428,7 @@
}
// Update local properties.
- updateLocalState(t.getResources());
+ updateLocalState();
}
private void updateStateFromTypedArray(TypedArray a) {
@@ -447,10 +449,10 @@
dither = a.getBoolean(R.styleable.ShapeDrawable_dither, dither);
paint.setDither(dither);
- setIntrinsicWidth((int) a.getDimension(
- R.styleable.ShapeDrawable_width, state.mIntrinsicWidth));
- setIntrinsicHeight((int) a.getDimension(
- R.styleable.ShapeDrawable_height, state.mIntrinsicHeight));
+ state.mIntrinsicWidth = (int) a.getDimension(
+ R.styleable.ShapeDrawable_width, state.mIntrinsicWidth);
+ state.mIntrinsicHeight = (int) a.getDimension(
+ R.styleable.ShapeDrawable_height, state.mIntrinsicHeight);
final int tintMode = a.getInt(R.styleable.ShapeDrawable_tintMode, -1);
if (tintMode != -1) {
@@ -494,21 +496,8 @@
@Override
public Drawable mutate() {
if (!mMutated && super.mutate() == this) {
- if (mShapeState.mPaint != null) {
- mShapeState.mPaint = new Paint(mShapeState.mPaint);
- } else {
- mShapeState.mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
- }
- if (mShapeState.mPadding != null) {
- mShapeState.mPadding = new Rect(mShapeState.mPadding);
- } else {
- mShapeState.mPadding = new Rect();
- }
- try {
- mShapeState.mShape = mShapeState.mShape.clone();
- } catch (CloneNotSupportedException e) {
- return null;
- }
+ mShapeState = new ShapeState(mShapeState);
+ updateLocalState();
mMutated = true;
}
return this;
@@ -525,12 +514,13 @@
/**
* Defines the intrinsic properties of this ShapeDrawable's Shape.
*/
- final static class ShapeState extends ConstantState {
- int[] mThemeAttrs;
+ static final class ShapeState extends ConstantState {
+ final @NonNull Paint mPaint;
+
@Config int mChangingConfigurations;
- Paint mPaint;
+ int[] mThemeAttrs;
Shape mShape;
- ColorStateList mTint = null;
+ ColorStateList mTint;
Mode mTintMode = DEFAULT_TINT_MODE;
Rect mPadding;
int mIntrinsicWidth;
@@ -538,21 +528,43 @@
int mAlpha = 255;
ShaderFactory mShaderFactory;
- ShapeState(ShapeState orig) {
- if (orig != null) {
- mThemeAttrs = orig.mThemeAttrs;
- mPaint = orig.mPaint;
- mShape = orig.mShape;
- mTint = orig.mTint;
- mTintMode = orig.mTintMode;
- mPadding = orig.mPadding;
- mIntrinsicWidth = orig.mIntrinsicWidth;
- mIntrinsicHeight = orig.mIntrinsicHeight;
- mAlpha = orig.mAlpha;
- mShaderFactory = orig.mShaderFactory;
- } else {
- mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ /**
+ * Constructs a new ShapeState.
+ */
+ ShapeState() {
+ mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ }
+
+ /**
+ * Constructs a new ShapeState that contains a deep copy of the
+ * specified ShapeState.
+ *
+ * @param orig the state to create a deep copy of
+ */
+ ShapeState(@NonNull ShapeState orig) {
+ mChangingConfigurations = orig.mChangingConfigurations;
+ mPaint = new Paint(orig.mPaint);
+ mThemeAttrs = orig.mThemeAttrs;
+ if (mShape != null) {
+ try {
+ mShape = orig.mShape.clone();
+ } catch (CloneNotSupportedException e) {
+ // Well, at least we tried.
+ mShape = orig.mShape;
+ }
}
+ mTint = orig.mTint;
+ mTintMode = orig.mTintMode;
+ if (orig.mPadding != null) {
+ mPadding = new Rect(orig.mPadding);
+ }
+ mIntrinsicWidth = orig.mIntrinsicWidth;
+ mIntrinsicHeight = orig.mIntrinsicHeight;
+ mAlpha = orig.mAlpha;
+
+ // We don't have any way to clone a shader factory, so hopefully
+ // this class doesn't contain any local state.
+ mShaderFactory = orig.mShaderFactory;
}
@Override
@@ -585,7 +597,7 @@
private ShapeDrawable(ShapeState state, Resources res) {
mShapeState = state;
- updateLocalState(res);
+ updateLocalState();
}
/**
@@ -593,7 +605,7 @@
* after significant state changes, e.g. from the One True Constructor and
* after inflating or applying a theme.
*/
- private void updateLocalState(Resources res) {
+ private void updateLocalState() {
mTintFilter = updateTintFilter(mTintFilter, mShapeState.mTint, mShapeState.mTintMode);
}
@@ -617,8 +629,4 @@
*/
public abstract Shader resize(int width, int height);
}
-
- // other subclass could wack the Shader's localmatrix based on the
- // resize params (e.g. scaletofit, etc.). This could be used to scale
- // a bitmap to fill the bounds without needing any other special casing.
}
diff --git a/graphics/java/android/graphics/drawable/shapes/ArcShape.java b/graphics/java/android/graphics/drawable/shapes/ArcShape.java
index c4b239f..85ba0a9 100644
--- a/graphics/java/android/graphics/drawable/shapes/ArcShape.java
+++ b/graphics/java/android/graphics/drawable/shapes/ArcShape.java
@@ -21,31 +21,47 @@
import android.graphics.Paint;
/**
- * Creates an arc shape. The arc shape starts at a specified
- * angle and sweeps clockwise, drawing slices of pie.
- * The arc can be drawn to a Canvas with its own draw() method,
- * but more graphical control is available if you instead pass
- * the ArcShape to a {@link android.graphics.drawable.ShapeDrawable}.
+ * Creates an arc shape. The arc shape starts at a specified angle and sweeps
+ * clockwise, drawing slices of pie.
+ * <p>
+ * The arc can be drawn to a {@link Canvas} with its own
+ * {@link #draw(Canvas, Paint)} method, but more graphical control is available
+ * if you instead pass the ArcShape to a
+ * {@link android.graphics.drawable.ShapeDrawable}.
*/
public class ArcShape extends RectShape {
- private float mStart;
- private float mSweep;
-
+ private final float mStartAngle;
+ private final float mSweepAngle;
+
/**
- * ArcShape constructor.
- *
+ * ArcShape constructor.
+ *
* @param startAngle the angle (in degrees) where the arc begins
- * @param sweepAngle the sweep angle (in degrees). Anything equal to or
+ * @param sweepAngle the sweep angle (in degrees). Anything equal to or
* greater than 360 results in a complete circle/oval.
*/
public ArcShape(float startAngle, float sweepAngle) {
- mStart = startAngle;
- mSweep = sweepAngle;
+ mStartAngle = startAngle;
+ mSweepAngle = sweepAngle;
}
-
+
+ /**
+ * @return the angle (in degrees) where the arc begins
+ */
+ public final float getStartAngle() {
+ return mStartAngle;
+ }
+
+ /**
+ * @return the sweep angle (in degrees)
+ */
+ public final float getSweepAngle() {
+ return mSweepAngle;
+ }
+
@Override
public void draw(Canvas canvas, Paint paint) {
- canvas.drawArc(rect(), mStart, mSweep, true, paint);
+ canvas.drawArc(rect(), mStartAngle, mSweepAngle, true, paint);
}
@Override
@@ -53,5 +69,10 @@
// Since we don't support concave outlines, arc shape does not attempt
// to provide an outline.
}
+
+ @Override
+ public ArcShape clone() throws CloneNotSupportedException {
+ return (ArcShape) super.clone();
+ }
}
diff --git a/graphics/java/android/graphics/drawable/shapes/OvalShape.java b/graphics/java/android/graphics/drawable/shapes/OvalShape.java
index c9473f0..fb87d28 100644
--- a/graphics/java/android/graphics/drawable/shapes/OvalShape.java
+++ b/graphics/java/android/graphics/drawable/shapes/OvalShape.java
@@ -22,7 +22,8 @@
import android.graphics.RectF;
/**
- * Defines an oval shape.
+ * Defines an oval shape.
+ * <p>
* The oval can be drawn to a Canvas with its own draw() method,
* but more graphical control is available if you instead pass
* the OvalShape to a {@link android.graphics.drawable.ShapeDrawable}.
@@ -42,5 +43,10 @@
outline.setOval((int) Math.ceil(rect.left), (int) Math.ceil(rect.top),
(int) Math.floor(rect.right), (int) Math.floor(rect.bottom));
}
+
+ @Override
+ public OvalShape clone() throws CloneNotSupportedException {
+ return (OvalShape) super.clone();
+ }
}
diff --git a/graphics/java/android/graphics/drawable/shapes/PathShape.java b/graphics/java/android/graphics/drawable/shapes/PathShape.java
index 30b7347..ce5552b 100644
--- a/graphics/java/android/graphics/drawable/shapes/PathShape.java
+++ b/graphics/java/android/graphics/drawable/shapes/PathShape.java
@@ -16,41 +16,44 @@
package android.graphics.drawable.shapes;
+import android.annotation.NonNull;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
/**
* Creates geometric paths, utilizing the {@link android.graphics.Path} class.
+ * <p>
* The path can be drawn to a Canvas with its own draw() method,
* but more graphical control is available if you instead pass
* the PathShape to a {@link android.graphics.drawable.ShapeDrawable}.
*/
public class PathShape extends Shape {
- private Path mPath;
- private float mStdWidth;
- private float mStdHeight;
-
- private float mScaleX; // cached from onResize
- private float mScaleY; // cached from onResize
-
+ private final float mStdWidth;
+ private final float mStdHeight;
+
+ private Path mPath;
+
+ private float mScaleX; // cached from onResize
+ private float mScaleY; // cached from onResize
+
/**
* PathShape constructor.
- *
- * @param path a Path that defines the geometric paths for this shape
- * @param stdWidth the standard width for the shape. Any changes to the
- * width with resize() will result in a width scaled based
- * on the new width divided by this width.
- * @param stdHeight the standard height for the shape. Any changes to the
- * height with resize() will result in a height scaled based
- * on the new height divided by this height.
+ *
+ * @param path a Path that defines the geometric paths for this shape
+ * @param stdWidth the standard width for the shape. Any changes to the
+ * width with resize() will result in a width scaled based
+ * on the new width divided by this width.
+ * @param stdHeight the standard height for the shape. Any changes to the
+ * height with resize() will result in a height scaled based
+ * on the new height divided by this height.
*/
- public PathShape(Path path, float stdWidth, float stdHeight) {
+ public PathShape(@NonNull Path path, float stdWidth, float stdHeight) {
mPath = path;
mStdWidth = stdWidth;
mStdHeight = stdHeight;
}
-
+
@Override
public void draw(Canvas canvas, Paint paint) {
canvas.save();
@@ -58,7 +61,7 @@
canvas.drawPath(mPath, paint);
canvas.restore();
}
-
+
@Override
protected void onResize(float width, float height) {
mScaleX = width / mStdWidth;
@@ -67,7 +70,7 @@
@Override
public PathShape clone() throws CloneNotSupportedException {
- PathShape shape = (PathShape) super.clone();
+ final PathShape shape = (PathShape) super.clone();
shape.mPath = new Path(mPath);
return shape;
}
diff --git a/graphics/java/android/graphics/drawable/shapes/RectShape.java b/graphics/java/android/graphics/drawable/shapes/RectShape.java
index 04cf293..e339a21 100644
--- a/graphics/java/android/graphics/drawable/shapes/RectShape.java
+++ b/graphics/java/android/graphics/drawable/shapes/RectShape.java
@@ -23,6 +23,7 @@
/**
* Defines a rectangle shape.
+ * <p>
* The rectangle can be drawn to a Canvas with its own draw() method,
* but more graphical control is available if you instead pass
* the RectShape to a {@link android.graphics.drawable.ShapeDrawable}.
diff --git a/graphics/java/android/graphics/drawable/shapes/RoundRectShape.java b/graphics/java/android/graphics/drawable/shapes/RoundRectShape.java
index e5253b8..f5cbb24 100644
--- a/graphics/java/android/graphics/drawable/shapes/RoundRectShape.java
+++ b/graphics/java/android/graphics/drawable/shapes/RoundRectShape.java
@@ -16,6 +16,7 @@
package android.graphics.drawable.shapes;
+import android.annotation.Nullable;
import android.graphics.Canvas;
import android.graphics.Outline;
import android.graphics.Paint;
@@ -24,40 +25,41 @@
/**
* Creates a rounded-corner rectangle. Optionally, an inset (rounded) rectangle
- * can be included (to make a sort of "O" shape).
+ * can be included (to make a sort of "O" shape).
+ * <p>
* The rounded rectangle can be drawn to a Canvas with its own draw() method,
* but more graphical control is available if you instead pass
* the RoundRectShape to a {@link android.graphics.drawable.ShapeDrawable}.
*/
public class RoundRectShape extends RectShape {
private float[] mOuterRadii;
- private RectF mInset;
+ private RectF mInset;
private float[] mInnerRadii;
private RectF mInnerRect;
- private Path mPath; // this is what we actually draw
+ private Path mPath; // this is what we actually draw
/**
* RoundRectShape constructor.
+ * <p>
* Specifies an outer (round)rect and an optional inner (round)rect.
*
* @param outerRadii An array of 8 radius values, for the outer roundrect.
- * The first two floats are for the
- * top-left corner (remaining pairs correspond clockwise).
- * For no rounded corners on the outer rectangle,
- * pass null.
- * @param inset A RectF that specifies the distance from the inner
- * rect to each side of the outer rect.
- * For no inner, pass null.
+ * The first two floats are for the top-left corner
+ * (remaining pairs correspond clockwise). For no rounded
+ * corners on the outer rectangle, pass {@code null}.
+ * @param inset A RectF that specifies the distance from the inner
+ * rect to each side of the outer rect. For no inner, pass
+ * {@code null}.
* @param innerRadii An array of 8 radius values, for the inner roundrect.
- * The first two floats are for the
- * top-left corner (remaining pairs correspond clockwise).
- * For no rounded corners on the inner rectangle,
- * pass null.
- * If inset parameter is null, this parameter is ignored.
+ * The first two floats are for the top-left corner
+ * (remaining pairs correspond clockwise). For no rounded
+ * corners on the inner rectangle, pass {@code null}. If
+ * inset parameter is {@code null}, this parameter is
+ * ignored.
*/
- public RoundRectShape(float[] outerRadii, RectF inset,
- float[] innerRadii) {
+ public RoundRectShape(@Nullable float[] outerRadii, @Nullable RectF inset,
+ @Nullable float[] innerRadii) {
if (outerRadii != null && outerRadii.length < 8) {
throw new ArrayIndexOutOfBoundsException("outer radii must have >= 8 values");
}
@@ -97,8 +99,7 @@
final RectF rect = rect();
outline.setRoundRect((int) Math.ceil(rect.left), (int) Math.ceil(rect.top),
- (int) Math.floor(rect.right), (int) Math.floor(rect.bottom),
- radius);
+ (int) Math.floor(rect.right), (int) Math.floor(rect.bottom), radius);
}
@Override
@@ -128,7 +129,7 @@
@Override
public RoundRectShape clone() throws CloneNotSupportedException {
- RoundRectShape shape = (RoundRectShape) super.clone();
+ final RoundRectShape shape = (RoundRectShape) super.clone();
shape.mOuterRadii = mOuterRadii != null ? mOuterRadii.clone() : null;
shape.mInnerRadii = mInnerRadii != null ? mInnerRadii.clone() : null;
shape.mInset = new RectF(mInset);
diff --git a/graphics/java/android/graphics/drawable/shapes/Shape.java b/graphics/java/android/graphics/drawable/shapes/Shape.java
index eab8666..30b28f3 100644
--- a/graphics/java/android/graphics/drawable/shapes/Shape.java
+++ b/graphics/java/android/graphics/drawable/shapes/Shape.java
@@ -23,21 +23,25 @@
/**
* Defines a generic graphical "shape."
- * Any Shape can be drawn to a Canvas with its own draw() method,
- * but more graphical control is available if you instead pass
- * it to a {@link android.graphics.drawable.ShapeDrawable}.
+ * <p>
+ * Any Shape can be drawn to a Canvas with its own draw() method, but more
+ * graphical control is available if you instead pass it to a
+ * {@link android.graphics.drawable.ShapeDrawable}.
+ * <p>
+ * Custom Shape classes must implement {@link #clone()} and return an instance
+ * of the custom Shape class.
*/
public abstract class Shape implements Cloneable {
private float mWidth;
private float mHeight;
-
+
/**
* Returns the width of the Shape.
*/
public final float getWidth() {
return mWidth;
}
-
+
/**
* Returns the height of the Shape.
*/
@@ -46,9 +50,10 @@
}
/**
- * Draw this shape into the provided Canvas, with the provided Paint.
+ * Draws this shape into the provided Canvas, with the provided Paint.
+ * <p>
* Before calling this, you must call {@link #resize(float,float)}.
- *
+ *
* @param canvas the Canvas within which this shape should be drawn
* @param paint the Paint object that defines this shape's characteristics
*/
@@ -56,8 +61,9 @@
/**
* Resizes the dimensions of this shape.
+ * <p>
* Must be called before {@link #draw(Canvas,Paint)}.
- *
+ *
* @param width the width of the shape (in pixels)
* @param height the height of the shape (in pixels)
*/
@@ -74,30 +80,34 @@
onResize(width, height);
}
}
-
+
/**
* Checks whether the Shape is opaque.
- * Default impl returns true. Override if your subclass can be opaque.
- *
- * @return true if any part of the drawable is <em>not</em> opaque.
+ * <p>
+ * Default impl returns {@code true}. Override if your subclass can be
+ * opaque.
+ *
+ * @return true if any part of the drawable is <em>not</em> opaque.
*/
public boolean hasAlpha() {
return true;
}
-
+
/**
* Callback method called when {@link #resize(float,float)} is executed.
- *
+ *
* @param width the new width of the Shape
* @param height the new height of the Shape
*/
protected void onResize(float width, float height) {}
/**
- * Compute the Outline of the shape and return it in the supplied Outline
- * parameter. The default implementation does nothing and {@code outline} is not changed.
+ * Computes the Outline of the shape and return it in the supplied Outline
+ * parameter. The default implementation does nothing and {@code outline}
+ * is not changed.
*
- * @param outline The Outline to be populated with the result. Should not be null.
+ * @param outline the Outline to be populated with the result. Must be
+ * non-{@code null}.
*/
public void getOutline(@NonNull Outline outline) {}
@@ -105,5 +115,4 @@
public Shape clone() throws CloneNotSupportedException {
return (Shape) super.clone();
}
-
}
diff --git a/keystore/java/android/security/IKeyChainAliasCallback.aidl b/keystore/java/android/security/IKeyChainAliasCallback.aidl
index 1ea9521..b9d3753 100644
--- a/keystore/java/android/security/IKeyChainAliasCallback.aidl
+++ b/keystore/java/android/security/IKeyChainAliasCallback.aidl
@@ -20,7 +20,7 @@
*
* @hide
*/
-interface IKeyChainAliasCallback {
+oneway interface IKeyChainAliasCallback {
void alias(String alias);
}
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index 4791cf0..e77c00b 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -53,6 +53,7 @@
* time-interval between key frames.
* Float support added in {@link android.os.Build.VERSION_CODES#N_MR1}</td></tr>
* <tr><td>{@link #KEY_INTRA_REFRESH_PERIOD}</td><td>Integer</td><td><b>encoder-only</b>, optional</td></tr>
+ * <tr><td>{@link #KEY_LATENCY}</td><td>Integer</td><td><b>encoder-only</b>, optional</td></tr>
* <tr><td>{@link #KEY_MAX_WIDTH}</td><td>Integer</td><td><b>decoder-only</b>, optional, max-resolution width</td></tr>
* <tr><td>{@link #KEY_MAX_HEIGHT}</td><td>Integer</td><td><b>decoder-only</b>, optional, max-resolution height</td></tr>
* <tr><td>{@link #KEY_REPEAT_PREVIOUS_FRAME_AFTER}</td><td>Long</td><td><b>encoder in surface-mode
@@ -577,6 +578,18 @@
public static final String KEY_LEVEL = "level";
/**
+ * An optional key describing the desired encoder latency in frames. This is an optional
+ * parameter that applies only to video encoders. If encoder supports it, it should ouput
+ * at least one output frame after being queued the specified number of frames. This key
+ * is ignored if the video encoder does not support the latency feature. Use the output
+ * format to verify that this feature was enabled and the actual value used by the encoder.
+ * <p>
+ * If the key is not specified, the default latency will be implenmentation specific.
+ * The associated value is an integer.
+ */
+ public static final String KEY_LATENCY = "latency";
+
+ /**
* A key describing the desired clockwise rotation on an output surface.
* This key is only used when the codec is configured using an output surface.
* The associated value is an integer, representing degrees. Supported values
diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java
index 12d0c03..1df626f 100644
--- a/packages/Shell/src/com/android/shell/BugreportProgressService.java
+++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java
@@ -44,6 +44,7 @@
import libcore.io.Streams;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.app.ChooserActivity;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.util.FastPrintWriter;
@@ -943,8 +944,13 @@
}
static void sendShareIntent(Context context, Intent intent) {
- context.startActivity(Intent.createChooser(intent,
- context.getResources().getText(R.string.bugreport_intent_chooser_title)));
+ final Intent chooserIntent = Intent.createChooser(intent,
+ context.getResources().getText(R.string.bugreport_intent_chooser_title));
+
+ // Since we may be launched behind lockscreen, make sure that ChooserActivity doesn't finish
+ // itself in onStop.
+ chooserIntent.putExtra(ChooserActivity.EXTRA_PRIVATE_RETAIN_IN_ON_STOP, true);
+ context.startActivity(chooserIntent);
}
/**
diff --git a/packages/SystemUI/res/drawable/ic_qs_network_logging.xml b/packages/SystemUI/res/drawable/ic_qs_network_logging.xml
index 87b5a14..7bdf50c 100644
--- a/packages/SystemUI/res/drawable/ic_qs_network_logging.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_network_logging.xml
@@ -20,8 +20,7 @@
android:width="12.0dp"
android:height="12.0dp"
android:viewportWidth="24.0"
- android:viewportHeight="24.0"
- android:tint="#4DFFFFFF" >
+ android:viewportHeight="24.0">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M2,24v-4h12v4H2z M2,16v-4h20v4H2z M5,7 12,0 19,7 14,7 14,15 10,15 10,7z"/>
diff --git a/packages/SystemUI/res/drawable/qs_ic_wifi_lock.xml b/packages/SystemUI/res/drawable/qs_ic_wifi_lock.xml
index b7da30b..bf405fa 100644
--- a/packages/SystemUI/res/drawable/qs_ic_wifi_lock.xml
+++ b/packages/SystemUI/res/drawable/qs_ic_wifi_lock.xml
@@ -20,10 +20,10 @@
android:viewportHeight="72.0"
android:tint="?android:attr/textColorPrimary">
<group
- android:translateX="52.0"
- android:translateY="42.0" >
+ android:translateX="28.0"
+ android:translateY="10.5" >
<path
- android:fillColor="#FFFFFFFF"
- android:pathData="M18.0,8.0l-1.0,0.0L17.0,6.0c0.0,-2.76 -2.24,-5.0 -5.0,-5.0S7.0,3.24 7.0,6.0l0.0,2.0L6.0,8.0c-1.1,0.0 -2.0,0.9 -2.0,2.0l0.0,10.0c0.0,1.0 0.9,2.0 2.0,2.0l12.0,0.0c1.1,0.0 2.0,-0.9 2.0,-2.0L20.0,10.0c0.0,-1.1 -0.9,-2.0 -2.0,-2.0zm-6.0,9.0c-1.1,0.0 -2.0,-0.9 -2.0,-2.0s0.9,-2.0 2.0,-2.0 2.0,0.9 2.0,2.0 -0.9,2.0 -2.0,2.0zm3.1,-9.0L8.9,8.0L8.9,6.0c0.0,-1.71 1.39,-3.1 3.1,-3.1 1.71,0.0 3.1,1.39 3.1,3.1l0.0,2.0z"/>
+ android:pathData="M36 16l-2 0 0 -4C34 6.48 29.52 2 24 2 18.48 2 14 6.48 14 12l0 4 -2 0c-2.21 0 -4 1.79 -4 4l0 20c0 2.21 1.79 4 4 4l24 0c2.21 0 4 -1.79 4 -4l0 -20c0 -2.21 -1.79 -4 -4 -4zM24 34c-2.21 0 -4 -1.79 -4 -4 0 -2.21 1.79 -4 4 -4 2.21 0 4 1.79 4 4 0 2.21 -1.79 4 -4 4zm6.2 -18l-12.4 0 0 -4c0 -3.42 2.78 -6.2 6.2 -6.2 3.42 0 6.2 2.78 6.2 6.2l0 4z"
+ android:fillColor="#FFFFFF" />
</group>
</vector>
diff --git a/packages/SystemUI/res/layout/qs_detail_item.xml b/packages/SystemUI/res/layout/qs_detail_item.xml
index 6edf135..6544f0d 100644
--- a/packages/SystemUI/res/layout/qs_detail_item.xml
+++ b/packages/SystemUI/res/layout/qs_detail_item.xml
@@ -63,7 +63,6 @@
android:focusable="true"
android:scaleType="center"
android:contentDescription="@*android:string/media_route_controller_disconnect"
- android:tint="?android:attr/textColorPrimary"
- android:src="@drawable/ic_qs_cancel" />
+ android:tint="?android:attr/textColorPrimary" />
</LinearLayout>
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
index 20866c0..8f7a81c 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
@@ -337,12 +337,11 @@
* Moves the PIPed activity to the fullscreen and closes PIP system UI.
*/
void movePipToFullscreen() {
- mState = STATE_NO_PIP;
mPipTaskId = TASK_ID_NO_PIP;
for (int i = mListeners.size() - 1; i >= 0; --i) {
mListeners.get(i).onMoveToFullscreen();
}
- resizePinnedStack(mState);
+ resizePinnedStack(STATE_NO_PIP);
updatePipVisibility(false);
}
@@ -388,6 +387,7 @@
if (DEBUG) Log.d(TAG, "resizePinnedStack() state=" + state);
boolean wasRecentsShown =
(mState == STATE_PIP_RECENTS || mState == STATE_PIP_RECENTS_FOCUSED);
+ boolean wasStateNoPip = (mState == STATE_NO_PIP);
mState = state;
for (int i = mListeners.size() - 1; i >= 0; --i) {
mListeners.get(i).onPipResizeAboutToStart();
@@ -401,6 +401,11 @@
switch (mState) {
case STATE_NO_PIP:
mCurrentPipBounds = null;
+ // If the state was already STATE_NO_PIP, then do not resize the stack below as it
+ // will not exist
+ if (wasStateNoPip) {
+ return;
+ }
break;
case STATE_PIP_MENU:
mCurrentPipBounds = mMenuModePipBounds;
@@ -418,18 +423,16 @@
mCurrentPipBounds = mPipBounds;
break;
}
- if (mCurrentPipBounds != null) {
- try {
- int animationDurationMs = -1;
- if (wasRecentsShown
- && (mState == STATE_PIP_RECENTS || mState == STATE_PIP_RECENTS_FOCUSED)) {
- animationDurationMs = mRecentsFocusChangedAnimationDurationMs;
- }
- mActivityManager.resizeStack(PINNED_STACK_ID, mCurrentPipBounds,
- true, true, true, animationDurationMs);
- } catch (RemoteException e) {
- Log.e(TAG, "resizeStack failed", e);
+ try {
+ int animationDurationMs = -1;
+ if (wasRecentsShown
+ && (mState == STATE_PIP_RECENTS || mState == STATE_PIP_RECENTS_FOCUSED)) {
+ animationDurationMs = mRecentsFocusChangedAnimationDurationMs;
}
+ mActivityManager.resizeStack(PINNED_STACK_ID, mCurrentPipBounds,
+ true, true, true, animationDurationMs);
+ } catch (RemoteException e) {
+ Log.e(TAG, "resizeStack failed", e);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDetailItems.java b/packages/SystemUI/src/com/android/systemui/qs/QSDetailItems.java
index dad8bea..65238b1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSDetailItems.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSDetailItems.java
@@ -203,16 +203,28 @@
}
}
});
- final ImageView disconnect = (ImageView) view.findViewById(android.R.id.icon2);
- disconnect.setVisibility(item.canDisconnect ? VISIBLE : GONE);
- disconnect.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- if (mCallback != null) {
- mCallback.onDetailItemDisconnect(item);
+
+ final ImageView icon2 = (ImageView) view.findViewById(android.R.id.icon2);
+ if (item.canDisconnect) {
+ icon2.setImageResource(R.drawable.ic_qs_cancel);
+ icon2.setVisibility(VISIBLE);
+ icon2.setClickable(true);
+ icon2.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (mCallback != null) {
+ mCallback.onDetailItemDisconnect(item);
+ }
}
- }
- });
+ });
+ } else if (item.icon2 != -1) {
+ icon2.setVisibility(VISIBLE);
+ icon2.setImageResource(item.icon2);
+ icon2.setClickable(false);
+ } else {
+ icon2.setVisibility(GONE);
+ }
+
return view;
}
};
@@ -245,6 +257,7 @@
public CharSequence line2;
public Object tag;
public boolean canDisconnect;
+ public int icon2 = -1;
}
public interface Callback {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
index 90a9db6..796967c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -372,9 +372,9 @@
item.icon = mWifiController.getIcon(ap);
item.line1 = ap.getSsid();
item.line2 = ap.isActive() ? ap.getSummary() : null;
- item.overlay = ap.getSecurity() != AccessPoint.SECURITY_NONE
- ? mContext.getDrawable(R.drawable.qs_ic_wifi_lock)
- : null;
+ item.icon2 = ap.getSecurity() != AccessPoint.SECURITY_NONE
+ ? R.drawable.qs_ic_wifi_lock
+ : -1;
items[i] = item;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
index 02b0113..e0dac09 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
@@ -197,6 +197,7 @@
bm.getHeight() - thumbnailData.insets.top - thumbnailData.insets.bottom);
mThumbnailData = thumbnailData;
updateThumbnailMatrix();
+ updateThumbnailPaintFilter();
} else {
mBitmapShader = null;
mDrawPaint.setShader(null);
diff --git a/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java
index 7e9cbca..bfc6e83 100644
--- a/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java
@@ -743,8 +743,9 @@
Slog.d(TAG, "finishSessionLocked(): found a change on " + id + ": "
+ state.mAutoFillValue);
}
- getUiForShowing().showSaveUi(mInfo.getServiceInfo()
- .loadLabel(mContext.getPackageManager()));
+ getUiForShowing().showSaveUi(
+ mInfo.getServiceInfo().loadLabel(mContext.getPackageManager()),
+ saveInfo);
return;
}
}
diff --git a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
index cc0baa3..949a80c 100644
--- a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
+++ b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
@@ -24,6 +24,7 @@
import android.os.IBinder;
import android.service.autofill.Dataset;
import android.service.autofill.FillResponse;
+import android.service.autofill.SaveInfo;
import android.text.TextUtils;
import android.view.autofill.AutoFillId;
import android.widget.Toast;
@@ -172,13 +173,13 @@
/**
* Shows the UI asking the user to save for auto-fill.
*/
- public void showSaveUi(@NonNull CharSequence providerLabel) {
+ public void showSaveUi(@NonNull CharSequence providerLabel, @NonNull SaveInfo info) {
mHandler.post(() -> {
if (!hasCallback()) {
return;
}
hideAllUiThread();
- mSaveUi = new SaveUi(mContext, providerLabel,
+ mSaveUi = new SaveUi(mContext, providerLabel, info,
new SaveUi.OnSaveListener() {
@Override
public void onSave() {
diff --git a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
index b7215d6..afe93c7 100644
--- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
@@ -20,6 +20,7 @@
import android.app.Dialog;
import android.content.Context;
import android.os.Handler;
+import android.service.autofill.SaveInfo;
import android.text.format.DateUtils;
import android.view.Gravity;
import android.view.Window;
@@ -50,15 +51,41 @@
private boolean mDestroyed;
- SaveUi(@NonNull Context context, @NonNull CharSequence providerLabel,
+ SaveUi(@NonNull Context context, @NonNull CharSequence providerLabel, @NonNull SaveInfo info,
@NonNull OnSaveListener listener) {
mListener = listener;
final LayoutInflater inflater = LayoutInflater.from(context);
final View view = inflater.inflate(R.layout.autofill_save, null);
- final TextView title = (TextView) view.findViewById(R.id.autofill_save_title);
- title.setText(context.getString(R.string.autofill_save_title, providerLabel));
+ final TextView titleView = (TextView) view.findViewById(R.id.autofill_save_title);
+ final String type;
+
+ switch(info.getType()) {
+ case SaveInfo.SAVE_DATA_TYPE_PASSWORD:
+ type = context.getString(R.string.autofill_save_type_password);
+ break;
+ case SaveInfo.SAVE_DATA_TYPE_ADDRESS:
+ type = context.getString(R.string.autofill_save_type_address);
+ break;
+ case SaveInfo.SAVE_DATA_TYPE_CREDIT_CARD:
+ type = context.getString(R.string.autofill_save_type_credit_card);
+ break;
+ default:
+ type = null;
+ }
+
+ final String title = (type == null)
+ ? context.getString(R.string.autofill_save_title, providerLabel)
+ : context.getString(R.string.autofill_save_title_with_type, type, providerLabel);
+
+ titleView.setText(title);
+ final CharSequence subTitle = info.getDescription();
+ if (subTitle != null) {
+ final TextView subTitleView = (TextView) view.findViewById(R.id.autofill_save_subtitle);
+ subTitleView.setText(subTitle);
+ subTitleView.setVisibility(View.VISIBLE);
+ }
final View noButton = view.findViewById(R.id.autofill_save_no);
noButton.setOnClickListener((v) -> mListener.onCancel());
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index d287d85..d9b6fd7 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -3023,15 +3023,24 @@
startRunningVoiceLocked(r.task.voiceSession, r.info.applicationInfo.uid);
} else {
finishRunningVoiceLocked();
- IVoiceInteractionSession session;
- if (mLastResumedActivity != null
- && ((session = mLastResumedActivity.task.voiceSession) != null
- || (session = mLastResumedActivity.voiceSession) != null)) {
- // We had been in a voice interaction session, but now focused has
- // move to something different. Just finish the session, we can't
- // return to it and retain the proper state and synchronization with
- // the voice interaction service.
- finishVoiceTask(session);
+
+ if (mLastResumedActivity != null) {
+ final IVoiceInteractionSession session;
+
+ if (mLastResumedActivity.task != null
+ && mLastResumedActivity.task.voiceSession != null) {
+ session = mLastResumedActivity.task.voiceSession;
+ } else {
+ session = mLastResumedActivity.voiceSession;
+ }
+
+ if (session != null) {
+ // We had been in a voice interaction session, but now focused has
+ // move to something different. Just finish the session, we can't
+ // return to it and retain the proper state and synchronization with
+ // the voice interaction service.
+ finishVoiceTask(session);
+ }
}
}
@@ -10636,7 +10645,7 @@
providers = AppGlobals.getPackageManager()
.queryContentProviders(app.processName, app.uid,
STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS
- | MATCH_DEBUG_TRIAGED_MISSING)
+ | MATCH_DEBUG_TRIAGED_MISSING, /*metadastaKey=*/ null)
.getList();
} catch (RemoteException ex) {
}
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index aef429e..10055c8 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -802,10 +802,7 @@
// Remove the activity from the old task and add it to the new task
prevTask.removeActivity(this);
- // TODO(b/34179495): This should really be set to null in removeActivity() call above,
- // but really bad things that I can't track down right now happen when I do that.
- // So, setting it here now and will change later when there is time for investigation.
- task = null;
+
newTask.addActivityAtIndex(position, this);
}
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 6f79bc27..ab1559d 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -177,7 +177,6 @@
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Set;
@@ -4902,7 +4901,7 @@
setResizingDuringAnimation(task);
}
- mService.mActivityStarter.postStartActivityUncheckedProcessing(task.getTopActivity(),
+ mService.mActivityStarter.postStartActivityProcessing(task.getTopActivity(),
ActivityManager.START_TASK_TO_FRONT,
sourceRecord != null ? sourceRecord.task.getStackId() : INVALID_STACK_ID,
sourceRecord, task.getStack());
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index 83d43db..d8c5533 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -17,6 +17,7 @@
package com.android.server.am;
import static android.app.Activity.RESULT_CANCELED;
+import static android.app.ActivityManager.START_CANCELED;
import static android.app.ActivityManager.START_CLASS_NOT_FOUND;
import static android.app.ActivityManager.START_DELIVERED_TO_TOP;
import static android.app.ActivityManager.START_FLAG_ONLY_IF_NEEDED;
@@ -88,12 +89,10 @@
import android.app.AppGlobals;
import android.app.IActivityContainer;
import android.app.IApplicationThread;
-import android.app.KeyguardManager;
import android.app.PendingIntent;
import android.app.ProfilerInfo;
import android.app.WaitResult;
import android.content.ComponentName;
-import android.content.Context;
import android.content.IIntentSender;
import android.content.Intent;
import android.content.IntentSender;
@@ -509,33 +508,26 @@
doPendingActivityLaunchesLocked(false);
- try {
- mService.mWindowManager.deferSurfaceLayout();
- err = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
- true, options, inTask);
- } finally {
- mService.mWindowManager.continueSurfaceLayout();
- }
- postStartActivityUncheckedProcessing(r, err, stack.mStackId, mSourceRecord, mTargetStack);
- return err;
+ return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true,
+ options, inTask);
}
/** Creates a launch intent for the given auxiliary resolution data. */
private @NonNull Intent createLaunchIntent(@NonNull AuxiliaryResolveInfo auxiliaryResponse,
- Intent originalIntent, String callingPackage,
- String resolvedType, int userId) {
+ Intent originalIntent, String callingPackage,
+ String resolvedType, int userId) {
if (auxiliaryResponse.needsPhaseTwo) {
// request phase two resolution
mService.getPackageManagerInternalLocked().requestInstantAppResolutionPhaseTwo(
- auxiliaryResponse, originalIntent, resolvedType, callingPackage, userId);
+ auxiliaryResponse, originalIntent, resolvedType, callingPackage, userId);
}
return EphemeralResolver.buildEphemeralInstallerIntent(originalIntent,
- callingPackage, resolvedType, userId, auxiliaryResponse.packageName,
- auxiliaryResponse.splitName, auxiliaryResponse.versionCode,
- auxiliaryResponse.token, auxiliaryResponse.needsPhaseTwo);
+ callingPackage, resolvedType, userId, auxiliaryResponse.packageName,
+ auxiliaryResponse.splitName, auxiliaryResponse.versionCode,
+ auxiliaryResponse.token, auxiliaryResponse.needsPhaseTwo);
}
- void postStartActivityUncheckedProcessing(
+ void postStartActivityProcessing(
ActivityRecord r, int result, int prevFocusedStackId, ActivityRecord sourceRecord,
ActivityStack targetStack) {
@@ -937,6 +929,32 @@
}
}
+ private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
+ IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
+ int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {
+ int result = START_CANCELED;
+ try {
+ mService.mWindowManager.deferSurfaceLayout();
+ result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
+ startFlags,
+ doResume, options, inTask);
+ } finally {
+ // If we are not able to proceed, disassociate the activity from the task. Leaving an
+ // activity in an incomplete state can lead to issues, such as performing operations
+ // without a window container.
+ if (result != START_SUCCESS && mStartActivity.task != null) {
+ mStartActivity.task.removeActivity(mStartActivity);
+ }
+ mService.mWindowManager.continueSurfaceLayout();
+ }
+
+ postStartActivityProcessing(r, result, mSupervisor.mFocusedStack.mStackId,
+ mSourceRecord, mTargetStack);
+
+ return result;
+ }
+
+ // Note: This method should only be called from {@link startActivity}.
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {
@@ -1843,11 +1861,8 @@
final PendingActivityLaunch pal = mPendingActivityLaunches.remove(0);
final boolean resume = doResume && mPendingActivityLaunches.isEmpty();
try {
- final int result = startActivityUnchecked(
- pal.r, pal.sourceRecord, null, null, pal.startFlags, resume, null, null);
- postStartActivityUncheckedProcessing(
- pal.r, result, mSupervisor.mFocusedStack.mStackId, mSourceRecord,
- mTargetStack);
+ startActivity(pal.r, pal.sourceRecord, null, null, pal.startFlags, resume, null,
+ null);
} catch (Exception e) {
Slog.e(TAG, "Exception during pending activity launch pal=" + pal, e);
pal.sendErrorResult(e.getMessage());
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index f8645d6..b051304 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -1083,6 +1083,13 @@
/** @return true if this was the last activity in the task */
boolean removeActivity(ActivityRecord r) {
+ if (r.task != this) {
+ throw new IllegalArgumentException(
+ "Activity=" + r + " does not belong to task=" + this);
+ }
+
+ r.task = null;
+
if (mActivities.remove(r) && r.fullscreen) {
// Was previously in list.
numFullscreen--;
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index c11131a..71bfa64 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -442,8 +442,8 @@
@Override
public ParceledListSlice getShortcuts(String callingPackage, long changedSince,
- String packageName, List shortcutIds, ComponentName componentName, int flags,
- UserHandle targetUser) {
+ String packageName, List shortcutIds, ComponentName componentName, Intent intent,
+ int flags, UserHandle targetUser) {
ensureShortcutPermission(callingPackage);
if (!canAccessProfile(callingPackage, targetUser, "Cannot get shortcuts")
|| !isUserEnabled(targetUser)) {
@@ -454,11 +454,17 @@
"To query by shortcut ID, package name must also be set");
}
+ if ((flags & ShortcutQuery.FLAG_MATCH_CHOOSER) == 0
+ && intent != null) {
+ throw new IllegalArgumentException("Supplied an intent in the query, but did "
+ + "not request chooser targets");
+ }
+
// TODO(b/29399275): Eclipse compiler requires explicit List<ShortcutInfo> cast below.
return new ParceledListSlice<>((List<ShortcutInfo>)
mShortcutServiceInternal.getShortcuts(getCallingUserId(),
callingPackage, changedSince, packageName, shortcutIds,
- componentName, flags, targetUser.getIdentifier()));
+ componentName, intent, flags, targetUser.getIdentifier()));
}
@Override
@@ -906,6 +912,7 @@
cookie.packageName,
/* changedSince= */ 0, packageName, /* shortcutIds=*/ null,
/* component= */ null,
+ /* intent= */ null,
ShortcutQuery.FLAG_GET_KEY_FIELDS_ONLY
| ShortcutQuery.FLAG_GET_ALL_KINDS
, userId);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 17045b4b..116c0a3 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -5684,6 +5684,11 @@
false, false, false, userId);
}
+ /**
+ * Returns whether or not instant apps have been disabled remotely.
+ * <p><em>IMPORTANT</em> This should not be called with the package manager lock
+ * held. Otherwise we run the risk of deadlock.
+ */
private boolean isEphemeralDisabled() {
// ephemeral apps have been disabled across the board
if (DISABLE_EPHEMERAL_APPS) {
@@ -5704,10 +5709,6 @@
private boolean isEphemeralAllowed(
Intent intent, List<ResolveInfo> resolvedActivities, int userId,
boolean skipPackageCheck) {
- // Short circuit and return early if possible.
- if (isEphemeralDisabled()) {
- return false;
- }
final int callingUser = UserHandle.getCallingUserId();
if (callingUser != UserHandle.USER_SYSTEM) {
return false;
@@ -6211,6 +6212,7 @@
boolean addEphemeral = false;
List<ResolveInfo> result;
final String pkgName = intent.getPackage();
+ final boolean ephemeralDisabled = isEphemeralDisabled();
synchronized (mPackages) {
if (pkgName == null) {
List<CrossProfileIntentFilter> matchingFilters =
@@ -6228,8 +6230,8 @@
// Check for results in the current profile.
result = filterIfNotSystemUser(mActivities.queryIntent(
intent, resolvedType, flags, userId), userId);
- addEphemeral =
- isEphemeralAllowed(intent, result, userId, false /*skipPackageCheck*/);
+ addEphemeral = !ephemeralDisabled
+ && isEphemeralAllowed(intent, result, userId, false /*skipPackageCheck*/);
// Check for cross profile results.
boolean hasNonNegativePriorityResult = hasNonNegativePriority(result);
@@ -6286,8 +6288,9 @@
} else {
// the caller wants to resolve for a particular package; however, there
// were no installed results, so, try to find an ephemeral result
- addEphemeral = isEphemeralAllowed(
- intent, null /*result*/, userId, true /*skipPackageCheck*/);
+ addEphemeral = !ephemeralDisabled
+ && isEphemeralAllowed(
+ intent, null /*result*/, userId, true /*skipPackageCheck*/);
result = new ArrayList<ResolveInfo>();
}
}
@@ -7469,7 +7472,7 @@
@Override
public @NonNull ParceledListSlice<ProviderInfo> queryContentProviders(String processName,
- int uid, int flags) {
+ int uid, int flags, String metaDataKey) {
final int userId = processName != null ? UserHandle.getUserId(uid)
: UserHandle.getCallingUserId();
if (!sUserManager.exists(userId)) return ParceledListSlice.emptyList();
@@ -7487,6 +7490,14 @@
|| (p.info.processName.equals(processName)
&& UserHandle.isSameApp(p.info.applicationInfo.uid, uid)))
&& mSettings.isEnabledAndMatchLPr(p.info, flags, userId)) {
+
+ // See PM.queryContentProviders()'s javadoc for why we have the metaData
+ // parameter.
+ if (metaDataKey != null
+ && (p.metaData == null || !p.metaData.containsKey(metaDataKey))) {
+ continue;
+ }
+
if (finalList == null) {
finalList = new ArrayList<ProviderInfo>(3);
}
@@ -11700,7 +11711,8 @@
if (!whitelisted) {
Slog.w(TAG, "Privileged permission " + perm + " for package "
+ pkg.packageName + " - not in privapp-permissions whitelist");
- if (!mSystemReady) {
+ // Only report violations for apps on system image
+ if (!mSystemReady && !pkg.isUpdatedSystemApp()) {
if (mPrivappPermissionsViolations == null) {
mPrivappPermissionsViolations = new ArraySet<>();
}
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index 570259b..ac98ab9 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -20,6 +20,7 @@
import android.annotation.UserIdInt;
import android.content.ComponentName;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.pm.PackageInfo;
import android.content.pm.ShortcutInfo;
import android.content.res.Resources;
@@ -31,6 +32,7 @@
import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ArrayUtils;
import com.android.internal.util.Preconditions;
import com.android.internal.util.XmlUtils;
import com.android.server.pm.ShortcutService.ShortcutOperation;
@@ -68,6 +70,9 @@
private static final String TAG_EXTRAS = "extras";
private static final String TAG_SHORTCUT = "shortcut";
private static final String TAG_CATEGORIES = "categories";
+ private static final String TAG_CHOOSER_EXTRAS = "chooser-extras";
+ private static final String TAG_CHOOSER_INTENT_FILTERS = "chooser-intent-filters";
+ private static final String TAG_CHOOSER_COMPONENT_NAMES = "chooser-component-names";
private static final String ATTR_NAME = "name";
private static final String ATTR_CALL_COUNT = "call-count";
@@ -91,6 +96,7 @@
private static final String ATTR_ICON_RES_ID = "icon-res";
private static final String ATTR_ICON_RES_NAME = "icon-resname";
private static final String ATTR_BITMAP_PATH = "bitmap-path";
+ private static final String ATTR_COMPONENT_NAMES = "component-names";
private static final String NAME_CATEGORIES = "categories";
@@ -200,7 +206,7 @@
if (shortcut != null) {
mShortcutUser.mService.removeIcon(getPackageUserId(), shortcut);
shortcut.clearFlags(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_PINNED
- | ShortcutInfo.FLAG_MANIFEST);
+ | ShortcutInfo.FLAG_MANIFEST | ShortcutInfo.FLAG_CHOOSER);
}
return shortcut;
}
@@ -226,7 +232,7 @@
Preconditions.checkArgument(newShortcut.isEnabled(),
"add/setDynamicShortcuts() cannot publish disabled shortcuts");
- newShortcut.addFlags(ShortcutInfo.FLAG_DYNAMIC);
+ addCorrectDynamicFlags(newShortcut);
final ShortcutInfo oldShortcut = mShortcuts.get(newShortcut.getId());
@@ -250,6 +256,17 @@
addShortcutInner(newShortcut);
}
+ // TODO: Sample code & JavaDoc for ShortcutManager needs updating to reflect the fact that
+ // Chooser shortcuts are not always dynamic.
+ public void addCorrectDynamicFlags(@NonNull ShortcutInfo shortcut) {
+ if (shortcut.getIntent() != null) {
+ shortcut.addFlags(ShortcutInfo.FLAG_DYNAMIC);
+ }
+ if (!ArrayUtils.isEmpty(shortcut.getChooserIntentFilters())) {
+ shortcut.addFlags(ShortcutInfo.FLAG_CHOOSER);
+ }
+ }
+
/**
* Remove all shortcuts that aren't pinned nor dynamic.
*/
@@ -282,11 +299,11 @@
boolean changed = false;
for (int i = mShortcuts.size() - 1; i >= 0; i--) {
final ShortcutInfo si = mShortcuts.valueAt(i);
- if (si.isDynamic()) {
+ if (si.isDynamic() || si.isChooser()) {
changed = true;
si.setTimestamp(now);
- si.clearFlags(ShortcutInfo.FLAG_DYNAMIC);
+ si.clearFlags(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_CHOOSER);
si.setRank(0); // It may still be pinned, so clear the rank.
}
}
@@ -355,7 +372,8 @@
if (oldShortcut.isPinned()) {
oldShortcut.setRank(0);
- oldShortcut.clearFlags(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_MANIFEST);
+ oldShortcut.clearFlags(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_MANIFEST
+ | ShortcutInfo.FLAG_CHOOSER);
if (disable) {
oldShortcut.addFlags(ShortcutInfo.FLAG_DISABLED);
}
@@ -1116,8 +1134,8 @@
// Don't adjust ranks for manifest shortcuts.
continue;
}
- // At this point, it must be dynamic.
- if (!si.isDynamic()) {
+ // At this point, it must be dynamic or a chooser.
+ if (!si.isDynamicOrChooser()) {
s.wtf("Non-dynamic shortcut found.");
continue;
}
@@ -1294,7 +1312,7 @@
ShortcutService.writeAttr(out, ATTR_FLAGS,
si.getFlags() &
~(ShortcutInfo.FLAG_HAS_ICON_FILE | ShortcutInfo.FLAG_HAS_ICON_RES
- | ShortcutInfo.FLAG_DYNAMIC));
+ | ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_CHOOSER));
} else {
// When writing for backup, ranks shouldn't be saved, since shortcuts won't be restored
// as dynamic.
@@ -1317,15 +1335,36 @@
}
final Intent[] intentsNoExtras = si.getIntentsNoExtras();
final PersistableBundle[] intentsExtras = si.getIntentPersistableExtrases();
- final int numIntents = intentsNoExtras.length;
- for (int i = 0; i < numIntents; i++) {
- out.startTag(null, TAG_INTENT);
- ShortcutService.writeAttr(out, ATTR_INTENT_NO_EXTRA, intentsNoExtras[i]);
- ShortcutService.writeTagExtra(out, TAG_EXTRAS, intentsExtras[i]);
- out.endTag(null, TAG_INTENT);
+ if (intentsNoExtras != null) {
+ final int numIntents = intentsNoExtras.length;
+ for (int i = 0; i < numIntents; i++) {
+ out.startTag(null, TAG_INTENT);
+ ShortcutService.writeAttr(out, ATTR_INTENT_NO_EXTRA, intentsNoExtras[i]);
+ ShortcutService.writeTagExtra(out, TAG_EXTRAS, intentsExtras[i]);
+ out.endTag(null, TAG_INTENT);
+ }
+ }
+ ShortcutService.writeTagExtra(out, TAG_EXTRAS, si.getExtras());
+
+ ShortcutService.writeTagExtra(out, TAG_CHOOSER_EXTRAS, si.getChooserExtras());
+
+ final IntentFilter[] intentFilters = si.getChooserIntentFilters();
+ if (intentFilters != null) {
+ for (int i = 0; i < intentFilters.length; i++) {
+ out.startTag(null, TAG_CHOOSER_INTENT_FILTERS);
+ intentFilters[i].writeToXml(out);
+ out.endTag(null, TAG_CHOOSER_INTENT_FILTERS);
+ }
}
- ShortcutService.writeTagExtra(out, TAG_EXTRAS, si.getExtras());
+ final ComponentName[] componentNames = si.getChooserComponentNames();
+ if (componentNames != null) {
+ for (int i = 0; i < componentNames.length; i++) {
+ out.startTag(null, TAG_CHOOSER_COMPONENT_NAMES);
+ ShortcutService.writeAttr(out, ATTR_COMPONENT_NAMES, componentNames[i]);
+ out.endTag(null, TAG_CHOOSER_COMPONENT_NAMES);
+ }
+ }
out.endTag(null, TAG_SHORTCUT);
}
@@ -1398,6 +1437,9 @@
String iconResName;
String bitmapPath;
ArraySet<String> categories = null;
+ PersistableBundle chooserExtras;
+ List<IntentFilter> chooserIntentFilters = new ArrayList<>();
+ List<ComponentName> chooserComponentNames = new ArrayList<>();
id = ShortcutService.parseStringAttribute(parser, ATTR_ID);
activityComponent = ShortcutService.parseComponentNameAttribute(parser,
@@ -1458,6 +1500,18 @@
}
}
continue;
+ case TAG_CHOOSER_EXTRAS:
+ chooserExtras = PersistableBundle.restoreFromXml(parser);
+ continue;
+ case TAG_CHOOSER_COMPONENT_NAMES:
+ chooserComponentNames.add(ShortcutService.parseComponentNameAttribute(parser,
+ ATTR_ACTIVITY));
+ continue;
+ case TAG_CHOOSER_INTENT_FILTERS:
+ IntentFilter toAdd = new IntentFilter();
+ toAdd.readFromXml(parser);
+ chooserIntentFilters.add(toAdd);
+ continue;
}
throw ShortcutService.throwForInvalidTag(depth, tag);
}
@@ -1551,10 +1605,10 @@
// Verify each shortcut's status.
for (int i = mShortcuts.size() - 1; i >= 0; i--) {
final ShortcutInfo si = mShortcuts.valueAt(i);
- if (!(si.isDeclaredInManifest() || si.isDynamic() || si.isPinned())) {
+ if (!(si.isDeclaredInManifest() || si.isDynamicOrChooser() || si.isPinned())) {
failed = true;
Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
- + " is not manifest, dynamic or pinned.");
+ + " is not manifest, dynamic, chooser or pinned.");
}
if (si.isDeclaredInManifest() && si.isDynamic()) {
failed = true;
@@ -1596,6 +1650,11 @@
Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
+ " has a dummy target activity");
}
+ if (si.getIntent() == null && !si.isChooser()) {
+ failed = true;
+ Log.e(TAG_VERIFY, "Package " + getPackageName() + ": shortcut " + si.getId()
+ + " has a null intent, but is not a chooser");
+ }
}
if (failed) {
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 057e781..74eb340 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -27,6 +27,7 @@
import android.appwidget.AppWidgetProviderInfo;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -64,6 +65,7 @@
import android.os.Handler;
import android.os.LocaleList;
import android.os.Looper;
+import android.os.Parcel;
import android.os.ParcelFileDescriptor;
import android.os.PersistableBundle;
import android.os.Process;
@@ -1750,6 +1752,7 @@
ps.clearAllImplicitRanks();
assignImplicitRanks(newShortcuts);
+ // TODO: Consider removing Chooser fields. If so, the FLAG_CHOOSER should be removed
for (int i = 0; i < size; i++) {
final ShortcutInfo source = newShortcuts.get(i);
fixUpIncomingShortcutInfo(source, /* forUpdate= */ true);
@@ -1789,6 +1792,13 @@
if (replacingIcon || source.hasStringResources()) {
fixUpShortcutResourceNamesAndValues(target);
}
+
+ // While updating, we keep the dynamic flag as it previously was, but refresh the
+ // chooser flag.
+ // TODO: If we support clearing Chooser fields, we should also remove the flag.
+ if (target.getChooserIntentFilters() != null) {
+ target.addFlags(ShortcutInfo.FLAG_CHOOSER);
+ }
}
// Lastly, adjust the ranks.
@@ -1852,6 +1862,7 @@
return true;
}
+ // TODO: Ensure non-launchable shortcuts can not be pinned
@Override
public boolean requestPinShortcut(String packageName, ShortcutInfo shortcut,
IntentSender resultIntent, int userId) {
@@ -2007,7 +2018,7 @@
return getShortcutsWithQueryLocked(
packageName, userId, ShortcutInfo.CLONE_REMOVE_FOR_CREATOR,
- ShortcutInfo::isDynamic);
+ ShortcutInfo::isDynamicOrChooser);
}
}
@@ -2200,6 +2211,14 @@
synchronized (mLock) {
throwIfUserLockedL(userId);
+ // For the chooser, we just check is the system is calling.
+ // STOPSHIP: We need to implement a new permission here rather than this terrible check.
+ // The packageName check is to try to distinguish between when an actual
+ // launcher is making the call, and when it's the system.
+ if (isCallerSystem() && packageName.equals("android")) {
+ return true;
+ }
+
final ShortcutUser user = getUserShortcutsLocked(userId);
// Always trust the cached component.
@@ -2372,7 +2391,7 @@
public List<ShortcutInfo> getShortcuts(int launcherUserId,
@NonNull String callingPackage, long changedSince,
@Nullable String packageName, @Nullable List<String> shortcutIds,
- @Nullable ComponentName componentName,
+ @Nullable ComponentName componentName, @Nullable Intent intent,
int queryFlags, int userId) {
final ArrayList<ShortcutInfo> ret = new ArrayList<>();
@@ -2394,13 +2413,13 @@
if (packageName != null) {
getShortcutsInnerLocked(launcherUserId,
callingPackage, packageName, shortcutIds, changedSince,
- componentName, queryFlags, userId, ret, cloneFlag);
+ componentName, intent, queryFlags, userId, ret, cloneFlag);
} else {
final List<String> shortcutIdsF = shortcutIds;
getUserShortcutsLocked(userId).forAllPackages(p -> {
getShortcutsInnerLocked(launcherUserId,
callingPackage, p.getPackageName(), shortcutIdsF, changedSince,
- componentName, queryFlags, userId, ret, cloneFlag);
+ componentName, intent, queryFlags, userId, ret, cloneFlag);
});
}
}
@@ -2409,7 +2428,7 @@
private void getShortcutsInnerLocked(int launcherUserId, @NonNull String callingPackage,
@Nullable String packageName, @Nullable List<String> shortcutIds, long changedSince,
- @Nullable ComponentName componentName, int queryFlags,
+ @Nullable ComponentName componentName, Intent intent, int queryFlags,
int userId, ArrayList<ShortcutInfo> ret, int cloneFlag) {
final ArraySet<String> ids = shortcutIds == null ? null
: new ArraySet<>(shortcutIds);
@@ -2434,6 +2453,15 @@
return false;
}
}
+ if (intent != null
+ && !si.hasMatchingFilter(mContext.getContentResolver(), intent)) {
+ return false;
+ }
+
+ if (((queryFlags & ShortcutQuery.FLAG_MATCH_CHOOSER) != 0)
+ && si.isChooser()) {
+ return true;
+ }
if (((queryFlags & ShortcutQuery.FLAG_GET_DYNAMIC) != 0)
&& si.isDynamic()) {
return true;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 474610b..2f1aab6 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -5172,7 +5172,7 @@
// Async Handler
// -------------------------------------------------------------
- final class H extends Handler {
+ final class H extends android.os.Handler {
public static final int REPORT_FOCUS_CHANGE = 2;
public static final int REPORT_LOSING_FOCUS = 3;
public static final int DO_TRAVERSAL = 4;
diff --git a/services/core/jni/com_android_server_vr_VrManagerService.cpp b/services/core/jni/com_android_server_vr_VrManagerService.cpp
index e06e051..9052697 100644
--- a/services/core/jni/com_android_server_vr_VrManagerService.cpp
+++ b/services/core/jni/com_android_server_vr_VrManagerService.cpp
@@ -38,7 +38,7 @@
return;
}
- gVr = IVr::getService("vr");
+ gVr = IVr::getService();
if (gVr == nullptr) {
ALOGW("%s: Could not open IVr interface", __FUNCTION__);
return;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 7b6b941..17e6bba 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -4851,19 +4851,15 @@
private void sendPrivateKeyAliasResponse(final String alias, final IBinder responseBinder) {
final IKeyChainAliasCallback keyChainAliasResponse =
IKeyChainAliasCallback.Stub.asInterface(responseBinder);
- new AsyncTask<Void, Void, Void>() {
- @Override
- protected Void doInBackground(Void... unused) {
- try {
- keyChainAliasResponse.alias(alias);
- } catch (Exception e) {
- // Catch everything (not just RemoteException): caller could throw a
- // RuntimeException back across processes.
- Log.e(LOG_TAG, "error while responding to callback", e);
- }
- return null;
- }
- }.execute();
+ // Send the response. It's OK to do this from the main thread because IKeyChainAliasCallback
+ // is oneway, which means it won't block if the recipient lives in another process.
+ try {
+ keyChainAliasResponse.alias(alias);
+ } catch (Exception e) {
+ // Caller could throw RuntimeException or RemoteException back across processes. Catch
+ // everything just to be sure.
+ Log.e(LOG_TAG, "error while responding to callback", e);
+ }
}
/**
diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
index 100338e..1b59d72 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -34,6 +34,7 @@
import static org.mockito.Mockito.when;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.Activity;
import android.app.ActivityManager;
@@ -1324,20 +1325,23 @@
protected ShortcutInfo makeShortcut(String id) {
return makeShortcut(
id, "Title-" + id, /* activity =*/ null, /* icon =*/ null,
- makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
+ makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
+ /* chooserFilter=*/ null, /* chooserComponentNames=*/ null);
}
@Deprecated // Title was renamed to short label.
protected ShortcutInfo makeShortcutWithTitle(String id, String title) {
return makeShortcut(
id, title, /* activity =*/ null, /* icon =*/ null,
- makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
+ makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
+ /* chooserFilter=*/ null, /* chooserComponentNames=*/ null);
}
protected ShortcutInfo makeShortcutWithShortLabel(String id, String shortLabel) {
return makeShortcut(
id, shortLabel, /* activity =*/ null, /* icon =*/ null,
- makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
+ makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
+ /* chooserFilter=*/ null, /* chooserComponentNames=*/ null);
}
/**
@@ -1346,7 +1350,8 @@
protected ShortcutInfo makeShortcutWithTimestamp(String id, long timestamp) {
final ShortcutInfo s = makeShortcut(
id, "Title-" + id, /* activity =*/ null, /* icon =*/ null,
- makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
+ makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
+ /* chooserFilter=*/ null, /* chooserComponentNames=*/ null);
s.setTimestamp(timestamp);
return s;
}
@@ -1358,7 +1363,8 @@
ComponentName activity) {
final ShortcutInfo s = makeShortcut(
id, "Title-" + id, activity, /* icon =*/ null,
- makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
+ makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
+ /* chooserFilter=*/ null, /* chooserComponentNames=*/ null);
s.setTimestamp(timestamp);
return s;
}
@@ -1369,7 +1375,27 @@
protected ShortcutInfo makeShortcutWithIcon(String id, Icon icon) {
return makeShortcut(
id, "Title-" + id, /* activity =*/ null, icon,
- makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
+ makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
+ /* chooserFilter=*/ null, /* chooserComponentNames=*/ null);
+ }
+
+ protected ShortcutInfo makeChooserShortcut(String id, int i, boolean includeIntent) {
+ List<IntentFilter> filters = new ArrayList<>();
+ List<ComponentName> componentNames = new ArrayList<>();
+ for(int j = 0; j < i; j++) {
+ final IntentFilter filter = new IntentFilter();
+ filter.addAction("view");
+ filters.add(filter);
+
+ componentNames.add(new ComponentName("xxxx", "yy" + i));
+ }
+ Intent intent = null;
+ if (includeIntent) {
+ intent = makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class);
+ }
+ return makeShortcut(
+ id, "Title-" + id, /* activity =*/ null, /* icon */ null,
+ intent, /* rank =*/ 0, filters, componentNames);
}
protected ShortcutInfo makePackageShortcut(String packageName, String id) {
@@ -1378,7 +1404,8 @@
setCaller(packageName);
ShortcutInfo s = makeShortcut(
id, "Title-" + id, /* activity =*/ null, /* icon =*/ null,
- makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
+ makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
+ /* chooserFilter=*/ null, /* chooserComponentNames=*/ null);
setCaller(origCaller); // restore the caller
return s;
@@ -1402,39 +1429,52 @@
protected ShortcutInfo makeShortcutWithActivity(String id, ComponentName activity) {
return makeShortcut(
id, "Title-" + id, activity, /* icon =*/ null,
- makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
+ makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
+ /* chooserFilters =*/ null, /* chooserComponentNames =*/ null);
}
protected ShortcutInfo makeShortcutWithIntent(String id, Intent intent) {
return makeShortcut(
id, "Title-" + id, /* activity =*/ null, /* icon =*/ null,
- intent, /* rank =*/ 0);
+ intent, /* rank =*/ 0, /* chooserFilters =*/ null,
+ /* chooserComponentNames =*/ null);
+
}
protected ShortcutInfo makeShortcutWithActivityAndTitle(String id, ComponentName activity,
String title) {
return makeShortcut(
id, title, activity, /* icon =*/ null,
- makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
+ makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
+ /* chooserFilters =*/ null, /* chooserComponentNames =*/ null);
}
protected ShortcutInfo makeShortcutWithActivityAndRank(String id, ComponentName activity,
int rank) {
return makeShortcut(
id, "Title-" + id, activity, /* icon =*/ null,
- makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), rank);
+ makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), rank,
+ /* chooserFilters =*/ null, /* chooserComponentNames =*/ null);
}
/**
* Make a shortcut with details.
*/
protected ShortcutInfo makeShortcut(String id, String title, ComponentName activity,
- Icon icon, Intent intent, int rank) {
+ Icon icon, Intent intent, int rank, @Nullable List<IntentFilter> chooserFilters,
+ @Nullable List<ComponentName> chooserComponentNames) {
final ShortcutInfo.Builder b = new ShortcutInfo.Builder(mClientContext, id)
.setActivity(new ComponentName(mClientContext.getPackageName(), "main"))
.setShortLabel(title)
- .setRank(rank)
- .setIntent(intent);
+ .setRank(rank);
+ if (intent != null) {
+ b.setIntent(intent);
+ }
+ if (chooserFilters != null) {
+ for (int i = 0; i < chooserFilters.size(); i++) {
+ b.addChooserIntentFilter(chooserFilters.get(i), chooserComponentNames.get(i));
+ }
+ }
if (icon != null) {
b.setIcon(icon);
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
index e4d92ba..94ff07f 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
@@ -15,6 +15,7 @@
*/
package com.android.server.pm;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllChooser;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllDisabled;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllDynamic;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertAllDynamicOrPinned;
@@ -256,7 +257,9 @@
icon1,
makeIntent(Intent.ACTION_ASSIST, ShortcutActivity2.class,
"key1", "val1", "nest", makeBundle("key", 123)),
- /* weight */ 10);
+ /* weight */ 10,
+ /* chooserFilter=*/ null,
+ /* chooserComponentNames=*/ null);
final ShortcutInfo si2 = makeShortcut(
"shortcut2",
@@ -264,14 +267,18 @@
/* activity */ null,
icon2,
makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
- /* weight */ 12);
+ /* weight */ 12,
+ /* chooserFilter=*/ null,
+ /* chooserComponentNames=*/ null);
final ShortcutInfo si3 = makeShortcut(
"shortcut3",
"Title 3",
/* activity */ null,
icon3,
makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
- /* weight */ 13);
+ /* weight */ 13,
+ /* chooserFilter=*/ null,
+ /* chooserComponentNames=*/ null);
assertTrue(mManager.setDynamicShortcuts(list(si1, si2, si3)));
assertShortcutIds(assertAllNotKeyFieldsOnly(
@@ -982,8 +989,10 @@
makeShortcut("s2"),
makeShortcut("s3"),
makeShortcut("s4"),
- makeShortcut("s5")
- )));
+ makeShortcut("s5"),
+ makeChooserShortcut("s6", 2, true),
+ makeChooserShortcut("s7", 2, true),
+ makeChooserShortcut("s8", 1, true))));
});
runWithCaller(CALLING_PACKAGE_2, UserHandle.USER_SYSTEM, () -> {
assertTrue(mManager.setDynamicShortcuts(list(
@@ -991,11 +1000,13 @@
makeShortcut("s2"),
makeShortcut("s3"),
makeShortcut("s4"),
- makeShortcut("s5")
- )));
+ makeShortcut("s5"),
+ makeChooserShortcut("s6", 2, true),
+ makeChooserShortcut("s7", 2, true),
+ makeChooserShortcut("s8", 1, true))));
});
runWithCaller(LAUNCHER_1, UserHandle.USER_SYSTEM, () -> {
- mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s2", "s3"),
+ mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s2", "s3", "s6"),
getCallingUser());
mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("s4", "s5"),
getCallingUser());
@@ -1008,19 +1019,20 @@
mManager.removeDynamicShortcuts(list("s1"));
mManager.removeDynamicShortcuts(list("s3"));
mManager.removeDynamicShortcuts(list("s5"));
+ mManager.removeDynamicShortcuts(list("s7"));
});
runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
assertShortcutIds(assertAllDynamic(
mManager.getDynamicShortcuts()),
- "s3", "s4", "s5");
+ "s3", "s4", "s5", "s6", "s7", "s8");
assertShortcutIds(assertAllPinned(
mManager.getPinnedShortcuts()),
- "s2", "s3");
+ "s2", "s3", "s6");
});
runWithCaller(CALLING_PACKAGE_2, UserHandle.USER_SYSTEM, () -> {
assertShortcutIds(assertAllDynamic(
mManager.getDynamicShortcuts()),
- "s2", "s4");
+ "s2", "s4", "s6", "s8");
assertShortcutIds(assertAllPinned(
mManager.getPinnedShortcuts()),
"s4", "s5");
@@ -1057,10 +1069,10 @@
runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
assertShortcutIds(assertAllDynamic(
mManager.getDynamicShortcuts()),
- "s3", "s4", "s5");
+ "s3", "s4", "s5", "s6", "s7", "s8");
assertShortcutIds(assertAllPinned(
mManager.getPinnedShortcuts()),
- "s2", "s3");
+ "s2", "s3", "s6");
ShortcutInfo s = getCallerShortcut("s2");
assertTrue(s.hasIconResource());
@@ -1076,7 +1088,7 @@
runWithCaller(CALLING_PACKAGE_2, UserHandle.USER_SYSTEM, () -> {
assertShortcutIds(assertAllDynamic(
mManager.getDynamicShortcuts()),
- "s2", "s4");
+ "s2", "s4", "s6", "s8");
assertShortcutIds(assertAllPinned(
mManager.getPinnedShortcuts()),
"s4", "s5");
@@ -1173,7 +1185,46 @@
});
}
- // === Test for launcher side APIs ===
+ public void testUpdateShortcuts_chooser() {
+ runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
+ assertTrue(mManager.setDynamicShortcuts(list(
+ makeShortcut("s1"),
+ makeChooserShortcut("s2", 2, false),
+ makeChooserShortcut("s3", 2, false)
+ )));
+
+ assertFalse(getCallerShortcut("s1").isChooser());
+ assertTrue(getCallerShortcut("s2").isChooser());
+ assertTrue(getCallerShortcut("s3").isChooser());
+
+ ShortcutInfo s = getCallerShortcut("s1");
+ assertNull(s.getChooserIntentFilters());
+ assertNull(s.getChooserComponentNames());
+
+ assertTrue(getCallerShortcut("s1").isDynamic());
+ assertFalse(getCallerShortcut("s2").isDynamic());
+ assertFalse(getCallerShortcut("s3").isDynamic());
+
+
+ // Replace 2 with a chooser shortcut
+ mManager.updateShortcuts(list(makeChooserShortcut("s1", 2, true)));
+
+ s = getCallerShortcut("s1");
+ assertEquals(2, s.getChooserIntentFilters().length);
+ assertEquals(2, s.getChooserComponentNames().length);
+
+ assertShortcutIds(assertAllChooser(
+ mManager.getDynamicShortcuts()),
+ "s1", "s2", "s3");
+
+ assertTrue(getCallerShortcut("s1").isDynamic());
+ assertFalse(getCallerShortcut("s2").isDynamic());
+ assertFalse(getCallerShortcut("s3").isDynamic());
+ });
+ }
+
+
+ // === Test for launcher side APIs ===
public void testGetShortcuts() {
@@ -1484,15 +1535,17 @@
/* icon =*/ null,
makeIntent(Intent.ACTION_ASSIST, ShortcutActivity2.class,
"key1", "val1", "nest", makeBundle("key", 123)),
- /* weight */ 10);
+ /* weight */ 10, /* chooserFilter=*/ null,
+ /* chooserComponentNames=*/ null);
final ShortcutInfo s1_2 = makeShortcut(
- "s2",
- "Title 2",
+ "s2", "Title 2",
/* activity */ null,
/* icon =*/ null,
makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
- /* weight */ 12);
+ /* weight */ 12,
+ /* chooserFilter=*/ null,
+ /* chooserComponentNames=*/ null);
assertTrue(mManager.setDynamicShortcuts(list(s1_1, s1_2)));
dumpsysOnLogcat();
@@ -1505,7 +1558,9 @@
/* icon =*/ null,
makeIntent(Intent.ACTION_ANSWER, ShortcutActivity2.class,
"key1", "val1", "nest", makeBundle("key", 123)),
- /* weight */ 10);
+ /* weight */ 10,
+ /* chooserFilter=*/ null,
+ /* chooserComponentNames=*/ null);
assertTrue(mManager.setDynamicShortcuts(list(s2_1)));
dumpsysOnLogcat();
@@ -2674,10 +2729,12 @@
final ShortcutInfo s1_2 = makeShortcut(
"s2",
"Title 2",
- /* activity */ null,
- /* icon =*/ null,
+ /* activity */ null,
+ /* icon =*/ null,
makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
- /* rank */ 12);
+ /* rank */ 12,
+ /* chooserFilter=*/ null,
+ /* chooserComponentNames=*/ null);
final ShortcutInfo s1_3 = makeShortcut("s3");
@@ -2692,7 +2749,9 @@
/* icon =*/ null,
makeIntent(Intent.ACTION_ANSWER, ShortcutActivity.class,
"key1", "val1", "nest", makeBundle("key", 123)),
- /* weight */ 10);
+ /* weight */ 10,
+ /* chooserFilter=*/ null,
+ /* chooserComponentNames=*/ null);
assertTrue(mManager.setDynamicShortcuts(list(s2_1)));
});
@@ -3110,7 +3169,9 @@
icon1,
makeIntent(Intent.ACTION_ASSIST, ShortcutActivity2.class,
"key1", "val1", "nest", makeBundle("key", 123)),
- /* weight */ 10);
+ /* weight */ 10,
+ /* chooserFilter=*/ null,
+ /* chooserComponentNames=*/ null);
final ShortcutInfo si2 = makeShortcut(
"s2",
@@ -3118,7 +3179,9 @@
/* activity */ null,
icon2,
makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
- /* weight */ 12);
+ /* weight */ 12,
+ /* chooserFilter=*/ null,
+ /* chooserComponentNames=*/ null);
assertTrue(mManager.setDynamicShortcuts(list(si1, si2)));
@@ -3136,8 +3199,8 @@
makeComponent(ShortcutActivity.class),
icon1,
makeIntent(Intent.ACTION_ASSIST, ShortcutActivity2.class,
- "key1", "val1", "nest", makeBundle("key", 123)),
- /* weight */ 10);
+ "key1", "val1", "nest", makeBundle("key", 123)), /* weight */ 10,
+ /* chooserFilter=*/ null, /* chooserComponentNames=*/ null);
final ShortcutInfo si2 = makeShortcut(
"s2",
@@ -3145,7 +3208,8 @@
/* activity */ null,
icon2,
makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
- /* weight */ 12);
+ /* weight */ 12, /* chooserFilter=*/ null,
+ /* chooserComponentNames=*/ null);
assertTrue(mManager.setDynamicShortcuts(list(si1, si2)));
@@ -3167,7 +3231,8 @@
icon1,
makeIntent(Intent.ACTION_ASSIST, ShortcutActivity2.class,
"key1", "val1", "nest", makeBundle("key", 123)),
- /* weight */ 10);
+ /* weight */ 10, /* chooserFilter=*/ null,
+ /* chooserComponentNames=*/ null);
final ShortcutInfo si2 = makeShortcut(
"s2",
@@ -3175,7 +3240,8 @@
/* activity */ null,
icon2,
makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
- /* weight */ 12);
+ /* weight */ 12, /* chooserFilter=*/ null,
+ /* chooserComponentNames=*/ null);
assertTrue(mManager.setDynamicShortcuts(list(si1, si2)));
@@ -6800,10 +6866,12 @@
mManager.setDynamicShortcuts(list(
makeShortcut("ms1", "title1",
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
- /* icon */ null, new Intent("action1"), /* rank */ 0),
+ /* icon */ null, new Intent("action1"), /* rank */ 0,
+ /* chooserFilter=*/ null, /* chooserComponentNames=*/ null),
makeShortcut("ms2", "title2",
new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
- /* icon */ null, new Intent("action1"), /* rank */ 0)));
+ /* icon */ null, new Intent("action1"), /* rank */ 0, /* chooserFilter=*/ null,
+ /* chooserComponentNames=*/ null)));
});
runWithCaller(LAUNCHER_1, USER_0, () -> {
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
index 28ec4fd..c54fa02 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
@@ -34,6 +34,7 @@
import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.pm.ShortcutInfo;
import android.content.res.Resources;
import android.graphics.BitmapFactory;
@@ -93,11 +94,6 @@
assertExpectException(
RuntimeException.class,
- "intents cannot contain null",
- () -> new ShortcutInfo.Builder(getTestContext(), "id").setIntent(null));
-
- assertExpectException(
- RuntimeException.class,
"action must be set",
() -> new ShortcutInfo.Builder(getTestContext(), "id").setIntent(new Intent()));
@@ -142,6 +138,19 @@
"disabledMessage cannot be empty",
() -> new ShortcutInfo.Builder(getTestContext(), "id").setDisabledMessage(""));
+
+ assertExpectException(
+ RuntimeException.class,
+ "component name cannot be null",
+ () -> new ShortcutInfo.Builder(getTestContext(), "id")
+ .addChooserIntentFilter(new IntentFilter(Intent.ACTION_SEND), null));
+
+ assertExpectException(
+ RuntimeException.class,
+ "intent filter cannot be null",
+ () -> new ShortcutInfo.Builder(getTestContext(), "id")
+ .addChooserIntentFilter(null, new ComponentName("xxx", "s")));
+
assertExpectException(NullPointerException.class, "action must be set",
() -> new ShortcutInfo.Builder(getTestContext(), "id").setIntent(new Intent()));
@@ -240,6 +249,10 @@
PersistableBundle pb = new PersistableBundle();
pb.putInt("k", 1);
+ IntentFilter chooserFilter = new IntentFilter();
+ chooserFilter.addAction(Intent.ACTION_VIEW);
+ PersistableBundle pb2 = new PersistableBundle();
+ pb2.putInt("l", 1);
si = new ShortcutInfo.Builder(getTestContext())
.setId("id")
@@ -252,6 +265,8 @@
.setCategories(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"))
.setRank(123)
.setExtras(pb)
+ .addChooserIntentFilter(chooserFilter, new ComponentName("a", "b"))
+ .setChooserExtras(pb2)
.build();
si.addFlags(ShortcutInfo.FLAG_PINNED);
si.setBitmapPath("abc");
@@ -282,6 +297,12 @@
assertEquals(null, si.getTextResName());
assertEquals(0, si.getDisabledMessageResourceId());
assertEquals(null, si.getDisabledMessageResName());
+
+ assertEquals(1, si.getChooserIntentFilters().length);
+ assertEquals(Intent.ACTION_VIEW, si.getChooserIntentFilters()[0].getAction(0));
+ assertEquals(1, si.getChooserComponentNames().length);
+ assertEquals(new ComponentName("a", "b"), si.getChooserComponentNames()[0]);
+ assertEquals(1, si.getChooserExtras().getInt("l"));
}
public void testShortcutInfoParcel_resId() {
@@ -290,6 +311,10 @@
PersistableBundle pb = new PersistableBundle();
pb.putInt("k", 1);
+ IntentFilter chooserFilter = new IntentFilter();
+ chooserFilter.addAction(Intent.ACTION_VIEW);
+ PersistableBundle pb2 = new PersistableBundle();
+ pb2.putInt("l", 1);
si = new ShortcutInfo.Builder(getTestContext())
.setId("id")
@@ -302,6 +327,8 @@
.setCategories(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"))
.setRank(123)
.setExtras(pb)
+ .addChooserIntentFilter(chooserFilter, new ComponentName("a", "b"))
+ .setChooserExtras(pb2)
.build();
si.addFlags(ShortcutInfo.FLAG_PINNED);
si.setBitmapPath("abc");
@@ -338,6 +365,11 @@
PersistableBundle pb = new PersistableBundle();
pb.putInt("k", 1);
+ IntentFilter chooserFilter = new IntentFilter();
+ chooserFilter.addAction(Intent.ACTION_VIEW);
+ PersistableBundle pb2 = new PersistableBundle();
+ pb2.putInt("l", 1);
+
ShortcutInfo sorig = new ShortcutInfo.Builder(mClientContext)
.setId("id")
.setActivity(new ComponentName("a", "b"))
@@ -349,6 +381,8 @@
.setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
.setRank(123)
.setExtras(pb)
+ .addChooserIntentFilter(chooserFilter, new ComponentName("a", "b"))
+ .setChooserExtras(pb2)
.build();
sorig.addFlags(ShortcutInfo.FLAG_PINNED);
sorig.setBitmapPath("abc");
@@ -378,6 +412,12 @@
assertEquals(456, si.getIconResourceId());
assertEquals("string/r456", si.getIconResName());
+ assertEquals(1, si.getChooserIntentFilters().length);
+ assertEquals(Intent.ACTION_VIEW, si.getChooserIntentFilters()[0].getAction(0));
+ assertEquals(1, si.getChooserComponentNames().length);
+ assertEquals(new ComponentName("a", "b"), si.getChooserComponentNames()[0]);
+ assertEquals(1, si.getChooserExtras().getInt("l"));
+
si = sorig.clone(ShortcutInfo.CLONE_REMOVE_FOR_CREATOR);
assertEquals(mClientContext.getPackageName(), si.getPackage());
@@ -445,6 +485,10 @@
PersistableBundle pb = new PersistableBundle();
pb.putInt("k", 1);
+ IntentFilter chooserFilter = new IntentFilter();
+ chooserFilter.addAction(Intent.ACTION_VIEW);
+ PersistableBundle pb2 = new PersistableBundle();
+ pb2.putInt("l", 1);
ShortcutInfo sorig = new ShortcutInfo.Builder(mClientContext)
.setId("id")
.setActivity(new ComponentName("a", "b"))
@@ -456,6 +500,8 @@
.setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
.setRank(123)
.setExtras(pb)
+ .addChooserIntentFilter(chooserFilter, new ComponentName("a", "b"))
+ .setChooserExtras(pb2)
.build();
sorig.addFlags(ShortcutInfo.FLAG_PINNED);
sorig.setBitmapPath("abc");
@@ -488,6 +534,12 @@
assertEquals(456, si.getIconResourceId());
assertEquals("string/r456", si.getIconResName());
+ assertEquals(1, si.getChooserIntentFilters().length);
+ assertEquals(Intent.ACTION_VIEW, si.getChooserIntentFilters()[0].getAction(0));
+ assertEquals(1, si.getChooserComponentNames().length);
+ assertEquals(new ComponentName("a", "b"), si.getChooserComponentNames()[0]);
+ assertEquals(1, si.getChooserExtras().getInt("l"));
+
si = sorig.clone(ShortcutInfo.CLONE_REMOVE_FOR_CREATOR);
assertEquals(mClientContext.getPackageName(), si.getPackage());
@@ -603,6 +655,10 @@
public void testShortcutInfoCopyNonNullFieldsFrom() throws InterruptedException {
PersistableBundle pb = new PersistableBundle();
pb.putInt("k", 1);
+ IntentFilter chooserFilter = new IntentFilter();
+ chooserFilter.addAction(Intent.ACTION_VIEW);
+ PersistableBundle pb2 = new PersistableBundle();
+ pb2.putInt("l", 1);
ShortcutInfo sorig = new ShortcutInfo.Builder(getTestContext())
.setId("id")
.setActivity(new ComponentName("a", "b"))
@@ -714,12 +770,12 @@
assertEquals(999, si.getRank());
- PersistableBundle pb2 = new PersistableBundle();
- pb2.putInt("x", 99);
+ PersistableBundle pb3 = new PersistableBundle();
+ pb3.putInt("x", 99);
si = sorig.clone(/* flags=*/ 0);
si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
- .setExtras(pb2).build());
+ .setExtras(pb3).build());
assertEquals("text", si.getText());
assertEquals(99, si.getExtras().getInt("x"));
}
diff --git a/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java b/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
index ea45bd1..fd335c3 100644
--- a/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
+++ b/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
@@ -508,6 +508,13 @@
return actualShortcuts;
}
+ public static List<ShortcutInfo> assertAllChooser(List<ShortcutInfo> actualShortcuts) {
+ for (ShortcutInfo s : actualShortcuts) {
+ assertTrue("ID " + s.getId(), s.isChooser());
+ }
+ return actualShortcuts;
+ }
+
public static List<ShortcutInfo> assertAllPinned(List<ShortcutInfo> actualShortcuts) {
for (ShortcutInfo s : actualShortcuts) {
assertTrue("ID " + s.getId(), s.isPinned());
diff --git a/tools/layoutlib/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java
index 174bbcf..cc7631a 100644
--- a/tools/layoutlib/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java
@@ -571,6 +571,8 @@
@NonNull
public Consumer<Float> getFloatPropertySetter(int propertyIdx) {
switch (propertyIdx) {
+ case STROKE_WIDTH_INDEX:
+ return this::setStrokeWidth;
case STROKE_ALPHA_INDEX:
return this::setStrokeAlpha;
case FILL_ALPHA_INDEX:
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png
index a53dcba..f15d669 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png
Binary files differ
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/allwidgets.xml b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/allwidgets.xml
index 05a3665..456b5f6 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/allwidgets.xml
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/allwidgets.xml
@@ -263,7 +263,8 @@
android:id="@id/radioButton2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:text="New RadioButton" />
+ android:text="New RadioButton"
+ android:checked="true" />
</RadioGroup>
diff --git a/wifi/java/android/net/wifi/aware/DiscoverySession.java b/wifi/java/android/net/wifi/aware/DiscoverySession.java
index adf189b..57b98e9 100644
--- a/wifi/java/android/net/wifi/aware/DiscoverySession.java
+++ b/wifi/java/android/net/wifi/aware/DiscoverySession.java
@@ -31,8 +31,7 @@
* {@link PublishDiscoverySession} and {@link SubscribeDiscoverySession}. This
* class provides functionality common to both publish and subscribe discovery sessions:
* <ul>
- * <li>Sending messages: {@link #sendMessage(PeerHandle, int, byte[])} or
- * {@link #sendMessage(PeerHandle, int, byte[], int)} methods.
+ * <li>Sending messages: {@link #sendMessage(PeerHandle, int, byte[])}.
* <li>Creating a network-specifier when requesting a Aware connection:
* {@link #createNetworkSpecifier(PeerHandle, byte[])}.
* </ul>
@@ -62,6 +61,8 @@
* {@link #sendMessage(PeerHandle, int, byte[], int)}.
*
* @return Maximum retry count when sending messages.
+ *
+ * @hide
*/
public static int getMaxSendRetryCount() {
return MAX_SEND_RETRY_COUNT;
@@ -163,6 +164,8 @@
* or MAC level) retries should be attempted if there is no ACK from the receiver
* (note: no retransmissions are attempted in other failure cases). A value of 0
* indicates no retries. Max permitted value is {@link #getMaxSendRetryCount()}.
+ *
+ * @hide
*/
public void sendMessage(@NonNull PeerHandle peerHandle, int messageId,
@Nullable byte[] message, int retryCount) {
@@ -195,8 +198,6 @@
* The peer will get a callback indicating a message was received using
* {@link DiscoverySessionCallback#onMessageReceived(PeerHandle,
* byte[])}.
- * Equivalent to {@link #sendMessage(PeerHandle, int, byte[], int)}
- * with a {@code retryCount} of 0.
*
* @param peerHandle The peer's handle for the message. Must be a result of an
* {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle,
diff --git a/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java b/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java
index 33da182..9645b1d 100644
--- a/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java
+++ b/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java
@@ -124,10 +124,9 @@
}
/**
- * Called when message transmission fails - when no ACK is received from the peer.
- * Retries when ACKs are not received are done by hardware, MAC, and in the Aware stack (using
- * the {@link DiscoverySession#sendMessage(PeerHandle, int,
- * byte[], int)} method) - this event is received after all retries are exhausted.
+ * Called when message transmission initiated with
+ * {@link DiscoverySession#sendMessage(PeerHandle, int, byte[])} fails. E.g. when no ACK is
+ * received from the peer.
* <p>
* Note that either this callback or
* {@link DiscoverySessionCallback#onMessageSendSucceeded(int)} will be received
@@ -141,9 +140,7 @@
/**
* Called when a message is received from a discovery session peer - in response to the
- * peer's {@link DiscoverySession#sendMessage(PeerHandle, int,
- * byte[])} or {@link DiscoverySession#sendMessage(PeerHandle,
- * int, byte[], int)}.
+ * peer's {@link DiscoverySession#sendMessage(PeerHandle, int, byte[])}.
*
* @param peerHandle An opaque handle to the peer matching our discovery operation.
* @param message A byte array containing the message.