Merge "Bluetooth: Fix startAdvertisingSet error handling" into oc-mr1-dev
diff --git a/api/current.txt b/api/current.txt
index 7584ba8..24ab586 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -47199,6 +47199,7 @@
method public java.util.List<android.accessibilityservice.AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int);
method public java.util.List<android.accessibilityservice.AccessibilityServiceInfo> getInstalledAccessibilityServiceList();
method public void interrupt();
+ method public static boolean isAccessibilityButtonSupported();
method public boolean isEnabled();
method public boolean isTouchExplorationEnabled();
method public void removeAccessibilityRequestPreparer(android.view.accessibility.AccessibilityRequestPreparer);
diff --git a/api/test-current.txt b/api/test-current.txt
index 1258554..343228a 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -47651,6 +47651,7 @@
method public java.util.List<android.accessibilityservice.AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int);
method public java.util.List<android.accessibilityservice.AccessibilityServiceInfo> getInstalledAccessibilityServiceList();
method public void interrupt();
+ method public static boolean isAccessibilityButtonSupported();
method public boolean isEnabled();
method public boolean isTouchExplorationEnabled();
method public void removeAccessibilityRequestPreparer(android.view.accessibility.AccessibilityRequestPreparer);
diff --git a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
index 5830c27..44c2667 100644
--- a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
+++ b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
@@ -455,8 +455,7 @@
gatt.stopAdvertisingSet(wrapped);
} catch (RemoteException e) {
Log.e(TAG, "Failed to stop advertising - ", e);
- throw new IllegalStateException("Failed to stop advertising");
- }
+ }
}
/**
diff --git a/core/java/android/util/Patterns.java b/core/java/android/util/Patterns.java
index ca39854..50cd7b1 100644
--- a/core/java/android/util/Patterns.java
+++ b/core/java/android/util/Patterns.java
@@ -406,7 +406,7 @@
* the local part to be at most 64 octets.
*/
private static final String EMAIL_ADDRESS_LOCAL_PART =
- "[" + EMAIL_CHAR + "]" + "(?:[" + EMAIL_CHAR + "\\.]{1,62}[" + EMAIL_CHAR + "])?";
+ "[" + EMAIL_CHAR + "]" + "(?:[" + EMAIL_CHAR + "\\.]{0,62}[" + EMAIL_CHAR + "])?";
/**
* Regular expression for the domain part of an email address. RFC5321 section 4.5.3.1.2 limits
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index d9128d8..0b9bc57 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -23,7 +23,6 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SdkConstant;
-import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.content.ComponentName;
import android.content.Context;
@@ -1113,9 +1112,7 @@
*
* @return {@code true} if the accessibility button is supported on this device,
* {@code false} otherwise
- * @hide
*/
- @SystemApi
public static boolean isAccessibilityButtonSupported() {
final Resources res = Resources.getSystem();
return res.getBoolean(com.android.internal.R.bool.config_showNavigationBar);
diff --git a/core/java/com/android/internal/notification/SystemNotificationChannels.java b/core/java/com/android/internal/notification/SystemNotificationChannels.java
index d327180..d64c9a1 100644
--- a/core/java/com/android/internal/notification/SystemNotificationChannels.java
+++ b/core/java/com/android/internal/notification/SystemNotificationChannels.java
@@ -132,10 +132,12 @@
context.getString(R.string.notification_channel_usb),
NotificationManager.IMPORTANCE_MIN));
- channelsList.add(new NotificationChannel(
+ NotificationChannel foregroundChannel = new NotificationChannel(
FOREGROUND_SERVICE,
context.getString(R.string.notification_channel_foreground_service),
- NotificationManager.IMPORTANCE_LOW));
+ NotificationManager.IMPORTANCE_LOW);
+ foregroundChannel.setBlockableSystem(true);
+ channelsList.add(foregroundChannel);
nm.createNotificationChannels(channelsList);
}
diff --git a/core/res/res/values-mcc310-mnc030/strings.xml b/core/res/res/values-mcc310-mnc030/strings.xml
new file mode 100644
index 0000000..a3fea29
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc030/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 2006, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="mmcc_imsi_unknown_in_hlr">SIM not provisioned MM#2</string>
+ <string name="mmcc_illegal_ms">SIM not allowed MM#3</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc170 b/core/res/res/values-mcc310-mnc170
deleted file mode 120000
index cfced17..0000000
--- a/core/res/res/values-mcc310-mnc170
+++ /dev/null
@@ -1 +0,0 @@
-./values-mcc310-mnc150
\ No newline at end of file
diff --git a/core/res/res/values-mcc310-mnc170/strings.xml b/core/res/res/values-mcc310-mnc170/strings.xml
new file mode 100644
index 0000000..a3fea29
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc170/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 2006, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="mmcc_imsi_unknown_in_hlr">SIM not provisioned MM#2</string>
+ <string name="mmcc_illegal_ms">SIM not allowed MM#3</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc280/strings.xml b/core/res/res/values-mcc310-mnc280/strings.xml
new file mode 100644
index 0000000..a3fea29
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc280/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 2006, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="mmcc_imsi_unknown_in_hlr">SIM not provisioned MM#2</string>
+ <string name="mmcc_illegal_ms">SIM not allowed MM#3</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc380 b/core/res/res/values-mcc310-mnc380
deleted file mode 120000
index cfced17..0000000
--- a/core/res/res/values-mcc310-mnc380
+++ /dev/null
@@ -1 +0,0 @@
-./values-mcc310-mnc150
\ No newline at end of file
diff --git a/core/res/res/values-mcc310-mnc380/strings.xml b/core/res/res/values-mcc310-mnc380/strings.xml
new file mode 100644
index 0000000..a3fea29
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc380/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 2006, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="mmcc_imsi_unknown_in_hlr">SIM not provisioned MM#2</string>
+ <string name="mmcc_illegal_ms">SIM not allowed MM#3</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc410/strings.xml b/core/res/res/values-mcc310-mnc410/strings.xml
new file mode 100644
index 0000000..a3fea29
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc410/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 2006, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="mmcc_imsi_unknown_in_hlr">SIM not provisioned MM#2</string>
+ <string name="mmcc_illegal_ms">SIM not allowed MM#3</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc560/strings.xml b/core/res/res/values-mcc310-mnc560/strings.xml
new file mode 100644
index 0000000..a3fea29
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc560/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 2006, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="mmcc_imsi_unknown_in_hlr">SIM not provisioned MM#2</string>
+ <string name="mmcc_illegal_ms">SIM not allowed MM#3</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc950/strings.xml b/core/res/res/values-mcc310-mnc950/strings.xml
new file mode 100644
index 0000000..a3fea29
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc950/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 2006, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="mmcc_imsi_unknown_in_hlr">SIM not provisioned MM#2</string>
+ <string name="mmcc_illegal_ms">SIM not allowed MM#3</string>
+</resources>
diff --git a/core/res/res/values-mcc311-mnc180/strings.xml b/core/res/res/values-mcc311-mnc180/strings.xml
new file mode 100644
index 0000000..a3fea29
--- /dev/null
+++ b/core/res/res/values-mcc311-mnc180/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 2006, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="mmcc_imsi_unknown_in_hlr">SIM not provisioned MM#2</string>
+ <string name="mmcc_illegal_ms">SIM not allowed MM#3</string>
+</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 8a5625b..ce6815f 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -593,17 +593,18 @@
<!-- This is the label for the notification channel settings that controls the behavior
of the notification about applications that are running in the background (that is,
perhaps confusingly, running foreground services but not the foreground UI on the screen).
- [CHAR LIMIT=NONE] -->
- <string name="notification_channel_foreground_service">Apps running in background</string>
+ [CHAR LIMIT=NONE BACKUP_MESSAGE_ID=6665375982962336520] -->
+ <string name="notification_channel_foreground_service">Apps consuming battery</string>
- <!-- Label for foreground service notification when one app is running. [CHAR LIMIT=NONE] -->
+ <!-- Label for foreground service notification when one app is running.
+ [CHAR LIMIT=NONE BACKUP_MESSAGE_ID=6826789589341671842] -->
<string name="foreground_service_app_in_background"><xliff:g id="app_name">%1$s</xliff:g> is
- running in the background</string>
+ using battery</string>
<!-- Label for foreground service notification when multiple apps are running.
- [CHAR LIMIT=NONE] -->
+ [CHAR LIMIT=NONE BACKUP_MESSAGE_ID=7150914856893450380] -->
<string name="foreground_service_apps_in_background"><xliff:g id="number">%1$d</xliff:g> apps
- are running in the background</string>
+ are using battery</string>
<!-- Content for foreground service notification when one app is running.
[CHAR LIMIT=NONE] -->
diff --git a/packages/SystemUI/res/layout/car_qs_panel.xml b/packages/SystemUI/res/layout/car_qs_panel.xml
index d1f7ff8..0b46b0b 100644
--- a/packages/SystemUI/res/layout/car_qs_panel.xml
+++ b/packages/SystemUI/res/layout/car_qs_panel.xml
@@ -24,4 +24,11 @@
<include layout="@layout/car_status_bar_header" />
<include layout="@layout/car_qs_footer" />
+
+ <com.android.systemui.statusbar.car.UserGridView
+ android:id="@+id/user_grid"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="@dimen/car_margin"
+ android:layout_marginRight="@dimen/car_margin" />
</LinearLayout>
diff --git a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java
index 9730f29..d42b87b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java
@@ -18,6 +18,7 @@
import android.graphics.drawable.Drawable;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
+import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.RelativeLayout;
@@ -27,6 +28,7 @@
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.qs.QSFooter;
import com.android.systemui.qs.QSPanel;
+import com.android.systemui.statusbar.car.UserGridView;
import com.android.systemui.statusbar.phone.MultiUserSwitch;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.UserInfoController;
@@ -37,10 +39,13 @@
*/
public class CarQSFooter extends RelativeLayout implements QSFooter,
UserInfoController.OnUserInfoChangedListener {
+ private static final String TAG = "CarQSFooter";
+
private UserInfoController mUserInfoController;
private MultiUserSwitch mMultiUserSwitch;
private ImageView mMultiUserAvatar;
+ private UserGridView mUserGridView;
public CarQSFooter(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -54,6 +59,19 @@
mUserInfoController = Dependency.get(UserInfoController.class);
+ mMultiUserSwitch.setOnClickListener(v -> {
+ if (mUserGridView == null) {
+ Log.e(TAG, "CarQSFooter not properly set up; cannot display user switcher.");
+ return;
+ }
+
+ if (!mUserGridView.isShowing()) {
+ mUserGridView.show();
+ } else {
+ mUserGridView.hide();
+ }
+ });
+
findViewById(R.id.settings_button).setOnClickListener(v -> {
ActivityStarter activityStarter = Dependency.get(ActivityStarter.class);
@@ -80,6 +98,10 @@
}
}
+ public void setUserGridView(UserGridView view) {
+ mUserGridView = view;
+ }
+
@Override
public void setListening(boolean listening) {
if (listening) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java
index 7c2a812..13298d3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java
@@ -22,9 +22,12 @@
import android.view.View.OnClickListener;
import android.view.ViewGroup;
+import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.qs.QSFooter;
+import com.android.systemui.statusbar.car.UserGridView;
+import com.android.systemui.statusbar.policy.UserSwitcherController;
/**
* A quick settings fragment for the car. For auto, there is no row for quick settings or ability
@@ -33,7 +36,8 @@
*/
public class CarQSFragment extends Fragment implements QS {
private View mHeader;
- private QSFooter mFooter;
+ private CarQSFooter mFooter;
+ private UserGridView mUserGridView;
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@@ -46,6 +50,12 @@
super.onViewCreated(view, savedInstanceState);
mHeader = view.findViewById(R.id.header);
mFooter = view.findViewById(R.id.qs_footer);
+
+ mUserGridView = view.findViewById(R.id.user_grid);
+ mUserGridView.init(null, Dependency.get(UserSwitcherController.class),
+ false /* showInitially */);
+
+ mFooter.setUserGridView(mUserGridView);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
index 6060134..172c62a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
@@ -53,7 +53,7 @@
mParent = containerStub.inflate();
mContainer = mParent.findViewById(R.id.container);
mUserGridView = mContainer.findViewById(R.id.user_grid);
- mUserGridView.init(statusBar, mUserSwitcherController);
+ mUserGridView.init(statusBar, mUserSwitcherController, true /* showInitially */);
mUserGridView.setUserSelectionListener(record -> {
if (!record.isCurrent) {
toggleSwitchInProgress(true);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridView.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridView.java
index f178aa6..e551801 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridView.java
@@ -16,20 +16,21 @@
package com.android.systemui.statusbar.car;
+import android.animation.Animator;
+import android.animation.Animator.AnimatorListener;
+import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
-import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
-import android.os.UserHandle;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
+import android.support.v4.view.animation.FastOutSlowInInterpolator;
import android.util.AttributeSet;
-import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -37,9 +38,7 @@
import android.widget.LinearLayout;
import android.widget.TextView;
-import com.android.internal.util.UserIcons;
import com.android.systemui.R;
-import com.android.systemui.statusbar.UserUtil;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.policy.UserSwitcherController;
@@ -48,21 +47,44 @@
* One of the uses of this is for the lock screen in auto.
*/
public class UserGridView extends ViewPager {
+ private static final int EXPAND_ANIMATION_TIME_MS = 200;
+ private static final int HIDE_ANIMATION_TIME_MS = 133;
+
private StatusBar mStatusBar;
private UserSwitcherController mUserSwitcherController;
private Adapter mAdapter;
private UserSelectionListener mUserSelectionListener;
+ private ValueAnimator mHeightAnimator;
+ private int mTargetHeight;
+ private int mHeightChildren;
+ private boolean mShowing;
public UserGridView(Context context, AttributeSet attrs) {
super(context, attrs);
}
- public void init(StatusBar statusBar, UserSwitcherController userSwitcherController) {
+ public void init(StatusBar statusBar, UserSwitcherController userSwitcherController,
+ boolean showInitially) {
mStatusBar = statusBar;
mUserSwitcherController = userSwitcherController;
mAdapter = new Adapter(mUserSwitcherController);
addOnLayoutChangeListener(mAdapter);
setAdapter(mAdapter);
+ mShowing = showInitially;
+ }
+
+ public boolean isShowing() {
+ return mShowing;
+ }
+
+ public void show() {
+ mShowing = true;
+ animateHeightChange(getMeasuredHeight(), mHeightChildren);
+ }
+
+ public void hide() {
+ mShowing = false;
+ animateHeightChange(getMeasuredHeight(), 0);
}
public void onUserSwitched(int newUserId) {
@@ -83,16 +105,85 @@
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// Wrap content doesn't work in ViewPagers, so simulate the behavior in code.
int height = 0;
- for(int i = 0; i < getChildCount(); i++) {
- View child = getChildAt(i);
- child.measure(widthMeasureSpec,
- MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
- height = Math.max(child.getMeasuredHeight(), height);
+ if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY) {
+ height = MeasureSpec.getSize(heightMeasureSpec);
+ } else {
+ for (int i = 0; i < getChildCount(); i++) {
+ View child = getChildAt(i);
+ child.measure(widthMeasureSpec,
+ MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
+ height = Math.max(child.getMeasuredHeight(), height);
+ }
+
+ mHeightChildren = height;
+
+ // Override the height if it's not showing.
+ if (!mShowing) {
+ height = 0;
+ }
+
+ // Respect the AT_MOST request from parent.
+ if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST) {
+ height = Math.min(MeasureSpec.getSize(heightMeasureSpec), height);
+ }
}
heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
+
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
+ private void animateHeightChange(int oldHeight, int newHeight) {
+ // If there is no change in height or an animation is already in progress towards the
+ // desired height, then there's no need to make any changes.
+ if (oldHeight == newHeight || newHeight == mTargetHeight) {
+ return;
+ }
+
+ // Animation in progress is not going towards the new target, so cancel it.
+ if (mHeightAnimator != null){
+ mHeightAnimator.cancel();
+ }
+
+ mTargetHeight = newHeight;
+ mHeightAnimator = ValueAnimator.ofInt(oldHeight, mTargetHeight);
+ mHeightAnimator.addUpdateListener(valueAnimator -> {
+ ViewGroup.LayoutParams layoutParams = getLayoutParams();
+ layoutParams.height = (Integer) valueAnimator.getAnimatedValue();
+ requestLayout();
+ });
+ mHeightAnimator.addListener(new AnimatorListener() {
+ @Override
+ public void onAnimationStart(Animator animator) {}
+
+ @Override
+ public void onAnimationEnd(Animator animator) {
+ // ValueAnimator does not guarantee that the update listener will get an update
+ // to the final value, so here, the final value is set. Though the final calculated
+ // height (mTargetHeight) could be set, WRAP_CONTENT is more appropriate.
+ ViewGroup.LayoutParams layoutParams = getLayoutParams();
+ layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
+ requestLayout();
+ mHeightAnimator = null;
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animator) {}
+
+ @Override
+ public void onAnimationRepeat(Animator animator) {}
+ });
+
+ mHeightAnimator.setInterpolator(new FastOutSlowInInterpolator());
+ if (oldHeight < newHeight) {
+ // Expanding
+ mHeightAnimator.setDuration(EXPAND_ANIMATION_TIME_MS);
+ } else {
+ // Hiding
+ mHeightAnimator.setDuration(HIDE_ANIMATION_TIME_MS);
+ }
+ mHeightAnimator.start();
+ }
+
/**
* This is a ViewPager.PagerAdapter which deletegates the work to a
* UserSwitcherController.BaseUserAdapter. Java doesn't support multiple inheritance so we have
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java
index 844a2c4..3115361 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java
@@ -16,7 +16,10 @@
package com.android.systemui.statusbar.notification;
+import android.content.Context;
import android.graphics.Color;
+import android.os.UserHandle;
+import android.provider.Settings;
import android.view.View;
import android.widget.ImageView;
@@ -57,4 +60,10 @@
offsetView.getLocationOnScreen(sLocationOffset);
return sLocationOffset[1] - sLocationBase[1];
}
+
+ public static boolean isHapticFeedbackDisabled(Context context) {
+ return Settings.System.getIntForUser(context.getContentResolver(),
+ Settings.System.HAPTIC_FEEDBACK_ENABLED, 0, UserHandle.USER_CURRENT) == 0;
+ }
+
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
index e0d9748..88a5626 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
@@ -16,14 +16,19 @@
package com.android.systemui.statusbar.phone;
+import static com.android.systemui.statusbar.notification.NotificationUtils.isHapticFeedbackDisabled;
+
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.drawable.Icon;
+import android.os.AsyncTask;
+import android.os.UserHandle;
import android.os.VibrationEffect;
import android.os.Vibrator;
+import android.provider.Settings;
import android.support.v4.util.ArrayMap;
import android.support.v4.util.ArraySet;
import android.util.AttributeSet;
@@ -34,6 +39,7 @@
import com.android.systemui.R;
import com.android.systemui.statusbar.AlphaOptimizedFrameLayout;
import com.android.systemui.statusbar.StatusBarIconView;
+import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.stack.AnimationFilter;
import com.android.systemui.statusbar.stack.AnimationProperties;
import com.android.systemui.statusbar.stack.StackStateAnimator;
@@ -623,9 +629,10 @@
boolean wasInShelf = icon.isInShelf();
boolean inShelf = iconAppearAmount == 1.0f;
icon.setIsInShelf(inShelf);
- if (mVibrateOnAnimation && !justAdded && mAnimationsEnabled
- && wasInShelf != inShelf) {
- mVibrator.vibrate(VibrationEffect.get(VibrationEffect.EFFECT_TICK));
+ if (shouldVibrateChange(wasInShelf != inShelf)) {
+ AsyncTask.execute(
+ () -> mVibrator.vibrate(VibrationEffect.get(
+ VibrationEffect.EFFECT_TICK)));
}
}
justAdded = false;
@@ -634,6 +641,25 @@
justUndarkened = false;
}
+ private boolean shouldVibrateChange(boolean inShelfChanged) {
+ if (!mVibrateOnAnimation) {
+ return false;
+ }
+ if (justAdded) {
+ return false;
+ }
+ if (!mAnimationsEnabled) {
+ return false;
+ }
+ if (!inShelfChanged) {
+ return false;
+ }
+ if (isHapticFeedbackDisabled(mContext)) {
+ return false;
+ }
+ return true;
+ }
+
public boolean hasCustomTransformHeight() {
return isLastExpandIcon && customTransformHeight != NO_VALUE;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index d3ee550..46f9c04 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -16,6 +16,8 @@
package com.android.systemui.statusbar.phone;
+import static com.android.systemui.statusbar.notification.NotificationUtils.isHapticFeedbackDisabled;
+
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
@@ -23,9 +25,12 @@
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.os.AsyncTask;
import android.os.SystemClock;
+import android.os.UserHandle;
import android.os.VibrationEffect;
import android.os.Vibrator;
+import android.provider.Settings;
import android.util.AttributeSet;
import android.util.Log;
import android.view.InputDevice;
@@ -45,6 +50,7 @@
import com.android.systemui.doze.DozeLog;
import com.android.systemui.statusbar.FlingAnimationUtils;
import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import java.io.FileDescriptor;
@@ -59,6 +65,7 @@
private float mMinExpandHeight;
private LockscreenGestureLogger mLockscreenGestureLogger = new LockscreenGestureLogger();
private boolean mPanelUpdateWhenAnimatorEnds;
+ private boolean mVibrateOnOpening;
private final void logf(String fmt, Object... args) {
Log.v(TAG, (mViewName != null ? (mViewName + ": ") : "") + String.format(fmt, args));
@@ -203,6 +210,8 @@
mNotificationsDragEnabled =
getResources().getBoolean(R.bool.config_enableNotificationShadeDrag);
mVibrator = mContext.getSystemService(Vibrator.class);
+ mVibrateOnOpening = mContext.getResources().getBoolean(
+ R.bool.config_vibrateOnIconAnimation);
}
protected void loadDimens() {
@@ -394,7 +403,10 @@
runPeekAnimation(INITIAL_OPENING_PEEK_DURATION, getOpeningHeight(),
false /* collapseWhenFinished */);
notifyBarPanelExpansionChanged();
- mVibrator.vibrate(VibrationEffect.get(VibrationEffect.EFFECT_CLICK));
+ if (mVibrateOnOpening && !isHapticFeedbackDisabled(mContext)) {
+ AsyncTask.execute(
+ () -> mVibrator.vibrate(VibrationEffect.get(VibrationEffect.EFFECT_TICK)));
+ }
}
protected abstract float getOpeningHeight();
diff --git a/wifi/java/android/net/wifi/RttManager.java b/wifi/java/android/net/wifi/RttManager.java
index ac5df05..dc5ba0c 100644
--- a/wifi/java/android/net/wifi/RttManager.java
+++ b/wifi/java/android/net/wifi/RttManager.java
@@ -1,5 +1,6 @@
package android.net.wifi;
+import android.Manifest;
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SuppressLint;
@@ -313,6 +314,7 @@
};
}
+ @RequiresPermission(Manifest.permission.LOCATION_HARDWARE)
public RttCapabilities getRttCapabilities() {
synchronized (mCapabilitiesLock) {
if (mRttCapabilities == null) {
@@ -925,6 +927,51 @@
public void onAborted();
}
+ /**
+ * A parcelable that contains rtt client information.
+ *
+ * @hide
+ */
+ public static class RttClient implements Parcelable {
+ // Package name of RttClient.
+ private final String mPackageName;
+
+ public RttClient(String packageName) {
+ mPackageName = packageName;
+ }
+
+ protected RttClient(Parcel in) {
+ mPackageName = in.readString();
+ }
+
+ public static final Creator<RttManager.RttClient> CREATOR =
+ new Creator<RttManager.RttClient>() {
+ @Override
+ public RttManager.RttClient createFromParcel(Parcel in) {
+ return new RttManager.RttClient(in);
+ }
+
+ @Override
+ public RttManager.RttClient[] newArray(int size) {
+ return new RttManager.RttClient[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel parcel, int i) {
+ parcel.writeString(mPackageName);
+ }
+
+ public String getPackageName() {
+ return mPackageName;
+ }
+ }
+
private boolean rttParamSanity(RttParams params, int index) {
if (mRttCapabilities == null) {
if(getRttCapabilities() == null) {
@@ -1236,7 +1283,8 @@
mAsyncChannel.connectSync(mContext, handler, messenger);
// We cannot use fullyConnectSync because it sends the FULL_CONNECTION message
// synchronously, which causes RttService to receive the wrong replyTo value.
- mAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
+ mAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION,
+ new RttClient(context.getPackageName()));
mAsyncChannel.sendMessage(CMD_OP_REG_BINDER, key[0]);
}