Merge "Show keyguard when SIM is removed"
diff --git a/Android.mk b/Android.mk
index 23aeae5..5d902c2 100644
--- a/Android.mk
+++ b/Android.mk
@@ -79,6 +79,7 @@
core/java/android/app/IBackupAgent.aidl \
core/java/android/app/IEphemeralResolver.aidl \
core/java/android/app/IInstrumentationWatcher.aidl \
+ core/java/android/app/IOnNotificationChannelCreatedListener.aidl \
core/java/android/app/INotificationManager.aidl \
core/java/android/app/IProcessObserver.aidl \
core/java/android/app/ISearchManager.aidl \
diff --git a/api/current.txt b/api/current.txt
index c755614..9489021 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -99,6 +99,7 @@
field public static final java.lang.String READ_FRAME_BUFFER = "android.permission.READ_FRAME_BUFFER";
field public static final deprecated java.lang.String READ_INPUT_STATE = "android.permission.READ_INPUT_STATE";
field public static final java.lang.String READ_LOGS = "android.permission.READ_LOGS";
+ field public static final java.lang.String READ_PHONE_NUMBER = "android.permission.READ_PHONE_NUMBER";
field public static final java.lang.String READ_PHONE_STATE = "android.permission.READ_PHONE_STATE";
field public static final java.lang.String READ_SMS = "android.permission.READ_SMS";
field public static final java.lang.String READ_SYNC_SETTINGS = "android.permission.READ_SYNC_SETTINGS";
@@ -4071,6 +4072,7 @@
field public static final java.lang.String OPSTR_READ_CELL_BROADCASTS = "android:read_cell_broadcasts";
field public static final java.lang.String OPSTR_READ_CONTACTS = "android:read_contacts";
field public static final java.lang.String OPSTR_READ_EXTERNAL_STORAGE = "android:read_external_storage";
+ field public static final java.lang.String OPSTR_READ_PHONE_NUMBER = "android:read_phone_number";
field public static final java.lang.String OPSTR_READ_PHONE_STATE = "android:read_phone_state";
field public static final java.lang.String OPSTR_READ_SMS = "android:read_sms";
field public static final java.lang.String OPSTR_RECEIVE_MMS = "android:receive_mms";
@@ -5393,7 +5395,7 @@
method public void cancel(int);
method public void cancel(java.lang.String, int);
method public void cancelAll();
- method public void createNotificationChannel(android.app.NotificationChannel);
+ method public void createNotificationChannel(android.app.NotificationChannel, android.app.NotificationManager.OnNotificationChannelCreatedListener, android.os.Handler);
method public void deleteNotificationChannel(java.lang.String);
method public android.service.notification.StatusBarNotification[] getActiveNotifications();
method public android.app.AutomaticZenRule getAutomaticZenRule(java.lang.String);
@@ -5427,6 +5429,10 @@
field public static final int INTERRUPTION_FILTER_UNKNOWN = 0; // 0x0
}
+ public static abstract interface NotificationManager.OnNotificationChannelCreatedListener {
+ method public abstract void onNotificationChannelCreated(android.app.NotificationChannel);
+ }
+
public static class NotificationManager.Policy implements android.os.Parcelable {
ctor public NotificationManager.Policy(int, int, int);
ctor public NotificationManager.Policy(int, int, int, int);
diff --git a/api/system-current.txt b/api/system-current.txt
index 8d4de74..2190abb 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -172,6 +172,7 @@
field public static final java.lang.String READ_LOGS = "android.permission.READ_LOGS";
field public static final java.lang.String READ_NETWORK_USAGE_HISTORY = "android.permission.READ_NETWORK_USAGE_HISTORY";
field public static final java.lang.String READ_OEM_UNLOCK_STATE = "android.permission.READ_OEM_UNLOCK_STATE";
+ field public static final java.lang.String READ_PHONE_NUMBER = "android.permission.READ_PHONE_NUMBER";
field public static final java.lang.String READ_PHONE_STATE = "android.permission.READ_PHONE_STATE";
field public static final java.lang.String READ_PRIVILEGED_PHONE_STATE = "android.permission.READ_PRIVILEGED_PHONE_STATE";
field public static final java.lang.String READ_SEARCH_INDEXABLES = "android.permission.READ_SEARCH_INDEXABLES";
@@ -4207,6 +4208,7 @@
field public static final java.lang.String OPSTR_READ_CELL_BROADCASTS = "android:read_cell_broadcasts";
field public static final java.lang.String OPSTR_READ_CONTACTS = "android:read_contacts";
field public static final java.lang.String OPSTR_READ_EXTERNAL_STORAGE = "android:read_external_storage";
+ field public static final java.lang.String OPSTR_READ_PHONE_NUMBER = "android:read_phone_number";
field public static final java.lang.String OPSTR_READ_PHONE_STATE = "android:read_phone_state";
field public static final java.lang.String OPSTR_READ_SMS = "android:read_sms";
field public static final java.lang.String OPSTR_RECEIVE_MMS = "android:receive_mms";
@@ -5560,7 +5562,7 @@
method public void cancel(int);
method public void cancel(java.lang.String, int);
method public void cancelAll();
- method public void createNotificationChannel(android.app.NotificationChannel);
+ method public void createNotificationChannel(android.app.NotificationChannel, android.app.NotificationManager.OnNotificationChannelCreatedListener, android.os.Handler);
method public void deleteNotificationChannel(java.lang.String);
method public android.service.notification.StatusBarNotification[] getActiveNotifications();
method public android.app.AutomaticZenRule getAutomaticZenRule(java.lang.String);
@@ -5594,6 +5596,10 @@
field public static final int INTERRUPTION_FILTER_UNKNOWN = 0; // 0x0
}
+ public static abstract interface NotificationManager.OnNotificationChannelCreatedListener {
+ method public abstract void onNotificationChannelCreated(android.app.NotificationChannel);
+ }
+
public static class NotificationManager.Policy implements android.os.Parcelable {
ctor public NotificationManager.Policy(int, int, int);
ctor public NotificationManager.Policy(int, int, int, int);
diff --git a/api/test-current.txt b/api/test-current.txt
index 072d7a1..a55fa4e 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -99,6 +99,7 @@
field public static final java.lang.String READ_FRAME_BUFFER = "android.permission.READ_FRAME_BUFFER";
field public static final deprecated java.lang.String READ_INPUT_STATE = "android.permission.READ_INPUT_STATE";
field public static final java.lang.String READ_LOGS = "android.permission.READ_LOGS";
+ field public static final java.lang.String READ_PHONE_NUMBER = "android.permission.READ_PHONE_NUMBER";
field public static final java.lang.String READ_PHONE_STATE = "android.permission.READ_PHONE_STATE";
field public static final java.lang.String READ_SMS = "android.permission.READ_SMS";
field public static final java.lang.String READ_SYNC_SETTINGS = "android.permission.READ_SYNC_SETTINGS";
@@ -4081,6 +4082,7 @@
field public static final java.lang.String OPSTR_READ_CELL_BROADCASTS = "android:read_cell_broadcasts";
field public static final java.lang.String OPSTR_READ_CONTACTS = "android:read_contacts";
field public static final java.lang.String OPSTR_READ_EXTERNAL_STORAGE = "android:read_external_storage";
+ field public static final java.lang.String OPSTR_READ_PHONE_NUMBER = "android:read_phone_number";
field public static final java.lang.String OPSTR_READ_PHONE_STATE = "android:read_phone_state";
field public static final java.lang.String OPSTR_READ_SMS = "android:read_sms";
field public static final java.lang.String OPSTR_RECEIVE_MMS = "android:receive_mms";
@@ -5403,7 +5405,7 @@
method public void cancel(int);
method public void cancel(java.lang.String, int);
method public void cancelAll();
- method public void createNotificationChannel(android.app.NotificationChannel);
+ method public void createNotificationChannel(android.app.NotificationChannel, android.app.NotificationManager.OnNotificationChannelCreatedListener, android.os.Handler);
method public void deleteNotificationChannel(java.lang.String);
method public android.service.notification.StatusBarNotification[] getActiveNotifications();
method public android.app.AutomaticZenRule getAutomaticZenRule(java.lang.String);
@@ -5438,6 +5440,10 @@
field public static final int INTERRUPTION_FILTER_UNKNOWN = 0; // 0x0
}
+ public static abstract interface NotificationManager.OnNotificationChannelCreatedListener {
+ method public abstract void onNotificationChannelCreated(android.app.NotificationChannel);
+ }
+
public static class NotificationManager.Policy implements android.os.Parcelable {
ctor public NotificationManager.Policy(int, int, int);
ctor public NotificationManager.Policy(int, int, int, int);
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index ba6bc15..67fbc5a 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -241,8 +241,10 @@
public static final int OP_RUN_IN_BACKGROUND = 63;
/** @hide */
public static final int OP_AUDIO_ACCESSIBILITY_VOLUME = 64;
+ /** @hide Read the phone number. */
+ public static final int OP_READ_PHONE_NUMBER = 65;
/** @hide */
- public static final int _NUM_OP = 65;
+ public static final int _NUM_OP = 66;
/** Access to coarse location information. */
public static final String OPSTR_COARSE_LOCATION = "android:coarse_location";
@@ -343,6 +345,8 @@
/** @hide Get device accounts. */
public static final String OPSTR_GET_ACCOUNTS
= "android:get_accounts";
+ public static final String OPSTR_READ_PHONE_NUMBER
+ = "android:read_phone_number";
private static final int[] RUNTIME_PERMISSIONS_OPS = {
// Contacts
@@ -367,6 +371,7 @@
OP_FINE_LOCATION,
// Phone
OP_READ_PHONE_STATE,
+ OP_READ_PHONE_NUMBER,
OP_CALL_PHONE,
OP_READ_CALL_LOG,
OP_WRITE_CALL_LOG,
@@ -455,6 +460,7 @@
OP_GET_ACCOUNTS,
OP_RUN_IN_BACKGROUND,
OP_AUDIO_ACCESSIBILITY_VOLUME,
+ OP_READ_PHONE_NUMBER,
};
/**
@@ -527,6 +533,7 @@
OPSTR_GET_ACCOUNTS,
null,
null, // OP_AUDIO_ACCESSIBILITY_VOLUME
+ OPSTR_READ_PHONE_NUMBER,
};
/**
@@ -599,6 +606,7 @@
"GET_ACCOUNTS",
"RUN_IN_BACKGROUND",
"AUDIO_ACCESSIBILITY_VOLUME",
+ "READ_PHONE_NUMBER",
};
/**
@@ -671,6 +679,7 @@
Manifest.permission.GET_ACCOUNTS,
null, // no permission for running in background
null, // no permission for changing accessibility volume
+ Manifest.permission.READ_PHONE_NUMBER,
};
/**
@@ -744,6 +753,7 @@
null, // GET_ACCOUNTS
null, // RUN_IN_BACKGROUND
UserManager.DISALLOW_ADJUST_VOLUME, //AUDIO_ACCESSIBILITY_VOLUME
+ null, // READ_PHONE_NUMBER
};
/**
@@ -816,6 +826,7 @@
false, // GET_ACCOUNTS
false, // RUN_IN_BACKGROUND
false, // AUDIO_ACCESSIBILITY_VOLUME
+ false, // READ_PHONE_NUMBER
};
/**
@@ -887,6 +898,7 @@
AppOpsManager.MODE_ALLOWED,
AppOpsManager.MODE_ALLOWED, // OP_RUN_IN_BACKGROUND
AppOpsManager.MODE_ALLOWED, // OP_AUDIO_ACCESSIBILITY_VOLUME
+ AppOpsManager.MODE_ALLOWED,
};
/**
@@ -962,6 +974,7 @@
false,
false,
false, // OP_AUDIO_ACCESSIBILITY_VOLUME
+ false,
};
/**
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 2a7341a..927ef6c 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -2,21 +2,22 @@
**
** Copyright 2007, 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
+** 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
+** 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
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
** limitations under the License.
*/
package android.app;
+import android.app.IOnNotificationChannelCreatedListener;
import android.app.ITransientNotification;
import android.app.Notification;
import android.app.NotificationChannel;
@@ -58,7 +59,8 @@
int getImportance(String pkg, int uid);
int getPackageImportance(String pkg);
- void createNotificationChannel(String pkg, in NotificationChannel channel);
+ void createNotificationChannel(String pkg, in NotificationChannel channel,
+ in IOnNotificationChannelCreatedListener listener);
void updateNotificationChannelForPackage(String pkg, int uid, in NotificationChannel channel);
NotificationChannel getNotificationChannel(String pkg, String channelId);
NotificationChannel getNotificationChannelForPackage(String pkg, int uid, String channelId);
diff --git a/core/java/android/app/IOnNotificationChannelCreatedListener.aidl b/core/java/android/app/IOnNotificationChannelCreatedListener.aidl
new file mode 100644
index 0000000..8e66542
--- /dev/null
+++ b/core/java/android/app/IOnNotificationChannelCreatedListener.aidl
@@ -0,0 +1,25 @@
+/*
+**
+** Copyright 2016, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.app;
+
+import android.app.NotificationChannel;
+
+/** {@hide} */
+oneway interface IOnNotificationChannelCreatedListener {
+ void onNotificationChannelCreated(in NotificationChannel channel);
+}
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 047f349..7693d76 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -18,6 +18,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.SdkConstant;
import android.annotation.TestApi;
import android.app.Notification.Builder;
@@ -30,6 +31,7 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
+import android.os.Looper;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.RemoteException;
@@ -379,12 +381,42 @@
}
/**
- * Creates a notification channel that notifications can be posted to.
+ * Listener passed to {@link NotificationManager#createNotificationChannel} to notify
+ * caller of result.
*/
- public void createNotificationChannel(NotificationChannel channel) {
+ public interface OnNotificationChannelCreatedListener {
+ /**
+ * @param createdChannel NotificationChannel created by the system. Value is null iff an
+ * exception was thrown during channel creation.
+ */
+ public void onNotificationChannelCreated(NotificationChannel createdChannel);
+ }
+
+ /**
+ * Creates a notification channel that notifications can be posted to.
+ *
+ * @param channel the channel to attempt to create. Note that the created channel may differ
+ * from this value.
+ * @param listener Called when operation is finished.
+ * @param handler The handler to invoke the listener on, or {@code null} to use the main
+ * handler.
+ */
+ public void createNotificationChannel(
+ @NonNull NotificationChannel channel,
+ @NonNull OnNotificationChannelCreatedListener listener,
+ @Nullable Handler handler) {
INotificationManager service = getService();
try {
- service.createNotificationChannel(mContext.getPackageName(), channel);
+ final Handler actualHandler =
+ handler != null ? handler : new Handler(Looper.getMainLooper());
+ service.createNotificationChannel(mContext.getPackageName(), channel,
+ new IOnNotificationChannelCreatedListener.Stub() {
+ @Override public void onNotificationChannelCreated(
+ NotificationChannel channel) {
+ actualHandler.post(
+ () -> { listener.onNotificationChannelCreated(channel); });
+ }
+ });
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -583,7 +615,7 @@
* <p>
* Callers can only update rules that they own. See {@link AutomaticZenRule#getOwner}.
* @param id The id of the rule to update
- * @param automaticZenRule the rule to update.
+ * @param automaticZenRule the rule to update.
* @return Whether the rule was successfully updated.
*/
public boolean updateAutomaticZenRule(String id, AutomaticZenRule automaticZenRule) {
diff --git a/core/java/android/view/animation/PathInterpolator.java b/core/java/android/view/animation/PathInterpolator.java
index eec5555..924437a 100644
--- a/core/java/android/view/animation/PathInterpolator.java
+++ b/core/java/android/view/animation/PathInterpolator.java
@@ -25,6 +25,9 @@
import android.view.InflateException;
import com.android.internal.R;
+import com.android.internal.view.animation.HasNativeInterpolator;
+import com.android.internal.view.animation.NativeInterpolatorFactory;
+import com.android.internal.view.animation.NativeInterpolatorFactoryHelper;
/**
* An interpolator that can traverse a Path that extends from <code>Point</code>
@@ -42,7 +45,8 @@
* path.lineTo(1f, 1f);
* </pre></blockquote></p>
*/
-public class PathInterpolator extends BaseInterpolator {
+@HasNativeInterpolator
+public class PathInterpolator extends BaseInterpolator implements NativeInterpolatorFactory {
// This governs how accurate the approximation of the Path is.
private static final float PRECISION = 0.002f;
@@ -229,4 +233,11 @@
float endY = mY[endIndex];
return startY + (fraction * (endY - startY));
}
+
+ /** @hide **/
+ @Override
+ public long createNativeInterpolator() {
+ return NativeInterpolatorFactoryHelper.createPathInterpolator(mX, mY);
+ }
+
}
diff --git a/core/java/com/android/internal/view/animation/NativeInterpolatorFactoryHelper.java b/core/java/com/android/internal/view/animation/NativeInterpolatorFactoryHelper.java
index 7cd75f3..ebeec40 100644
--- a/core/java/com/android/internal/view/animation/NativeInterpolatorFactoryHelper.java
+++ b/core/java/com/android/internal/view/animation/NativeInterpolatorFactoryHelper.java
@@ -32,5 +32,6 @@
public static native long createDecelerateInterpolator(float factor);
public static native long createLinearInterpolator();
public static native long createOvershootInterpolator(float tension);
+ public static native long createPathInterpolator(float[] x, float[] y);
public static native long createLutInterpolator(float[] values);
}
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index be2e404..77934fe 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -217,7 +217,6 @@
external/skia/src/images \
external/sqlite/dist \
external/sqlite/android \
- external/expat/lib \
external/tremor/Tremor \
external/harfbuzz_ng/src \
libcore/include \
@@ -234,17 +233,14 @@
libandroidfw \
libappfuse \
libbase \
- libexpat \
libnativehelper \
liblog \
libcutils \
libutils \
libbinder \
- libnetutils \
libui \
libgui \
libinput \
- libinputflinger \
libcamera_client \
libcamera_metadata \
libskia \
@@ -257,18 +253,13 @@
libhardware \
libhardware_legacy \
libselinux \
- libsonivox \
- libcrypto \
- libssl \
libicuuc \
- libicui18n \
libmedia \
libaudioclient \
libjpeg \
libusbhost \
libharfbuzz_ng \
libz \
- libaudioutils \
libpdfium \
libimg_utils \
libnetd_client \
diff --git a/core/jni/com_android_internal_view_animation_NativeInterpolatorFactoryHelper.cpp b/core/jni/com_android_internal_view_animation_NativeInterpolatorFactoryHelper.cpp
index 6781e13..f4d2e7b 100644
--- a/core/jni/com_android_internal_view_animation_NativeInterpolatorFactoryHelper.cpp
+++ b/core/jni/com_android_internal_view_animation_NativeInterpolatorFactoryHelper.cpp
@@ -18,6 +18,7 @@
#include "jni.h"
#include <nativehelper/JNIHelp.h>
+#include <cutils/log.h>
#include "core_jni_helpers.h"
#include <Interpolator.h>
@@ -62,6 +63,19 @@
return reinterpret_cast<jlong>(new OvershootInterpolator(tension));
}
+static jlong createPathInterpolator(JNIEnv* env, jobject clazz, jfloatArray jX, jfloatArray jY) {
+ jsize lenX = env->GetArrayLength(jX);
+ jsize lenY = env->GetArrayLength(jY);
+ LOG_ALWAYS_FATAL_IF(lenX != lenY || lenX <= 0, "Invalid path interpolator, x size: %d,"
+ " y size: %d", lenX, lenY);
+ std::vector<float> x(lenX);
+ std::vector<float> y(lenY);
+ env->GetFloatArrayRegion(jX, 0, lenX, x.data());
+ env->GetFloatArrayRegion(jY, 0, lenX, y.data());
+
+ return reinterpret_cast<jlong>(new PathInterpolator(std::move(x), std::move(y)));
+}
+
static jlong createLutInterpolator(JNIEnv* env, jobject clazz, jfloatArray jlut) {
jsize len = env->GetArrayLength(jlut);
if (len <= 0) {
@@ -88,6 +102,7 @@
{ "createDecelerateInterpolator", "(F)J", (void*) createDecelerateInterpolator },
{ "createLinearInterpolator", "()J", (void*) createLinearInterpolator },
{ "createOvershootInterpolator", "(F)J", (void*) createOvershootInterpolator },
+ { "createPathInterpolator", "([F[F)J", (void*) createPathInterpolator },
{ "createLutInterpolator", "([F)J", (void*) createLutInterpolator },
};
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 94f7bec..6f33f27 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -769,6 +769,15 @@
android:permissionGroup="android.permission-group.PHONE"
android:label="@string/permlab_readPhoneState"
android:description="@string/permdesc_readPhoneState"
+ android:protectionLevel="dangerous" />
+
+ <!-- Allows read access to the device's phone number. This is a subset of the capabilities
+ granted by {@link #READ_PHONE_STATE} but is exposed to ephemeral applications.
+ <p>Protection level: dangerous-->
+ <permission android:name="android.permission.READ_PHONE_NUMBER"
+ android:permissionGroup="android.permission-group.PHONE"
+ android:label="@string/permlab_readPhoneNumber"
+ android:description="@string/permdesc_readPhoneNumber"
android:protectionLevel="dangerous|ephemeral" />
<!-- Allows an application to initiate a phone call without going through
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 8546aa5..af77b1f 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1059,6 +1059,11 @@
connected by a call.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permlab_readPhoneNumber">read phone number</string>
+ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permdesc_readPhoneNumber">Allows the app to access the phone number of the device.</string>
+
+ <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_wakeLock" product="tablet">prevent tablet from sleeping</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_wakeLock" product="tv">prevent TV from sleeping</string>
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index 361e901..cf571e9 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -298,6 +298,7 @@
tests/unit/MeshStateTests.cpp \
tests/unit/OffscreenBufferPoolTests.cpp \
tests/unit/OpDumperTests.cpp \
+ tests/unit/PathInterpolatorTests.cpp \
tests/unit/RenderNodeDrawableTests.cpp \
tests/unit/RecordingCanvasTests.cpp \
tests/unit/RenderNodeTests.cpp \
diff --git a/libs/hwui/Extensions.cpp b/libs/hwui/Extensions.cpp
index 1d67579..00238a2 100644
--- a/libs/hwui/Extensions.cpp
+++ b/libs/hwui/Extensions.cpp
@@ -37,6 +37,26 @@
Extensions::Extensions() {
+ const char* version = (const char*) glGetString(GL_VERSION);
+
+ // Section 6.1.5 of the OpenGL ES specification indicates the GL version
+ // string strictly follows this format:
+ //
+ // OpenGL<space>ES<space><version number><space><vendor-specific information>
+ //
+ // In addition section 6.1.5 describes the version number thusly:
+ //
+ // "The version number is either of the form major number.minor number or
+ // major number.minor number.release number, where the numbers all have one
+ // or more digits. The release number and vendor specific information are
+ // optional."
+
+ if (sscanf(version, "OpenGL ES %d.%d", &mVersionMajor, &mVersionMinor) != 2) {
+ // If we cannot parse the version number, assume OpenGL ES 2.0
+ mVersionMajor = 2;
+ mVersionMinor = 0;
+ }
+
auto extensions = StringUtils::split((const char*) glGetString(GL_EXTENSIONS));
mHasNPot = extensions.has("GL_OES_texture_npot");
mHasFramebufferFetch = extensions.has("GL_NV_shader_framebuffer_fetch");
@@ -58,26 +78,6 @@
mHasSRGB = false;
mHasSRGBWriteControl = false;
#endif
-
- const char* version = (const char*) glGetString(GL_VERSION);
-
- // Section 6.1.5 of the OpenGL ES specification indicates the GL version
- // string strictly follows this format:
- //
- // OpenGL<space>ES<space><version number><space><vendor-specific information>
- //
- // In addition section 6.1.5 describes the version number thusly:
- //
- // "The version number is either of the form major number.minor number or
- // major number.minor number.release number, where the numbers all have one
- // or more digits. The release number and vendor specific information are
- // optional."
-
- if (sscanf(version, "OpenGL ES %d.%d", &mVersionMajor, &mVersionMinor) != 2) {
- // If we cannot parse the version number, assume OpenGL ES 2.0
- mVersionMajor = 2;
- mVersionMinor = 0;
- }
}
}; // namespace uirenderer
diff --git a/libs/hwui/Interpolator.cpp b/libs/hwui/Interpolator.cpp
index bddb01b..f94a22d 100644
--- a/libs/hwui/Interpolator.cpp
+++ b/libs/hwui/Interpolator.cpp
@@ -88,6 +88,39 @@
return t * t * ((mTension + 1) * t + mTension) + 1.0f;
}
+float PathInterpolator::interpolate(float t) {
+ if (t <= 0) {
+ return 0;
+ } else if (t >= 1) {
+ return 1;
+ }
+ // Do a binary search for the correct x to interpolate between.
+ size_t startIndex = 0;
+ size_t endIndex = mX.size() - 1;
+
+ while (endIndex > startIndex + 1) {
+ int midIndex = (startIndex + endIndex) / 2;
+ if (t < mX[midIndex]) {
+ endIndex = midIndex;
+ } else {
+ startIndex = midIndex;
+ }
+ }
+
+ float xRange = mX[endIndex] - mX[startIndex];
+ if (xRange == 0) {
+ return mY[startIndex];
+ }
+
+ float tInRange = t - mX[startIndex];
+ float fraction = tInRange / xRange;
+
+ float startY = mY[startIndex];
+ float endY = mY[endIndex];
+ return startY + (fraction * (endY - startY));
+
+}
+
LUTInterpolator::LUTInterpolator(float* values, size_t size)
: mValues(values)
, mSize(size) {
diff --git a/libs/hwui/Interpolator.h b/libs/hwui/Interpolator.h
index 6512008..224cee7 100644
--- a/libs/hwui/Interpolator.h
+++ b/libs/hwui/Interpolator.h
@@ -20,6 +20,7 @@
#include <memory>
#include <cutils/compiler.h>
+#include <vector>
namespace android {
namespace uirenderer {
@@ -100,6 +101,16 @@
const float mTension;
};
+class ANDROID_API PathInterpolator : public Interpolator {
+public:
+ explicit PathInterpolator(std::vector<float>&& x, std::vector<float>&& y)
+ : mX (x), mY(y) {}
+ virtual float interpolate(float input) override;
+private:
+ std::vector<float> mX;
+ std::vector<float> mY;
+};
+
class ANDROID_API LUTInterpolator : public Interpolator {
public:
LUTInterpolator(float* values, size_t size);
diff --git a/libs/hwui/tests/unit/PathInterpolatorTests.cpp b/libs/hwui/tests/unit/PathInterpolatorTests.cpp
new file mode 100644
index 0000000..d7cb23a
--- /dev/null
+++ b/libs/hwui/tests/unit/PathInterpolatorTests.cpp
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#include <gtest/gtest.h>
+
+#include <Interpolator.h>
+
+namespace android {
+namespace uirenderer {
+
+struct TestData {
+ const std::vector<float> x;
+ const std::vector<float> y;
+ const std::vector<float> inFraction;
+ const std::vector<float> outFraction;
+};
+
+const static TestData sTestDataSet[] = {
+ {
+ // Straight line as a path.
+ {0.0f, 1.0f},
+ {0.0f, 1.0f},
+ {0.0f, 0.2f, 0.4f, 0.6f, 0.8f, 1.0f},
+ {0.0f, 0.2f, 0.4f, 0.6f, 0.8f, 1.0f},
+ },
+
+ {
+ {
+ 0.0f, 0.5f, 0.5178955f, 0.5341797f, 0.5489991f, 0.5625f, 0.5748291f,
+ 0.5861328f, 0.60625005f, 0.62402344f, 0.640625f, 0.675f, 0.6951172f,
+ 0.71875f, 0.7470703f, 0.78125f, 0.82246095f, 0.84606934f, 0.871875f,
+ 0.9000244f, 0.93066406f, 0.96394044f, 1.0f
+ },
+ {
+ 0.0f, 0.0f, 0.0028686523f, 0.011230469f, 0.024719238f, 0.04296875f,
+ 0.06561279f, 0.092285156f, 0.15625f, 0.2319336f, 0.31640625f, 0.5f,
+ 0.5932617f, 0.68359375f, 0.7680664f, 0.84375f, 0.90771484f, 0.9343872f,
+ 0.95703125f, 0.97528076f, 0.98876953f, 0.99713135f, 1.0f
+ },
+ {
+ 0.0f, 0.03375840187072754f, 0.13503384590148926f, 0.23630905151367188f,
+ 0.336834192276001f, 0.4508626461029053f, 0.564141035079956f,
+ 0.6781694889068604f, 0.7921979427337646f, 0.9054763317108154f, 1.0f
+ },
+ {
+ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0459827296435833f,
+ 0.5146934390068054f, 0.8607426285743713f, 0.9776809215545654f, 1.0f
+
+ }
+
+ },
+ {
+ {
+ 0.0f, 0.017895509f, 0.034179688f, 0.048999026f, 0.0625f, 0.0748291f,
+ 0.08613282f, 0.10625f, 0.12402344f, 0.140625f, 0.17500001f, 0.19511719f,
+ 0.21875f, 0.24707031f, 0.28125f, 0.32246095f, 0.34606934f, 0.371875f,
+ 0.4000244f, 0.43066406f, 0.46394044f, 0.5f, 1.0f
+ },
+ {
+ 0.0f, 0.0028686523f, 0.011230469f, 0.024719238f, 0.04296875f, 0.06561279f,
+ 0.092285156f, 0.15625f, 0.2319336f, 0.31640625f, 0.5f, 0.5932617f,
+ 0.68359375f, 0.7680664f, 0.84375f, 0.90771484f, 0.9343872f, 0.95703125f,
+ 0.97528076f, 0.98876953f, 0.99713135f, 1.0f, 1.0f
+ },
+ {
+ 0.0f, 0.102020263671875f, 0.20330810546875f, 0.3165740966796875f,
+ 0.43060302734375f, 0.5318756103515625f, 0.6331634521484375f,
+ 0.746429443359375f, 0.84771728515625f, 0.9617462158203125f, 1.0f
+ },
+ {
+ 0.0f, 0.14280107617378235f, 0.6245699524879456f, 0.8985776901245117f,
+ 0.9887426495552063f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f
+ }
+ },
+
+
+};
+
+static std::vector<float> getX(const TestData& data) {
+ return data.x;
+}
+
+static std::vector<float> getY(const TestData& data) {
+ return data.y;
+}
+
+TEST(Interpolator, pathInterpolation) {
+ for (const TestData& data: sTestDataSet) {
+ PathInterpolator interpolator(getX(data), getY(data));
+ for (size_t i = 0; i < data.inFraction.size(); i++) {
+ EXPECT_FLOAT_EQ(data.outFraction[i], interpolator.interpolate(data.inFraction[i]));
+ }
+ }
+}
+
+}
+}
diff --git a/opengl/java/android/opengl/GLES30.java b/opengl/java/android/opengl/GLES30.java
index 74181c5..3b805d2 100644
--- a/opengl/java/android/opengl/GLES30.java
+++ b/opengl/java/android/opengl/GLES30.java
@@ -590,6 +590,10 @@
// C function void glGetBufferPointerv ( GLenum target, GLenum pname, GLvoid** params )
+ /**
+ * The {@link java.nio.Buffer} instance returned by this method is guaranteed
+ * to be an instance of {@link java.nio.ByteBuffer}.
+ */
public static native java.nio.Buffer glGetBufferPointerv(
int target,
int pname
@@ -761,6 +765,10 @@
// C function GLvoid * glMapBufferRange ( GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access )
+ /**
+ * The {@link java.nio.Buffer} instance returned by this method is guaranteed
+ * to be an instance of {@link java.nio.ByteBuffer}.
+ */
public static native java.nio.Buffer glMapBufferRange(
int target,
int offset,
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index af1fc59..bfc26e3 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1126,7 +1126,6 @@
<item></item> <!-- STREAM_SYSTEM_ENFORCED -->
<item></item> <!-- STREAM_DTMF -->
<item></item> <!-- STREAM_TTS -->
- <item>Accessibility</item> <!-- STREAM_ACCESSIBILITY -->
</string-array>
<string name="volume_stream_muted" translatable="false">%s silent</string>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index a1384dcb..661cc3c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -1685,6 +1685,9 @@
if (mGuts != null) {
mGuts.setClipBottomAmount(clipBottomAmount);
}
+ if (mChildrenContainer != null) {
+ mChildrenContainer.setClipBottomAmount(clipBottomAmount);
+ }
}
public boolean isMaxExpandHeightInitialized() {
@@ -1863,9 +1866,6 @@
super.applyToView(view);
if (view instanceof ExpandableNotificationRow) {
ExpandableNotificationRow row = (ExpandableNotificationRow) view;
- if (this.isBottomClipped) {
- row.setClipToActualHeight(true);
- }
row.applyChildrenState(mOverallState);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java
index 4b95f07..91abc87 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java
@@ -41,7 +41,7 @@
outline.setRect(translation,
mClipTopAmount,
getWidth() + translation,
- Math.max(getActualHeight(), mClipTopAmount));
+ Math.max(getActualHeight() - mClipBottomAmount, mClipTopAmount));
} else {
outline.setRect(mOutlineRect);
}
@@ -66,6 +66,12 @@
invalidateOutline();
}
+ @Override
+ public void setClipBottomAmount(int clipBottomAmount) {
+ super.setClipBottomAmount(clipBottomAmount);
+ invalidateOutline();
+ }
+
protected void setOutlineAlpha(float alpha) {
if (alpha != mOutlineAlpha) {
mOutlineAlpha = alpha;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
index 0f5981b..37a900e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
@@ -38,7 +38,7 @@
protected OnHeightChangedListener mOnHeightChangedListener;
private int mActualHeight;
protected int mClipTopAmount;
- private float mClipBottomAmount;
+ protected int mClipBottomAmount;
private boolean mDark;
private ArrayList<View> mMatchParentViews = new ArrayList<View>();
private static Rect mClipRect = new Rect();
@@ -241,7 +241,7 @@
return mClipTopAmount;
}
- public float getClipBottomAmount() {
+ public int getClipBottomAmount() {
return mClipBottomAmount;
}
@@ -354,11 +354,8 @@
private void updateClipping() {
if (mClipToActualHeight) {
int top = getClipTopAmount();
- if (top >= getActualHeight()) {
- top = getActualHeight() - 1;
- }
- mClipRect.set(0, top, getWidth(), (int) (getActualHeight() + getExtraBottomPadding()
- - mClipBottomAmount));
+ mClipRect.set(0, top, getWidth(), Math.max(getActualHeight() + getExtraBottomPadding()
+ - mClipBottomAmount, top));
setClipBounds(mClipRect);
} else {
setClipBounds(null);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index add4764..680562a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -156,7 +156,6 @@
mShelfState.alpha = 1.0f;
mShelfState.belowSpeedBump = mAmbientState.getSpeedBumpIndex() == 0;
mShelfState.shadowAlpha = 1.0f;
- mShelfState.isBottomClipped = false;
mShelfState.hideSensitive = false;
mShelfState.xTranslation = getTranslationX();
if (mNotGoneIndex != -1) {
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 2895890..03697b8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
@@ -48,7 +48,7 @@
return mAnimationFilter;
}
}.setDuration(200);
-
+
private static final AnimationProperties ADD_ICON_PROPERTIES = new AnimationProperties() {
private AnimationFilter mAnimationFilter = new AnimationFilter().animateAlpha();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 523528d..99e98f2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -404,12 +404,9 @@
mKeyguardStatusView.getHeight());
int notificationPadding = Math.max(1, getResources().getDimensionPixelSize(
R.dimen.notification_divider_height));
- final int overflowheight = getResources().getDimensionPixelSize(
- R.dimen.notification_shelf_height);
float shelfSize = mNotificationStackScroller.getNotificationShelf().getIntrinsicHeight()
+ notificationPadding;
- float availableSpace = mNotificationStackScroller.getHeight() - minPadding - overflowheight
- - shelfSize;
+ float availableSpace = mNotificationStackScroller.getHeight() - minPadding - shelfSize;
int count = 0;
for (int i = 0; i < mNotificationStackScroller.getChildCount(); i++) {
ExpandableView child = (ExpandableView) mNotificationStackScroller.getChildAt(i);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/ExpandableViewState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/ExpandableViewState.java
index 58e6838..7854c98 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/ExpandableViewState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/ExpandableViewState.java
@@ -106,11 +106,6 @@
*/
public int location;
- /**
- * Whether a child in a group is being clipped at the bottom.
- */
- public boolean isBottomClipped;
-
@Override
public void copyFrom(ViewState viewState) {
super.copyFrom(viewState);
@@ -125,7 +120,6 @@
clipTopAmount = svs.clipTopAmount;
notGoneIndex = svs.notGoneIndex;
location = svs.location;
- isBottomClipped = svs.isBottomClipped;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
index 26e1342..b8f8cb2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
@@ -76,6 +76,7 @@
private NotificationViewWrapper mNotificationHeaderWrapper;
private NotificationHeaderUtil mHeaderUtil;
private ViewState mHeaderViewState;
+ private int mClipBottomAmount;
public NotificationChildrenContainer(Context context) {
this(context, null);
@@ -433,7 +434,6 @@
boolean childrenExpanded = !mNotificationParent.isGroupExpansionChanging()
&& mChildrenExpanded;
- int parentHeight = parentState.height;
for (int i = 0; i < childCount; i++) {
ExpandableNotificationRow child = mChildren.get(i);
if (!firstChild) {
@@ -457,20 +457,9 @@
ExpandableViewState childState = resultState.getViewStateForView(child);
int intrinsicHeight = child.getIntrinsicHeight();
- if (childrenExpanded) {
- // When a group is expanded and moving into bottom stack, the bottom visible child
- // adjusts its height to move into it. Children after it are hidden.
- if (updateChildStateForExpandedGroup(child, parentHeight, childState, yPosition)) {
- // Clipping might be deactivated if the view is transforming, however, clipping
- // the child into the bottom stack should take precedent over this.
- childState.isBottomClipped = true;
- }
- } else {
- childState.hidden = false;
- childState.height = intrinsicHeight;
- childState.isBottomClipped = false;
- }
+ childState.height = intrinsicHeight;
childState.yTranslation = yPosition;
+ childState.hidden = false;
// When the group is expanded, the children cast the shadows rather than the parent
// so use the parent's elevation here.
childState.zTranslation = childrenExpanded
@@ -601,6 +590,34 @@
if (mHeaderViewState != null) {
mHeaderViewState.applyToView(mNotificationHeader);
}
+ updateChildrenClipping();
+ }
+
+ private void updateChildrenClipping() {
+ int childCount = mChildren.size();
+ int layoutEnd = mNotificationParent.getActualHeight() - mClipBottomAmount;
+ for (int i = 0; i < childCount; i++) {
+ ExpandableNotificationRow child = mChildren.get(i);
+ if (child.getVisibility() == GONE) {
+ continue;
+ }
+ float childTop = child.getTranslationY();
+ float childBottom = childTop + child.getActualHeight();
+ boolean visible = true;
+ int clipBottomAmount = 0;
+ if (childTop > layoutEnd) {
+ visible = false;
+ } else if (childBottom > layoutEnd) {
+ clipBottomAmount = (int) (childBottom - layoutEnd);
+ }
+
+ boolean isVisible = child.getVisibility() == VISIBLE;
+ if (visible != isVisible) {
+ child.setVisibility(visible ? VISIBLE : INVISIBLE);
+ }
+
+ child.setClipBottomAmount(clipBottomAmount);
+ }
}
/**
@@ -653,6 +670,7 @@
if (mNotificationHeader != null) {
mHeaderViewState.applyToView(mNotificationHeader);
}
+ updateChildrenClipping();
}
public ExpandableNotificationRow getViewAtPosition(float y) {
@@ -889,4 +907,9 @@
}
}
}
+
+ public void setClipBottomAmount(int clipBottomAmount) {
+ mClipBottomAmount = clipBottomAmount;
+ updateChildrenClipping();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 522e4a9..10d995c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -766,12 +766,14 @@
*/
private float getAppearEndPosition() {
int appearPosition;
+ int minNotificationsForShelf = 1;
if (mTrackingHeadsUp || mHeadsUpManager.hasPinnedHeadsUp()) {
appearPosition = mHeadsUpManager.getTopHeadsUpPinnedHeight();
+ minNotificationsForShelf = 2;
} else {
- appearPosition = getFirstItemMinHeight();
+ appearPosition = 0;
}
- if (getNotGoneChildCount() > 1) {
+ if (getNotGoneChildCount() >= minNotificationsForShelf) {
appearPosition += mShelf.getIntrinsicHeight();
}
return appearPosition + (onKeyguard() ? mTopPadding : mIntrinsicPadding);
@@ -1092,29 +1094,7 @@
@Override
public int getMaxExpandHeight(ExpandableView view) {
- int maxContentHeight = view.getMaxContentHeight();
- if (view.isSummaryWithChildren() && view.getParent() == this) {
- // Faking a measure with the group expanded to simulate how the group would look if
- // it was. Doing a calculation here would be highly non-trivial because of the
- // algorithm
- mGroupExpandedForMeasure = true;
- ExpandableNotificationRow row = (ExpandableNotificationRow) view;
- mGroupManager.toggleGroupExpansion(row.getStatusBarNotification());
- row.setForceUnlocked(true);
- mAmbientState.setLayoutHeight(mMaxLayoutHeight);
- mStackScrollAlgorithm.getStackScrollState(mAmbientState, mCurrentStackScrollState);
- mAmbientState.setLayoutHeight(getLayoutHeight());
- mGroupManager.toggleGroupExpansion(
- row.getStatusBarNotification());
- mGroupExpandedForMeasure = false;
- row.setForceUnlocked(false);
- ExpandableViewState viewState = mCurrentStackScrollState.getViewStateForView(view);
- if (viewState != null) {
- // The view could have been removed
- return Math.min(viewState.height, maxContentHeight);
- }
- }
- return maxContentHeight;
+ return view.getMaxContentHeight();
}
public void setScrollingEnabled(boolean enable) {
@@ -2126,7 +2106,7 @@
finalTranslationY = (int) ViewState.getFinalTranslationY(lastView);
}
int finalHeight = ExpandableViewState.getFinalActualHeight(lastView);
- int finalBottom = finalTranslationY + finalHeight;
+ int finalBottom = finalTranslationY + finalHeight - lastView.getClipBottomAmount();
finalBottom = Math.min(finalBottom, getHeight());
if (mAnimateNextBackgroundBottom
|| mBottomAnimator == null && mCurrentBounds.bottom == finalBottom
@@ -2134,10 +2114,10 @@
// we're ending up at the same location as we are now, lets just skip the animation
bottom = finalBottom;
} else {
- bottom = (int) (lastView.getTranslationY() + lastView.getActualHeight());
+ bottom = (int) (lastView.getTranslationY() + lastView.getActualHeight()
+ - lastView.getClipBottomAmount());
bottom = Math.min(bottom, getHeight());
}
- bottom -= lastView.getClipBottomAmount();
} else {
top = mTopPadding;
bottom = top;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
index 1dc346d..7afc7ba 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -140,7 +140,7 @@
float newNotificationEnd = newYTranslation + newHeight;
boolean isHeadsUp = (child instanceof ExpandableNotificationRow)
&& ((ExpandableNotificationRow) child).isPinned();
- if (newYTranslation < previousNotificationEnd
+ if (!state.inShelf && newYTranslation < previousNotificationEnd
&& (!isHeadsUp || ambientState.isShadeExpanded())) {
// The previous view is overlapping on top, clip!
float overlapAmount = previousNotificationEnd - newYTranslation;
@@ -323,9 +323,6 @@
int childHeight = getMaxAllowedChildHeight(child);
childViewState.yTranslation = currentYPosition;
boolean isDismissView = child instanceof DismissView;
- if (i == 0) {
- updateFirstChildHeight(child, childViewState, childHeight, algorithmState, ambientState);
- }
childViewState.location = ExpandableViewState.LOCATION_MAIN_AREA;
if (isDismissView) {
@@ -450,29 +447,6 @@
}
/**
- * Update the height of the first child i.e clamp it to the bottom stack
- * @param child the child to update
- * @param childViewState the viewstate of the child
- * @param childHeight the height of the child
- * @param algorithmState the algorithm state
- * @param ambientState The ambient state of the algorithm
- */
- protected void updateFirstChildHeight(ExpandableView child, ExpandableViewState childViewState,
- int childHeight, StackScrollAlgorithmState algorithmState,
- AmbientState ambientState) {
-
- int bottomStart= ambientState.getInnerHeight();
- if (algorithmState.visibleChildren.size() > 1) {
- bottomStart -= ambientState.getShelf().getIntrinsicHeight()
- - mPaddingBetweenElements;
- }
- bottomStart += ambientState.getScrollY();
- // Collapse and expand the first child while the shade is being expanded
- childViewState.height = (int) Math.max(Math.min(bottomStart, (float) childHeight),
- child.getCollapsedHeight());
- }
-
- /**
* Calculate the Z positions for all children based on the number of items in both stacks and
* save it in the resultState
* @param resultState The result state to update the zTranslation values
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogController.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogController.java
index 5393d60..ec0e4cd 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogController.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogController.java
@@ -78,7 +78,6 @@
AudioSystem.STREAM_SYSTEM_ENFORCED,
AudioSystem.STREAM_TTS,
AudioSystem.STREAM_VOICE_CALL,
- AudioSystem.STREAM_ACCESSIBILITY,
};
private final HandlerThread mWorkerThread;
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 599d876..229a68b 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -200,6 +200,7 @@
import android.os.storage.IStorageManager;
import android.os.storage.StorageManagerInternal;
import android.os.storage.StorageManager;
+import android.provider.Downloads;
import android.provider.Settings;
import android.service.voice.IVoiceInteractionSession;
import android.service.voice.VoiceInteractionManagerInternal;
@@ -8513,6 +8514,12 @@
// Only inspect grants matching package
if (packageName == null || perm.sourcePkg.equals(packageName)
|| perm.targetPkg.equals(packageName)) {
+ // Hacky solution as part of fixing a security bug; ignore
+ // grants associated with DownloadManager so we don't have
+ // to immediately launch it to regrant the permissions
+ if (Downloads.Impl.AUTHORITY.equals(perm.uri.uri.getAuthority())
+ && !persistable) continue;
+
persistChanged |= perm.revokeModes(persistable
? ~0 : ~Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION, true);
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 84c298b..c78a0f5 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -53,16 +53,17 @@
import android.app.AppGlobals;
import android.app.AppOpsManager;
import android.app.AutomaticZenRule;
+import android.app.backup.BackupManager;
import android.app.IActivityManager;
+import android.app.IOnNotificationChannelCreatedListener;
import android.app.INotificationManager;
import android.app.ITransientNotification;
import android.app.Notification;
import android.app.NotificationChannel;
-import android.app.NotificationManager;
import android.app.NotificationManager.Policy;
+import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.StatusBarManager;
-import android.app.backup.BackupManager;
import android.app.usage.UsageEvents;
import android.app.usage.UsageStatsManagerInternal;
import android.content.BroadcastReceiver;
@@ -224,6 +225,7 @@
private static final long MIN_PACKAGE_OVERRATE_LOG_INTERVAL = 5000; // milliseconds
private IActivityManager mAm;
+ private IPackageManager mPackageManager;
AudioManager mAudioManager;
AudioManagerInternal mAudioManagerInternal;
@Nullable StatusBarManagerInternal mStatusBar;
@@ -718,10 +720,10 @@
if (packageChanged) {
// We cancel notifications for packages which have just been disabled
try {
- final IPackageManager pm = AppGlobals.getPackageManager();
- final int enabled = pm.getApplicationEnabledSetting(pkgName,
+ final int enabled = mPackageManager.getApplicationEnabledSetting(
+ pkgName,
changeUserId != UserHandle.USER_ALL ? changeUserId :
- UserHandle.USER_SYSTEM);
+ UserHandle.USER_SYSTEM);
if (enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED
|| enabled == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
cancelNotifications = false;
@@ -884,6 +886,7 @@
super(context);
}
+ // TODO - replace these methods with a single VisibleForTesting constructor
@VisibleForTesting
void setAudioManager(AudioManager audioMananger) {
mAudioManager = audioMananger;
@@ -931,6 +934,17 @@
mFallbackVibrationPattern = vibrationPattern;
}
+ @VisibleForTesting
+ void setPackageManager(IPackageManager packageManager) {
+ mPackageManager = packageManager;
+ }
+
+ // TODO: This probably should not be mocked, it's an implementation detail.
+ @VisibleForTesting
+ void setRankingHelper(RankingHelper rankingHelper) {
+ mRankingHelper = rankingHelper;
+ }
+
@Override
public void onStart() {
Resources resources = getContext().getResources();
@@ -940,6 +954,7 @@
DEFAULT_MAX_NOTIFICATION_ENQUEUE_RATE);
mAm = ActivityManager.getService();
+ mPackageManager = AppGlobals.getPackageManager();
mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE);
mVibrator = (Vibrator) getContext().getSystemService(Context.VIBRATOR_SERVICE);
mAppUsageStats = LocalServices.getService(UsageStatsManagerInternal.class);
@@ -1312,6 +1327,11 @@
scheduleInterruptionFilterChanged(interruptionFilter);
}
+ @VisibleForTesting
+ INotificationManager getBinderService() {
+ return INotificationManager.Stub.asInterface(mService);
+ }
+
private final IBinder mService = new INotificationManager.Stub() {
// Toasts
// ============================================================================
@@ -1529,13 +1549,15 @@
}
@Override
- public void createNotificationChannel(String pkg, NotificationChannel channel) {
+ public void createNotificationChannel(String pkg, NotificationChannel channel,
+ IOnNotificationChannelCreatedListener listener) throws RemoteException {
Preconditions.checkNotNull(channel);
Preconditions.checkNotNull(channel.getId());
Preconditions.checkNotNull(channel.getName());
checkCallerIsSystemOrSameApp(pkg);
mRankingHelper.createNotificationChannel(pkg, Binder.getCallingUid(), channel);
savePolicyFile();
+ listener.onNotificationChannelCreated(channel);
}
@Override
@@ -3906,23 +3928,23 @@
throw new SecurityException("Disallowed call for uid " + Binder.getCallingUid());
}
- private static void checkCallerIsSystemOrSameApp(String pkg) {
+ private void checkCallerIsSystemOrSameApp(String pkg) {
if (isCallerSystem()) {
return;
}
checkCallerIsSameApp(pkg);
}
- private static void checkCallerIsSameApp(String pkg) {
+ private void checkCallerIsSameApp(String pkg) {
final int uid = Binder.getCallingUid();
try {
- ApplicationInfo ai = AppGlobals.getPackageManager().getApplicationInfo(
+ ApplicationInfo ai = mPackageManager.getApplicationInfo(
pkg, 0, UserHandle.getCallingUserId());
if (ai == null) {
throw new SecurityException("Unknown package " + pkg);
}
if (!UserHandle.isSameApp(ai.uid, uid)) {
- throw new SecurityException("Calling uid " + uid + " gave package"
+ throw new SecurityException("Calling uid " + uid + " gave package "
+ pkg + " which is owned by uid " + ai.uid);
}
} catch (RemoteException re) {
@@ -4009,7 +4031,7 @@
private boolean isPackageSuspendedForUser(String pkg, int uid) {
int userId = UserHandle.getUserId(uid);
try {
- return AppGlobals.getPackageManager().isPackageSuspendedForUser(pkg, userId);
+ return mPackageManager.isPackageSuspendedForUser(pkg, userId);
} catch (RemoteException re) {
throw new SecurityException("Could not talk to package manager service");
} catch (IllegalArgumentException ex) {
@@ -4510,7 +4532,7 @@
}
public String[] getRequestingPackages() throws RemoteException {
- final ParceledListSlice list = AppGlobals.getPackageManager()
+ final ParceledListSlice list = mPackageManager
.getPackagesHoldingPermissions(PERM, 0 /*flags*/,
ActivityManager.getCurrentUser());
final List<PackageInfo> pkgs = list.getList();
diff --git a/services/core/java/com/android/server/pm/ShortcutPackageItem.java b/services/core/java/com/android/server/pm/ShortcutPackageItem.java
index 1f195a7..e59d69f 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackageItem.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackageItem.java
@@ -106,27 +106,31 @@
}
return; // Not installed, no need to restore yet.
}
+ boolean blockRestore = false;
if (!mPackageInfo.hasSignatures()) {
s.wtf("Attempted to restore package " + mPackageName + ", user=" + mPackageUserId
+ " but signatures not found in the restore data.");
+ blockRestore = true;
+ }
+ if (!blockRestore) {
+ final PackageInfo pi = s.getPackageInfoWithSignatures(mPackageName, mPackageUserId);
+ if (!mPackageInfo.canRestoreTo(s, pi)) {
+ // Package is now installed, but can't restore. Let the subclass do the cleanup.
+ blockRestore = true;
+ }
+ }
+ if (blockRestore) {
onRestoreBlocked();
- return;
+ } else {
+ if (ShortcutService.DEBUG) {
+ Slog.d(TAG, String.format("Restored package: %s/%d on user %d", mPackageName,
+ mPackageUserId, getOwnerUserId()));
+ }
+
+ onRestored();
}
- final PackageInfo pi = s.getPackageInfoWithSignatures(mPackageName, mPackageUserId);
- if (!mPackageInfo.canRestoreTo(s, pi)) {
- // Package is now installed, but can't restore. Let the subclass do the cleanup.
- onRestoreBlocked();
- return;
- }
- if (ShortcutService.DEBUG) {
- Slog.d(TAG, String.format("Restored package: %s/%d on user %d", mPackageName,
- mPackageUserId, getOwnerUserId()));
- }
-
- onRestored();
-
- // Now the package is not shadow.
+ // Either way, it's no longer a shadow.
mPackageInfo.setShadow(false);
s.scheduleSaveUser(mPackageUserId);
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 7b877f7..16f209b 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -3733,6 +3733,16 @@
}
}
+ @VisibleForTesting
+ ShortcutLauncher getLauncherShortcutForTest(String packageName, int userId) {
+ synchronized (mLock) {
+ final ShortcutUser user = mUsers.get(userId);
+ if (user == null) return null;
+
+ return user.getAllLaunchersForTest().get(PackageWithUser.of(userId, packageName));
+ }
+ }
+
/**
* Control whether {@link #verifyStates} should be performed. We always perform it during unit
* tests.
diff --git a/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
new file mode 100644
index 0000000..e4a355f
--- /dev/null
+++ b/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2016 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.server.notification;
+
+import static junit.framework.Assert.fail;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.app.INotificationManager;
+import android.app.IOnNotificationChannelCreatedListener;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageManager;
+import android.os.Binder;
+import android.os.Handler;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+import android.test.suitebuilder.annotation.SmallTest;
+import java.util.concurrent.CountDownLatch;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class NotificationManagerServiceTest {
+ private NotificationManagerService mNotificationManagerService;
+ private INotificationManager mBinderService;
+
+ @Before
+ public void setUp() throws Exception {
+ final Context context = InstrumentationRegistry.getTargetContext();
+ mNotificationManagerService = new NotificationManagerService(context);
+
+ // MockPackageManager - default returns ApplicationInfo with matching calling UID
+ final IPackageManager mockPackageManager = mock(IPackageManager.class);
+ final ApplicationInfo applicationInfo = new ApplicationInfo();
+ applicationInfo.uid = Binder.getCallingUid();
+ when(mockPackageManager.getApplicationInfo(any(), anyInt(), anyInt()))
+ .thenReturn(applicationInfo);
+ mNotificationManagerService.setPackageManager(mockPackageManager);
+
+ mNotificationManagerService.setRankingHelper(mock(RankingHelper.class));
+ mNotificationManagerService.setHandler(new Handler(context.getMainLooper()));
+
+ // Tests call directly into the Binder.
+ mBinderService = mNotificationManagerService.getBinderService();
+ }
+
+ @Test
+ public void testCreateNotificationChannel_SuccessCallsListener() throws Exception {
+ final NotificationChannel channel =
+ new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_DEFAULT);
+ final CountDownLatch latch = new CountDownLatch(1);
+ mBinderService.createNotificationChannel("test_pkg", channel,
+ new IOnNotificationChannelCreatedListener.Stub() {
+ @Override public void onNotificationChannelCreated(
+ NotificationChannel channel) {
+ latch.countDown();
+ }});
+ latch.await();
+ }
+
+ @Test
+ public void testCreateNotificationChannel_FailureDoesNotCallListener() throws Exception {
+ try {
+ mBinderService.createNotificationChannel("test_pkg", null,
+ new IOnNotificationChannelCreatedListener.Stub() {
+ @Override public void onNotificationChannelCreated(
+ NotificationChannel channel) {
+ fail("Listener was triggered from failure.");
+ }});
+ fail("Exception should be thrown immediately.");
+ } catch (NullPointerException e) {
+ // pass
+ }
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
index 771ca146..74c1ca5 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
@@ -4921,6 +4921,9 @@
assertEquals(0, mManager.getDynamicShortcuts().size());
assertEquals(0, mManager.getPinnedShortcuts().size());
});
+ assertFalse(mService.getPackageShortcutForTest(CALLING_PACKAGE_1, USER_0)
+ .getPackageInfo().isShadow());
+
installPackage(USER_0, CALLING_PACKAGE_2);
runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
@@ -4929,6 +4932,8 @@
mManager.getPinnedShortcuts()),
"s1", "s2", "s3");
});
+ assertFalse(mService.getPackageShortcutForTest(CALLING_PACKAGE_2, USER_0)
+ .getPackageInfo().isShadow());
installPackage(USER_0, LAUNCHER_1);
runWithCaller(LAUNCHER_1, USER_0, () -> {
@@ -5052,6 +5057,8 @@
mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
/* empty */);
});
+ assertFalse(mService.getLauncherShortcutForTest(LAUNCHER_1, USER_0)
+ .getPackageInfo().isShadow());
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
assertEquals(0, mManager.getDynamicShortcuts().size());
@@ -5074,6 +5081,8 @@
mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
/* empty */);
});
+ assertFalse(mService.getLauncherShortcutForTest(LAUNCHER_2, USER_0)
+ .getPackageInfo().isShadow());
installPackage(USER_0, CALLING_PACKAGE_3);
runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 457fd88..918ef5e 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -2275,6 +2275,8 @@
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
* OR
* {@link android.Manifest.permission#READ_SMS}
+ * OR
+ * {@link android.Manifest.permission#READ_PHONE_NUMBER}
* <p>
* The default SMS app can also use this.
*/
@@ -2290,6 +2292,8 @@
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
* OR
* {@link android.Manifest.permission#READ_SMS}
+ * OR
+ * {@link android.Manifest.permission#READ_PHONE_NUMBER}
* <p>
* The default SMS app can also use this.
*
diff --git a/tools/apilint/apilint.py b/tools/apilint/apilint.py
index ca2d2e7..6ca59b0 100644
--- a/tools/apilint/apilint.py
+++ b/tools/apilint/apilint.py
@@ -91,7 +91,7 @@
while r in raw: raw.remove(r)
self.split = list(raw)
- for r in ["method", "public", "protected", "static", "final", "deprecated", "abstract"]:
+ for r in ["method", "public", "protected", "static", "final", "deprecated", "abstract", "default"]:
while r in raw: raw.remove(r)
self.typ = raw[0]