diff options
58 files changed, 823 insertions, 215 deletions
diff --git a/core/java/android/accounts/AbstractAccountAuthenticator.java b/core/java/android/accounts/AbstractAccountAuthenticator.java index a3b3a9f21954..79d1361192e3 100644 --- a/core/java/android/accounts/AbstractAccountAuthenticator.java +++ b/core/java/android/accounts/AbstractAccountAuthenticator.java @@ -17,7 +17,6 @@ package android.accounts; import android.Manifest; -import android.annotation.SystemApi; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; @@ -32,8 +31,8 @@ import java.util.Arrays; /** * Abstract base class for creating AccountAuthenticators. - * In order to be an authenticator one must extend this class, provider implementations for the - * abstract methods and write a service that returns the result of {@link #getIBinder()} + * In order to be an authenticator one must extend this class, provide implementations for the + * abstract methods, and write a service that returns the result of {@link #getIBinder()} * in the service's {@link android.app.Service#onBind(android.content.Intent)} when invoked * with an intent with action {@link AccountManager#ACTION_AUTHENTICATOR_INTENT}. This service * must specify the following intent filter and metadata tags in its AndroidManifest.xml file diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 0fb85d25cf1a..1925f431b3b6 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -393,7 +393,7 @@ import java.util.List; * <td>The final call you receive before your * activity is destroyed. This can happen either because the * activity is finishing (someone called {@link Activity#finish} on - * it, or because the system is temporarily destroying this + * it), or because the system is temporarily destroying this * instance of the activity to save space. You can distinguish * between these two scenarios with the {@link * Activity#isFinishing} method.</td> @@ -1937,7 +1937,7 @@ public class Activity extends ContextThemeWrapper /** * Perform any final cleanup before an activity is destroyed. This can * happen either because the activity is finishing (someone called - * {@link #finish} on it, or because the system is temporarily destroying + * {@link #finish} on it), or because the system is temporarily destroying * this instance of the activity to save space. You can distinguish * between these two scenarios with the {@link #isFinishing} method. * diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java index c7618fe62c87..d4385549da02 100644 --- a/core/java/android/app/Instrumentation.java +++ b/core/java/android/app/Instrumentation.java @@ -1749,7 +1749,7 @@ public class Instrumentation { /** * Like {@link #execStartActivity(android.content.Context, android.os.IBinder, * android.os.IBinder, String, android.content.Intent, int, android.os.Bundle)}, - * but for calls from a {#link Fragment}. + * but for calls from a {@link Fragment}. * * @param who The Context from which the activity is being started. * @param contextThread The main thread of the Context from which the activity diff --git a/core/java/android/app/Service.java b/core/java/android/app/Service.java index ea0fd75bec90..6cee2da5762e 100644 --- a/core/java/android/app/Service.java +++ b/core/java/android/app/Service.java @@ -20,13 +20,13 @@ import android.annotation.IntDef; import android.annotation.Nullable; import android.content.ComponentCallbacks2; import android.content.ComponentName; -import android.content.Intent; -import android.content.ContextWrapper; import android.content.Context; +import android.content.ContextWrapper; +import android.content.Intent; import android.content.res.Configuration; import android.os.Build; -import android.os.RemoteException; import android.os.IBinder; +import android.os.RemoteException; import android.util.Log; import java.io.FileDescriptor; @@ -390,7 +390,7 @@ public abstract class Service extends ContextWrapper implements ComponentCallbac * don't recreate until a future explicit call to * {@link Context#startService Context.startService(Intent)}. The * service will not receive a {@link #onStartCommand(Intent, int, int)} - * call with a null Intent because it will not be re-started if there + * call with a null Intent because it will not be restarted if there * are no pending Intents to deliver. * * <p>This mode makes sense for things that want to do some work as a @@ -415,7 +415,7 @@ public abstract class Service extends ContextWrapper implements ComponentCallbac * redelivery until the service calls {@link #stopSelf(int)} with the * start ID provided to {@link #onStartCommand}. The * service will not receive a {@link #onStartCommand(Intent, int, int)} - * call with a null Intent because it will will only be re-started if + * call with a null Intent because it will only be restarted if * it is not finished processing all Intents sent to it (and any such * pending events will be delivered at the point of restart). */ diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java index 1b6b5a01ec7e..44051081b595 100644 --- a/core/java/android/bluetooth/BluetoothAdapter.java +++ b/core/java/android/bluetooth/BluetoothAdapter.java @@ -2797,7 +2797,7 @@ public final class BluetoothAdapter { * socket will be encrypted. * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming connections from a listening * {@link BluetoothServerSocket}. - * <p>The system will assign a dynamic PSM value. This PSM value can be read from the {#link + * <p>The system will assign a dynamic PSM value. This PSM value can be read from the {@link * BluetoothServerSocket#getPsm()} and this value will be released when this server socket is * closed, Bluetooth is turned off, or the application exits unexpectedly. * <p>The mechanism of disclosing the assigned dynamic PSM value to the initiating peer is @@ -2847,7 +2847,7 @@ public final class BluetoothAdapter { * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming connections from a listening * {@link BluetoothServerSocket}. * <p>The system will assign a dynamic protocol/service multiplexer (PSM) value. This PSM value - * can be read from the {#link BluetoothServerSocket#getPsm()} and this value will be released + * can be read from the {@link BluetoothServerSocket#getPsm()} and this value will be released * when this server socket is closed, Bluetooth is turned off, or the application exits * unexpectedly. * <p>The mechanism of disclosing the assigned dynamic PSM value to the initiating peer is diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java index 7a6b72e980f5..f4b7d7c700c5 100644 --- a/core/java/android/bluetooth/BluetoothDevice.java +++ b/core/java/android/bluetooth/BluetoothDevice.java @@ -1567,7 +1567,7 @@ public final class BluetoothDevice implements Parcelable { * For example, for Bluetooth 2.1 devices, if any of the devices does not * have an input and output capability or just has the ability to * display a numeric key, a secure socket connection is not possible. - * In such a case, use {#link createInsecureRfcommSocket}. + * In such a case, use {@link createInsecureRfcommSocket}. * For more details, refer to the Security Model section 5.2 (vol 3) of * Bluetooth Core Specification version 2.1 + EDR. * <p>Use {@link BluetoothSocket#connect} to initiate the outgoing @@ -1601,7 +1601,7 @@ public final class BluetoothDevice implements Parcelable { * For example, for Bluetooth 2.1 devices, if any of the devices does not * have an input and output capability or just has the ability to * display a numeric key, a secure socket connection is not possible. - * In such a case, use {#link createInsecureRfcommSocket}. + * In such a case, use {@link createInsecureRfcommSocket}. * For more details, refer to the Security Model section 5.2 (vol 3) of * Bluetooth Core Specification version 2.1 + EDR. * <p>Use {@link BluetoothSocket#connect} to initiate the outgoing @@ -1658,7 +1658,7 @@ public final class BluetoothDevice implements Parcelable { * For example, for Bluetooth 2.1 devices, if any of the devices does not * have an input and output capability or just has the ability to * display a numeric key, a secure socket connection is not possible. - * In such a case, use {#link createInsecureRfcommSocketToServiceRecord}. + * In such a case, use {@link #createInsecureRfcommSocketToServiceRecord}. * For more details, refer to the Security Model section 5.2 (vol 3) of * Bluetooth Core Specification version 2.1 + EDR. * <p>Hint: If you are connecting to a Bluetooth serial board then try @@ -1938,7 +1938,7 @@ public final class BluetoothDevice implements Parcelable { * encrypted. * <p> Use this socket if an authenticated socket link is possible. Authentication refers * to the authentication of the link key to prevent man-in-the-middle type of attacks. When a - * secure socket connection is not possible, use {#link createInsecureLeL2capCocSocket(int, + * secure socket connection is not possible, use {@link createInsecureLeL2capCocSocket(int, * int)}. * * @param transport Bluetooth transport to use, must be {@link #TRANSPORT_LE} diff --git a/core/java/android/bluetooth/BluetoothServerSocket.java b/core/java/android/bluetooth/BluetoothServerSocket.java index ebb7f187aea5..ca29ef37a228 100644 --- a/core/java/android/bluetooth/BluetoothServerSocket.java +++ b/core/java/android/bluetooth/BluetoothServerSocket.java @@ -201,7 +201,7 @@ public final class BluetoothServerSocket implements Closeable { /** * Returns the assigned dynamic protocol/service multiplexer (PSM) value for the listening L2CAP * Connection-oriented Channel (CoC) server socket. This server socket must be returned by the - * {#link BluetoothAdapter.listenUsingL2capCoc(int)} or {#link + * {@link BluetoothAdapter.listenUsingL2capCoc(int)} or {@link * BluetoothAdapter.listenUsingInsecureL2capCoc(int)}. The returned value is undefined if this * method is called on non-L2CAP server sockets. * diff --git a/core/java/android/hardware/GeomagneticField.java b/core/java/android/hardware/GeomagneticField.java index 94f2ac085965..0d7b695d7f1d 100644 --- a/core/java/android/hardware/GeomagneticField.java +++ b/core/java/android/hardware/GeomagneticField.java @@ -31,7 +31,7 @@ import java.util.GregorianCalendar; * Android may use a newer version of the model. */ public class GeomagneticField { - // The magnetic field at a given point, in nonoteslas in geodetic + // The magnetic field at a given point, in nanoteslas in geodetic // coordinates. private float mX; private float mY; @@ -278,7 +278,7 @@ public class GeomagneticField { } /** - * @return Horizontal component of the field strength in nonoteslas. + * @return Horizontal component of the field strength in nanoteslas. */ public float getHorizontalStrength() { return (float) Math.hypot(mX, mY); diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index b4c8a5e504bc..d26c51628e22 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -2110,7 +2110,7 @@ public class InputMethodService extends AbstractInputMethodService { * Called when the application has reported a new location of its text * cursor. This is only called if explicitly requested by the input method. * The default implementation does nothing. - * @deprecated Use {#link onUpdateCursorAnchorInfo(CursorAnchorInfo)} instead. + * @deprecated Use {@link #onUpdateCursorAnchorInfo(CursorAnchorInfo)} instead. */ @Deprecated public void onUpdateCursor(Rect newCursor) { @@ -2177,7 +2177,7 @@ public class InputMethodService extends AbstractInputMethodService { } /** - * @return {#link ExtractEditText} if it is considered to be visible and active. Otherwise + * @return {@link ExtractEditText} if it is considered to be visible and active. Otherwise * {@code null} is returned. */ private ExtractEditText getExtractEditTextIfVisible() { diff --git a/core/java/android/inputmethodservice/SoftInputWindow.java b/core/java/android/inputmethodservice/SoftInputWindow.java index 795117e493b6..bf579a703567 100644 --- a/core/java/android/inputmethodservice/SoftInputWindow.java +++ b/core/java/android/inputmethodservice/SoftInputWindow.java @@ -103,9 +103,9 @@ public class SoftInputWindow extends Dialog { /** * Set which boundary of the screen the DockWindow sticks to. * - * @param gravity The boundary of the screen to stick. See {#link - * android.view.Gravity.LEFT}, {#link android.view.Gravity.TOP}, - * {#link android.view.Gravity.BOTTOM}, {#link + * @param gravity The boundary of the screen to stick. See {@link + * android.view.Gravity.LEFT}, {@link android.view.Gravity.TOP}, + * {@link android.view.Gravity.BOTTOM}, {@link * android.view.Gravity.RIGHT}. */ public void setGravity(int gravity) { diff --git a/core/java/android/net/NetworkMisc.java b/core/java/android/net/NetworkMisc.java index 69f50a272af0..a2da6eaa4922 100644 --- a/core/java/android/net/NetworkMisc.java +++ b/core/java/android/net/NetworkMisc.java @@ -46,7 +46,7 @@ public class NetworkMisc implements Parcelable { /** * Set if the user desires to use this network even if it is unvalidated. This field has meaning - * only if {#link explicitlySelected} is true. If it is, this field must also be set to the + * only if {@link explicitlySelected} is true. If it is, this field must also be set to the * appropriate value based on previous user choice. */ public boolean acceptUnvalidated; diff --git a/core/java/android/net/UrlQuerySanitizer.java b/core/java/android/net/UrlQuerySanitizer.java index d2073b4dfd3a..5b674067192e 100644 --- a/core/java/android/net/UrlQuerySanitizer.java +++ b/core/java/android/net/UrlQuerySanitizer.java @@ -287,7 +287,7 @@ public class UrlQuerySanitizer { /** * Sanitize a value. * <ol> - * <li>If script URLs are not OK, the will be removed. + * <li>If script URLs are not OK, they will be removed. * <li>If neither spaces nor other white space is OK, then * white space will be trimmed from the beginning and end of * the URL. (Just the actual white space characters are trimmed, not @@ -563,7 +563,7 @@ public class UrlQuerySanitizer { } /** - * Constructs a UrlQuerySanitizer and parse a URL. + * Constructs a UrlQuerySanitizer and parses a URL. * This constructor is provided for convenience when the * default parsing behavior is acceptable. * <p> @@ -644,7 +644,7 @@ public class UrlQuerySanitizer { } /** - * An array list of all of the parameter value pairs in the sanitized + * An array list of all of the parameter-value pairs in the sanitized * query, in the order they appeared in the query. May contain duplicate * parameters. * <p class="note"><b>Note:</b> Do not modify this list. Treat it as a read-only list.</p> @@ -656,7 +656,7 @@ public class UrlQuerySanitizer { /** * Check if a parameter exists in the current sanitized query. * @param parameter the unencoded name of a parameter. - * @return true if the paramater exists in the current sanitized queary. + * @return true if the parameter exists in the current sanitized queary. */ public boolean hasParameter(String parameter) { return mEntries.containsKey(parameter); @@ -766,7 +766,7 @@ public class UrlQuerySanitizer { * the value. If all goes well then addSanitizedValue is called with * the unescaped parameter and the sanitized unescaped value. * @param parameter an escaped parameter - * @param value an unsanitzied escaped value + * @param value an unsanitized escaped value */ protected void parseEntry(String parameter, String value) { String unescapedParameter = unescape(parameter); @@ -812,7 +812,7 @@ public class UrlQuerySanitizer { /** * Get the effective value sanitizer for a parameter. Like getValueSanitizer, * except if there is no value sanitizer registered for a parameter, and - * unregistered paramaters are allowed, then the default value sanitizer is + * unregistered parameters are allowed, then the default value sanitizer is * returned. * @param parameter an unescaped parameter * @return the effective value sanitizer for a parameter. diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java index c86149907323..01e2db2e3939 100644 --- a/core/java/android/util/FeatureFlagUtils.java +++ b/core/java/android/util/FeatureFlagUtils.java @@ -33,6 +33,8 @@ public class FeatureFlagUtils { public static final String FFLAG_PREFIX = "sys.fflag."; public static final String FFLAG_OVERRIDE_PREFIX = FFLAG_PREFIX + "override."; + public static final String PERSIST_PREFIX = "persist." + FFLAG_OVERRIDE_PREFIX; + public static final String HEARING_AID_SETTINGS = "settings_bluetooth_hearing_aid"; private static final Map<String, String> DEFAULT_FLAGS; static { @@ -44,6 +46,7 @@ public class FeatureFlagUtils { DEFAULT_FLAGS.put("settings_data_usage_v2", "true"); DEFAULT_FLAGS.put("settings_audio_switcher", "true"); DEFAULT_FLAGS.put("settings_systemui_theme", "true"); + DEFAULT_FLAGS.put(HEARING_AID_SETTINGS, "true"); } /** diff --git a/core/java/android/util/JsonReader.java b/core/java/android/util/JsonReader.java index 7d1c6c4918db..50f63f8db304 100644 --- a/core/java/android/util/JsonReader.java +++ b/core/java/android/util/JsonReader.java @@ -16,13 +16,15 @@ package android.util; +import libcore.internal.StringPool; + import java.io.Closeable; import java.io.EOFException; import java.io.IOException; import java.io.Reader; import java.util.ArrayList; import java.util.List; -import libcore.internal.StringPool; + /** * Reads a JSON (<a href="http://www.ietf.org/rfc/rfc4627.txt">RFC 4627</a>) @@ -295,7 +297,7 @@ public final class JsonReader implements Closeable { /** * Consumes the next token from the JSON stream and asserts that it is the - * end of the current array. + * end of the current object. */ public void endObject() throws IOException { expect(JsonToken.END_OBJECT); diff --git a/core/java/android/view/KeyCharacterMap.java b/core/java/android/view/KeyCharacterMap.java index 02202db52fac..503eb9738362 100644 --- a/core/java/android/view/KeyCharacterMap.java +++ b/core/java/android/view/KeyCharacterMap.java @@ -123,7 +123,7 @@ public class KeyCharacterMap implements Parcelable { /** * Modifier keys may be chorded with character keys. * - * @see {#link #getModifierBehavior()} for more details. + * @see {@link #getModifierBehavior()} for more details. */ public static final int MODIFIER_BEHAVIOR_CHORDED = 0; @@ -131,7 +131,7 @@ public class KeyCharacterMap implements Parcelable { * Modifier keys may be chorded with character keys or they may toggle * into latched or locked states when pressed independently. * - * @see {#link #getModifierBehavior()} for more details. + * @see {@link #getModifierBehavior()} for more details. */ public static final int MODIFIER_BEHAVIOR_CHORDED_OR_TOGGLED = 1; diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java index a59740563ceb..86554fee04b9 100644 --- a/core/java/android/view/KeyEvent.java +++ b/core/java/android/view/KeyEvent.java @@ -883,8 +883,8 @@ public class KeyEvent extends InputEvent implements Parcelable { /** * {@link #getAction} value: multiple duplicate key events have * occurred in a row, or a complex string is being delivered. If the - * key code is not {#link {@link #KEYCODE_UNKNOWN} then the - * {#link {@link #getRepeatCount()} method returns the number of times + * key code is not {@link #KEYCODE_UNKNOWN} then the + * {@link #getRepeatCount()} method returns the number of times * the given key code should be executed. * Otherwise, if the key code is {@link #KEYCODE_UNKNOWN}, then * this is a sequence of characters as returned by {@link #getCharacters}. diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 2c9e543c3abd..04e818247e39 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -15493,7 +15493,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, /** * Sets the visual z position of this view, in pixels. This is equivalent to setting the * {@link #setTranslationZ(float) translationZ} property to be the difference between - * the x value passed in and the current {@link #getElevation() elevation} property. + * the z value passed in and the current {@link #getElevation() elevation} property. * * @param z The visual z position of this view, in pixels. */ diff --git a/core/java/android/view/accessibility/AccessibilityCache.java b/core/java/android/view/accessibility/AccessibilityCache.java index da5a1cd67922..0e1e379d610a 100644 --- a/core/java/android/view/accessibility/AccessibilityCache.java +++ b/core/java/android/view/accessibility/AccessibilityCache.java @@ -418,20 +418,28 @@ public class AccessibilityCache { * * @param nodes The nodes in the hosting window. * @param rootNodeId The id of the root to evict. + * + * @return {@code true} if the cache was cleared */ - private void clearSubTreeRecursiveLocked(LongSparseArray<AccessibilityNodeInfo> nodes, + private boolean clearSubTreeRecursiveLocked(LongSparseArray<AccessibilityNodeInfo> nodes, long rootNodeId) { AccessibilityNodeInfo current = nodes.get(rootNodeId); if (current == null) { - return; + // The node isn't in the cache, but its descendents might be. + clear(); + return true; } nodes.remove(rootNodeId); final int childCount = current.getChildCount(); for (int i = 0; i < childCount; i++) { final long childNodeId = current.getChildId(i); - clearSubTreeRecursiveLocked(nodes, childNodeId); + if (clearSubTreeRecursiveLocked(nodes, childNodeId)) { + current.recycle(); + return true; + } } current.recycle(); + return false; } /** diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index cda1293e93c7..42bbe20a1cab 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -995,7 +995,7 @@ <!-- Allows a calling application which manages it own calls through the self-managed {@link android.telecom.ConnectionService} APIs. See - {@link android.telecom.PhoneAccount#CAPABILITY_SELF_MANAGED for more information on the + {@link android.telecom.PhoneAccount#CAPABILITY_SELF_MANAGED} for more information on the self-managed ConnectionService APIs. <p>Protection level: normal --> @@ -1080,9 +1080,9 @@ android:priority="700" /> <!-- Required to be able to access the camera device. - <p>This will automatically enforce the <a - href="{@docRoot}guide/topics/manifest/uses-feature-element.html"> - <uses-feature>}</a> manifest element for <em>all</em> camera features. + <p>This will automatically enforce the + <a href="{@docRoot}guide/topics/manifest/uses-feature-element.html"> + uses-feature</a> manifest element for <em>all</em> camera features. If you do not require all camera features or can properly operate if a camera is not available, then you must modify your manifest as appropriate in order to install on devices that don't support all camera features.</p> diff --git a/core/res/res/drawable/emergency_icon.xml b/core/res/res/drawable/emergency_icon.xml index b2ffa2b4481c..c142be356a2b 100644 --- a/core/res/res/drawable/emergency_icon.xml +++ b/core/res/res/drawable/emergency_icon.xml @@ -18,7 +18,7 @@ Copyright (C) 2014 The Android Open Source Project android:height="24.0dp" android:viewportWidth="24.0" android:viewportHeight="24.0" - android:tint="?attr/colorControlNormal"> + android:tint="?attr/colorError"> <path android:fillColor="#FF000000" android:pathData="M6.8,17.3C5.3,15.9 4.5,14.0 4.5,12.0c0.0,-2.0 0.8,-3.8 2.1,-5.2l1.4,1.4c-1.0,1.0 -1.6,2.4 -1.6,3.8c0.0,1.5 0.6,2.9 1.6,3.9L6.8,17.3z"/> diff --git a/core/res/res/drawable/ic_faster_emergency.xml b/core/res/res/drawable/ic_faster_emergency.xml new file mode 100644 index 000000000000..680dfce5d632 --- /dev/null +++ b/core/res/res/drawable/ic_faster_emergency.xml @@ -0,0 +1,31 @@ +<!-- +Copyright (C) 2018 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24.0dp" + android:height="24.0dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0" + android:tint="?attr/colorError"> + <path + android:fillColor="#FF000000" + android:pathData="M19,3H5C3.9,3,3.01,3.9,3.01,5L3,19c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M19,19L5,19V5h14V19z" /> + <path + android:fillColor="#FF000000" + android:pathData="M 10.5 17 L 13.5 17 L 13.5 13.5 L 17 13.5 L 17 10.5 L 13.5 10.5 L 13.5 7 L 10.5 7 L 10.5 10.5 L 7 10.5 L 7 13.5 L 10.5 13.5 Z" /> + <path + android:pathData="M0,0h24v24H0V0z" /> + +</vector> diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 21c10ce89c1a..6b5a91489697 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -1423,7 +1423,7 @@ at {@link android.view.inputmethod.InputConnection#performEditorAction(int) InputConnection.performEditorAction(int)}. <p>Corresponds to - {@link android.view.inputmethod.EditorInfo#IME_FLAG_NO_FULLSCREEN}. --> + {@link android.view.inputmethod.EditorInfo#IME_FLAG_NAVIGATE_PREVIOUS}. --> <flag name="flagNavigatePrevious" value="0x4000000" /> <!-- Used to specify that there is something interesting that a forward navigation can focus on. This is like using @@ -4166,9 +4166,9 @@ row is full. The rowCount attribute may be used similarly in the vertical case. The default is horizontal. --> <attr name="orientation" /> - <!-- The maxmimum number of rows to create when automatically positioning children. --> + <!-- The maximum number of rows to create when automatically positioning children. --> <attr name="rowCount" format="integer" /> - <!-- The maxmimum number of columns to create when automatically positioning children. --> + <!-- The maximum number of columns to create when automatically positioning children. --> <attr name="columnCount" format="integer" /> <!-- When set to true, tells GridLayout to use default margins when none are specified in a view's layout parameters. diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index a10c1975339d..db03eee26630 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -2613,6 +2613,7 @@ "silent" = silent mode "users" = list of users "restart" = restart device + "emergency" = Launch emergency dialer "lockdown" = Lock down device until the user authenticates "logout" = Logout the current user --> @@ -2623,6 +2624,7 @@ <item>logout</item> <item>bugreport</item> <item>screenshot</item> + <item>emergency</item> </string-array> <!-- Number of milliseconds to hold a wake lock to ensure that drawing is fully diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 95af9a602577..eaaa86610f75 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -2989,7 +2989,7 @@ <!-- Global actions icons --> <java-symbol type="drawable" name="ic_restart" /> <java-symbol type="drawable" name="ic_screenshot" /> - + <java-symbol type="drawable" name="ic_faster_emergency" /> <java-symbol type="drawable" name="emergency_icon" /> <java-symbol type="array" name="config_convert_to_emergency_number_map" /> diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityCacheTest.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityCacheTest.java index 4de8155663f5..993378d8a4d0 100644 --- a/core/tests/coretests/src/android/view/accessibility/AccessibilityCacheTest.java +++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityCacheTest.java @@ -300,6 +300,26 @@ public class AccessibilityCacheTest { } @Test + public void subTreeChangeEventFromUncachedNode_clearsNodeInCache() { + AccessibilityNodeInfo nodeInfo = getNodeWithA11yAndWindowId(CHILD_VIEW_ID, WINDOW_ID_1); + long id = nodeInfo.getSourceNodeId(); + mAccessibilityCache.add(nodeInfo); + nodeInfo.recycle(); + + AccessibilityEvent event = AccessibilityEvent + .obtain(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED); + event.setContentChangeTypes(AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE); + event.setSource(getMockViewWithA11yAndWindowIds(PARENT_VIEW_ID, WINDOW_ID_1)); + + mAccessibilityCache.onAccessibilityEvent(event); + AccessibilityNodeInfo shouldBeNull = mAccessibilityCache.getNode(WINDOW_ID_1, id); + if (shouldBeNull != null) { + shouldBeNull.recycle(); + } + assertNull(shouldBeNull); + } + + @Test public void scrollEvent_clearsNodeAndChild() { AccessibilityEvent event = AccessibilityEvent .obtain(AccessibilityEvent.TYPE_VIEW_SCROLLED); diff --git a/location/java/android/location/Criteria.java b/location/java/android/location/Criteria.java index a6099be60875..74eb4450d42c 100644 --- a/location/java/android/location/Criteria.java +++ b/location/java/android/location/Criteria.java @@ -21,9 +21,9 @@ import android.os.Parcelable; /** * A class indicating the application criteria for selecting a - * location provider. Providers maybe ordered according to accuracy, - * power usage, ability to report altitude, speed, - * and bearing, and monetary cost. + * location provider. Providers may be ordered according to accuracy, + * power usage, ability to report altitude, speed, bearing, and monetary + * cost. */ public class Criteria implements Parcelable { /** diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index 0c38c38e88ff..8686253506f4 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -4552,7 +4552,7 @@ public class AudioManager { /** * The message sent to apps when the contents of the device list changes if they provide - * a {#link Handler} object to addOnAudioDeviceConnectionListener(). + * a {@link Handler} object to addOnAudioDeviceConnectionListener(). */ private final static int MSG_DEVICES_CALLBACK_REGISTERED = 0; private final static int MSG_DEVICES_DEVICES_ADDED = 1; diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java index 54800ae213cd..2c67f3205eb1 100644 --- a/media/java/android/media/AudioRecord.java +++ b/media/java/android/media/AudioRecord.java @@ -467,7 +467,7 @@ public class AudioRecord implements AudioRouting * .setSampleRate(32000) * .setChannelMask(AudioFormat.CHANNEL_IN_MONO) * .build()) - * .setBufferSize(2*minBuffSize) + * .setBufferSizeInBytes(2*minBuffSize) * .build(); * </pre> * <p> diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java index 97d0a6ecd6a3..3151c2818d71 100644 --- a/media/java/android/media/MediaPlayer.java +++ b/media/java/android/media/MediaPlayer.java @@ -226,7 +226,7 @@ import java.util.Vector; * transfers the object to the <em>Prepared</em> state once the method call * returns, or a call to {@link #prepareAsync()} (asynchronous) which * first transfers the object to the <em>Preparing</em> state after the - * call returns (which occurs almost right way) while the internal + * call returns (which occurs almost right away) while the internal * player engine continues working on the rest of preparation work * until the preparation work completes. When the preparation completes or when {@link #prepare()} call returns, * the internal player engine then calls a user supplied callback method, diff --git a/media/java/android/media/MediaPlayer2Impl.java b/media/java/android/media/MediaPlayer2Impl.java index 56423fda0404..828c673944cc 100644 --- a/media/java/android/media/MediaPlayer2Impl.java +++ b/media/java/android/media/MediaPlayer2Impl.java @@ -4781,7 +4781,7 @@ public final class MediaPlayer2Impl extends MediaPlayer2 { private void sendCompleteNotification(int status) { // In {@link #notifyWhenCommandLabelReached} case, a separate callback - // {#link #onCommandLabelReached} is already called in {@code process()}. + // {@link #onCommandLabelReached} is already called in {@code process()}. if (mMediaCallType == CALL_COMPLETED_NOTIFY_WHEN_COMMAND_LABEL_REACHED) { return; } diff --git a/media/mca/filterpacks/java/android/filterpacks/videosrc/SurfaceTextureSource.java b/media/mca/filterpacks/java/android/filterpacks/videosrc/SurfaceTextureSource.java index 6595baa594d2..7919723b80a8 100644 --- a/media/mca/filterpacks/java/android/filterpacks/videosrc/SurfaceTextureSource.java +++ b/media/mca/filterpacks/java/android/filterpacks/videosrc/SurfaceTextureSource.java @@ -38,7 +38,7 @@ import android.util.Log; * <p>To use, connect up the sourceListener callback, and then when executing * the graph, use the SurfaceTexture object passed to the callback to feed * frames into the filter graph. For example, pass the SurfaceTexture into - * {#link + * {@link * android.hardware.Camera.setPreviewTexture(android.graphics.SurfaceTexture)}. * This filter is intended for applications that need for flexibility than the * CameraSource and MediaSource provide. Note that the application needs to diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java index bb8fbe2da9c9..1a8e24f46d48 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java @@ -143,8 +143,8 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> void onProfileStateChanged(LocalBluetoothProfile profile, int newProfileState) { if (Utils.D) { - Log.d(TAG, "onProfileStateChanged: profile " + profile + - " newProfileState " + newProfileState); + Log.d(TAG, "onProfileStateChanged: profile " + profile + ", device=" + mDevice + + ", newProfileState " + newProfileState); } if (mLocalAdapter.getBluetoothState() == BluetoothAdapter.STATE_TURNING_OFF) { @@ -224,6 +224,10 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> connectWithoutResettingTimer(connectAllProfiles); } + public boolean isHearingAidDevice() { + return mHiSyncId != BluetoothHearingAid.HI_SYNC_ID_INVALID; + } + void onBondingDockConnect() { // Attempt to connect if UUIDs are available. Otherwise, // we will connect when the ACTION_UUID intent arrives. @@ -1189,7 +1193,8 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> * @return {@code true} if {@code cachedBluetoothDevice} is a2dp device */ public boolean isA2dpDevice() { - return mProfileManager.getA2dpProfile().getConnectionStatus(mDevice) == + A2dpProfile a2dpProfile = mProfileManager.getA2dpProfile(); + return a2dpProfile != null && a2dpProfile.getConnectionStatus(mDevice) == BluetoothProfile.STATE_CONNECTED; } @@ -1197,7 +1202,17 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> * @return {@code true} if {@code cachedBluetoothDevice} is HFP device */ public boolean isHfpDevice() { - return mProfileManager.getHeadsetProfile().getConnectionStatus(mDevice) == + HeadsetProfile headsetProfile = mProfileManager.getHeadsetProfile(); + return headsetProfile != null && headsetProfile.getConnectionStatus(mDevice) == + BluetoothProfile.STATE_CONNECTED; + } + + /** + * @return {@code true} if {@code cachedBluetoothDevice} is Hearing Aid device + */ + public boolean isConnectedHearingAidDevice() { + HearingAidProfile hearingAidProfile = mProfileManager.getHearingAidProfile(); + return hearingAidProfile != null && hearingAidProfile.getConnectionStatus(mDevice) == BluetoothProfile.STATE_CONNECTED; } } diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java index e9d96ae0310f..1bfcf9ade8a5 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java @@ -162,14 +162,14 @@ public class CachedBluetoothDeviceManager { */ public synchronized String getHearingAidPairDeviceSummary(CachedBluetoothDevice device) { String pairDeviceSummary = null; - if (device.getHiSyncId() != BluetoothHearingAid.HI_SYNC_ID_INVALID) { - for (CachedBluetoothDevice hearingAidDevice : mHearingAidDevicesNotAddedInCache) { - if (hearingAidDevice.getHiSyncId() != BluetoothHearingAid.HI_SYNC_ID_INVALID - && hearingAidDevice.getHiSyncId() == device.getHiSyncId()) { - pairDeviceSummary = hearingAidDevice.getConnectionSummary(); - } - } + CachedBluetoothDevice otherHearingAidDevice = + getHearingAidOtherDevice(device, device.getHiSyncId()); + if (otherHearingAidDevice != null) { + pairDeviceSummary = otherHearingAidDevice.getConnectionSummary(); } + log("getHearingAidPairDeviceSummary: pairDeviceSummary=" + pairDeviceSummary + + ", otherHearingAidDevice=" + otherHearingAidDevice); + return pairDeviceSummary; } @@ -358,7 +358,7 @@ public class CachedBluetoothDeviceManager { } } - private CachedBluetoothDevice getHearingAidOtherDevice(CachedBluetoothDevice thisDevice, + public CachedBluetoothDevice getHearingAidOtherDevice(CachedBluetoothDevice thisDevice, long hiSyncId) { if (hiSyncId == BluetoothHearingAid.HI_SYNC_ID_INVALID) { return null; diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java index 62f8724870e3..7ff5448ba766 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java @@ -123,6 +123,14 @@ public class LocalBluetoothProfileManager { ParcelUuid[] uuids = adapter.getUuids(); + List<Integer> supportedList = mLocalAdapter.getSupportedProfiles(); + if (supportedList.contains(BluetoothProfile.HEARING_AID)) { + mHearingAidProfile = new HearingAidProfile(mContext, mLocalAdapter, mDeviceManager, + this); + addProfile(mHearingAidProfile, HearingAidProfile.NAME, + BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED); + } + // uuids may be null if Bluetooth is turned off if (uuids != null) { updateLocalProfiles(uuids); @@ -159,13 +167,6 @@ public class LocalBluetoothProfileManager { addProfile(mPbapProfile, PbapServerProfile.NAME, BluetoothPbap.ACTION_CONNECTION_STATE_CHANGED); - List<Integer> supportedList = mLocalAdapter.getSupportedProfiles(); - if (supportedList.contains(BluetoothProfile.HEARING_AID)) { - mHearingAidProfile = new HearingAidProfile(mContext, mLocalAdapter, mDeviceManager, - this); - addProfile(mHearingAidProfile, HearingAidProfile.NAME, - BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED); - } if (DEBUG) Log.d(TAG, "LocalBluetoothProfileManager construction complete"); } @@ -360,9 +361,10 @@ public class LocalBluetoothProfileManager { Log.i(TAG, "Failed to connect " + mProfile + " device"); } - if (getHearingAidProfile() != null && - mProfile instanceof HearingAidProfile && - (newState == BluetoothProfile.STATE_CONNECTED)) { + boolean isHearingAidProfile = (getHearingAidProfile() != null) && + (mProfile instanceof HearingAidProfile); + + if (isHearingAidProfile && (newState == BluetoothProfile.STATE_CONNECTED)) { // Check if the HiSyncID has being initialized if (cachedDevice.getHiSyncId() == BluetoothHearingAid.HI_SYNC_ID_INVALID) { @@ -375,10 +377,22 @@ public class LocalBluetoothProfileManager { } } - mEventManager.dispatchProfileConnectionStateChanged(cachedDevice, newState, - mProfile.getProfileId()); cachedDevice.onProfileStateChanged(mProfile, newState); cachedDevice.refresh(); + + if (isHearingAidProfile) { + CachedBluetoothDevice otherDevice = + mDeviceManager.getHearingAidOtherDevice(cachedDevice, cachedDevice.getHiSyncId()); + if (otherDevice != null) { + if (DEBUG) { + Log.d(TAG, "Refreshing other hearing aid=" + otherDevice + + ", newState=" + newState); + } + otherDevice.refresh(); + } + } + mEventManager.dispatchProfileConnectionStateChanged(cachedDevice, newState, + mProfile.getProfileId()); } } diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java index 16ed85cf5afa..db9b44f2c132 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java @@ -835,4 +835,20 @@ public class CachedBluetoothDeviceManagerTest { assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.HEADSET)).isFalse(); assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.HEARING_AID)).isFalse(); } + + /** + * Test to verify getHearingAidOtherDevice() for hearing aid devices with same HiSyncId. + */ + @Test + public void testGetHearingAidOtherDevice_bothHearingAidsPaired_returnsOtherDevice() { + mCachedDevice1.setHiSyncId(HISYNCID1); + mCachedDevice2.setHiSyncId(HISYNCID1); + mCachedDeviceManager.mCachedDevices.add(mCachedDevice1); + mCachedDeviceManager.mHearingAidDevicesNotAddedInCache.add(mCachedDevice2); + doAnswer((invocation) -> DEVICE_SUMMARY_1).when(mCachedDevice1).getConnectionSummary(); + doAnswer((invocation) -> DEVICE_SUMMARY_2).when(mCachedDevice2).getConnectionSummary(); + + assertThat(mCachedDeviceManager.getHearingAidOtherDevice(mCachedDevice1, HISYNCID1)) + .isEqualTo(mCachedDevice2); + } } diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java index 927a94f6b017..30da88245913 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java @@ -28,6 +28,7 @@ import static org.robolectric.Shadows.shadowOf; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothHearingAid; import android.bluetooth.BluetoothProfile; import android.content.Context; import android.media.AudioManager; @@ -572,4 +573,55 @@ public class CachedBluetoothDeviceTest { assertThat(mCachedDevice.isHfpDevice()).isFalse(); } + + @Test + public void isConnectedHearingAidDevice_connected_returnTrue() { + when(mProfileManager.getHearingAidProfile()).thenReturn(mHearingAidProfile); + when(mHearingAidProfile.getConnectionStatus(mDevice)). + thenReturn(BluetoothProfile.STATE_CONNECTED); + + assertThat(mCachedDevice.isConnectedHearingAidDevice()).isTrue(); + } + + @Test + public void isConnectedHearingAidDevice_disconnected_returnFalse() { + when(mProfileManager.getHearingAidProfile()).thenReturn(mHearingAidProfile); + when(mHearingAidProfile.getConnectionStatus(mDevice)). + thenReturn(BluetoothProfile.STATE_DISCONNECTED); + + assertThat(mCachedDevice.isConnectedHearingAidDevice()).isFalse(); + } + + @Test + public void isConnectedHfpDevice_profileIsNull_returnFalse() { + when(mProfileManager.getHeadsetProfile()).thenReturn(null); + + assertThat(mCachedDevice.isHfpDevice()).isFalse(); + } + + @Test + public void isConnectedA2dpDevice_profileIsNull_returnFalse() { + when(mProfileManager.getA2dpProfile()).thenReturn(null); + + assertThat(mCachedDevice.isA2dpDevice()).isFalse(); + } + + @Test + public void isConnectedHearingAidDevice_profileIsNull_returnFalse() { + when(mProfileManager.getHearingAidProfile()).thenReturn(null); + + assertThat(mCachedDevice.isConnectedHearingAidDevice()).isFalse(); + } + + @Test + public void testIsHearingAidDevice_isHearingAidDevice() { + mCachedDevice.setHiSyncId(0x1234); + assertThat(mCachedDevice.isHearingAidDevice()).isTrue(); + } + + @Test + public void testIsHearingAidDevice_isNotHearingAidDevice() { + mCachedDevice.setHiSyncId(BluetoothHearingAid.HI_SYNC_ID_INVALID); + assertThat(mCachedDevice.isHearingAidDevice()).isFalse(); + } } diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java index d342bc878477..d7b651b876d3 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java @@ -21,6 +21,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.anyLong; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -52,6 +53,7 @@ import org.robolectric.annotation.Config; @RunWith(RobolectricTestRunner.class) @Config(resourceDir = "../../res") public class LocalBluetoothProfileManagerTest { + private final static long HI_SYNC_ID = 0x1234; @Mock private CachedBluetoothDeviceManager mDeviceManager; @Mock @@ -62,6 +64,8 @@ public class LocalBluetoothProfileManagerTest { private BluetoothDevice mDevice; @Mock private CachedBluetoothDevice mCachedBluetoothDevice; + @Mock + private CachedBluetoothDevice mHearingAidOtherDevice; private Context mContext; private LocalBluetoothProfileManager mProfileManager; @@ -200,6 +204,32 @@ public class LocalBluetoothProfileManagerTest { } /** + * Verify BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED with uuid intent will dispatch to + * refresh both sides devices. + */ + @Test + public void stateChangedHandler_receiveHAPConnectionStateChanged_shouldRefreshBothSides() { + ArrayList<Integer> supportProfiles = new ArrayList<>(); + supportProfiles.add(BluetoothProfile.HEARING_AID); + when(mAdapter.getSupportedProfiles()).thenReturn(supportProfiles); + when(mCachedBluetoothDevice.getHiSyncId()).thenReturn(HI_SYNC_ID); + when(mDeviceManager.getHearingAidOtherDevice(mCachedBluetoothDevice, HI_SYNC_ID)) + .thenReturn(mHearingAidOtherDevice); + + mProfileManager = new LocalBluetoothProfileManager(mContext, mAdapter, mDeviceManager, + mEventManager); + mIntent = new Intent(BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED); + mIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice); + mIntent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, BluetoothProfile.STATE_CONNECTING); + mIntent.putExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_CONNECTED); + + mContext.sendBroadcast(mIntent); + + verify(mCachedBluetoothDevice).refresh(); + verify(mHearingAidOtherDevice).refresh(); + } + + /** * Verify BluetoothPan.ACTION_CONNECTION_STATE_CHANGED intent with uuid will dispatch to * profile connection state changed callback */ diff --git a/packages/SystemUI/res/layout/global_actions_wrapped.xml b/packages/SystemUI/res/layout/global_actions_wrapped.xml index b715def73294..7f4e0d21078f 100644 --- a/packages/SystemUI/res/layout/global_actions_wrapped.xml +++ b/packages/SystemUI/res/layout/global_actions_wrapped.xml @@ -3,7 +3,9 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" + android:layout_gravity="top|right" android:layout_marginBottom="0dp" + android:orientation="vertical" android:paddingTop="@dimen/global_actions_top_padding" android:clipToPadding="false" android:theme="@style/qs_theme" @@ -17,7 +19,19 @@ android:layout_gravity="top|right" android:gravity="center" android:orientation="vertical" - android:padding="12dp" - android:translationZ="9dp" /> + android:padding="@dimen/global_actions_padding" + android:translationZ="@dimen/global_actions_translate" /> + + <!-- For separated button--> + <FrameLayout + android:id="@+id/separated_button" + android:layout_width="@dimen/global_actions_panel_width" + android:layout_height="wrap_content" + android:layout_gravity="top|right" + android:layout_marginTop="6dp" + android:gravity="center" + android:orientation="vertical" + android:padding="@dimen/global_actions_padding" + android:translationZ="@dimen/global_actions_translate" /> </com.android.systemui.HardwareUiLayout> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 7d90e02d0f2f..79e1fae98c21 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -922,6 +922,10 @@ <dimen name="global_actions_top_padding">120dp</dimen> + <dimen name="global_actions_padding">12dp</dimen> + + <dimen name="global_actions_translate">9dp</dimen> + <!-- The maximum offset in either direction that elements are moved horizontally to prevent burn-in on AOD. --> <dimen name="burn_in_prevention_offset_x">8dp</dimen> diff --git a/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java b/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java index 943558943821..f4f2ebce4f53 100644 --- a/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java +++ b/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java @@ -38,6 +38,7 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.telephony.IccCardConstants.State; import com.android.internal.widget.LockPatternUtils; import com.android.internal.util.EmergencyAffordanceManager; +import com.android.systemui.util.EmergencyDialerConstants; /** * This class implements a smart emergency button that updates itself based @@ -47,11 +48,13 @@ import com.android.internal.util.EmergencyAffordanceManager; */ public class EmergencyButton extends Button { private static final Intent INTENT_EMERGENCY_DIAL = new Intent() - .setAction("com.android.phone.EmergencyDialer.DIAL") + .setAction(EmergencyDialerConstants.ACTION_DIAL) .setPackage("com.android.phone") .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS - | Intent.FLAG_ACTIVITY_CLEAR_TOP); + | Intent.FLAG_ACTIVITY_CLEAR_TOP) + .putExtra(EmergencyDialerConstants.EXTRA_ENTRY_TYPE, + EmergencyDialerConstants.ENTRY_TYPE_LOCKSCREEN_BUTTON); private static final String LOG_TAG = "EmergencyButton"; private final EmergencyAffordanceManager mEmergencyAffordanceManager; diff --git a/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java b/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java index 98dc3219acc6..198a4e6cedb8 100644 --- a/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java +++ b/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java @@ -27,32 +27,33 @@ import android.view.View; import android.view.ViewGroup; import android.view.ViewOutlineProvider; import android.view.ViewTreeObserver; -import android.widget.FrameLayout; import android.widget.LinearLayout; + import com.android.systemui.tuner.TunerService; import com.android.systemui.tuner.TunerService.Tunable; import com.android.systemui.util.leak.RotationUtils; -import java.util.ArrayList; - import static com.android.systemui.util.leak.RotationUtils.ROTATION_LANDSCAPE; import static com.android.systemui.util.leak.RotationUtils.ROTATION_NONE; import static com.android.systemui.util.leak.RotationUtils.ROTATION_SEASCAPE; -public class HardwareUiLayout extends FrameLayout implements Tunable { +public class HardwareUiLayout extends LinearLayout implements Tunable { private static final String EDGE_BLEED = "sysui_hwui_edge_bleed"; private static final String ROUNDED_DIVIDER = "sysui_hwui_rounded_divider"; private final int[] mTmp2 = new int[2]; - private View mChild; + private View mList; + private View mSeparatedView; private int mOldHeight; private boolean mAnimating; private AnimatorSet mAnimation; private View mDivision; private boolean mHasOutsideTouch; - private HardwareBgDrawable mBackground; + private HardwareBgDrawable mListBackground; + private HardwareBgDrawable mSeparatedViewBackground; private Animator mAnimator; private boolean mCollapse; + private boolean mHasSeparatedButton; private int mEndPoint; private boolean mEdgeBleed; private boolean mRoundedDivider; @@ -91,16 +92,19 @@ public class HardwareUiLayout extends FrameLayout implements Tunable { mRoundedDivider = Settings.Secure.getInt(getContext().getContentResolver(), ROUNDED_DIVIDER, 0) != 0; updateEdgeMargin(mEdgeBleed ? 0 : getEdgePadding()); - mBackground = new HardwareBgDrawable(mRoundedDivider, !mEdgeBleed, getContext()); - if (mChild != null) { - mChild.setBackground(mBackground); + mListBackground = new HardwareBgDrawable(mRoundedDivider, !mEdgeBleed, getContext()); + mSeparatedViewBackground = new HardwareBgDrawable(mRoundedDivider, !mEdgeBleed, + getContext()); + if (mList != null) { + mList.setBackground(mListBackground); + mSeparatedView.setBackground(mSeparatedViewBackground); requestLayout(); } } private void updateEdgeMargin(int edge) { - if (mChild != null) { - MarginLayoutParams params = (MarginLayoutParams) mChild.getLayoutParams(); + if (mList != null) { + MarginLayoutParams params = (MarginLayoutParams) mList.getLayoutParams(); if (mRotation == ROTATION_LANDSCAPE) { params.topMargin = edge; } else if (mRotation == ROTATION_SEASCAPE) { @@ -108,7 +112,19 @@ public class HardwareUiLayout extends FrameLayout implements Tunable { } else { params.rightMargin = edge; } - mChild.setLayoutParams(params); + mList.setLayoutParams(params); + } + + if (mSeparatedView != null) { + MarginLayoutParams params = (MarginLayoutParams) mSeparatedView.getLayoutParams(); + if (mRotation == ROTATION_LANDSCAPE) { + params.topMargin = edge; + } else if (mRotation == ROTATION_SEASCAPE) { + params.bottomMargin = edge; + } else { + params.rightMargin = edge; + } + mSeparatedView.setLayoutParams(params); } } @@ -119,13 +135,15 @@ public class HardwareUiLayout extends FrameLayout implements Tunable { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); - if (mChild == null) { + if (mList == null) { if (getChildCount() != 0) { - mChild = getChildAt(0); - mChild.setBackground(mBackground); + mList = getChildAt(0); + mList.setBackground(mListBackground); + mSeparatedView = getChildAt(1); + mSeparatedView.setBackground(mSeparatedViewBackground); updateEdgeMargin(mEdgeBleed ? 0 : getEdgePadding()); - mOldHeight = mChild.getMeasuredHeight(); - mChild.addOnLayoutChangeListener( + mOldHeight = mList.getMeasuredHeight(); + mList.addOnLayoutChangeListener( (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> updatePosition()); updateRotation(); @@ -133,7 +151,7 @@ public class HardwareUiLayout extends FrameLayout implements Tunable { return; } } - int newHeight = mChild.getMeasuredHeight(); + int newHeight = mList.getMeasuredHeight(); if (newHeight != mOldHeight) { animateChild(mOldHeight, newHeight); } @@ -170,37 +188,60 @@ public class HardwareUiLayout extends FrameLayout implements Tunable { } else { rotateLeft(); } + if (mHasSeparatedButton) { + if (from == ROTATION_SEASCAPE || to == ROTATION_SEASCAPE) { + // Separated view has top margin, so seascape separated view need special rotation, + // not a full left or right rotation. + swapLeftAndTop(mSeparatedView); + } else if (from == ROTATION_LANDSCAPE) { + rotateRight(mSeparatedView); + } else { + rotateLeft(mSeparatedView); + } + } if (to != ROTATION_NONE) { - if (mChild instanceof LinearLayout) { + if (mList instanceof LinearLayout) { mRotatedBackground = true; - mBackground.setRotatedBackground(true); - LinearLayout linearLayout = (LinearLayout) mChild; + mListBackground.setRotatedBackground(true); + mSeparatedViewBackground.setRotatedBackground(true); + LinearLayout linearLayout = (LinearLayout) mList; if (mSwapOrientation) { linearLayout.setOrientation(LinearLayout.HORIZONTAL); + setOrientation(LinearLayout.HORIZONTAL); } - swapDimens(this.mChild); + swapDimens(mList); + swapDimens(mSeparatedView); } } else { - if (mChild instanceof LinearLayout) { + if (mList instanceof LinearLayout) { mRotatedBackground = false; - mBackground.setRotatedBackground(false); - LinearLayout linearLayout = (LinearLayout) mChild; + mListBackground.setRotatedBackground(false); + mSeparatedViewBackground.setRotatedBackground(false); + LinearLayout linearLayout = (LinearLayout) mList; if (mSwapOrientation) { linearLayout.setOrientation(LinearLayout.VERTICAL); + setOrientation(LinearLayout.VERTICAL); } - swapDimens(mChild); + swapDimens(mList); + swapDimens(mSeparatedView); } } } private void rotateRight() { rotateRight(this); - rotateRight(mChild); + rotateRight(mList); swapDimens(this); - LayoutParams p = (LayoutParams) mChild.getLayoutParams(); + LayoutParams p = (LayoutParams) mList.getLayoutParams(); p.gravity = rotateGravityRight(p.gravity); - mChild.setLayoutParams(p); + mList.setLayoutParams(p); + + LayoutParams separatedViewLayoutParams = (LayoutParams) mSeparatedView.getLayoutParams(); + separatedViewLayoutParams.gravity = rotateGravityRight(separatedViewLayoutParams.gravity); + mSeparatedView.setLayoutParams(separatedViewLayoutParams); + + setGravity(p.gravity); } private void swapDimens(View v) { @@ -247,12 +288,18 @@ public class HardwareUiLayout extends FrameLayout implements Tunable { private void rotateLeft() { rotateLeft(this); - rotateLeft(mChild); + rotateLeft(mList); swapDimens(this); - LayoutParams p = (LayoutParams) mChild.getLayoutParams(); + LayoutParams p = (LayoutParams) mList.getLayoutParams(); p.gravity = rotateGravityLeft(p.gravity); - mChild.setLayoutParams(p); + mList.setLayoutParams(p); + + LayoutParams separatedViewLayoutParams = (LayoutParams) mSeparatedView.getLayoutParams(); + separatedViewLayoutParams.gravity = rotateGravityLeft(separatedViewLayoutParams.gravity); + mSeparatedView.setLayoutParams(separatedViewLayoutParams); + + setGravity(p.gravity); } private int rotateGravityLeft(int gravity) { @@ -310,6 +357,15 @@ public class HardwareUiLayout extends FrameLayout implements Tunable { v.setLayoutParams(params); } + private void swapLeftAndTop(View v) { + v.setPadding(v.getPaddingTop(), v.getPaddingLeft(), v.getPaddingBottom(), + v.getPaddingRight()); + MarginLayoutParams params = (MarginLayoutParams) v.getLayoutParams(); + params.setMargins(params.topMargin, params.leftMargin, params.bottomMargin, + params.rightMargin); + v.setLayoutParams(params); + } + @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); @@ -329,14 +385,14 @@ public class HardwareUiLayout extends FrameLayout implements Tunable { mAnimating = false; } }); - int fromTop = mChild.getTop(); - int fromBottom = mChild.getBottom(); + int fromTop = mList.getTop(); + int fromBottom = mList.getBottom(); int toTop = fromTop - ((newHeight - oldHeight) / 2); int toBottom = fromBottom + ((newHeight - oldHeight) / 2); - ObjectAnimator top = ObjectAnimator.ofInt(mChild, "top", fromTop, toTop); - top.addUpdateListener(animation -> mBackground.invalidateSelf()); + ObjectAnimator top = ObjectAnimator.ofInt(mList, "top", fromTop, toTop); + top.addUpdateListener(animation -> mListBackground.invalidateSelf()); mAnimation.playTogether(top, - ObjectAnimator.ofInt(mChild, "bottom", fromBottom, toBottom)); + ObjectAnimator.ofInt(mList, "bottom", fromBottom, toBottom)); } public void setDivisionView(View v) { @@ -350,26 +406,30 @@ public class HardwareUiLayout extends FrameLayout implements Tunable { } private void updatePosition() { - if (mChild == null) return; + if (mList == null) return; + // If got separated button, setRotatedBackground to false, + // all items won't get white background. + mListBackground.setRotatedBackground(mHasSeparatedButton); + mSeparatedViewBackground.setRotatedBackground(mHasSeparatedButton); if (mDivision != null && mDivision.getVisibility() == VISIBLE) { int index = mRotatedBackground ? 0 : 1; mDivision.getLocationOnScreen(mTmp2); float trans = mRotatedBackground ? mDivision.getTranslationX() : mDivision.getTranslationY(); int viewTop = (int) (mTmp2[index] + trans); - mChild.getLocationOnScreen(mTmp2); + mList.getLocationOnScreen(mTmp2); viewTop -= mTmp2[index]; setCutPoint(viewTop); } else { - setCutPoint(mChild.getMeasuredHeight()); + setCutPoint(mList.getMeasuredHeight()); } } private void setCutPoint(int point) { - int curPoint = mBackground.getCutPoint(); + int curPoint = mListBackground.getCutPoint(); if (curPoint == point) return; if (getAlpha() == 0 || curPoint == 0) { - mBackground.setCutPoint(point); + mListBackground.setCutPoint(point); return; } if (mAnimator != null) { @@ -379,7 +439,7 @@ public class HardwareUiLayout extends FrameLayout implements Tunable { mAnimator.cancel(); } mEndPoint = point; - mAnimator = ObjectAnimator.ofInt(mBackground, "cutPoint", curPoint, point); + mAnimator = ObjectAnimator.ofInt(mListBackground, "cutPoint", curPoint, point); if (mCollapse) { mAnimator.setStartDelay(300); mCollapse = false; @@ -404,6 +464,10 @@ public class HardwareUiLayout extends FrameLayout implements Tunable { mCollapse = true; } + public void setHasSeparatedButton(boolean hasSeparatedButton) { + mHasSeparatedButton = hasSeparatedButton; + } + public static HardwareUiLayout get(View v) { if (v instanceof HardwareUiLayout) return (HardwareUiLayout) v; if (v.getParent() instanceof View) { @@ -413,14 +477,14 @@ public class HardwareUiLayout extends FrameLayout implements Tunable { } private final ViewTreeObserver.OnComputeInternalInsetsListener mInsetsListener = inoutInfo -> { - if (mHasOutsideTouch || (mChild == null)) { + if (mHasOutsideTouch || (mList == null)) { inoutInfo.setTouchableInsets( ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME); return; } inoutInfo.setTouchableInsets( ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT); - inoutInfo.contentInsets.set(mChild.getLeft(), mChild.getTop(), - 0, getBottom() - mChild.getBottom()); + inoutInfo.contentInsets.set(mList.getLeft(), mList.getTop(), + 0, getBottom() - mList.getBottom()); }; } diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java index d232108ded40..897ab88215ef 100644 --- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java +++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java @@ -28,12 +28,10 @@ import android.app.WallpaperManager; import android.app.admin.DevicePolicyManager; import android.app.trust.TrustManager; import android.content.BroadcastReceiver; -import android.content.ComponentName; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; -import android.content.ServiceConnection; import android.content.pm.UserInfo; import android.database.ContentObserver; import android.graphics.Point; @@ -42,9 +40,7 @@ import android.media.AudioManager; import android.net.ConnectivityManager; import android.os.Build; import android.os.Handler; -import android.os.IBinder; import android.os.Message; -import android.os.Messenger; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemProperties; @@ -68,9 +64,9 @@ import android.view.Window; import android.view.WindowManager; import android.view.WindowManagerGlobal; import android.view.accessibility.AccessibilityEvent; -import android.widget.AdapterView; import android.widget.AdapterView.OnItemLongClickListener; import android.widget.BaseAdapter; +import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.ImageView.ScaleType; import android.widget.LinearLayout; @@ -93,6 +89,7 @@ import com.android.systemui.Interpolators; import com.android.systemui.colorextraction.SysuiColorExtractor; import com.android.systemui.plugins.GlobalActions.GlobalActionsManager; import com.android.systemui.statusbar.phone.ScrimController; +import com.android.systemui.util.EmergencyDialerConstants; import com.android.systemui.volume.SystemUIInterpolators.LogAccelerateInterpolator; import java.util.ArrayList; @@ -104,7 +101,7 @@ import java.util.List; * is provisioned. */ class GlobalActionsDialog implements DialogInterface.OnDismissListener, - DialogInterface.OnClickListener { + DialogInterface.OnClickListener, DialogInterface.OnShowListener { static public final String SYSTEM_DIALOG_REASON_KEY = "reason"; static public final String SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS = "globalactions"; @@ -127,6 +124,7 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, private static final String GLOBAL_ACTION_KEY_ASSIST = "assist"; private static final String GLOBAL_ACTION_KEY_RESTART = "restart"; private static final String GLOBAL_ACTION_KEY_LOGOUT = "logout"; + private static final String GLOBAL_ACTION_KEY_EMERGENCY = "emergency"; private static final String GLOBAL_ACTION_KEY_SCREENSHOT = "screenshot"; private final Context mContext; @@ -153,6 +151,7 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, private boolean mHasVibrator; private boolean mHasLogoutButton; private boolean mHasLockdownButton; + private boolean mSeparatedEmergencyButtonEnabled; private final boolean mShowSilentToggle; private final EmergencyAffordanceManager mEmergencyAffordanceManager; private final ScreenshotHelper mScreenshotHelper; @@ -319,6 +318,7 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, ArraySet<String> addedKeys = new ArraySet<String>(); mHasLogoutButton = false; mHasLockdownButton = false; + mSeparatedEmergencyButtonEnabled = true; for (int i = 0; i < defaultActions.length; i++) { String actionKey = defaultActions[i]; if (addedKeys.contains(actionKey)) { @@ -365,6 +365,11 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, mItems.add(new LogoutAction()); mHasLogoutButton = true; } + } else if (GLOBAL_ACTION_KEY_EMERGENCY.equals(actionKey)) { + if (mSeparatedEmergencyButtonEnabled + && !mEmergencyAffordanceManager.needsEmergencyAffordance()) { + mItems.add(new EmergencyDialerAction()); + } } else { Log.e(TAG, "Invalid global action key " + actionKey); } @@ -386,11 +391,13 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, } return false; }; - ActionsDialog dialog = new ActionsDialog(mContext, this, mAdapter, onItemLongClickListener); + ActionsDialog dialog = new ActionsDialog(mContext, this, mAdapter, onItemLongClickListener, + mSeparatedEmergencyButtonEnabled); dialog.setCanceledOnTouchOutside(false); // Handled by the custom class. dialog.setKeyguardShowing(mKeyguardShowing); dialog.setOnDismissListener(this); + dialog.setOnShowListener(this); return dialog; } @@ -441,6 +448,33 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, } } + private class EmergencyDialerAction extends SinglePressAction { + private EmergencyDialerAction() { + super(R.drawable.ic_faster_emergency, + R.string.global_action_emergency); + } + + @Override + public void onPress() { + MetricsLogger.action(mContext, MetricsEvent.ACTION_EMERGENCY_DIALER_FROM_POWER_MENU); + Intent intent = new Intent(EmergencyDialerConstants.ACTION_DIAL); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); + intent.putExtra(EmergencyDialerConstants.EXTRA_ENTRY_TYPE, + EmergencyDialerConstants.ENTRY_TYPE_POWER_MENU); + mContext.startActivityAsUser(intent, UserHandle.CURRENT); + } + + @Override + public boolean showDuringKeyguard() { + return true; + } + + @Override + public boolean showBeforeProvisioning() { + return true; + } + } + private final class RestartAction extends SinglePressAction implements LongPressAction { private RestartAction() { super(R.drawable.ic_restart, R.string.global_action_restart); @@ -626,6 +660,12 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, } private Action getEmergencyAction() { + Drawable emergencyIcon = mContext.getDrawable(R.drawable.emergency_icon); + if(!mSeparatedEmergencyButtonEnabled) { + // use un-colored legacy treatment + emergencyIcon.setTintList(null); + } + return new SinglePressAction(R.drawable.emergency_icon, R.string.global_action_emergency) { @Override @@ -823,6 +863,11 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, item.onPress(); } + /** {@inheritDoc} */ + public void onShow(DialogInterface dialog) { + MetricsLogger.visible(mContext, MetricsEvent.POWER_MENU); + } + /** * The adapter used for the list within the global actions dialog, taking * into account whether the keyguard is showing via @@ -1354,15 +1399,17 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, private final Context mContext; private final MyAdapter mAdapter; private final LinearLayout mListView; + private final FrameLayout mSeparatedView; private final HardwareUiLayout mHardwareLayout; private final OnClickListener mClickListener; private final OnItemLongClickListener mLongClickListener; private final GradientDrawable mGradientDrawable; private final ColorExtractor mColorExtractor; private boolean mKeyguardShowing; + private boolean mShouldDisplaySeparatedButton; public ActionsDialog(Context context, OnClickListener clickListener, MyAdapter adapter, - OnItemLongClickListener longClickListener) { + OnItemLongClickListener longClickListener, boolean shouldDisplaySeparatedButton) { super(context, com.android.systemui.R.style.Theme_SystemUI_Dialog_GlobalActions); mContext = context; mAdapter = adapter; @@ -1370,6 +1417,7 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, mLongClickListener = longClickListener; mGradientDrawable = new GradientDrawable(mContext); mColorExtractor = Dependency.get(SysuiColorExtractor.class); + mShouldDisplaySeparatedButton = shouldDisplaySeparatedButton; // Window initialization Window window = getWindow(); @@ -1393,8 +1441,13 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, setContentView(com.android.systemui.R.layout.global_actions_wrapped); mListView = findViewById(android.R.id.list); + mSeparatedView = findViewById(com.android.systemui.R.id.separated_button); + if (!mShouldDisplaySeparatedButton) { + mSeparatedView.setVisibility(View.GONE); + } mHardwareLayout = HardwareUiLayout.get(mListView); mHardwareLayout.setOutsideTouchListener(view -> dismiss()); + mHardwareLayout.setHasSeparatedButton(mShouldDisplaySeparatedButton); setTitle(R.string.global_actions); mListView.setAccessibilityDelegate(new View.AccessibilityDelegate() { @Override @@ -1409,13 +1462,16 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, private void updateList() { mListView.removeAllViews(); + mSeparatedView.removeAllViews(); for (int i = 0; i < mAdapter.getCount(); i++) { - View v = mAdapter.getView(i, null, mListView); + ViewGroup parentView = mShouldDisplaySeparatedButton && i == mAdapter.getCount() - 1 + ? mSeparatedView : mListView; + View v = mAdapter.getView(i, null, parentView); final int pos = i; v.setOnClickListener(view -> mClickListener.onClick(this, pos)); v.setOnLongClickListener(view -> mLongClickListener.onItemLongClick(null, v, pos, 0)); - mListView.addView(v); + parentView.addView(v); } } diff --git a/packages/SystemUI/src/com/android/systemui/util/EmergencyDialerConstants.java b/packages/SystemUI/src/com/android/systemui/util/EmergencyDialerConstants.java new file mode 100644 index 000000000000..d101ccbe30ea --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/util/EmergencyDialerConstants.java @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.util; + +/** + * Constants defined and used in emergency dialer. + * Please keep these constants being consistent with those in com.android.phone.EmergencyDialer. + */ +public class EmergencyDialerConstants { + // Intent action for emergency dialer activity. + public static final String ACTION_DIAL = "com.android.phone.EmergencyDialer.DIAL"; + + /** + * Extra included in {@link #ACTION_DIAL} to indicate the entry type that user starts + * the emergency dialer. + */ + public static final String EXTRA_ENTRY_TYPE = + "com.android.phone.EmergencyDialer.extra.ENTRY_TYPE"; + + // Indicating the entrance to emergency dialer + public static final int ENTRY_TYPE_UNKNOWN = 0; + public static final int ENTRY_TYPE_LOCKSCREEN_BUTTON = 1; + public static final int ENTRY_TYPE_POWER_MENU = 2; +} diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto index 0833e34ff8b3..d79d833f2233 100644 --- a/proto/src/metrics_constants.proto +++ b/proto/src/metrics_constants.proto @@ -6429,6 +6429,69 @@ message MetricsEvent { // OS: Q (will also ship in PQ1A) FIELD_ACTIVITY_RECORD_MILLIS_SINCE_LAST_LAUNCH = 1553; + // OPEN: Emergency dialer opened + // CLOSE: Emergency dialer closed + // SUBTYPE: The entry type that user opened emergency dialer + // CATEGORY: EMERGENCY_DIALER + // OS: Q + EMERGENCY_DIALER = 1558; + + // FIELD: The screen is currently locked + // CATEGORY: EMERGENCY_DIALER + // OS: Q + FIELD_EMERGENCY_DIALER_IS_SCREEN_LOCKED = 1559; + + // FIELD: Bit flag indicating the actions performed by user + // CATEGORY: EMERGENCY_DIALER + // OS: Q + FIELD_EMERGENCY_DIALER_USER_ACTIONS = 1560; + + // FIELD: The duration user stayed at emergency dialer + // CATEGORY: EMERGENCY_DIALER + // OS: Q + FIELD_EMERGENCY_DIALER_DURATION_MS = 1561; + + // ACTION: Making call via emergency dialer + // SUBTYPE: The UI that user made phone call + // CATEGORY: EMERGENCY_DIALER + // OS: Q + EMERGENCY_DIALER_MAKE_CALL = 1562; + + // FIELD: The phone number type of a call user made + // CATEGORY: EMERGENCY_DIALER + // OS: Q + FIELD_EMERGENCY_DIALER_PHONE_NUMBER_TYPE = 1563; + + // FIELD: There is a shortcut for the phone number + // CATEGORY: EMERGENCY_DIALER + // OS: Q + FIELD_EMERGENCY_DIALER_PHONE_NUMBER_HAS_SHORTCUT = 1564; + + // FIELD: The phone is in pocket while using emergency dialer + // CATEGORY: EMERGENCY_DIALER + // OS: Q + FIELD_EMERGENCY_DIALER_IN_POCKET = 1565; + + // ACTION: The second tap on emergency shortcut to make a phone call + // CATEGORY: EMERGENCY_DIALER + // OS: Q + EMERGENCY_DIALER_SHORTCUT_CONFIRM_TAP = 1566; + + // FIELD: The time in milliseconds of second tap on shortcut since first tap + // CATEGORY: EMERGENCY_DIALER + // OS: Q + FIELD_EMERGENCY_DIALER_SHORTCUT_TAPS_INTERVAL = 1567; + + // OPEN: Power menu is opened + // CATEGORY: GLOBAL_SYSTEM_UI + // OS: Q + POWER_MENU = 1568; + + // ACTION: User tapped emergency dialer icon in the power menu. + // CATEGORY: GLOBAL_SYSTEM_UI + // OS: Q + ACTION_EMERGENCY_DIALER_FROM_POWER_MENU = 1569; + // ---- End Q Constants, all Q constants go above this line ---- // Add new aosp constants above this line. diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java index aa426d3cd31f..78b738500a97 100644 --- a/services/core/java/com/android/server/BluetoothManagerService.java +++ b/services/core/java/com/android/server/BluetoothManagerService.java @@ -53,12 +53,16 @@ import android.os.Process; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.SystemClock; +import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserManager; import android.os.UserManagerInternal; import android.os.UserManagerInternal.UserRestrictionsListener; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; +import android.text.TextUtils; +import android.util.FeatureFlagUtils; +import android.util.Log; import android.util.Slog; import android.util.StatsLog; @@ -386,6 +390,15 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mCallbacks = new RemoteCallbackList<IBluetoothManagerCallback>(); mStateChangeCallbacks = new RemoteCallbackList<IBluetoothStateChangeCallback>(); + // TODO: We need a more generic way to initialize the persist keys of FeatureFlagUtils + boolean isHearingAidEnabled; + String value = SystemProperties.get(FeatureFlagUtils.PERSIST_PREFIX + FeatureFlagUtils.HEARING_AID_SETTINGS); + if (!TextUtils.isEmpty(value)) { + isHearingAidEnabled = Boolean.parseBoolean(value); + Log.v(TAG, "set feature flag HEARING_AID_SETTINGS to " + isHearingAidEnabled); + FeatureFlagUtils.setEnabled(context, FeatureFlagUtils.HEARING_AID_SETTINGS, isHearingAidEnabled); + } + IntentFilter filter = new IntentFilter(); filter.addAction(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED); filter.addAction(BluetoothAdapter.ACTION_BLUETOOTH_ADDRESS_CHANGED); diff --git a/services/core/java/com/android/server/am/MemoryStatUtil.java b/services/core/java/com/android/server/am/MemoryStatUtil.java index f9dccea0d34c..aad890b8bd74 100644 --- a/services/core/java/com/android/server/am/MemoryStatUtil.java +++ b/services/core/java/com/android/server/am/MemoryStatUtil.java @@ -22,6 +22,7 @@ import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NA import android.annotation.Nullable; import android.os.FileUtils; +import android.os.SystemProperties; import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; @@ -38,6 +39,10 @@ import java.util.regex.Pattern; final class MemoryStatUtil { private static final String TAG = TAG_WITH_CLASS_NAME ? "MemoryStatUtil" : TAG_AM; + /** True if device has per-app memcg */ + private static final Boolean DEVICE_HAS_PER_APP_MEMCG = + SystemProperties.getBoolean("ro.config.per_app_memcg", false); + /** Path to check if device has memcg */ private static final String MEMCG_TEST_PATH = "/dev/memcg/apps/memory.stat"; /** Path to memory stat file for logging app start memory state */ @@ -55,15 +60,12 @@ final class MemoryStatUtil { private static final int PGMAJFAULT_INDEX = 11; private static final int RSS_IN_BYTES_INDEX = 23; - /** True if device has memcg */ - private static volatile Boolean sDeviceHasMemCg; - private MemoryStatUtil() {} /** * Reads memory stat for a process. * - * Reads from memcg if available on device, else fallback to procfs. + * Reads from per-app memcg if available on device, else fallback to procfs. * Returns null if no stats can be read. */ @Nullable @@ -156,15 +158,10 @@ final class MemoryStatUtil { } /** - * Checks if memcg is available on device. - * - * Touches the filesystem to do the check. + * Returns whether per-app memcg is available on device. */ static boolean hasMemcg() { - if (sDeviceHasMemCg == null) { - sDeviceHasMemCg = (new File(MEMCG_TEST_PATH)).exists(); - } - return sDeviceHasMemCg; + return DEVICE_HAS_PER_APP_MEMCG; } static final class MemoryStat { diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java index 415a822e3160..4746e12e2838 100644 --- a/services/core/java/com/android/server/am/UserController.java +++ b/services/core/java/com/android/server/am/UserController.java @@ -845,10 +845,16 @@ class UserController implements Handler.Callback { } void scheduleStartProfiles() { - if (!mHandler.hasMessages(START_PROFILES_MSG)) { - mHandler.sendMessageDelayed(mHandler.obtainMessage(START_PROFILES_MSG), - DateUtils.SECOND_IN_MILLIS); - } + // Parent user transition to RUNNING_UNLOCKING happens on FgThread, so it is busy, there is + // a chance the profile will reach RUNNING_LOCKED while parent is still locked, so no + // attempt will be made to unlock the profile. If we go via FgThread, this will be executed + // after the parent had chance to unlock fully. + FgThread.getHandler().post(() -> { + if (!mHandler.hasMessages(START_PROFILES_MSG)) { + mHandler.sendMessageDelayed(mHandler.obtainMessage(START_PROFILES_MSG), + DateUtils.SECOND_IN_MILLIS); + } + }); } void startProfiles() { diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index f2b7bbe636e5..b7247166855d 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -2299,8 +2299,9 @@ public class NotificationManagerService extends SystemService { public ParceledListSlice<NotificationChannelGroup> getNotificationChannelGroups( String pkg) { checkCallerIsSystemOrSameApp(pkg); + return mRankingHelper.getNotificationChannelGroups( - pkg, Binder.getCallingUid(), false, false); + pkg, Binder.getCallingUid(), false, false, true); } @Override @@ -2376,7 +2377,9 @@ public class NotificationManagerService extends SystemService { public ParceledListSlice<NotificationChannelGroup> getNotificationChannelGroupsForPackage( String pkg, int uid, boolean includeDeleted) { checkCallerIsSystem(); - return mRankingHelper.getNotificationChannelGroups(pkg, uid, includeDeleted, true); + + return mRankingHelper.getNotificationChannelGroups( + pkg, uid, includeDeleted, true, false); } @Override @@ -4255,13 +4258,6 @@ public class NotificationManagerService extends SystemService { final String pkg = r.sbn.getPackageName(); final int callingUid = r.sbn.getUid(); - final boolean isPackageSuspended = isPackageSuspendedForUser(pkg, callingUid); - if (isPackageSuspended) { - Slog.e(TAG, "Suppressing notification from package due to package " - + "suspended by administrator."); - usageStats.registerSuspendedByAdmin(r); - return isPackageSuspended; - } final boolean isBlocked = mRankingHelper.isGroupBlocked(pkg, callingUid, r.getChannel().getGroup()) || mRankingHelper.getImportance(pkg, callingUid) @@ -4270,8 +4266,9 @@ public class NotificationManagerService extends SystemService { if (isBlocked) { Slog.e(TAG, "Suppressing notification from package by user request."); usageStats.registerBlocked(r); + return true; } - return isBlocked; + return false; } protected class SnoozeNotificationRunnable implements Runnable { @@ -4449,7 +4446,11 @@ public class NotificationManagerService extends SystemService { return; } - r.setHidden(isPackageSuspendedLocked(r)); + final boolean isPackageSuspended = isPackageSuspendedLocked(r); + r.setHidden(isPackageSuspended); + if (isPackageSuspended) { + mUsageStats.registerSuspendedByAdmin(r); + } NotificationRecord old = mNotificationsByKey.get(key); final StatusBarNotification n = r.sbn; final Notification notification = n.getNotification(); @@ -6625,7 +6626,6 @@ public class NotificationManagerService extends SystemService { if (!oldSbnVisible && !sbnVisible) { continue; } - // If the notification is hidden, don't notifyPosted listeners targeting < P. // Instead, those listeners will receive notifyPosted when the notification is // unhidden. @@ -7059,7 +7059,7 @@ public class NotificationManagerService extends SystemService { new String[]{pkg}); final String action = suspend ? Intent.ACTION_PACKAGES_SUSPENDED - : Intent.ACTION_PACKAGES_UNSUSPENDED; + : Intent.ACTION_PACKAGES_UNSUSPENDED; final Intent intent = new Intent(action); intent.putExtras(extras); diff --git a/services/core/java/com/android/server/notification/RankingConfig.java b/services/core/java/com/android/server/notification/RankingConfig.java index af6468333ba0..605348b4d52d 100644 --- a/services/core/java/com/android/server/notification/RankingConfig.java +++ b/services/core/java/com/android/server/notification/RankingConfig.java @@ -36,7 +36,7 @@ public interface RankingConfig { void createNotificationChannelGroup(String pkg, int uid, NotificationChannelGroup group, boolean fromTargetApp); ParceledListSlice<NotificationChannelGroup> getNotificationChannelGroups(String pkg, - int uid, boolean includeDeleted, boolean includeNonGrouped); + int uid, boolean includeDeleted, boolean includeNonGrouped, boolean includeEmpty); void createNotificationChannel(String pkg, int uid, NotificationChannel channel, boolean fromTargetApp, boolean hasDndAccess); void updateNotificationChannel(String pkg, int uid, NotificationChannel channel, boolean fromUser); diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java index 61b5415ec7a3..da6e9c02c96a 100644 --- a/services/core/java/com/android/server/notification/RankingHelper.java +++ b/services/core/java/com/android/server/notification/RankingHelper.java @@ -830,7 +830,7 @@ public class RankingHelper implements RankingConfig { @Override public ParceledListSlice<NotificationChannelGroup> getNotificationChannelGroups(String pkg, - int uid, boolean includeDeleted, boolean includeNonGrouped) { + int uid, boolean includeDeleted, boolean includeNonGrouped, boolean includeEmpty) { Preconditions.checkNotNull(pkg); Map<String, NotificationChannelGroup> groups = new ArrayMap<>(); Record r = getRecord(pkg, uid); @@ -861,6 +861,13 @@ public class RankingHelper implements RankingConfig { if (includeNonGrouped && nonGrouped.getChannels().size() > 0) { groups.put(null, nonGrouped); } + if (includeEmpty) { + for (NotificationChannelGroup group : r.groups.values()) { + if (!groups.containsKey(group.getId())) { + groups.put(group.getId(), group); + } + } + } return new ParceledListSlice<>(new ArrayList<>(groups.values())); } @@ -1244,7 +1251,7 @@ public class RankingHelper implements RankingConfig { /** * Dump only the ban information as structured JSON for the stats collector. * - * This is intentionally redundant with {#link dumpJson} because the old + * This is intentionally redundant with {@link dumpJson} because the old * scraper will expect this format. * * @param filter @@ -1288,7 +1295,7 @@ public class RankingHelper implements RankingConfig { /** * Dump only the channel information as structured JSON for the stats collector. * - * This is intentionally redundant with {#link dumpJson} because the old + * This is intentionally redundant with {@link dumpJson} because the old * scraper will expect this format. * * @param filter diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java index cdbf3c66767b..955e2477fc66 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java @@ -500,8 +500,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { NotificationChannel channel = new NotificationChannel("id", "name", IMPORTANCE_HIGH); NotificationRecord r = generateNotificationRecord(channel); - assertTrue(mService.isBlocked(r, mUsageStats)); - verify(mUsageStats, times(1)).registerSuspendedByAdmin(eq(r)); + + // isBlocked is only used for user blocking, not app suspension + assertFalse(mService.isBlocked(r, mUsageStats)); } @Test diff --git a/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java index 98c6ec42207f..a9e713e5778b 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java @@ -399,7 +399,7 @@ public class RankingHelperTest extends UiServiceTestCase { mHelper.getNotificationChannel(PKG, UID, channel2.getId(), false)); List<NotificationChannelGroup> actualGroups = - mHelper.getNotificationChannelGroups(PKG, UID, false, true).getList(); + mHelper.getNotificationChannelGroups(PKG, UID, false, true, false).getList(); boolean foundNcg = false; for (NotificationChannelGroup actual : actualGroups) { if (ncg.getId().equals(actual.getId())) { @@ -469,7 +469,7 @@ public class RankingHelperTest extends UiServiceTestCase { mHelper.getNotificationChannel(PKG, UID, channel3.getId(), false)); List<NotificationChannelGroup> actualGroups = - mHelper.getNotificationChannelGroups(PKG, UID, false, true).getList(); + mHelper.getNotificationChannelGroups(PKG, UID, false, true, false).getList(); boolean foundNcg = false; for (NotificationChannelGroup actual : actualGroups) { if (ncg.getId().equals(actual.getId())) { @@ -784,6 +784,31 @@ public class RankingHelperTest extends UiServiceTestCase { new NotificationChannel("bananas", "bananas", IMPORTANCE_MAX), true, false); } + @Test + public void testGetChannelGroups_includeEmptyGroups() { + NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1"); + mHelper.createNotificationChannelGroup(PKG, UID, ncg, true); + NotificationChannelGroup ncgEmpty = new NotificationChannelGroup("group2", "name2"); + mHelper.createNotificationChannelGroup(PKG, UID, ncgEmpty, true); + + NotificationChannel channel1 = + new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); + channel1.setGroup(ncg.getId()); + mHelper.createNotificationChannel(PKG, UID, channel1, true, false); + + List<NotificationChannelGroup> actual = mHelper.getNotificationChannelGroups( + PKG, UID, false, false, true).getList(); + + assertEquals(2, actual.size()); + for (NotificationChannelGroup group : actual) { + if (Objects.equals(group.getId(), ncg.getId())) { + assertEquals(1, group.getChannels().size()); + } + if (Objects.equals(group.getId(), ncgEmpty.getId())) { + assertEquals(0, group.getChannels().size()); + } + } + } @Test public void testUpdate() throws Exception { @@ -1421,7 +1446,7 @@ public class RankingHelperTest extends UiServiceTestCase { mHelper.onPackagesChanged(true, UserHandle.USER_SYSTEM, new String[]{PKG}, new int[]{UID}); assertEquals(0, - mHelper.getNotificationChannelGroups(PKG, UID, true, true).getList().size()); + mHelper.getNotificationChannelGroups(PKG, UID, true, true, false).getList().size()); } @Test @@ -1510,7 +1535,7 @@ public class RankingHelperTest extends UiServiceTestCase { mHelper.createNotificationChannel(PKG, UID, channel3, true, false); List<NotificationChannelGroup> actual = - mHelper.getNotificationChannelGroups(PKG, UID, true, true).getList(); + mHelper.getNotificationChannelGroups(PKG, UID, true, true, false).getList(); assertEquals(3, actual.size()); for (NotificationChannelGroup group : actual) { if (group.getId() == null) { @@ -1542,13 +1567,13 @@ public class RankingHelperTest extends UiServiceTestCase { new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); channel1.setGroup(ncg.getId()); mHelper.createNotificationChannel(PKG, UID, channel1, true, false); - mHelper.getNotificationChannelGroups(PKG, UID, true, true).getList(); + mHelper.getNotificationChannelGroups(PKG, UID, true, true, false).getList(); channel1.setImportance(IMPORTANCE_LOW); mHelper.updateNotificationChannel(PKG, UID, channel1, true); List<NotificationChannelGroup> actual = - mHelper.getNotificationChannelGroups(PKG, UID, true, true).getList(); + mHelper.getNotificationChannelGroups(PKG, UID, true, true, false).getList(); assertEquals(2, actual.size()); for (NotificationChannelGroup group : actual) { diff --git a/telecomm/java/android/telecom/ParcelableCallAnalytics.java b/telecomm/java/android/telecom/ParcelableCallAnalytics.java index 383d10baeb12..bb066ad428c6 100644 --- a/telecomm/java/android/telecom/ParcelableCallAnalytics.java +++ b/telecomm/java/android/telecom/ParcelableCallAnalytics.java @@ -195,6 +195,8 @@ public class ParcelableCallAnalytics implements Parcelable { public static final int BLOCK_CHECK_FINISHED_TIMING = 9; public static final int FILTERING_COMPLETED_TIMING = 10; public static final int FILTERING_TIMED_OUT_TIMING = 11; + /** {@hide} */ + public static final int START_CONNECTION_TO_REQUEST_DISCONNECT_TIMING = 12; public static final int INVALID = 999999; @@ -256,6 +258,27 @@ public class ParcelableCallAnalytics implements Parcelable { public static final int SIP_PHONE = 0x8; public static final int THIRD_PARTY_PHONE = 0x10; + /** + * Indicating the call source is not specified. + * + * @hide + */ + public static final int CALL_SOURCE_UNSPECIFIED = 0; + + /** + * Indicating the call is initiated via emergency dialer's dialpad. + * + * @hide + */ + public static final int CALL_SOURCE_EMERGENCY_DIALPAD = 1; + + /** + * Indicating the call is initiated via emergency dialer's shortcut button. + * + * @hide + */ + public static final int CALL_SOURCE_EMERGENCY_SHORTCUT = 2; + public static final long MILLIS_IN_5_MINUTES = 1000 * 60 * 5; public static final long MILLIS_IN_1_SECOND = 1000; @@ -319,6 +342,9 @@ public class ParcelableCallAnalytics implements Parcelable { // A list of video events that have occurred. private List<VideoEvent> videoEvents; + // The source where user initiated this call. ONE OF the CALL_SOURCE_* constants. + private int callSource = CALL_SOURCE_UNSPECIFIED; + public ParcelableCallAnalytics(long startTimeMillis, long callDurationMillis, int callType, boolean isAdditionalCall, boolean isInterrupted, int callTechnologies, int callTerminationCode, boolean isEmergencyCall, String connectionService, @@ -356,6 +382,7 @@ public class ParcelableCallAnalytics implements Parcelable { isVideoCall = readByteAsBoolean(in); videoEvents = new LinkedList<>(); in.readTypedList(videoEvents, VideoEvent.CREATOR); + callSource = in.readInt(); } public void writeToParcel(Parcel out, int flags) { @@ -373,6 +400,7 @@ public class ParcelableCallAnalytics implements Parcelable { out.writeTypedList(eventTimings); writeBooleanAsByte(out, isVideoCall); out.writeTypedList(videoEvents); + out.writeInt(callSource); } /** {@hide} */ @@ -385,6 +413,11 @@ public class ParcelableCallAnalytics implements Parcelable { this.videoEvents = videoEvents; } + /** {@hide} */ + public void setCallSource(int callSource) { + this.callSource = callSource; + } + public long getStartTimeMillis() { return startTimeMillis; } @@ -443,6 +476,11 @@ public class ParcelableCallAnalytics implements Parcelable { return videoEvents; } + /** {@hide} */ + public int getCallSource() { + return callSource; + } + @Override public int describeContents() { return 0; diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java index 29898ffbd343..573f7db6b20c 100644 --- a/telecomm/java/android/telecom/TelecomManager.java +++ b/telecomm/java/android/telecom/TelecomManager.java @@ -619,6 +619,18 @@ public class TelecomManager { "android.telecom.extra.USE_ASSISTED_DIALING"; /** + * Optional extra for {@link #placeCall(Uri, Bundle)} containing an integer that specifies + * the source where user initiated this call. This data is used in metrics. + * Valid source are: + * {@link ParcelableCallAnalytics#CALL_SOURCE_UNSPECIFIED}, + * {@link ParcelableCallAnalytics#CALL_SOURCE_EMERGENCY_DIALPAD}, + * {@link ParcelableCallAnalytics#CALL_SOURCE_EMERGENCY_SHORTCUT}. + * + * @hide + */ + public static final String EXTRA_CALL_SOURCE = "android.telecom.extra.CALL_SOURCE"; + + /** * The following 4 constants define how properties such as phone numbers and names are * displayed to the user. */ diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index deb289c8e614..bae18840506b 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -110,6 +110,28 @@ public class CarrierConfigManager { "call_barring_visibility_bool"; /** + * Flag indicating whether or not changing the call barring password via the "Call Barring" + * settings menu is supported. If true, the option will be visible in the "Call + * Barring" settings menu. If false, the option will not be visible. + * + * Enabled by default. + * @hide + */ + public static final String KEY_CALL_BARRING_SUPPORTS_PASSWORD_CHANGE_BOOL = + "call_barring_supports_password_change_bool"; + + /** + * Flag indicating whether or not deactivating all call barring features via the "Call Barring" + * settings menu is supported. If true, the option will be visible in the "Call + * Barring" settings menu. If false, the option will not be visible. + * + * Enabled by default. + * @hide + */ + public static final String KEY_CALL_BARRING_SUPPORTS_DEACTIVATE_ALL_BOOL = + "call_barring_supports_deactivate_all_bool"; + + /** * Flag indicating whether the Phone app should ignore EVENT_SIM_NETWORK_LOCKED * events from the Sim. * If true, this will prevent the IccNetworkDepersonalizationPanel from being shown, and @@ -2095,6 +2117,8 @@ public class CarrierConfigManager { sDefaults.putBoolean(KEY_CARRIER_VOLTE_PROVISIONED_BOOL, false); sDefaults.putBoolean(KEY_CALL_BARRING_VISIBILITY_BOOL, false); + sDefaults.putBoolean(KEY_CALL_BARRING_SUPPORTS_PASSWORD_CHANGE_BOOL, true); + sDefaults.putBoolean(KEY_CALL_BARRING_SUPPORTS_DEACTIVATE_ALL_BOOL, true); sDefaults.putBoolean(KEY_CALL_FORWARDING_VISIBILITY_BOOL, true); sDefaults.putBoolean(KEY_ADDITIONAL_SETTINGS_CALLER_ID_VISIBILITY_BOOL, true); sDefaults.putBoolean(KEY_ADDITIONAL_SETTINGS_CALL_WAITING_VISIBILITY_BOOL, true); diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java b/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java index 6bf22a05beec..8015b07fa024 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java +++ b/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java @@ -33,6 +33,7 @@ import com.android.internal.telephony.GsmAlphabet; import com.android.internal.telephony.SmsConstants; import java.io.UnsupportedEncodingException; +import java.util.Locale; /** * Parses a GSM or UMTS format SMS-CB message into an {@link SmsCbMessage} object. The class is @@ -44,16 +45,34 @@ public class GsmSmsCbMessage { * Languages in the 0000xxxx DCS group as defined in 3GPP TS 23.038, section 5. */ private static final String[] LANGUAGE_CODES_GROUP_0 = { - "de", "en", "it", "fr", "es", "nl", "sv", "da", "pt", "fi", "no", "el", "tr", "hu", - "pl", null + Locale.GERMAN.getLanguage(), // German + Locale.ENGLISH.getLanguage(), // English + Locale.ITALIAN.getLanguage(), // Italian + Locale.FRENCH.getLanguage(), // French + new Locale("es").getLanguage(), // Spanish + new Locale("nl").getLanguage(), // Dutch + new Locale("sv").getLanguage(), // Swedish + new Locale("da").getLanguage(), // Danish + new Locale("pt").getLanguage(), // Portuguese + new Locale("fi").getLanguage(), // Finnish + new Locale("nb").getLanguage(), // Norwegian + new Locale("el").getLanguage(), // Greek + new Locale("tr").getLanguage(), // Turkish + new Locale("hu").getLanguage(), // Hungarian + new Locale("pl").getLanguage(), // Polish + null }; /** * Languages in the 0010xxxx DCS group as defined in 3GPP TS 23.038, section 5. */ private static final String[] LANGUAGE_CODES_GROUP_2 = { - "cs", "he", "ar", "ru", "is", null, null, null, null, null, null, null, null, null, - null, null + new Locale("cs").getLanguage(), // Czech + new Locale("he").getLanguage(), // Hebrew + new Locale("ar").getLanguage(), // Arabic + new Locale("ru").getLanguage(), // Russian + new Locale("is").getLanguage(), // Icelandic + null, null, null, null, null, null, null, null, null, null, null }; private static final char CARRIAGE_RETURN = 0x0d; diff --git a/telephony/java/com/android/internal/telephony/gsm/SmsCbConstants.java b/telephony/java/com/android/internal/telephony/gsm/SmsCbConstants.java index 0fabc2ff6b86..541ca8d1e5c0 100644 --- a/telephony/java/com/android/internal/telephony/gsm/SmsCbConstants.java +++ b/telephony/java/com/android/internal/telephony/gsm/SmsCbConstants.java @@ -118,71 +118,103 @@ public class SmsCbConstants { public static final int MESSAGE_ID_CMAS_ALERT_OPERATOR_DEFINED_USE = 0x111E; // 4382 - /** CMAS Message Identifier for Presidential Level alerts for additional languages - * for additional languages. */ + /** + * CMAS Message Identifier for Presidential Level alerts for additional languages. + */ public static final int MESSAGE_ID_CMAS_ALERT_PRESIDENTIAL_LEVEL_LANGUAGE = 0x111F; // 4383 - /** CMAS Message Identifier for Extreme alerts, Urgency=Immediate, Certainty=Observed - * for additional languages. */ + /** + * CMAS Message Identifier for Extreme alerts, Urgency=Immediate, Certainty=Observed + * for additional languages. + */ public static final int MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_OBSERVED_LANGUAGE = 0x1120; // 4384 - /** CMAS Message Identifier for Extreme alerts, Urgency=Immediate, Certainty=Likely - * for additional languages. */ + /** + * CMAS Message Identifier for Extreme alerts, Urgency=Immediate, Certainty=Likely + * for additional languages. + */ public static final int MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_LIKELY_LANGUAGE = 0x1121; // 4385 - /** CMAS Message Identifier for Extreme alerts, Urgency=Expected, Certainty=Observed - * for additional languages. */ + /** + * CMAS Message Identifier for Extreme alerts, Urgency=Expected, Certainty=Observed + * for additional languages. + */ public static final int MESSAGE_ID_CMAS_ALERT_EXTREME_EXPECTED_OBSERVED_LANGUAGE = 0x1122; // 4386 - /** CMAS Message Identifier for Extreme alerts, Urgency=Expected, Certainty=Likely - * for additional languages. */ + /** + * CMAS Message Identifier for Extreme alerts, Urgency=Expected, Certainty=Likely + * for additional languages. + */ public static final int MESSAGE_ID_CMAS_ALERT_EXTREME_EXPECTED_LIKELY_LANGUAGE = 0x1123; // 4387 - /** CMAS Message Identifier for Severe alerts, Urgency=Immediate, Certainty=Observed - * for additional languages. */ + /** + * CMAS Message Identifier for Severe alerts, Urgency=Immediate, Certainty=Observed + * for additional languages. + */ public static final int MESSAGE_ID_CMAS_ALERT_SEVERE_IMMEDIATE_OBSERVED_LANGUAGE = 0x1124; // 4388 - /** CMAS Message Identifier for Severe alerts, Urgency=Immediate, Certainty=Likely - * for additional languages.*/ + /** + * CMAS Message Identifier for Severe alerts, Urgency=Immediate, Certainty=Likely + * for additional languages. + */ public static final int MESSAGE_ID_CMAS_ALERT_SEVERE_IMMEDIATE_LIKELY_LANGUAGE = 0x1125; // 4389 - /** CMAS Message Identifier for Severe alerts, Urgency=Expected, Certainty=Observed - * for additional languages. */ + /** + * CMAS Message Identifier for Severe alerts, Urgency=Expected, Certainty=Observed + * for additional languages. + */ public static final int MESSAGE_ID_CMAS_ALERT_SEVERE_EXPECTED_OBSERVED_LANGUAGE = 0x1126; // 4390 - /** CMAS Message Identifier for Severe alerts, Urgency=Expected, Certainty=Likely - * for additional languages.*/ + /** + * CMAS Message Identifier for Severe alerts, Urgency=Expected, Certainty=Likely + * for additional languages. + */ public static final int MESSAGE_ID_CMAS_ALERT_SEVERE_EXPECTED_LIKELY_LANGUAGE = 0x1127; // 4391 - /** CMAS Message Identifier for Child Abduction Emergency (Amber Alert) - * for additional languages. */ + /** + * CMAS Message Identifier for Child Abduction Emergency (Amber Alert) + * for additional languages. + */ public static final int MESSAGE_ID_CMAS_ALERT_CHILD_ABDUCTION_EMERGENCY_LANGUAGE = 0x1128; // 4392 - /** CMAS Message Identifier for the Required Monthly Test - * for additional languages. */ + /** CMAS Message Identifier for the Required Monthly Test for additional languages. */ public static final int MESSAGE_ID_CMAS_ALERT_REQUIRED_MONTHLY_TEST_LANGUAGE = 0x1129; // 4393 - /** CMAS Message Identifier for CMAS Exercise - * for additional languages. */ + /** CMAS Message Identifier for CMAS Exercise for additional languages. */ public static final int MESSAGE_ID_CMAS_ALERT_EXERCISE_LANGUAGE = 0x112A; // 4394 - /** CMAS Message Identifier for operator defined use - * for additional languages. */ + /** CMAS Message Identifier for operator defined use for additional languages. */ public static final int MESSAGE_ID_CMAS_ALERT_OPERATOR_DEFINED_USE_LANGUAGE = 0x112B; // 4395 + /** CMAS Message Identifier for CMAS Public Safety Alerts. */ + public static final int MESSAGE_ID_CMAS_ALERT_PUBLIC_SAFETY + = 0x112C; // 4396 + + /** CMAS Message Identifier for CMAS Public Safety Alerts for additional languages. */ + public static final int MESSAGE_ID_CMAS_ALERT_PUBLIC_SAFETY_LANGUAGE + = 0x112D; // 4397 + + /** CMAS Message Identifier for CMAS State/Local Test. */ + public static final int MESSAGE_ID_CMAS_ALERT_STATE_LOCAL_TEST + = 0x112E; // 4398 + + /** CMAS Message Identifier for CMAS State/Local Test for additional languages. */ + public static final int MESSAGE_ID_CMAS_ALERT_STATE_LOCAL_TEST_LANGUAGE + = 0x112F; // 4399 + /** End of CMAS Message Identifier range (including future extensions). */ public static final int MESSAGE_ID_CMAS_LAST_IDENTIFIER = 0x112F; // 4399 diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java index 4a7d7038457e..55c7fc18f6af 100644 --- a/wifi/java/android/net/wifi/WifiConfiguration.java +++ b/wifi/java/android/net/wifi/WifiConfiguration.java @@ -504,7 +504,7 @@ public class WifiConfiguration implements Parcelable { /** * @hide * Universal name for app creating the configuration - * see {#link {@link PackageManager#getNameForUid(int)} + * see {@link PackageManager#getNameForUid(int)} */ @SystemApi public String creatorName; @@ -512,7 +512,7 @@ public class WifiConfiguration implements Parcelable { /** * @hide * Universal name for app updating the configuration - * see {#link {@link PackageManager#getNameForUid(int)} + * see {@link PackageManager#getNameForUid(int)} */ @SystemApi public String lastUpdateName; |