diff options
38 files changed, 586 insertions, 226 deletions
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 9bad9bb..2e45b79 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -114,7 +114,6 @@ import java.io.IOException; import java.io.PrintWriter; import java.lang.ref.WeakReference; import java.net.InetAddress; -import java.security.Security; import java.text.DateFormat; import java.util.ArrayList; import java.util.List; @@ -5338,7 +5337,7 @@ public final class ActivityThread { // Set the reporter for event logging in libcore EventLogger.setReporter(new EventLoggingReporter()); - Security.addProvider(new AndroidKeyStoreProvider()); + AndroidKeyStoreProvider.install(); // Make sure TrustedCertificateStore looks in the right place for CA certificates final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId()); diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index 1127436..8a3c9c8 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java @@ -217,8 +217,14 @@ public class AppOpsManager { public static final int OP_READ_PHONE_STATE = 51; /** @hide Add voicemail messages to the voicemail content provider. */ public static final int OP_ADD_VOICEMAIL = 52; + /** @hide Access APIs for SIP calling over VOIP or WiFi. */ + public static final int OP_USE_SIP = 53; + /** @hide Intercept outgoing calls. */ + public static final int OP_PROCESS_OUTGOING_CALLS = 54; + /** @hide User the fingerprint API. */ + public static final int OP_USE_FINGERPRINT = 55; /** @hide */ - public static final int _NUM_OP = 53; + public static final int _NUM_OP = 56; /** Access to coarse location information. */ public static final String OPSTR_COARSE_LOCATION = "android:coarse_location"; @@ -351,7 +357,10 @@ public class AppOpsManager { OP_ASSIST_STRUCTURE, OP_ASSIST_SCREENSHOT, OP_READ_PHONE_STATE, - OP_ADD_VOICEMAIL + OP_ADD_VOICEMAIL, + OP_USE_SIP, + OP_PROCESS_OUTGOING_CALLS, + OP_USE_FINGERPRINT }; /** @@ -411,6 +420,9 @@ public class AppOpsManager { null, null, null, + null, + null, + null, null }; @@ -471,7 +483,10 @@ public class AppOpsManager { "ASSIST_STRUCTURE", "ASSIST_SCREENSHOT", "OP_READ_PHONE_STATE", - "ADD_VOICEMAIL" + "ADD_VOICEMAIL", + "USE_SIP", + "PROCESS_OUTGOING_CALLS", + "USE_FINGERPRINT" }; /** @@ -531,7 +546,10 @@ public class AppOpsManager { null, // no permission for receiving assist structure null, // no permission for receiving assist screenshot Manifest.permission.READ_PHONE_STATE, - Manifest.permission.ADD_VOICEMAIL + Manifest.permission.ADD_VOICEMAIL, + Manifest.permission.USE_SIP, + Manifest.permission.PROCESS_OUTGOING_CALLS, + Manifest.permission.USE_FINGERPRINT }; /** @@ -592,7 +610,10 @@ public class AppOpsManager { null, // ASSIST_STRUCTURE null, // ASSIST_SCREENSHOT null, // READ_PHONE_STATE - null // ADD_VOICEMAIL + null, // ADD_VOICEMAIL + null, // USE_SIP + null, // PROCESS_OUTGOING_CALLS + null // USE_FINGERPRINT }; /** @@ -652,7 +673,10 @@ public class AppOpsManager { false, //ASSIST_STRUCTURE false, //ASSIST_SCREENSHOT false, //READ_PHONE_STATE - false //ADD_VOICEMAIL + false, //ADD_VOICEMAIL + false, // USE_SIP + false, // PROCESS_OUTGOING_CALLS + false // USE_FINGERPRINT }; /** @@ -711,6 +735,9 @@ public class AppOpsManager { AppOpsManager.MODE_ALLOWED, AppOpsManager.MODE_ALLOWED, AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, + AppOpsManager.MODE_ALLOWED, AppOpsManager.MODE_ALLOWED }; @@ -774,6 +801,9 @@ public class AppOpsManager { false, false, false, + false, + false, + false, false }; diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 0bd60ef..8687c6b 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -389,24 +389,30 @@ public abstract class Context { } /** - * Return a localized string from the application's package's + * Returns a localized string from the application's package's * default string table. * * @param resId Resource id for the string + * @return The string data associated with the resource, stripped of styled + * text information. */ + @NonNull public final String getString(@StringRes int resId) { return getResources().getString(resId); } /** - * Return a localized formatted string from the application's package's + * Returns a localized formatted string from the application's package's * default string table, substituting the format arguments as defined in * {@link java.util.Formatter} and {@link java.lang.String#format}. * * @param resId Resource id for the format string - * @param formatArgs The format arguments that will be used for substitution. + * @param formatArgs The format arguments that will be used for + * substitution. + * @return The string data associated with the resource, formatted and + * stripped of styled text information. */ - + @NonNull public final String getString(@StringRes int resId, Object... formatArgs) { return getResources().getString(resId, formatArgs); } diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java index 334d180..6e77e33 100644 --- a/core/java/android/content/res/Resources.java +++ b/core/java/android/content/res/Resources.java @@ -393,10 +393,11 @@ public class Resources { * @throws NotFoundException Throws NotFoundException if the given ID does not exist. * * @return String The string data associated with the resource, - * stripped of styled text information. + * stripped of styled text information. */ + @NonNull public String getString(@StringRes int id) throws NotFoundException { - CharSequence res = getText(id); + final CharSequence res = getText(id); if (res != null) { return res.toString(); } @@ -421,11 +422,11 @@ public class Resources { * @throws NotFoundException Throws NotFoundException if the given ID does not exist. * * @return String The string data associated with the resource, - * stripped of styled text information. + * stripped of styled text information. */ - public String getString(@StringRes int id, Object... formatArgs) - throws NotFoundException { - String raw = getString(id); + @NonNull + public String getString(@StringRes int id, Object... formatArgs) throws NotFoundException { + final String raw = getString(id); return String.format(mConfiguration.locale, raw, formatArgs); } diff --git a/core/java/android/hardware/camera2/CameraCaptureSession.java b/core/java/android/hardware/camera2/CameraCaptureSession.java index 0cf8df1..aeddf03 100644 --- a/core/java/android/hardware/camera2/CameraCaptureSession.java +++ b/core/java/android/hardware/camera2/CameraCaptureSession.java @@ -114,6 +114,11 @@ public abstract class CameraCaptureSession implements AutoCloseable { * the Surface provided to prepare must not be used as a target of a CaptureRequest submitted * to this session.</p> * + * <p>{@link android.hardware.camera2.CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY LEGACY} + * devices cannot pre-allocate output buffers; for those devices, + * {@link StateCallback#onSurfacePrepared} will be immediately called, and no preallocation is + * done.</p> + * * @param surface the output Surface for which buffers should be pre-allocated. Must be one of * the output Surfaces used to create this session. * diff --git a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java index abe26ea..edad00f 100644 --- a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java +++ b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java @@ -202,6 +202,7 @@ public class CameraDeviceUserShim implements ICameraDeviceUser { private static final int CAMERA_IDLE = 1; private static final int CAPTURE_STARTED = 2; private static final int RESULT_RECEIVED = 3; + private static final int PREPARED = 4; private final HandlerThread mHandlerThread; private Handler mHandler; @@ -253,7 +254,9 @@ public class CameraDeviceUserShim implements ICameraDeviceUser { @Override public void onPrepared(int streamId) { - // TODO + Message msg = getHandler().obtainMessage(PREPARED, + /*arg1*/ streamId, /*arg2*/ 0); + getHandler().sendMessage(msg); } @Override @@ -301,6 +304,11 @@ public class CameraDeviceUserShim implements ICameraDeviceUser { mCallbacks.onResultReceived(result, resultExtras); break; } + case PREPARED: { + int streamId = msg.arg1; + mCallbacks.onPrepared(streamId); + break; + } default: throw new IllegalArgumentException( "Unknown callback message " + msg.what); @@ -631,7 +639,9 @@ public class CameraDeviceUserShim implements ICameraDeviceUser { return CameraBinderDecorator.ENODEV; } - // TODO: Implement and fire callback + // LEGACY doesn't support actual prepare, just signal success right away + mCameraCallbacks.onPrepared(streamId); + return CameraBinderDecorator.NO_ERROR; } diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java index 9f344ad..779448b 100644 --- a/core/java/android/hardware/fingerprint/FingerprintManager.java +++ b/core/java/android/hardware/fingerprint/FingerprintManager.java @@ -434,7 +434,8 @@ public class FingerprintManager { mAuthenticationCallback = callback; mCryptoObject = crypto; long sessionId = crypto != null ? crypto.getOpId() : 0; - mService.authenticate(mToken, sessionId, userId, mServiceReceiver, flags); + mService.authenticate(mToken, sessionId, userId, mServiceReceiver, flags, + mContext.getOpPackageName()); } catch (RemoteException e) { Log.w(TAG, "Remote exception while authenticating: ", e); if (callback != null) { @@ -555,7 +556,7 @@ public class FingerprintManager { */ public List<Fingerprint> getEnrolledFingerprints(int userId) { if (mService != null) try { - return mService.getEnrolledFingerprints(userId); + return mService.getEnrolledFingerprints(userId, mContext.getOpPackageName()); } catch (RemoteException e) { Log.v(TAG, "Remote exception in getEnrolledFingerprints: ", e); } @@ -579,7 +580,8 @@ public class FingerprintManager { */ public boolean hasEnrolledFingerprints() { if (mService != null) try { - return mService.hasEnrolledFingerprints(UserHandle.myUserId()); + return mService.hasEnrolledFingerprints(UserHandle.myUserId(), + mContext.getOpPackageName()); } catch (RemoteException e) { Log.v(TAG, "Remote exception in getEnrolledFingerprints: ", e); } @@ -595,7 +597,7 @@ public class FingerprintManager { if (mService != null) { try { long deviceId = 0; /* TODO: plumb hardware id to FPMS */ - return mService.isHardwareDetected(deviceId); + return mService.isHardwareDetected(deviceId, mContext.getOpPackageName()); } catch (RemoteException e) { Log.v(TAG, "Remote exception in isFingerprintHardwareDetected(): ", e); } @@ -614,7 +616,7 @@ public class FingerprintManager { public long getAuthenticatorId() { if (mService != null) { try { - return mService.getAuthenticatorId(); + return mService.getAuthenticatorId(mContext.getOpPackageName()); } catch (RemoteException e) { Log.v(TAG, "Remote exception in getAuthenticatorId(): ", e); } @@ -736,7 +738,7 @@ public class FingerprintManager { private void cancelAuthentication(CryptoObject cryptoObject) { if (mService != null) try { - mService.cancelAuthentication(mToken); + mService.cancelAuthentication(mToken, mContext.getOpPackageName()); } catch (RemoteException e) { if (DEBUG) Log.w(TAG, "Remote exception while canceling enrollment"); } diff --git a/core/java/android/hardware/fingerprint/IFingerprintService.aidl b/core/java/android/hardware/fingerprint/IFingerprintService.aidl index c5ec08c..0484806 100644 --- a/core/java/android/hardware/fingerprint/IFingerprintService.aidl +++ b/core/java/android/hardware/fingerprint/IFingerprintService.aidl @@ -27,10 +27,10 @@ import java.util.List; interface IFingerprintService { // Authenticate the given sessionId with a fingerprint void authenticate(IBinder token, long sessionId, int groupId, - IFingerprintServiceReceiver receiver, int flags); + IFingerprintServiceReceiver receiver, int flags, String opPackageName); // Cancel authentication for the given sessionId - void cancelAuthentication(IBinder token); + void cancelAuthentication(IBinder token, String opPackageName); // Start fingerprint enrollment void enroll(IBinder token, in byte [] cryptoToken, int groupId, IFingerprintServiceReceiver receiver, @@ -46,16 +46,16 @@ interface IFingerprintService { void rename(int fingerId, int groupId, String name); // Get a list of enrolled fingerprints in the given group. - List<Fingerprint> getEnrolledFingerprints(int groupId); + List<Fingerprint> getEnrolledFingerprints(int groupId, String opPackageName); // Determine if HAL is loaded and ready - boolean isHardwareDetected(long deviceId); + boolean isHardwareDetected(long deviceId, String opPackageName); // Get a pre-enrollment authentication token long preEnroll(IBinder token); // Determine if a user has at least one enrolled fingerprint - boolean hasEnrolledFingerprints(int groupId); + boolean hasEnrolledFingerprints(int groupId, String opPackageName); // Gets the number of hardware devices // int getHardwareDeviceCount(); @@ -64,5 +64,5 @@ interface IFingerprintService { // long getHardwareDevice(int i); // Gets the authenticator ID for fingerprint - long getAuthenticatorId(); + long getAuthenticatorId(String opPackageName); } diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java index 355ec8c..009649f 100644 --- a/core/java/android/os/Process.java +++ b/core/java/android/os/Process.java @@ -634,6 +634,9 @@ public class Process { if ((debugFlags & Zygote.DEBUG_ENABLE_JIT) != 0) { argsForZygote.add("--enable-jit"); } + if ((debugFlags & Zygote.DEBUG_GENERATE_CFI) != 0) { + argsForZygote.add("--generate-cfi"); + } if ((debugFlags & Zygote.DEBUG_ENABLE_ASSERT) != 0) { argsForZygote.add("--enable-assert"); } diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java index bbf120a..088adbb 100644 --- a/core/java/android/widget/SearchView.java +++ b/core/java/android/widget/SearchView.java @@ -18,6 +18,7 @@ package android.widget; import static android.widget.SuggestionsAdapter.getColumnString; +import android.annotation.Nullable; import android.app.PendingIntent; import android.app.SearchManager; import android.app.SearchableInfo; @@ -120,6 +121,8 @@ public class SearchView extends LinearLayout implements CollapsibleActionView { private final Intent mVoiceWebSearchIntent; private final Intent mVoiceAppSearchIntent; + private final CharSequence mDefaultQueryHint; + private OnQueryTextListener mOnQueryChangeListener; private OnCloseListener mOnCloseListener; private OnFocusChangeListener mOnQueryTextFocusChangeListener; @@ -329,10 +332,8 @@ public class SearchView extends LinearLayout implements CollapsibleActionView { setMaxWidth(maxWidth); } - final CharSequence queryHint = a.getText(R.styleable.SearchView_queryHint); - if (!TextUtils.isEmpty(queryHint)) { - setQueryHint(queryHint); - } + mDefaultQueryHint = a.getText(R.styleable.SearchView_defaultQueryHint); + mQueryHint = a.getText(R.styleable.SearchView_queryHint); final int imeOptions = a.getInt(R.styleable.SearchView_imeOptions, -1); if (imeOptions != -1) { @@ -570,36 +571,48 @@ public class SearchView extends LinearLayout implements CollapsibleActionView { } /** - * Sets the hint text to display in the query text field. This overrides any hint specified - * in the SearchableInfo. - * - * @param hint the hint text to display + * Sets the hint text to display in the query text field. This overrides + * any hint specified in the {@link SearchableInfo}. + * <p> + * This value may be specified as an empty string to prevent any query hint + * from being displayed. * + * @param hint the hint text to display or {@code null} to clear * @attr ref android.R.styleable#SearchView_queryHint */ - public void setQueryHint(CharSequence hint) { + public void setQueryHint(@Nullable CharSequence hint) { mQueryHint = hint; updateQueryHint(); } /** - * Gets the hint text to display in the query text field. - * @return the query hint text, if specified, null otherwise. + * Returns the hint text that will be displayed in the query text field. + * <p> + * The displayed query hint is chosen in the following order: + * <ol> + * <li>Non-null value set with {@link #setQueryHint(CharSequence)} + * <li>Value specified in XML using + * {@link android.R.styleable#SearchView_queryHint android:queryHint} + * <li>Valid string resource ID exposed by the {@link SearchableInfo} via + * {@link SearchableInfo#getHintId()} + * <li>Default hint provided by the theme against which the view was + * inflated + * </ol> * + * @return the displayed query hint text, or {@code null} if none set * @attr ref android.R.styleable#SearchView_queryHint */ + @Nullable public CharSequence getQueryHint() { + final CharSequence hint; if (mQueryHint != null) { - return mQueryHint; - } else if (mSearchable != null) { - CharSequence hint = null; - int hintId = mSearchable.getHintId(); - if (hintId != 0) { - hint = getContext().getString(hintId); - } - return hint; + hint = mQueryHint; + } else if (mSearchable != null && mSearchable.getHintId() != 0) { + hint = getContext().getText(mSearchable.getHintId()); + } else { + hint = mDefaultQueryHint; } - return null; + return hint; } /** @@ -1113,20 +1126,8 @@ public class SearchView extends LinearLayout implements CollapsibleActionView { } private void updateQueryHint() { - if (mQueryHint != null) { - mSearchSrcTextView.setHint(getDecoratedHint(mQueryHint)); - } else if (mSearchable != null) { - CharSequence hint = null; - int hintId = mSearchable.getHintId(); - if (hintId != 0) { - hint = getContext().getString(hintId); - } - if (hint != null) { - mSearchSrcTextView.setHint(getDecoratedHint(hint)); - } - } else { - mSearchSrcTextView.setHint(getDecoratedHint("")); - } + final CharSequence hint = getQueryHint(); + mSearchSrcTextView.setHint(getDecoratedHint(hint == null ? "" : hint)); } /** diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java index 75b6446..1e7ee5a 100644 --- a/core/java/com/android/internal/os/Zygote.java +++ b/core/java/com/android/internal/os/Zygote.java @@ -40,6 +40,8 @@ public final class Zygote { public static final int DEBUG_ENABLE_JNI_LOGGING = 1 << 4; /** enable the JIT compiler */ public static final int DEBUG_ENABLE_JIT = 1 << 5; + /** Force generation of CFI code */ + public static final int DEBUG_GENERATE_CFI = 1 << 6; /** No external storage should be mounted. */ public static final int MOUNT_EXTERNAL_NONE = 0; diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java index 9106ccd..969d236 100644 --- a/core/java/com/android/internal/os/ZygoteConnection.java +++ b/core/java/com/android/internal/os/ZygoteConnection.java @@ -321,7 +321,7 @@ class ZygoteConnection { /** * From --enable-debugger, --enable-checkjni, --enable-assert, - * --enable-safemode, --enable-jit, and --enable-jni-logging. + * --enable-safemode, --enable-jit, --generate-cfi and --enable-jni-logging. */ int debugFlags; @@ -433,6 +433,8 @@ class ZygoteConnection { debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI; } else if (arg.equals("--enable-jit")) { debugFlags |= Zygote.DEBUG_ENABLE_JIT; + } else if (arg.equals("--generate-cfi")) { + debugFlags |= Zygote.DEBUG_GENERATE_CFI; } else if (arg.equals("--enable-jni-logging")) { debugFlags |= Zygote.DEBUG_ENABLE_JNI_LOGGING; } else if (arg.equals("--enable-assert")) { diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index 88f0697..7c2b28d 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -875,6 +875,19 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv) parseRuntimeOption("dalvik.vm.zygote.max-boot-retry", cachePruneBuf, "-Xzygote-max-boot-retry="); + /* + * When running with debug.gencfi, add --include-cfi to the compiler options so that the boot + * image, if it is compiled on device, will include CFI info, as well as other compilations + * started by the runtime. + */ + property_get("debug.gencfi", propBuf, ""); + if (strcmp(propBuf, "true") == 0) { + addOption("-Xcompiler-option"); + addOption("--include-cfi"); + addOption("-Ximage-compiler-option"); + addOption("--include-cfi"); + } + initArgs.version = JNI_VERSION_1_4; initArgs.options = mOptions.editArray(); initArgs.nOptions = mOptions.size(); diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp index fc05a6d..3655adc 100644 --- a/core/jni/android_media_AudioSystem.cpp +++ b/core/jni/android_media_AudioSystem.cpp @@ -111,6 +111,7 @@ static struct { jfieldID mRouteFlags; jfieldID mRegistrationId; jfieldID mMixType; + jfieldID mCallbackFlags; } gAudioMixFields; static jclass gAudioFormatClass; @@ -149,6 +150,10 @@ static struct { jmethodID postEventFromNative; } gAudioPortEventHandlerMethods; +static struct { + jmethodID postDynPolicyEventFromNative; +} gDynPolicyEventHandlerMethods; + static Mutex gLock; enum AudioError { @@ -166,7 +171,7 @@ enum { #define MAX_PORT_GENERATION_SYNC_ATTEMPTS 5 // ---------------------------------------------------------------------------- -// ref-counted object for callbacks +// ref-counted object for audio port callbacks class JNIAudioPortCallback: public AudioSystem::AudioPortCallback { public: @@ -361,6 +366,26 @@ android_media_AudioSystem_error_callback(status_t err) env->DeleteLocalRef(clazz); } +static void +android_media_AudioSystem_dyn_policy_callback(int event, String8 regId, int val) +{ + JNIEnv *env = AndroidRuntime::getJNIEnv(); + if (env == NULL) { + return; + } + + jclass clazz = env->FindClass(kClassPathName); + const char* zechars = regId.string(); + jstring zestring = env->NewStringUTF(zechars); + + env->CallStaticVoidMethod(clazz, gDynPolicyEventHandlerMethods.postDynPolicyEventFromNative, + event, zestring, val); + + env->ReleaseStringUTFChars(zestring, zechars); + env->DeleteLocalRef(clazz); + +} + static jint android_media_AudioSystem_setDeviceConnectionState(JNIEnv *env, jobject thiz, jint device, jint state, jstring device_address, jstring device_name) { @@ -1402,7 +1427,11 @@ android_media_AudioSystem_getAudioHwSyncForSession(JNIEnv *env, jobject thiz, ji return (jint)AudioSystem::getAudioHwSyncForSession((audio_session_t)sessionId); } - +static void +android_media_AudioSystem_registerDynPolicyCallback(JNIEnv *env, jobject thiz) +{ + AudioSystem::setDynPolicyCallback(android_media_AudioSystem_dyn_policy_callback); +} static jint convertAudioMixToNative(JNIEnv *env, @@ -1419,6 +1448,8 @@ static jint convertAudioMixToNative(JNIEnv *env, env->ReleaseStringUTFChars(jRegistrationId, nRegistrationId); env->DeleteLocalRef(jRegistrationId); + nAudioMix->mCbFlags = env->GetIntField(jAudioMix, gAudioMixFields.mCallbackFlags); + jobject jFormat = env->GetObjectField(jAudioMix, gAudioMixFields.mFormat); nAudioMix->mFormat.sample_rate = env->GetIntField(jFormat, gAudioFormatFields.mSampleRate); @@ -1567,7 +1598,8 @@ static JNINativeMethod gMethods[] = { (void *)android_media_AudioSystem_getAudioHwSyncForSession}, {"registerPolicyMixes", "(Ljava/util/ArrayList;Z)I", (void *)android_media_AudioSystem_registerPolicyMixes}, - + {"native_register_dynamic_policy_callback", "()V", + (void *)android_media_AudioSystem_registerDynPolicyCallback}, }; @@ -1670,6 +1702,10 @@ int register_android_media_AudioSystem(JNIEnv *env) gEventHandlerFields.mJniCallback = GetFieldIDOrDie(env, eventHandlerClass, "mJniCallback", "J"); + gDynPolicyEventHandlerMethods.postDynPolicyEventFromNative = + GetStaticMethodIDOrDie(env, env->FindClass(kClassPathName), + "dynamicPolicyCallbackFromNative", "(ILjava/lang/String;I)V"); + jclass audioMixClass = FindClassOrDie(env, "android/media/audiopolicy/AudioMix"); gAudioMixClass = MakeGlobalRefOrDie(env, audioMixClass); gAudioMixFields.mRule = GetFieldIDOrDie(env, audioMixClass, "mRule", @@ -1680,6 +1716,7 @@ int register_android_media_AudioSystem(JNIEnv *env) gAudioMixFields.mRegistrationId = GetFieldIDOrDie(env, audioMixClass, "mRegistrationId", "Ljava/lang/String;"); gAudioMixFields.mMixType = GetFieldIDOrDie(env, audioMixClass, "mMixType", "I"); + gAudioMixFields.mCallbackFlags = GetFieldIDOrDie(env, audioMixClass, "mCallbackFlags", "I"); jclass audioFormatClass = FindClassOrDie(env, "android/media/AudioFormat"); gAudioFormatClass = MakeGlobalRefOrDie(env, audioFormatClass); diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 87dc3fa..702f720 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -7435,6 +7435,10 @@ <attr name="maxWidth" /> <!-- An optional query hint string to be displayed in the empty query field. --> <attr name="queryHint" format="string" /> + <!-- Default query hint used when {@code queryHint} is undefined and + the search view's {@code SearchableInfo} does not provide a hint. + @hide --> + <attr name="defaultQueryHint" format="string" /> <!-- The IME options to set on the query text field. --> <attr name="imeOptions" /> <!-- The input type to set on the query text field. --> diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml index f81ee8c..c2371ee 100644 --- a/core/res/res/values/styles_material.xml +++ b/core/res/res/values/styles_material.xml @@ -533,7 +533,7 @@ please see styles_device_defaults.xml. <item name="queryBackground">@empty</item> <item name="submitBackground">@empty</item> <item name="searchHintIcon">@empty</item> - <item name="queryHint">@string/search_hint</item> + <item name="defaultQueryHint">@string/search_hint</item> </style> <style name="Widget.Material.SegmentedButton" parent="SegmentedButton"> diff --git a/keystore/java/android/security/AndroidKeyStore.java b/keystore/java/android/security/AndroidKeyStore.java index ed91d70..72cb062 100644 --- a/keystore/java/android/security/AndroidKeyStore.java +++ b/keystore/java/android/security/AndroidKeyStore.java @@ -486,16 +486,6 @@ public class AndroidKeyStore extends KeyStoreSpi { } } args.addInts(KeymasterDefs.KM_TAG_DIGEST, keymasterDigests); - if (keymasterDigests.length > 0) { - // TODO: Remove MAC length constraint once Keymaster API no longer requires it. - // This code will blow up if mode than one digest is specified. - int digestOutputSizeBytes = - KeymasterUtils.getDigestOutputSizeBytes(keymasterDigests[0]); - if (digestOutputSizeBytes != -1) { - // TODO: Switch to bits instead of bytes, once this is fixed in Keymaster - args.addInt(KeymasterDefs.KM_TAG_MAC_LENGTH, digestOutputSizeBytes); - } - } if (keymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_HMAC) { if (keymasterDigests.length == 0) { throw new KeyStoreException("At least one digest algorithm must be specified" diff --git a/keystore/java/android/security/AndroidKeyStoreBCWorkaroundProvider.java b/keystore/java/android/security/AndroidKeyStoreBCWorkaroundProvider.java new file mode 100644 index 0000000..45329cf --- /dev/null +++ b/keystore/java/android/security/AndroidKeyStoreBCWorkaroundProvider.java @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2015 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.security; + +import java.security.Provider; + +/** + * {@link Provider} of JCA crypto operations operating on Android KeyStore keys. + * + * <p>This provider was separated out of {@link AndroidKeyStoreProvider} to work around the issue + * that Bouncy Castle provider incorrectly declares that it accepts arbitrary keys (incl. Android + * KeyStore ones). This causes JCA to select the Bouncy Castle's implementation of JCA crypto + * operations for Android KeyStore keys unless Android KeyStore's own implementations are installed + * as higher-priority than Bouncy Castle ones. The purpose of this provider is to do just that: to + * offer crypto operations operating on Android KeyStore keys and to be installed at higher priority + * than the Bouncy Castle provider. + * + * <p>Once Bouncy Castle provider is fixed, this provider can be merged into the + * {@code AndroidKeyStoreProvider}. + * + * @hide + */ +class AndroidKeyStoreBCWorkaroundProvider extends Provider { + + // IMPLEMENTATION NOTE: Class names are hard-coded in this provider to avoid loading these + // classes when this provider is instantiated and installed early on during each app's + // initialization process. + + private static final String PACKAGE_NAME = "android.security"; + private static final String KEYSTORE_SECRET_KEY_CLASS_NAME = + PACKAGE_NAME + ".KeyStoreSecretKey"; + + AndroidKeyStoreBCWorkaroundProvider() { + super("AndroidKeyStoreBCWorkaround", + 1.0, + "Android KeyStore security provider to work around Bouncy Castle"); + + // javax.crypto.Mac + putMacImpl("HmacSHA1", PACKAGE_NAME + ".KeyStoreHmacSpi$HmacSHA1"); + putMacImpl("HmacSHA224", PACKAGE_NAME + ".KeyStoreHmacSpi$HmacSHA224"); + putMacImpl("HmacSHA256", PACKAGE_NAME + ".KeyStoreHmacSpi$HmacSHA256"); + putMacImpl("HmacSHA384", PACKAGE_NAME + ".KeyStoreHmacSpi$HmacSHA384"); + putMacImpl("HmacSHA512", PACKAGE_NAME + ".KeyStoreHmacSpi$HmacSHA512"); + + // javax.crypto.Cipher + putSymmetricCipherImpl("AES/ECB/NoPadding", + PACKAGE_NAME + ".KeyStoreCipherSpi$AES$ECB$NoPadding"); + putSymmetricCipherImpl("AES/ECB/PKCS7Padding", + PACKAGE_NAME + ".KeyStoreCipherSpi$AES$ECB$PKCS7Padding"); + + putSymmetricCipherImpl("AES/CBC/NoPadding", + PACKAGE_NAME + ".KeyStoreCipherSpi$AES$CBC$NoPadding"); + putSymmetricCipherImpl("AES/CBC/PKCS7Padding", + PACKAGE_NAME + ".KeyStoreCipherSpi$AES$CBC$PKCS7Padding"); + + putSymmetricCipherImpl("AES/CTR/NoPadding", + PACKAGE_NAME + ".KeyStoreCipherSpi$AES$CTR$NoPadding"); + } + + private void putMacImpl(String algorithm, String implClass) { + put("Mac." + algorithm, implClass); + put("Mac." + algorithm + " SupportedKeyClasses", KEYSTORE_SECRET_KEY_CLASS_NAME); + } + + private void putSymmetricCipherImpl(String transformation, String implClass) { + put("Cipher." + transformation, implClass); + put("Cipher." + transformation + " SupportedKeyClasses", KEYSTORE_SECRET_KEY_CLASS_NAME); + } +} diff --git a/keystore/java/android/security/AndroidKeyStoreProvider.java b/keystore/java/android/security/AndroidKeyStoreProvider.java index 43f3b30..518067b 100644 --- a/keystore/java/android/security/AndroidKeyStoreProvider.java +++ b/keystore/java/android/security/AndroidKeyStoreProvider.java @@ -17,6 +17,7 @@ package android.security; import java.security.Provider; +import java.security.Security; import javax.crypto.Cipher; import javax.crypto.Mac; @@ -32,10 +33,12 @@ public class AndroidKeyStoreProvider extends Provider { // IMPLEMENTATION NOTE: Class names are hard-coded in this provider to avoid loading these // classes when this provider is instantiated and installed early on during each app's // initialization process. + // + // Crypto operations operating on the AndroidKeyStore keys must not be offered by this provider. + // Instead, they need to be offered by AndroidKeyStoreBCWorkaroundProvider. See its Javadoc + // for details. private static final String PACKAGE_NAME = "android.security"; - private static final String KEYSTORE_SECRET_KEY_CLASS_NAME = - PACKAGE_NAME + ".KeyStoreSecretKey"; public AndroidKeyStoreProvider() { super(PROVIDER_NAME, 1.0, "Android KeyStore security provider"); @@ -62,43 +65,39 @@ public class AndroidKeyStoreProvider extends Provider { putSecretKeyFactoryImpl("HmacSHA256"); putSecretKeyFactoryImpl("HmacSHA384"); putSecretKeyFactoryImpl("HmacSHA512"); + } - // javax.crypto.Mac - putMacImpl("HmacSHA1", PACKAGE_NAME + ".KeyStoreHmacSpi$HmacSHA1"); - putMacImpl("HmacSHA224", PACKAGE_NAME + ".KeyStoreHmacSpi$HmacSHA224"); - putMacImpl("HmacSHA256", PACKAGE_NAME + ".KeyStoreHmacSpi$HmacSHA256"); - putMacImpl("HmacSHA384", PACKAGE_NAME + ".KeyStoreHmacSpi$HmacSHA384"); - putMacImpl("HmacSHA512", PACKAGE_NAME + ".KeyStoreHmacSpi$HmacSHA512"); - - // javax.crypto.Cipher - putSymmetricCipherImpl("AES/ECB/NoPadding", - PACKAGE_NAME + ".KeyStoreCipherSpi$AES$ECB$NoPadding"); - putSymmetricCipherImpl("AES/ECB/PKCS7Padding", - PACKAGE_NAME + ".KeyStoreCipherSpi$AES$ECB$PKCS7Padding"); - - putSymmetricCipherImpl("AES/CBC/NoPadding", - PACKAGE_NAME + ".KeyStoreCipherSpi$AES$CBC$NoPadding"); - putSymmetricCipherImpl("AES/CBC/PKCS7Padding", - PACKAGE_NAME + ".KeyStoreCipherSpi$AES$CBC$PKCS7Padding"); + /** + * Installs a new instance of this provider (and the + * {@link AndroidKeyStoreBCWorkaroundProvider}). + */ + public static void install() { + Provider[] providers = Security.getProviders(); + int bcProviderPosition = -1; + for (int position = 0; position < providers.length; position++) { + Provider provider = providers[position]; + if ("BC".equals(provider.getName())) { + bcProviderPosition = position; + break; + } + } - putSymmetricCipherImpl("AES/CTR/NoPadding", - PACKAGE_NAME + ".KeyStoreCipherSpi$AES$CTR$NoPadding"); + Security.addProvider(new AndroidKeyStoreProvider()); + Provider workaroundProvider = new AndroidKeyStoreBCWorkaroundProvider(); + if (bcProviderPosition != -1) { + // Bouncy Castle provider found -- install the workaround provider above it. + Security.insertProviderAt(workaroundProvider, bcProviderPosition); + } else { + // Bouncy Castle provider not found -- install the workaround provider at lowest + // priority. + Security.addProvider(workaroundProvider); + } } private void putSecretKeyFactoryImpl(String algorithm) { put("SecretKeyFactory." + algorithm, PACKAGE_NAME + ".KeyStoreSecretKeyFactorySpi"); } - private void putMacImpl(String algorithm, String implClass) { - put("Mac." + algorithm, implClass); - put("Mac." + algorithm + " SupportedKeyClasses", KEYSTORE_SECRET_KEY_CLASS_NAME); - } - - private void putSymmetricCipherImpl(String transformation, String implClass) { - put("Cipher." + transformation, implClass); - put("Cipher." + transformation + " SupportedKeyClasses", KEYSTORE_SECRET_KEY_CLASS_NAME); - } - /** * Gets the {@link KeyStore} operation handle corresponding to the provided JCA crypto * primitive. diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java index 1563863..5b0e74a 100644 --- a/keystore/java/android/security/KeyStore.java +++ b/keystore/java/android/security/KeyStore.java @@ -16,6 +16,8 @@ package android.security; +import android.app.ActivityThread; +import android.app.Application; import com.android.org.conscrypt.NativeConstants; import android.content.Context; @@ -625,18 +627,31 @@ public class KeyStore { return 0; } + String opPackageName = getMyOpPackageName(); + try { long deviceId = 0; // TODO: plumb hardware id to FPMS - if (!service.isHardwareDetected(deviceId)) { + if (!service.isHardwareDetected(deviceId, opPackageName)) { return 0; } - return service.getAuthenticatorId(); + return service.getAuthenticatorId(opPackageName); } catch (RemoteException e) { throw new IllegalStateException("Failed to communicate with fingerprint service", e); } } + private static String getMyOpPackageName() { + ActivityThread activityThread = ActivityThread.currentActivityThread(); + if (activityThread != null) { + Application application = activityThread.getApplication(); + if (application != null) { + return application.getOpPackageName(); + } + } + throw new IllegalStateException("Cannot create AudioRecord outside of an app"); + } + /** * Returns an {@link InvalidKeyException} corresponding to the provided keystore/keymaster error * code. diff --git a/keystore/java/android/security/KeyStoreHmacSpi.java b/keystore/java/android/security/KeyStoreHmacSpi.java index 4590b9c..c52f61b 100644 --- a/keystore/java/android/security/KeyStoreHmacSpi.java +++ b/keystore/java/android/security/KeyStoreHmacSpi.java @@ -67,7 +67,7 @@ public abstract class KeyStoreHmacSpi extends MacSpi implements KeyStoreCryptoOp private final KeyStore mKeyStore = KeyStore.getInstance(); private final int mKeymasterDigest; - private final int mMacSizeBytes; + private final int mMacSizeBits; // Fields below are populated by engineInit and should be preserved after engineDoFinal. private KeyStoreSecretKey mKey; @@ -79,12 +79,12 @@ public abstract class KeyStoreHmacSpi extends MacSpi implements KeyStoreCryptoOp protected KeyStoreHmacSpi(int keymasterDigest) { mKeymasterDigest = keymasterDigest; - mMacSizeBytes = KeymasterUtils.getDigestOutputSizeBytes(keymasterDigest); + mMacSizeBits = KeymasterUtils.getDigestOutputSizeBits(keymasterDigest); } @Override protected int engineGetMacLength() { - return mMacSizeBytes; + return (mMacSizeBits + 7) / 8; } @Override @@ -158,14 +158,16 @@ public abstract class KeyStoreHmacSpi extends MacSpi implements KeyStoreCryptoOp KeymasterArguments keymasterArgs = new KeymasterArguments(); keymasterArgs.addInt(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_HMAC); keymasterArgs.addInt(KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigest); + keymasterArgs.addInt(KeymasterDefs.KM_TAG_MAC_LENGTH, mMacSizeBits); + KeymasterArguments keymasterOutputArgs = new KeymasterArguments(); OperationResult opResult = mKeyStore.begin( mKey.getAlias(), KeymasterDefs.KM_PURPOSE_SIGN, true, keymasterArgs, - null, - new KeymasterArguments()); + null, // no additional entropy needed for HMAC because it's deterministic + keymasterOutputArgs); if (opResult == null) { throw new KeyStoreConnectException(); } else if ((opResult.resultCode != KeyStore.NO_ERROR) diff --git a/keystore/java/android/security/KeyStoreKeyGeneratorSpi.java b/keystore/java/android/security/KeyStoreKeyGeneratorSpi.java index 20f6042..68b5751 100644 --- a/keystore/java/android/security/KeyStoreKeyGeneratorSpi.java +++ b/keystore/java/android/security/KeyStoreKeyGeneratorSpi.java @@ -45,7 +45,7 @@ public abstract class KeyStoreKeyGeneratorSpi extends KeyGeneratorSpi { protected HmacBase(int keymasterDigest) { super(KeymasterDefs.KM_ALGORITHM_HMAC, keymasterDigest, - KeymasterUtils.getDigestOutputSizeBytes(keymasterDigest) * 8); + KeymasterUtils.getDigestOutputSizeBits(keymasterDigest)); } } @@ -120,13 +120,6 @@ public abstract class KeyStoreKeyGeneratorSpi extends KeyGeneratorSpi { args.addInt(KeymasterDefs.KM_TAG_ALGORITHM, mKeymasterAlgorithm); if (mKeymasterDigest != -1) { args.addInt(KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigest); - int digestOutputSizeBytes = - KeymasterUtils.getDigestOutputSizeBytes(mKeymasterDigest); - if (digestOutputSizeBytes != -1) { - // TODO: Remove MAC length constraint once Keymaster API no longer requires it. - // TODO: Switch to bits instead of bytes, once this is fixed in Keymaster - args.addInt(KeymasterDefs.KM_TAG_MAC_LENGTH, digestOutputSizeBytes); - } } if (mKeymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_HMAC) { if (mKeymasterDigest == -1) { diff --git a/keystore/java/android/security/KeymasterUtils.java b/keystore/java/android/security/KeymasterUtils.java index 3ccb588..aa44ecd 100644 --- a/keystore/java/android/security/KeymasterUtils.java +++ b/keystore/java/android/security/KeymasterUtils.java @@ -179,22 +179,22 @@ public abstract class KeymasterUtils { return result; } - public static int getDigestOutputSizeBytes(int keymasterDigest) { + public static int getDigestOutputSizeBits(int keymasterDigest) { switch (keymasterDigest) { case KeymasterDefs.KM_DIGEST_NONE: return -1; case KeymasterDefs.KM_DIGEST_MD5: - return 128 / 8; + return 128; case KeymasterDefs.KM_DIGEST_SHA1: - return 160 / 8; + return 160; case KeymasterDefs.KM_DIGEST_SHA_2_224: - return 224 / 8; + return 224; case KeymasterDefs.KM_DIGEST_SHA_2_256: - return 256 / 8; + return 256; case KeymasterDefs.KM_DIGEST_SHA_2_384: - return 384 / 8; + return 384; case KeymasterDefs.KM_DIGEST_SHA_2_512: - return 512 / 8; + return 512; default: throw new IllegalArgumentException("Unknown digest: " + keymasterDigest); } diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h index 4863ed2..e9d6ebc 100644 --- a/libs/hwui/DisplayListOp.h +++ b/libs/hwui/DisplayListOp.h @@ -1423,7 +1423,7 @@ public: } virtual void output(int level, uint32_t logFlags) const override { - OP_LOG("Draw RenderNode %p %s, flags %#x", mRenderNode, mRenderNode->getName()); + OP_LOG("Draw RenderNode %p %s", mRenderNode, mRenderNode->getName()); if (mRenderNode && (logFlags & kOpLogFlag_Recurse)) { mRenderNode->output(level + 1); } diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java index 25e6594..3dae543 100644 --- a/media/java/android/media/AudioSystem.java +++ b/media/java/android/media/AudioSystem.java @@ -19,6 +19,7 @@ package android.media; import android.content.Context; import android.content.pm.PackageManager; import android.media.audiopolicy.AudioMix; +import android.util.Log; import java.util.ArrayList; @@ -32,6 +33,7 @@ import java.util.ArrayList; */ public class AudioSystem { + private static final String TAG = "AudioSystem"; /* These values must be kept in sync with system/audio.h */ /* * If these are modified, please also update Settings.System.VOLUME_SETTINGS @@ -224,6 +226,48 @@ public class AudioSystem } } + /** + * Handles events for the audio policy manager about dynamic audio policies + * @see android.media.audiopolicy.AudioPolicy + */ + public interface DynamicPolicyCallback + { + void onDynamicPolicyMixStateUpdate(String regId, int state); + } + + //keep in sync with include/media/AudioPolicy.h + private final static int DYNAMIC_POLICY_EVENT_MIX_STATE_UPDATE = 0; + + private static DynamicPolicyCallback sDynPolicyCallback; + + public static void setDynamicPolicyCallback(DynamicPolicyCallback cb) + { + synchronized (AudioSystem.class) { + sDynPolicyCallback = cb; + native_register_dynamic_policy_callback(); + } + } + + private static void dynamicPolicyCallbackFromNative(int event, String regId, int val) + { + DynamicPolicyCallback cb = null; + synchronized (AudioSystem.class) { + if (sDynPolicyCallback != null) { + cb = sDynPolicyCallback; + } + } + if (cb != null) { + switch(event) { + case DYNAMIC_POLICY_EVENT_MIX_STATE_UPDATE: + cb.onDynamicPolicyMixStateUpdate(regId, val); + break; + default: + Log.e(TAG, "dynamicPolicyCallbackFromNative: unknown event " + event); + } + } + } + + /* * Error codes used by public APIs (AudioTrack, AudioRecord, AudioManager ...) * Must be kept in sync with frameworks/base/core/jni/android_media_AudioErrors.h @@ -580,6 +624,9 @@ public class AudioSystem public static native int listAudioPatches(ArrayList<AudioPatch> patches, int[] generation); public static native int setAudioPortConfig(AudioPortConfig config); + // declare this instance as having a dynamic policy callback handler + private static native final void native_register_dynamic_policy_callback(); + // must be kept in sync with value in include/system/audio.h public static final int AUDIO_HW_SYNC_INVALID = 0; diff --git a/media/java/android/media/audiopolicy/AudioMix.java b/media/java/android/media/audiopolicy/AudioMix.java index 6aa4d8a..4ffac6d 100644 --- a/media/java/android/media/audiopolicy/AudioMix.java +++ b/media/java/android/media/audiopolicy/AudioMix.java @@ -36,20 +36,30 @@ public class AudioMix { private int mRouteFlags; private String mRegistrationId; private int mMixType = MIX_TYPE_INVALID; - private int mMixState = MIX_STATE_DISABLED; + int mMixState = MIX_STATE_DISABLED; + int mCallbackFlags; /** * All parameters are guaranteed valid through the Builder. */ - private AudioMix(AudioMixingRule rule, AudioFormat format, int routeFlags) { + private AudioMix(AudioMixingRule rule, AudioFormat format, int routeFlags, int callbackFlags) { mRule = rule; mFormat = format; mRouteFlags = routeFlags; mRegistrationId = null; mMixType = rule.getTargetMixType(); + mCallbackFlags = callbackFlags; } - // ROUTE_FLAG_* values to keep in sync with frameworks/av/include/media/AudioPolicy.h + // CALLBACK_FLAG_* values: keep in sync with AudioMix::kCbFlag* values defined + // in frameworks/av/include/media/AudioPolicy.h + /** @hide */ + public final static int CALLBACK_FLAG_NOTIFY_ACTIVITY = 0x1; + // when adding new MIX_FLAG_* flags, add them to this mask of authorized masks: + private final static int CALLBACK_FLAGS_ALL = CALLBACK_FLAG_NOTIFY_ACTIVITY; + + // ROUTE_FLAG_* values: keep in sync with MIX_ROUTE_FLAG_* values defined + // in frameworks/av/include/media/AudioPolicy.h /** * An audio mix behavior where the output of the mix is sent to the original destination of * the audio signal, i.e. an output device for an output mix, or a recording for an input mix. @@ -161,6 +171,7 @@ public class AudioMix { private AudioMixingRule mRule = null; private AudioFormat mFormat = null; private int mRouteFlags = 0; + private int mCallbackFlags = 0; /** * @hide @@ -199,6 +210,22 @@ public class AudioMix { } /** + * @hide + * Only used by AudioPolicyConfig, not a public API. + * @param callbackFlags which callbacks are called from native + * @return the same Builder instance. + * @throws IllegalArgumentException + */ + public Builder setCallbackFlags(int flags) throws IllegalArgumentException { + if ((flags != 0) && ((flags & CALLBACK_FLAGS_ALL) == 0)) { + throw new IllegalArgumentException("Illegal callback flags 0x" + + Integer.toHexString(flags).toUpperCase()); + } + mCallbackFlags = flags; + return this; + } + + /** * Sets the {@link AudioFormat} for the mix. * @param format a non-null {@link AudioFormat} instance. * @return the same Builder instance. @@ -256,7 +283,7 @@ public class AudioMix { } mFormat = new AudioFormat.Builder().setSampleRate(rate).build(); } - return new AudioMix(mRule, mFormat, mRouteFlags); + return new AudioMix(mRule, mFormat, mRouteFlags, mCallbackFlags); } } } diff --git a/media/java/android/media/audiopolicy/AudioPolicy.java b/media/java/android/media/audiopolicy/AudioPolicy.java index f128044..423b467 100644 --- a/media/java/android/media/audiopolicy/AudioPolicy.java +++ b/media/java/android/media/audiopolicy/AudioPolicy.java @@ -189,6 +189,12 @@ public class AudioPolicy { @SystemApi public AudioPolicy build() { + if (mStatusListener != null) { + // the AudioPolicy status listener includes updates on each mix activity state + for (AudioMix mix : mMixes) { + mix.mCallbackFlags |= AudioMix.CALLBACK_FLAG_NOTIFY_ACTIVITY; + } + } return new AudioPolicy(new AudioPolicyConfig(mMixes), mContext, mLooper, mFocusListener, mStatusListener); } @@ -432,6 +438,18 @@ public class AudioPolicy { + afi.getClientId() + "wasNotified=" + wasNotified); } } + + public void notifyMixStateUpdate(String regId, int state) { + for (AudioMix mix : mConfig.getMixes()) { + if (mix.getRegistration().equals(regId)) { + mix.mMixState = state; + sendMsg(MSG_MIX_STATE_UPDATE, mix, 0/*ignored*/); + if (DEBUG) { + Log.v(TAG, "notifyMixStateUpdate: regId=" + regId + " state=" + state); + } + } + } + } }; //================================================== @@ -440,6 +458,7 @@ public class AudioPolicy { private final static int MSG_POLICY_STATUS_CHANGE = 0; private final static int MSG_FOCUS_GRANT = 1; private final static int MSG_FOCUS_LOSS = 2; + private final static int MSG_MIX_STATE_UPDATE = 3; private class EventHandler extends Handler { public EventHandler(AudioPolicy ap, Looper looper) { @@ -464,6 +483,11 @@ public class AudioPolicy { (AudioFocusInfo) msg.obj, msg.arg1 != 0); } break; + case MSG_MIX_STATE_UPDATE: + if (mStatusListener != null) { + mStatusListener.onMixStateUpdate((AudioMix) msg.obj); + } + break; default: Log.e(TAG, "Unknown event " + msg.what); } diff --git a/media/java/android/media/audiopolicy/AudioPolicyConfig.java b/media/java/android/media/audiopolicy/AudioPolicyConfig.java index 917e07b..252f5f4 100644 --- a/media/java/android/media/audiopolicy/AudioPolicyConfig.java +++ b/media/java/android/media/audiopolicy/AudioPolicyConfig.java @@ -59,6 +59,10 @@ public class AudioPolicyConfig implements Parcelable { mMixes.add(mix); } + public ArrayList<AudioMix> getMixes() { + return mMixes; + } + @Override public int hashCode() { return Objects.hash(mMixes); @@ -75,6 +79,8 @@ public class AudioPolicyConfig implements Parcelable { for (AudioMix mix : mMixes) { // write mix route flags dest.writeInt(mix.getRouteFlags()); + // write callback flags + dest.writeInt(mix.mCallbackFlags); // write mix format dest.writeInt(mix.getFormat().getSampleRate()); dest.writeInt(mix.getFormat().getEncoding()); @@ -96,6 +102,8 @@ public class AudioPolicyConfig implements Parcelable { // read mix route flags int routeFlags = in.readInt(); mixBuilder.setRouteFlags(routeFlags); + // read callback flags + mixBuilder.setCallbackFlags(in.readInt()); // read mix format int sampleRate = in.readInt(); int encoding = in.readInt(); diff --git a/media/java/android/media/audiopolicy/IAudioPolicyCallback.aidl b/media/java/android/media/audiopolicy/IAudioPolicyCallback.aidl index c777c58..ad8af15 100644 --- a/media/java/android/media/audiopolicy/IAudioPolicyCallback.aidl +++ b/media/java/android/media/audiopolicy/IAudioPolicyCallback.aidl @@ -25,4 +25,7 @@ oneway interface IAudioPolicyCallback { // callbacks for audio focus void notifyAudioFocusGrant(in AudioFocusInfo afi, int requestResult); void notifyAudioFocusLoss(in AudioFocusInfo afi, boolean wasNotified); + + // callback for mix activity status update + void notifyMixStateUpdate(in String regId, int state); } diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 8b50774..f3a2912 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -752,22 +752,22 @@ <!-- Shows when people have clicked at the right edge of the screen to explain how to open the phone. In right-to-left languages, this is the opposite direction. [CHAR LIMIT=60] --> <string name="camera_hint">Swipe left for camera</string> - <!-- Interruption level: None. [CHAR LIMIT=20] --> + <!-- Interruption level: None. [CHAR LIMIT=40] --> <string name="interruption_level_none">Total silence</string> - <!-- Interruption level: Priority. [CHAR LIMIT=20] --> + <!-- Interruption level: Priority. [CHAR LIMIT=40] --> <string name="interruption_level_priority">Priority only</string> - <!-- Interruption level: Alarms only. [CHAR LIMIT=20] --> + <!-- Interruption level: Alarms only. [CHAR LIMIT=40] --> <string name="interruption_level_alarms">Alarms only</string> - <!-- Interruption level: None. Optimized for narrow two-line display. [CHAR LIMIT=20] --> + <!-- Interruption level: None. Optimized for narrow two-line display. [CHAR LIMIT=40] --> <string name="interruption_level_none_twoline">Total\nsilence</string> - <!-- Interruption level: Priority. Optimized for narrow two-line display. [CHAR LIMIT=20] --> + <!-- Interruption level: Priority. Optimized for narrow two-line display. [CHAR LIMIT=40] --> <string name="interruption_level_priority_twoline">Priority\nonly</string> - <!-- Interruption level: Alarms only. Optimized for narrow two-line display. [CHAR LIMIT=20] --> + <!-- Interruption level: Alarms only. Optimized for narrow two-line display. [CHAR LIMIT=40] --> <string name="interruption_level_alarms_twoline">Alarms\nonly</string> <!-- Indication on the keyguard that is shown when the device is charging. [CHAR LIMIT=40]--> @@ -890,23 +890,32 @@ <!-- Monitoring dialog device owner body text [CHAR LIMIT=400] --> <string name="monitoring_description_device_owned">Your device is managed by <xliff:g id="organization">%1$s</xliff:g>.\n\nYour administrator can monitor and manage settings, corporate access, apps, data associated with your device, and your device\'s location information. For more information, contact your administrator.</string> - <!-- Monitoring dialog profile owner body text [CHAR LIMIT=400] --> - <string name="monitoring_description_profile_owned">Your work profile is managed by <xliff:g id="organization">%1$s</xliff:g>.\n\nYour administrator is capable of monitoring your network activity including emails, apps and secure websites.\n\nFor more information, contact your administrator.</string> - - <!-- Monitoring dialog device and profile owner body text [CHAR LIMIT=400] --> - <string name="monitoring_description_device_and_profile_owned">Your device is managed by:\n<xliff:g id="organization">%1$s</xliff:g>.\nYour work profile is managed by:\n<xliff:g id="organization">%2$s</xliff:g>.\n\nYour administrator can monitor your device and network activity, including emails, apps and secure websites.\n\nFor more information, contact your administrator.</string> - <!-- Monitoring dialog VPN text [CHAR LIMIT=400] --> - <string name="monitoring_description_vpn">You gave an app permission to set up a VPN connection.\n\nThis app can monitor your device and network activity, including emails, apps and secure websites.</string> + <string name="monitoring_description_vpn">You gave an app permission to set up a VPN connection.\n\nThis app can monitor your device and network activity, including emails, apps and websites.</string> <!-- Monitoring dialog VPN with device owner text [CHAR LIMIT=400] --> <string name="monitoring_description_vpn_device_owned">Your device is managed by <xliff:g id="organization">%1$s</xliff:g>.\n\nYour administrator can monitor and manage settings, corporate access, apps, data associated with your device, and your device\'s location information.\n\nYou\'re connected to a VPN, which can monitor your network activity, including emails, apps, and websites.\n\nFor more information, contact your administrator.</string> <!-- Monitoring dialog VPN with profile owner text [CHAR LIMIT=400] --> - <string name="monitoring_description_vpn_profile_owned">Your work profile is managed by <xliff:g id="organization">%1$s</xliff:g>.\n\nYour administrator is capable of monitoring your network activity including emails, apps, and secure websites.\n\nFor more information, contact your administrator.\n\nYou\'re also connected to a VPN, which can monitor your network activity.</string> + <string name="monitoring_description_vpn_profile_owned">Your work profile is managed by <xliff:g id="organization">%1$s</xliff:g>.\n\nYour administrator is capable of monitoring your network activity including emails, apps, and websites.\n\nFor more information, contact your administrator.\n\nYou\'re also connected to a VPN, which can monitor your network activity.</string> + + <!-- Name for a generic legacy VPN connection [CHAR LIMIT=20] --> + <string name="legacy_vpn_name">VPN</string> + + <!-- Monitoring dialog text for single app (no profile or device owner) [CHAR LIMIT=400] --> + <string name="monitoring_description_app">You\'re connected to <xliff:g id="application">%1$s</xliff:g>, which can monitor your network activity including emails, apps and websites.</string> + + <!-- Monitoring dialog text for single app (inside personal profile) [CHAR LIMIT=400] --> + <string name="monitoring_description_app_personal">You\'re connected to <xliff:g id="application">%1$s</xliff:g>, which can monitor your personal network activity, including emails, apps and websites.</string> + + <!-- Monitoring dialog text for single app (inside work profile) [CHAR LIMIT=400] --> + <string name="monitoring_description_app_work">Your work profile is managed by <xliff:g id="organization">%1$s</xliff:g>. It is connected to <xliff:g id="application">%2$s</xliff:g>, which can monitor your work network activity, including emails, apps and websites.\n\nFor more information, contact your administrator.</string> + + <!-- Monitoring dialog text for multiple apps (in personal and work profiles) [CHAR LIMIT=400] --> + <string name="monitoring_description_app_personal_work">Your work profile is managed by <xliff:g id="organization">%1$s</xliff:g>. It is connected to <xliff:g id="application_work">%2$s</xliff:g>, which can monitor your work network activity, including emails, apps and websites.\n\nYou\'re also connected to <xliff:g id="application_personal">%3$s</xliff:g>, which can monitor your personal network activity.</string> - <!-- Monitoring dialog VPN with device and profile owner text [CHAR LIMIT=400] --> - <string name="monitoring_description_vpn_device_and_profile_owned">Your device is managed by <xliff:g id="organization">%1$s</xliff:g>.\nYour work profile is managed by:\n<xliff:g id="organization">%2$s</xliff:g>.\n\nYour administrator is capable of monitoring your network activity including emails, apps, and secure websites.\n\nFor more information, contact your administrator.\n\nYou\'re also connected to a VPN, which can monitor your personal network activity</string> + <!-- Monitoring dialog text for single app (with device owner) [CHAR LIMIT=400] --> + <string name="monitoring_description_vpn_app_device_owned">Your device is managed by <xliff:g id="organization">%1$s</xliff:g>.\n\nYour administrator can monitor and manage settings, corporate access, apps, data associated with your device, and your device\'s location information.\n\nYou\'re connected to <xliff:g id="application">%2$s</xliff:g>, which can monitor your network activity, including emails, apps, and websites.\n\nFor more information, contact your administrator.</string> <!-- Indication on the keyguard that appears when the user disables trust agents until the next time they unlock manually. [CHAR LIMIT=NONE] --> <string name="keyguard_indication_trust_disabled">Device will stay locked until you manually unlock</string> diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java index d8e3984..f59e864 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java @@ -110,21 +110,15 @@ public class QSFooter implements OnClickListener, DialogInterface.OnClickListene } private void handleRefreshState() { - if (mSecurityController.hasDeviceOwner()) { + boolean hasDeviceOwner = mSecurityController.hasDeviceOwner(); + boolean hasVpn = mSecurityController.isVpnEnabled(); + + mIsVisible = (hasVpn || hasDeviceOwner); + mIsIconVisible = hasVpn; + if (hasDeviceOwner) { mFooterTextId = R.string.device_owned_footer; - mIsVisible = true; - mIsIconVisible = false; - } else if (mSecurityController.hasProfileOwner()) { - mFooterTextId = R.string.profile_owned_footer; - mIsVisible = true; - mIsIconVisible = false; - } else if (mSecurityController.isVpnEnabled()) { - mFooterTextId = R.string.vpn_footer; - mIsVisible = true; - mIsIconVisible = true; } else { - mIsVisible = false; - mIsIconVisible = false; + mFooterTextId = R.string.vpn_footer; } mMainHandler.post(mUpdateDisplayState); } @@ -162,37 +156,17 @@ public class QSFooter implements OnClickListener, DialogInterface.OnClickListene private String getMessage(boolean hasDeviceOwner, boolean hasProfile, boolean hasVpn) { if (hasDeviceOwner) { - if (hasProfile) { - if (hasVpn) { - return mContext.getString( - R.string.monitoring_description_vpn_device_and_profile_owned, - mSecurityController.getDeviceOwnerName(), - mSecurityController.getProfileOwnerName()); - } else { - return mContext.getString( - R.string.monitoring_description_device_and_profile_owned, - mSecurityController.getDeviceOwnerName(), - mSecurityController.getProfileOwnerName()); - } - } else { - if (hasVpn) { - return mContext.getString(R.string.monitoring_description_vpn_device_owned, - mSecurityController.getDeviceOwnerName()); - } else { - return mContext.getString(R.string.monitoring_description_device_owned, - mSecurityController.getDeviceOwnerName()); - } - } - } else if (hasProfile) { if (hasVpn) { - return mContext.getString( - R.string.monitoring_description_vpn_profile_owned, - mSecurityController.getProfileOwnerName()); + return mContext.getString(R.string.monitoring_description_vpn_device_owned, + mSecurityController.getDeviceOwnerName()); } else { - return mContext.getString( - R.string.monitoring_description_profile_owned, - mSecurityController.getProfileOwnerName()); + return mContext.getString(R.string.monitoring_description_device_owned, + mSecurityController.getDeviceOwnerName()); } + } else if (hasProfile) { + return mContext.getString( + R.string.monitoring_description_vpn_profile_owned, + mSecurityController.getProfileOwnerName()); } else { return mContext.getString(R.string.monitoring_description_vpn); } diff --git a/preloaded-classes b/preloaded-classes index c94623a..d2ed762 100644 --- a/preloaded-classes +++ b/preloaded-classes @@ -1152,6 +1152,7 @@ android.provider.Settings$SettingNotFoundException android.provider.Settings$System android.provider.Telephony$Mms android.renderscript.RenderScript +android.security.AndroidKeyStoreBCWorkaroundProvider android.security.AndroidKeyStoreProvider android.speech.tts.TextToSpeechService android.speech.tts.TextToSpeechService$SpeechItemV1 diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index ddcfb15..069878e 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -3185,6 +3185,10 @@ public final class ActivityManagerService extends ActivityManagerNative debugFlags |= Zygote.DEBUG_ENABLE_JIT; } } + String genCFIDebugProperty = SystemProperties.get("debug.gencfi"); + if ("true".equals(genCFIDebugProperty)) { + debugFlags |= Zygote.DEBUG_GENERATE_CFI; + } if ("1".equals(SystemProperties.get("debug.jni.logging"))) { debugFlags |= Zygote.DEBUG_ENABLE_JNI_LOGGING; } diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index eb28ed0..06fba34 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -65,6 +65,7 @@ import android.media.SoundPool; import android.media.VolumePolicy; import android.media.MediaPlayer.OnCompletionListener; import android.media.MediaPlayer.OnErrorListener; +import android.media.audiopolicy.AudioMix; import android.media.audiopolicy.AudioPolicy; import android.media.audiopolicy.AudioPolicyConfig; import android.media.audiopolicy.IAudioPolicyCallback; @@ -206,6 +207,7 @@ public class AudioService extends IAudioService.Stub { private static final int MSG_PERSIST_MUSIC_ACTIVE_MS = 22; private static final int MSG_PERSIST_MICROPHONE_MUTE = 23; private static final int MSG_UNMUTE_STREAM = 24; + private static final int MSG_DYN_POLICY_MIX_STATE_UPDATE = 25; // start of messages handled under wakelock // these messages can only be queued, i.e. sent with queueMsgUnderWakeLock(), // and not with sendMsg(..., ..., SENDMSG_QUEUE, ...) @@ -4337,6 +4339,9 @@ public class AudioService extends IAudioService.Stub { case MSG_UNMUTE_STREAM: onUnmuteStream(msg.arg1, msg.arg2); break; + case MSG_DYN_POLICY_MIX_STATE_UPDATE: + onDynPolicyMixStateUpdate((String) msg.obj, msg.arg1); + break; } } } @@ -5758,6 +5763,8 @@ public class AudioService extends IAudioService.Stub { //========================================================================================== public String registerAudioPolicy(AudioPolicyConfig policyConfig, IAudioPolicyCallback pcb, boolean hasFocusListener) { + AudioSystem.setDynamicPolicyCallback(mDynPolicyCallback); + if (DEBUG_AP) Log.d(TAG, "registerAudioPolicy for " + pcb.asBinder() + " with config:" + policyConfig); String regId = null; @@ -5853,6 +5860,39 @@ public class AudioService extends IAudioService.Stub { } //====================== + // Audio policy callback from AudioSystem + //====================== + private final AudioSystem.DynamicPolicyCallback mDynPolicyCallback = + new AudioSystem.DynamicPolicyCallback() { + public void onDynamicPolicyMixStateUpdate(String regId, int state) { + if (!TextUtils.isEmpty(regId)) { + sendMsg(mAudioHandler, MSG_DYN_POLICY_MIX_STATE_UPDATE, SENDMSG_QUEUE, + state /*arg1*/, 0 /*arg2 ignored*/, regId /*obj*/, 0 /*delay*/); + } + } + }; + + private void onDynPolicyMixStateUpdate(String regId, int state) { + if (DEBUG_AP) Log.d(TAG, "onDynamicPolicyMixStateUpdate("+ regId + ", " + state +")"); + synchronized (mAudioPolicies) { + for (AudioPolicyProxy policy : mAudioPolicies.values()) { + for (AudioMix mix : policy.getMixes()) { + if (mix.getRegistration().equals(regId)) { + try { + policy.mPolicyCallback.notifyMixStateUpdate(regId, state); + } catch (RemoteException e) { + Log.e(TAG, "Can't call notifyMixStateUpdate() on IAudioPolicyCallback " + + policy.mPolicyCallback.asBinder(), e); + } + return; + } + } + } + } + + } + + //====================== // Audio policy proxy //====================== /** @@ -5861,8 +5901,7 @@ public class AudioService extends IAudioService.Stub { */ public class AudioPolicyProxy extends AudioPolicyConfig implements IBinder.DeathRecipient { private static final String TAG = "AudioPolicyProxy"; - AudioPolicyConfig mConfig; - IAudioPolicyCallback mPolicyToken; + IAudioPolicyCallback mPolicyCallback; boolean mHasFocusListener; /** * Audio focus ducking behavior for an audio policy. @@ -5877,19 +5916,19 @@ public class AudioService extends IAudioService.Stub { boolean hasFocusListener) { super(config); setRegistration(new String(config.hashCode() + ":ap:" + mAudioPolicyCounter++)); - mPolicyToken = token; + mPolicyCallback = token; mHasFocusListener = hasFocusListener; if (mHasFocusListener) { - mMediaFocusControl.addFocusFollower(mPolicyToken); + mMediaFocusControl.addFocusFollower(mPolicyCallback); } connectMixes(); } public void binderDied() { synchronized (mAudioPolicies) { - Log.i(TAG, "audio policy " + mPolicyToken + " died"); + Log.i(TAG, "audio policy " + mPolicyCallback + " died"); release(); - mAudioPolicies.remove(mPolicyToken.asBinder()); + mAudioPolicies.remove(mPolicyCallback.asBinder()); } } @@ -5902,7 +5941,7 @@ public class AudioService extends IAudioService.Stub { mMediaFocusControl.setDuckingInExtPolicyAvailable(false); } if (mHasFocusListener) { - mMediaFocusControl.removeFocusFollower(mPolicyToken); + mMediaFocusControl.removeFocusFollower(mPolicyCallback); } AudioSystem.registerPolicyMixes(mMixes, false); } diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java index 6b5908d..ed8519a 100644 --- a/services/core/java/com/android/server/fingerprint/FingerprintService.java +++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java @@ -16,14 +16,15 @@ package com.android.server.fingerprint; +import android.app.AppOpsManager; import android.content.ContentResolver; import android.content.Context; +import android.os.Binder; import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.MessageQueue; import android.os.RemoteException; -import android.util.ArrayMap; import android.util.Slog; import com.android.server.SystemService; @@ -39,6 +40,7 @@ import static android.Manifest.permission.USE_FINGERPRINT; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; /** @@ -55,6 +57,8 @@ public class FingerprintService extends SystemService { private ClientMonitor mEnrollClient = null; private ClientMonitor mRemoveClient = null; + private final AppOpsManager mAppOps; + private static final int MSG_NOTIFY = 10; private static final int ENROLLMENT_TIMEOUT_MS = 60 * 1000; // 1 minute @@ -96,6 +100,7 @@ public class FingerprintService extends SystemService { public FingerprintService(Context context) { super(context); mContext = context; + mAppOps = context.getSystemService(AppOpsManager.class); nativeInit(Looper.getMainLooper().getQueue(), this); } @@ -361,6 +366,13 @@ public class FingerprintService extends SystemService { "Must have " + permission + " permission."); } + private boolean canUserFingerPrint(String opPackageName) { + checkPermission(USE_FINGERPRINT); + + return mAppOps.noteOp(AppOpsManager.OP_USE_FINGERPRINT, Binder.getCallingUid(), + opPackageName) == AppOpsManager.MODE_ALLOWED; + } + private class ClientMonitor implements IBinder.DeathRecipient { IBinder token; IFingerprintServiceReceiver receiver; @@ -522,8 +534,11 @@ public class FingerprintService extends SystemService { @Override // Binder call public void authenticate(final IBinder token, final long opId, final int groupId, - final IFingerprintServiceReceiver receiver, final int flags) { + final IFingerprintServiceReceiver receiver, final int flags, String opPackageName) { checkPermission(USE_FINGERPRINT); + if (!canUserFingerPrint(opPackageName)) { + return; + } mHandler.post(new Runnable() { @Override public void run() { @@ -535,8 +550,10 @@ public class FingerprintService extends SystemService { @Override // Binder call - public void cancelAuthentication(final IBinder token) { - checkPermission(USE_FINGERPRINT); + public void cancelAuthentication(final IBinder token, String opPackageName) { + if (!canUserFingerPrint(opPackageName)) { + return; + } mHandler.post(new Runnable() { @Override public void run() { @@ -561,8 +578,10 @@ public class FingerprintService extends SystemService { @Override // Binder call - public boolean isHardwareDetected(long deviceId) { - checkPermission(USE_FINGERPRINT); + public boolean isHardwareDetected(long deviceId, String opPackageName) { + if (!canUserFingerPrint(opPackageName)) { + return false; + } return mHalDeviceId != 0; // TODO } @@ -580,21 +599,27 @@ public class FingerprintService extends SystemService { @Override // Binder call - public List<Fingerprint> getEnrolledFingerprints(int groupId) { - checkPermission(USE_FINGERPRINT); + public List<Fingerprint> getEnrolledFingerprints(int groupId, String opPackageName) { + if (!canUserFingerPrint(opPackageName)) { + return Collections.emptyList(); + } return FingerprintService.this.getEnrolledFingerprints(groupId); } @Override // Binder call - public boolean hasEnrolledFingerprints(int groupId) { - checkPermission(USE_FINGERPRINT); + public boolean hasEnrolledFingerprints(int groupId, String opPackageName) { + if (!canUserFingerPrint(opPackageName)) { + return false; + } return FingerprintService.this.hasEnrolledFingerprints(groupId); } @Override - public long getAuthenticatorId() { - checkPermission(USE_FINGERPRINT); + public long getAuthenticatorId(String opPackageName) { + if (!canUserFingerPrint(opPackageName)) { + return 0; + } return nativeGetAuthenticatorId(); } } diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java index 8d6bda8..1431eb8 100644 --- a/telecomm/java/android/telecom/TelecomManager.java +++ b/telecomm/java/android/telecom/TelecomManager.java @@ -921,7 +921,7 @@ public class TelecomManager { public void silenceRinger() { try { if (isServiceConnected()) { - getTelecomService().silenceRinger(); + getTelecomService().silenceRinger(mContext.getOpPackageName()); } } catch (RemoteException e) { Log.e(TAG, "Error calling ITelecomService#silenceRinger", e); @@ -1029,7 +1029,7 @@ public class TelecomManager { ITelecomService service = getTelecomService(); if (service != null) { try { - return service.handlePinMmi(dialString); + return service.handlePinMmi(dialString, mContext.getOpPackageName()); } catch (RemoteException e) { Log.e(TAG, "Error calling ITelecomService#handlePinMmi", e); } @@ -1053,7 +1053,8 @@ public class TelecomManager { ITelecomService service = getTelecomService(); if (service != null) { try { - return service.handlePinMmiForPhoneAccount(accountHandle, dialString); + return service.handlePinMmiForPhoneAccount(accountHandle, dialString, + mContext.getOpPackageName()); } catch (RemoteException e) { Log.e(TAG, "Error calling ITelecomService#handlePinMmi", e); } @@ -1071,7 +1072,7 @@ public class TelecomManager { ITelecomService service = getTelecomService(); if (service != null && accountHandle != null) { try { - return service.getAdnUriForPhoneAccount(accountHandle); + return service.getAdnUriForPhoneAccount(accountHandle, mContext.getOpPackageName()); } catch (RemoteException e) { Log.e(TAG, "Error calling ITelecomService#getAdnUriForPhoneAccount", e); } @@ -1089,7 +1090,7 @@ public class TelecomManager { ITelecomService service = getTelecomService(); if (service != null) { try { - service.cancelMissedCallsNotification(); + service.cancelMissedCallsNotification(mContext.getOpPackageName()); } catch (RemoteException e) { Log.e(TAG, "Error calling ITelecomService#cancelMissedCallsNotification", e); } diff --git a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl index 49f2aad..bc76f06 100644 --- a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl +++ b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl @@ -154,7 +154,7 @@ interface ITelecomService { /** * @see TelecomServiceImpl#silenceRinger */ - void silenceRinger(); + void silenceRinger(String callingPackage); /** * @see TelecomServiceImpl#isInCall @@ -184,22 +184,23 @@ interface ITelecomService { /** * @see TelecomServiceImpl#cancelMissedCallsNotification */ - void cancelMissedCallsNotification(); + void cancelMissedCallsNotification(String callingPackage); /** * @see TelecomServiceImpl#handleMmi */ - boolean handlePinMmi(String dialString); + boolean handlePinMmi(String dialString, String callingPackage); /** * @see TelecomServiceImpl#handleMmi */ - boolean handlePinMmiForPhoneAccount(in PhoneAccountHandle accountHandle, String dialString); + boolean handlePinMmiForPhoneAccount(in PhoneAccountHandle accountHandle, String dialString, + String callingPackage); /** * @see TelecomServiceImpl#getAdnUriForPhoneAccount */ - Uri getAdnUriForPhoneAccount(in PhoneAccountHandle accountHandle); + Uri getAdnUriForPhoneAccount(in PhoneAccountHandle accountHandle, String callingPackage); /** * @see TelecomServiceImpl#isTtySupported diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index ee7f0ea..d674b31 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -3703,7 +3703,7 @@ public class TelephonyManager { @SystemApi public void silenceRinger() { try { - getTelecomService().silenceRinger(); + getTelecomService().silenceRinger(mContext.getOpPackageName()); } catch (RemoteException e) { Log.e(TAG, "Error calling ITelecomService#silenceRinger", e); } |