Merge "RESTRICT AUTOMERGE Use consistent calling uid and package in navigateUpTo" into qt-qpr1-dev
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index cd0b340..c2a7c79 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -665,6 +665,8 @@
char dex2oatImageCompilerFilterBuf[sizeof("--compiler-filter=")-1 + PROPERTY_VALUE_MAX];
char dex2oatThreadsBuf[sizeof("-j")-1 + PROPERTY_VALUE_MAX];
char dex2oatThreadsImageBuf[sizeof("-j")-1 + PROPERTY_VALUE_MAX];
+ char dex2oatCpuSetBuf[sizeof("--cpu-set=")-1 + PROPERTY_VALUE_MAX];
+ char dex2oatCpuSetImageBuf[sizeof("--cpu-set=")-1 + PROPERTY_VALUE_MAX];
char dex2oat_isa_variant_key[PROPERTY_KEY_MAX];
char dex2oat_isa_variant[sizeof("--instruction-set-variant=") -1 + PROPERTY_VALUE_MAX];
char dex2oat_isa_features_key[PROPERTY_KEY_MAX];
@@ -937,6 +939,10 @@
parseCompilerOption("dalvik.vm.dex2oat-threads", dex2oatThreadsBuf, "-j", "-Xcompiler-option");
parseCompilerOption("dalvik.vm.image-dex2oat-threads", dex2oatThreadsImageBuf, "-j",
"-Ximage-compiler-option");
+ parseCompilerOption("dalvik.vm.dex2oat-cpu-set", dex2oatCpuSetBuf, "--cpu-set=",
+ "-Xcompiler-option");
+ parseCompilerOption("dalvik.vm.image-dex2oat-cpu-set", dex2oatCpuSetImageBuf, "--cpu-set=",
+ "-Ximage-compiler-option");
// The runtime will compile a boot image, when necessary, not using installd. Thus, we need to
// pass the instruction-set-features/variant as an image-compiler-option.
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index a0d2d84..5d5729b 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1212,12 +1212,16 @@
<string name="permdesc_readPhoneNumbers">Allows the app to access the phone numbers 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="automotive">keep car screen turned on</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>
<!-- 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="default">prevent phone from sleeping</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_wakeLock" product="automotive">Allows the app to keep the car screen turned on.</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_wakeLock" product="tablet">Allows the app to prevent the tablet from going to sleep.</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_wakeLock" product="tv">Allows the app to prevent the TV from going to sleep.</string>
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index 646aa13..9866c30 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -1067,6 +1067,17 @@
return onUserPasswordChanged(UserHandle.getUserId(Process.myUid()), newPassword);
}
+ /**
+ * Notify keystore about the latest user locked state. This is to support keyguard-bound key.
+ */
+ public void onUserLockedStateChanged(int userHandle, boolean locked) {
+ try {
+ mBinder.onKeyguardVisibilityChanged(locked, userHandle);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to update user locked state " + userHandle, e);
+ }
+ }
+
private class KeyAttestationCallbackResult {
private KeystoreResponse keystoreResponse;
private KeymasterCertificateChain certificateChain;
diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index 820d82d..d2ae7c1 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -1251,7 +1251,10 @@
}
}
- static int capturePolicyToFlags(@CapturePolicy int capturePolicy, int flags) {
+ /**
+ * @hide
+ */
+ public static int capturePolicyToFlags(@CapturePolicy int capturePolicy, int flags) {
switch (capturePolicy) {
case ALLOW_CAPTURE_BY_NONE:
flags |= FLAG_NO_MEDIA_PROJECTION | FLAG_NO_SYSTEM_CAPTURE;
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 6890270..142bc12 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -1507,23 +1507,22 @@
* {@link AudioAttributes#ALLOW_CAPTURE_BY_ALL},
* {@link AudioAttributes#ALLOW_CAPTURE_BY_SYSTEM},
* {@link AudioAttributes#ALLOW_CAPTURE_BY_NONE}.
- * @throws IllegalArgumentException if the argument is not a valid value.
+ * @throws RuntimeException if the argument is not a valid value.
*/
public void setAllowedCapturePolicy(@AudioAttributes.CapturePolicy int capturePolicy) {
- int flags = AudioAttributes.capturePolicyToFlags(capturePolicy, 0x0);
- // TODO: got trough AudioService and save a cache to restore in case of AP crash
// TODO: also pass the package in case multiple packages have the same UID
- int result = AudioSystem.setAllowedCapturePolicy(Process.myUid(), flags);
- if (result != AudioSystem.AUDIO_STATUS_OK) {
- Log.e(TAG, "Could not setAllowedCapturePolicy: " + result);
- return;
+ final IAudioService service = getService();
+ try {
+ int result = service.setAllowedCapturePolicy(capturePolicy);
+ if (result != AudioSystem.AUDIO_STATUS_OK) {
+ Log.e(TAG, "Could not setAllowedCapturePolicy: " + result);
+ return;
+ }
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
- mCapturePolicy = capturePolicy;
}
- @AudioAttributes.CapturePolicy
- private int mCapturePolicy = AudioAttributes.ALLOW_CAPTURE_BY_ALL;
-
/**
* Return the capture policy.
* @return the capture policy set by {@link #setAllowedCapturePolicy(int)} or
@@ -1531,7 +1530,13 @@
*/
@AudioAttributes.CapturePolicy
public int getAllowedCapturePolicy() {
- return mCapturePolicy;
+ int result = AudioAttributes.ALLOW_CAPTURE_BY_ALL;
+ try {
+ result = getService().getAllowedCapturePolicy();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to query allowed capture policy: " + e);
+ }
+ return result;
}
//====================================================================
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 71f52a1..7052e5a 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -259,6 +259,10 @@
boolean hasHapticChannels(in Uri uri);
+ int setAllowedCapturePolicy(in int capturePolicy);
+
+ int getAllowedCapturePolicy();
+
// WARNING: read warning at top of file, new methods that need to be used by native
// code via IAudioManager.h need to be added to the top section.
}
diff --git a/packages/SystemUI/src/com/android/systemui/CameraAvailabilityListener.kt b/packages/SystemUI/src/com/android/systemui/CameraAvailabilityListener.kt
index 24fa91b..284074e 100644
--- a/packages/SystemUI/src/com/android/systemui/CameraAvailabilityListener.kt
+++ b/packages/SystemUI/src/com/android/systemui/CameraAvailabilityListener.kt
@@ -26,7 +26,7 @@
import kotlin.math.roundToInt
-const val TAG = "CameraOpTransitionController"
+const val TAG = "CameraAvailabilityListener"
/**
* Listens for usage of the Camera and controls the ScreenDecorations transition to show extra
diff --git a/packages/SystemUI/src/com/android/systemui/ConfigurationChangedReceiver.java b/packages/SystemUI/src/com/android/systemui/ConfigurationChangedReceiver.java
deleted file mode 100644
index 4fba640..0000000
--- a/packages/SystemUI/src/com/android/systemui/ConfigurationChangedReceiver.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package com.android.systemui;
-
-import android.content.res.Configuration;
-
-public interface ConfigurationChangedReceiver {
- void onConfigurationChanged(Configuration newConfiguration);
-}
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index 15bea24..c09c767 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -16,7 +16,6 @@
import android.annotation.Nullable;
import android.app.INotificationManager;
-import android.content.res.Configuration;
import android.hardware.SensorPrivacyManager;
import android.hardware.display.NightDisplayListener;
import android.os.Handler;
@@ -521,15 +520,6 @@
.forEach(o -> ((Dumpable) o).dump(fd, pw, args));
}
- protected static void staticOnConfigurationChanged(Configuration newConfig) {
- sDependency.onConfigurationChanged(newConfig);
- }
-
- protected synchronized void onConfigurationChanged(Configuration newConfig) {
- mDependencies.values().stream().filter(obj -> obj instanceof ConfigurationChangedReceiver)
- .forEach(o -> ((ConfigurationChangedReceiver) o).onConfigurationChanged(newConfig));
- }
-
protected final <T> T getDependency(Class<T> cls) {
return getDependencyInner(cls);
}
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
index 3a8524a..6ea6a74 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
@@ -26,8 +26,10 @@
import static com.android.systemui.tuner.TunablePadding.FLAG_START;
import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
import android.annotation.Dimension;
import android.annotation.NonNull;
import android.app.ActivityManager;
@@ -869,14 +871,17 @@
public static class DisplayCutoutView extends View implements DisplayManager.DisplayListener,
RegionInterceptableView {
+ private static final float HIDDEN_CAMERA_PROTECTION_SCALE = 0.5f;
+
private final DisplayInfo mInfo = new DisplayInfo();
private final Paint mPaint = new Paint();
private final List<Rect> mBounds = new ArrayList();
private final Rect mBoundingRect = new Rect();
private final Path mBoundingPath = new Path();
- // Don't initialize these because they are cached elsewhere and may not exist
+ // Don't initialize these yet because they may never exist
private Rect mProtectionRect;
private Path mProtectionPath;
+ private Path mProtectionPathOrig;
private Rect mTotalBounds = new Rect();
// Whether or not to show the cutout protection path
private boolean mShowProtection = false;
@@ -888,6 +893,8 @@
private int mColor = Color.BLACK;
private boolean mStart;
private int mRotation;
+ private float mCameraProtectionProgress = HIDDEN_CAMERA_PROTECTION_SCALE;
+ private ValueAnimator mCameraProtectionAnimator;
public DisplayCutoutView(Context context, boolean start,
Runnable visibilityChangedListener, ScreenDecorations decorations) {
@@ -928,17 +935,18 @@
getLocationOnScreen(mLocation);
canvas.translate(-mLocation[0], -mLocation[1]);
- if (mShowProtection && !mProtectionRect.isEmpty()) {
- mPaint.setColor(mColor);
- mPaint.setStyle(Paint.Style.FILL);
- mPaint.setAntiAlias(true);
- canvas.drawPath(mProtectionPath, mPaint);
- } else if (!mBoundingPath.isEmpty()) {
+ if (!mBoundingPath.isEmpty()) {
mPaint.setColor(mColor);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setAntiAlias(true);
canvas.drawPath(mBoundingPath, mPaint);
}
+ if (mCameraProtectionProgress > HIDDEN_CAMERA_PROTECTION_SCALE
+ && !mProtectionRect.isEmpty()) {
+ canvas.scale(mCameraProtectionProgress, mCameraProtectionProgress,
+ mProtectionRect.centerX(), mProtectionRect.centerY());
+ canvas.drawPath(mProtectionPath, mPaint);
+ }
}
@Override
@@ -962,7 +970,11 @@
}
void setProtection(Path protectionPath, Rect pathBounds) {
- mProtectionPath = protectionPath;
+ if (mProtectionPathOrig == null) {
+ mProtectionPathOrig = new Path();
+ mProtectionPath = new Path();
+ }
+ mProtectionPathOrig.set(protectionPath);
mProtectionRect = pathBounds;
}
@@ -973,8 +985,31 @@
mShowProtection = shouldShow;
updateBoundingPath();
- requestLayout();
- invalidate();
+ // Delay the relayout until the end of the animation when hiding the cutout,
+ // otherwise we'd clip it.
+ if (mShowProtection) {
+ requestLayout();
+ }
+ if (mCameraProtectionAnimator != null) {
+ mCameraProtectionAnimator.cancel();
+ }
+ mCameraProtectionAnimator = ValueAnimator.ofFloat(mCameraProtectionProgress,
+ mShowProtection ? 1.0f : HIDDEN_CAMERA_PROTECTION_SCALE).setDuration(750);
+ mCameraProtectionAnimator.setInterpolator(Interpolators.DECELERATE_QUINT);
+ mCameraProtectionAnimator.addUpdateListener(animation -> {
+ mCameraProtectionProgress = (float) animation.getAnimatedValue();
+ invalidate();
+ });
+ mCameraProtectionAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mCameraProtectionAnimator = null;
+ if (!mShowProtection) {
+ requestLayout();
+ }
+ }
+ });
+ mCameraProtectionAnimator.start();
}
private boolean isStart() {
@@ -1023,7 +1058,9 @@
Matrix m = new Matrix();
transformPhysicalToLogicalCoordinates(mInfo.rotation, dw, dh, m);
mBoundingPath.transform(m);
- if (mProtectionPath != null) {
+ if (mProtectionPathOrig != null) {
+ // Reset the protection path so we don't aggregate rotations
+ mProtectionPath.set(mProtectionPathOrig);
mProtectionPath.transform(m);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index 9252e57..0d1bd6b 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -286,7 +286,11 @@
@Override
public void onConfigurationChanged(Configuration newConfig) {
if (mServicesStarted) {
- Dependency.staticOnConfigurationChanged(newConfig);
+ SystemUIFactory
+ .getInstance()
+ .getRootComponent()
+ .getConfigurationController()
+ .onConfigurationChanged(newConfig);
int len = mServices.length;
for (int i = 0; i < len; i++) {
if (mServices[i] != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIRootComponent.java b/packages/SystemUI/src/com/android/systemui/SystemUIRootComponent.java
index f18c8b2..a5b386e 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIRootComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIRootComponent.java
@@ -20,6 +20,7 @@
import com.android.systemui.fragments.FragmentService;
import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.util.InjectionInflationController;
import com.android.systemui.util.leak.GarbageMonitor;
@@ -40,12 +41,20 @@
SystemUIModule.class,
SystemUIDefaultModule.class})
public interface SystemUIRootComponent {
+
/**
* Main dependency providing module.
*/
@Singleton
Dependency.DependencyInjector createDependency();
+
+ /**
+ * Creates a ConfigurationController.
+ */
+ @Singleton
+ ConfigurationController getConfigurationController();
+
/**
* Injects the StatusBar.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
index 1a2d062..74b4f95 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
@@ -39,13 +39,13 @@
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.settingslib.applications.InterestingConfigChanges;
-import com.android.systemui.ConfigurationChangedReceiver;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.assist.ui.DefaultUiController;
import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import javax.inject.Inject;
@@ -55,7 +55,7 @@
* Class to manage everything related to assist in SystemUI.
*/
@Singleton
-public class AssistManager implements ConfigurationChangedReceiver {
+public class AssistManager {
/**
* Controls the UI for showing Assistant invocation progress.
@@ -153,12 +153,40 @@
}
};
+ private ConfigurationController.ConfigurationListener mConfigurationListener =
+ new ConfigurationController.ConfigurationListener() {
+ @Override
+ public void onConfigChanged(Configuration newConfig) {
+ if (!mInterestingConfigChanges.applyNewConfig(mContext.getResources())) {
+ return;
+ }
+ boolean visible = false;
+ if (mView != null) {
+ visible = mView.isShowing();
+ mWindowManager.removeView(mView);
+ }
+
+ mView = (AssistOrbContainer) LayoutInflater.from(mContext).inflate(
+ R.layout.assist_orb, null);
+ mView.setVisibility(View.GONE);
+ mView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+ | View.SYSTEM_UI_FLAG_LAYOUT_STABLE
+ | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
+ WindowManager.LayoutParams lp = getLayoutParams();
+ mWindowManager.addView(mView, lp);
+ if (visible) {
+ mView.show(true /* show */, false /* animate */);
+ }
+ }
+ };
+
@Inject
public AssistManager(
DeviceProvisionedController controller,
Context context,
AssistUtils assistUtils,
- AssistHandleBehaviorController handleController) {
+ AssistHandleBehaviorController handleController,
+ ConfigurationController configurationController) {
mContext = context;
mDeviceProvisionedController = controller;
mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
@@ -167,11 +195,13 @@
mPhoneStateMonitor = new PhoneStateMonitor(context);
mHandleController = handleController;
+ configurationController.addCallback(mConfigurationListener);
+
registerVoiceInteractionSessionListener();
mInterestingConfigChanges = new InterestingConfigChanges(ActivityInfo.CONFIG_ORIENTATION
| ActivityInfo.CONFIG_LOCALE | ActivityInfo.CONFIG_UI_MODE
| ActivityInfo.CONFIG_SCREEN_LAYOUT | ActivityInfo.CONFIG_ASSETS_PATHS);
- onConfigurationChanged(context.getResources().getConfiguration());
+ mConfigurationListener.onConfigChanged(context.getResources().getConfiguration());
mShouldEnableOrb = !ActivityManager.isLowRamDeviceStatic();
mUiController = new DefaultUiController(mContext);
@@ -221,29 +251,6 @@
});
}
- public void onConfigurationChanged(Configuration newConfiguration) {
- if (!mInterestingConfigChanges.applyNewConfig(mContext.getResources())) {
- return;
- }
- boolean visible = false;
- if (mView != null) {
- visible = mView.isShowing();
- mWindowManager.removeView(mView);
- }
-
- mView = (AssistOrbContainer) LayoutInflater.from(mContext).inflate(
- R.layout.assist_orb, null);
- mView.setVisibility(View.GONE);
- mView.setSystemUiVisibility(
- View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE
- | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
- WindowManager.LayoutParams lp = getLayoutParams();
- mWindowManager.addView(mView, lp);
- if (visible) {
- mView.show(true /* show */, false /* animate */);
- }
- }
-
protected boolean shouldShowOrb() {
return false;
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
index b7c8f70..e6cbab2 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
@@ -305,7 +305,7 @@
mContext.getResources());
} else {
sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
- mSensorThreshold = sensor.getMaximumRange();
+ mSensorThreshold = sensor == null ? 0 : sensor.getMaximumRange();
}
mSensor = sensor;
}
diff --git a/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java b/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java
index b4cc571..bbf49e3 100644
--- a/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java
+++ b/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java
@@ -20,11 +20,11 @@
import android.util.ArrayMap;
import android.view.View;
-import com.android.systemui.ConfigurationChangedReceiver;
import com.android.systemui.Dumpable;
import com.android.systemui.SystemUIRootComponent;
import com.android.systemui.qs.QSFragment;
import com.android.systemui.statusbar.phone.NavigationBarFragment;
+import com.android.systemui.statusbar.policy.ConfigurationController;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -41,7 +41,7 @@
* Also dispatches the configuration changes to all current FragmentHostStates.
*/
@Singleton
-public class FragmentService implements ConfigurationChangedReceiver, Dumpable {
+public class FragmentService implements Dumpable {
private static final String TAG = "FragmentService";
@@ -50,10 +50,22 @@
private final Handler mHandler = new Handler();
private final FragmentCreator mFragmentCreator;
+ private ConfigurationController.ConfigurationListener mConfigurationListener =
+ new ConfigurationController.ConfigurationListener() {
+ @Override
+ public void onConfigChanged(Configuration newConfig) {
+ for (FragmentHostState state : mHosts.values()) {
+ state.sendConfigurationChange(newConfig);
+ }
+ }
+ };
+
@Inject
- public FragmentService(SystemUIRootComponent rootComponent) {
+ public FragmentService(SystemUIRootComponent rootComponent,
+ ConfigurationController configurationController) {
mFragmentCreator = rootComponent.createFragmentCreator();
initInjectionMap();
+ configurationController.addCallback(mConfigurationListener);
}
ArrayMap<String, Method> getInjectionMap() {
@@ -97,13 +109,6 @@
}
@Override
- public void onConfigurationChanged(Configuration newConfig) {
- for (FragmentHostState state : mHosts.values()) {
- state.sendConfigurationChange(newConfig);
- }
- }
-
- @Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("Dumping fragments:");
for (FragmentHostState state : mHosts.values()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java
index 04f1c32..1524b07 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java
@@ -16,6 +16,8 @@
package com.android.systemui.statusbar;
+import static java.lang.Float.isNaN;
+
import android.annotation.NonNull;
import android.content.Context;
import android.graphics.Canvas;
@@ -179,6 +181,9 @@
* @param alpha Gradient alpha from 0 to 1.
*/
public void setViewAlpha(float alpha) {
+ if (isNaN(alpha)) {
+ throw new IllegalArgumentException("alpha cannot be NaN");
+ }
if (alpha != mViewAlpha) {
mViewAlpha = alpha;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt
index 424acfd..54ef623 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt
@@ -18,14 +18,11 @@
import android.content.pm.ActivityInfo
import android.content.res.Configuration
import android.os.LocaleList
-
-import com.android.systemui.ConfigurationChangedReceiver
import com.android.systemui.statusbar.policy.ConfigurationController
import java.util.ArrayList
-class ConfigurationControllerImpl(context: Context)
- : ConfigurationController, ConfigurationChangedReceiver {
+class ConfigurationControllerImpl(context: Context) : ConfigurationController {
private val listeners: MutableList<ConfigurationController.ConfigurationListener> = ArrayList()
private val lastConfig = Configuration()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 9019e9a..08ba508 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -16,6 +16,8 @@
package com.android.systemui.statusbar.phone;
+import static java.lang.Float.isNaN;
+
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
@@ -261,6 +263,10 @@
mCurrentBehindTint = state.getBehindTint();
mCurrentInFrontAlpha = state.getFrontAlpha();
mCurrentBehindAlpha = state.getBehindAlpha();
+ if (isNaN(mCurrentBehindAlpha) || isNaN(mCurrentInFrontAlpha)) {
+ throw new IllegalStateException("Scrim opacity is NaN for state: " + state + ", front: "
+ + mCurrentInFrontAlpha + ", back: " + mCurrentBehindAlpha);
+ }
applyExpansionToAlpha();
// Scrim might acquire focus when user is navigating with a D-pad or a keyboard.
@@ -390,6 +396,9 @@
* @param fraction From 0 to 1 where 0 means collapsed and 1 expanded.
*/
public void setPanelExpansion(float fraction) {
+ if (isNaN(fraction)) {
+ throw new IllegalArgumentException("Fraction should not be NaN");
+ }
if (mExpansionFraction != fraction) {
mExpansionFraction = fraction;
@@ -464,6 +473,10 @@
mCurrentBehindTint = ColorUtils.blendARGB(ScrimState.BOUNCER.getBehindTint(),
mState.getBehindTint(), interpolatedFract);
}
+ if (isNaN(mCurrentBehindAlpha) || isNaN(mCurrentInFrontAlpha)) {
+ throw new IllegalStateException("Scrim opacity is NaN for state: " + mState
+ + ", front: " + mCurrentInFrontAlpha + ", back: " + mCurrentBehindAlpha);
+ }
}
/**
@@ -523,6 +536,10 @@
float newBehindAlpha = mState.getBehindAlpha();
if (mCurrentBehindAlpha != newBehindAlpha) {
mCurrentBehindAlpha = newBehindAlpha;
+ if (isNaN(mCurrentBehindAlpha)) {
+ throw new IllegalStateException("Scrim opacity is NaN for state: " + mState
+ + ", back: " + mCurrentBehindAlpha);
+ }
updateScrims();
}
}
@@ -903,7 +920,9 @@
pw.print(" alpha="); pw.print(mCurrentBehindAlpha);
pw.print(" tint=0x"); pw.println(Integer.toHexString(mScrimBehind.getTint()));
- pw.print(" mTracking="); pw.println(mTracking);
+ pw.print(" mTracking="); pw.println(mTracking);
+
+ pw.print(" mExpansionFraction="); pw.println(mExpansionFraction);
}
public void setWallpaperSupportsAmbientMode(boolean wallpaperSupportsAmbientMode) {
@@ -950,6 +969,10 @@
// in this case, back-scrim needs to be re-evaluated
if (mState == ScrimState.AOD || mState == ScrimState.PULSING) {
float newBehindAlpha = mState.getBehindAlpha();
+ if (isNaN(newBehindAlpha)) {
+ throw new IllegalStateException("Scrim opacity is NaN for state: " + mState
+ + ", back: " + mCurrentBehindAlpha);
+ }
if (mCurrentBehindAlpha != newBehindAlpha) {
mCurrentBehindAlpha = newBehindAlpha;
updateScrims();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ConfigurationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ConfigurationController.java
index 0e5c8c1..0a6cf7b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ConfigurationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ConfigurationController.java
@@ -24,7 +24,11 @@
*/
public interface ConfigurationController extends CallbackController<ConfigurationListener> {
- public void notifyThemeChanged();
+ /** Alert controller of a change in the configuration. */
+ void onConfigurationChanged(Configuration newConfiguration);
+
+ /** Alert controller of a change in between light and dark themes. */
+ void notifyThemeChanged();
interface ConfigurationListener {
default void onConfigChanged(Configuration newConfig) {}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index 7a09455..2ad5a8a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -61,7 +61,6 @@
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.TelephonyIntents;
import com.android.settingslib.net.DataUsageController;
-import com.android.systemui.ConfigurationChangedReceiver;
import com.android.systemui.DemoMode;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
@@ -87,8 +86,7 @@
/** Platform implementation of the network controller. **/
@Singleton
public class NetworkControllerImpl extends BroadcastReceiver
- implements NetworkController, DemoMode, DataUsageController.NetworkNameProvider,
- ConfigurationChangedReceiver, Dumpable {
+ implements NetworkController, DemoMode, DataUsageController.NetworkNameProvider, Dumpable {
// debug
static final String TAG = "NetworkController";
static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
@@ -166,6 +164,14 @@
private boolean mUserSetup;
private boolean mSimDetected;
+ private ConfigurationController.ConfigurationListener mConfigurationListener =
+ new ConfigurationController.ConfigurationListener() {
+ @Override
+ public void onConfigChanged(Configuration newConfig) {
+ mConfig = Config.readConfig(mContext);
+ mReceiverHandler.post(() -> handleConfigurationChanged());
+ }
+ };
/**
* Construct this controller object and register for updates.
*/
@@ -553,16 +559,6 @@
}
}
- public void onConfigurationChanged(Configuration newConfig) {
- mConfig = Config.readConfig(mContext);
- mReceiverHandler.post(new Runnable() {
- @Override
- public void run() {
- handleConfigurationChanged();
- }
- });
- }
-
@VisibleForTesting
void handleConfigurationChanged() {
updateMobileControllers();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/DependencyTest.java b/packages/SystemUI/tests/src/com/android/systemui/DependencyTest.java
index b9d09ce..420acc5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/DependencyTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/DependencyTest.java
@@ -36,8 +36,6 @@
public class DependencyTest extends SysuiTestCase {
public static final DependencyKey<Dumpable> DUMPABLE = new DependencyKey<>("dumpable");
- public static final DependencyKey<ConfigurationChangedReceiver> CONFIGURATION_CHANGED_RECEIVER
- = new DependencyKey<>("config_changed_receiver");
@Test
public void testClassDependency() {
@@ -63,15 +61,6 @@
}
@Test
- public void testConfigurationChanged() {
- ConfigurationChangedReceiver d = mock(ConfigurationChangedReceiver.class);
- mDependency.injectTestDependency(CONFIGURATION_CHANGED_RECEIVER, d);
- Dependency.get(CONFIGURATION_CHANGED_RECEIVER);
- mDependency.onConfigurationChanged(null);
- verify(d).onConfigurationChanged(eq(null));
- }
-
- @Test
public void testInitDependency() {
Dependency.clearDependencies();
Dependency.initDependencies(SystemUIFactory.getInstance().getRootComponent());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeConfigurationController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeConfigurationController.java
index 5ddf7a2..f5ccac3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeConfigurationController.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeConfigurationController.java
@@ -14,6 +14,8 @@
package com.android.systemui.utils.leaks;
+import android.content.res.Configuration;
+
import com.android.systemui.statusbar.policy.ConfigurationController;
public class FakeConfigurationController
@@ -25,6 +27,10 @@
}
@Override
+ public void onConfigurationChanged(Configuration newConfiguration) {
+ }
+
+ @Override
public void notifyThemeChanged() {
}
}
diff --git a/proto/src/wifi.proto b/proto/src/wifi.proto
index 353a187..03495d2 100644
--- a/proto/src/wifi.proto
+++ b/proto/src/wifi.proto
@@ -635,6 +635,66 @@
ROUTER_TECH_OTHER = 6;
}
+ enum EapMethod {
+
+ // No EAP method used
+ TYPE_EAP_UNKNOWN = 0;
+
+ // EAP with Transport Layer Security
+ TYPE_EAP_TLS = 1;
+
+ // EAP with Tunneled Transport Layer Security
+ TYPE_EAP_TTLS = 2;
+
+ // EAP with Subscriber Identity Module [RFC-4186]
+ TYPE_EAP_SIM = 3;
+
+ // EAP with Authentication and Key Agreement [RFC-4187]
+ TYPE_EAP_AKA = 4;
+
+ // EAP with Authentication and Key Agreement Prime [RFC-5448]
+ TYPE_EAP_AKA_PRIME = 5;
+
+ // Protected EAP
+ TYPE_EAP_PEAP = 6;
+
+ // EAP for Hotspot 2.0 r2 OSEN
+ TYPE_EAP_UNAUTH_TLS = 7;
+
+ // EAP with Password
+ TYPE_EAP_PWD = 8;
+
+ // EAP with WAPI certifcate
+ TYPE_EAP_WAPI_CERT = 9;
+ }
+
+ enum AuthPhase2Method {
+
+ // No phase2 method
+ TYPE_PHASE2_NONE = 0;
+
+ // Password Authentication Protocol
+ TYPE_PHASE2_PAP = 1;
+
+ // Microsoft Challenge Handshake Authentication Protocol
+ TYPE_PHASE2_MSCHAP = 2;
+
+ // Microsoft Challenge Handshake Authentication Protocol v2
+ TYPE_PHASE2_MSCHAPV2 = 3;
+
+ // Generic Token Card
+ TYPE_PHASE2_GTC = 4;
+
+ // EAP-Subscriber Identity Module [RFC-4186]
+ TYPE_PHASE2_SIM = 5;
+
+ // EAP-Authentication and Key Agreement [RFC-4187]
+ TYPE_PHASE2_AKA = 6;
+
+ // EAP-Authentication and Key Agreement Prime [RFC-5448]
+ TYPE_PHASE2_AKA_PRIME = 7;
+ }
+
optional RoamType roam_type = 1;
// Channel on which the connection takes place.
@@ -657,6 +717,12 @@
// If the router is a passpoint / hotspot 2.0 network
optional bool passpoint = 8;
+
+ // EAP method used by the enterprise network
+ optional EapMethod eap_method = 9;
+
+ // Phase 2 authentication method after setting up a secure channel
+ optional AuthPhase2Method auth_phase2_method = 10;
}
message ConnectionEvent {
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 3a5d4bc..d7bb4c0 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -1041,6 +1041,27 @@
}
}
+ // Restore capture policies
+ synchronized (mPlaybackMonitor) {
+ HashMap<Integer, Integer> allowedCapturePolicies =
+ mPlaybackMonitor.getAllAllowedCapturePolicies();
+ for (HashMap.Entry<Integer, Integer> entry : allowedCapturePolicies.entrySet()) {
+ int result = AudioSystem.setAllowedCapturePolicy(
+ entry.getKey(),
+ AudioAttributes.capturePolicyToFlags(entry.getValue(), 0x0));
+ if (result != AudioSystem.AUDIO_STATUS_OK) {
+ Log.e(TAG, "Failed to restore capture policy, uid: "
+ + entry.getKey() + ", capture policy: " + entry.getValue()
+ + ", result: " + result);
+ // When restoring capture policy failed, set the capture policy as
+ // ALLOW_CAPTURE_BY_ALL, which will result in removing the cached
+ // capture policy in PlaybackActivityMonitor.
+ mPlaybackMonitor.setAllowedCapturePolicy(
+ entry.getKey(), AudioAttributes.ALLOW_CAPTURE_BY_ALL);
+ }
+ }
+ }
+
onIndicateSystemReady();
// indicate the end of reconfiguration phase to audio HAL
AudioSystem.setParameters("restarting=false");
@@ -7250,6 +7271,43 @@
mPlaybackMonitor.releasePlayer(piid, Binder.getCallingUid());
}
+ /**
+ * Specifies whether the audio played by this app may or may not be captured by other apps or
+ * the system.
+ *
+ * @param capturePolicy one of
+ * {@link AudioAttributes#ALLOW_CAPTURE_BY_ALL},
+ * {@link AudioAttributes#ALLOW_CAPTURE_BY_SYSTEM},
+ * {@link AudioAttributes#ALLOW_CAPTURE_BY_NONE}.
+ * @return AudioSystem.AUDIO_STATUS_OK if set allowed capture policy succeed.
+ * @throws IllegalArgumentException if the argument is not a valid value.
+ */
+ public int setAllowedCapturePolicy(int capturePolicy) {
+ int callingUid = Binder.getCallingUid();
+ int flags = AudioAttributes.capturePolicyToFlags(capturePolicy, 0x0);
+ final long identity = Binder.clearCallingIdentity();
+ synchronized (mPlaybackMonitor) {
+ int result = AudioSystem.setAllowedCapturePolicy(callingUid, flags);
+ if (result == AudioSystem.AUDIO_STATUS_OK) {
+ mPlaybackMonitor.setAllowedCapturePolicy(callingUid, capturePolicy);
+ }
+ Binder.restoreCallingIdentity(identity);
+ return result;
+ }
+ }
+
+ /**
+ * Return the capture policy.
+ * @return the cached capture policy for the calling uid.
+ */
+ public int getAllowedCapturePolicy() {
+ int callingUid = Binder.getCallingUid();
+ final long identity = Binder.clearCallingIdentity();
+ int capturePolicy = mPlaybackMonitor.getAllowedCapturePolicy(callingUid);
+ Binder.restoreCallingIdentity(identity);
+ return capturePolicy;
+ }
+
//======================
// Audio device management
//======================
diff --git a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
index 3a25d98..93ffe83 100644
--- a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
+++ b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
@@ -160,6 +160,12 @@
new AudioPlaybackConfiguration(pic, newPiid,
Binder.getCallingUid(), Binder.getCallingPid());
apc.init();
+ synchronized (mAllowedCapturePolicies) {
+ int uid = apc.getClientUid();
+ if (mAllowedCapturePolicies.containsKey(uid)) {
+ updateAllowedCapturePolicy(apc, mAllowedCapturePolicies.get(uid));
+ }
+ }
sEventLogger.log(new NewPlayerEvent(apc));
synchronized(mPlayerLock) {
mPlayers.put(newPiid, apc);
@@ -169,6 +175,13 @@
public void playerAttributes(int piid, @NonNull AudioAttributes attr, int binderUid) {
final boolean change;
+ synchronized (mAllowedCapturePolicies) {
+ if (mAllowedCapturePolicies.containsKey(binderUid)
+ && attr.getAllowedCapturePolicy() < mAllowedCapturePolicies.get(binderUid)) {
+ attr = new AudioAttributes.Builder(attr)
+ .setAllowedCapturePolicy(mAllowedCapturePolicies.get(binderUid)).build();
+ }
+ }
synchronized(mPlayerLock) {
final AudioPlaybackConfiguration apc = mPlayers.get(new Integer(piid));
if (checkConfigurationCaller(piid, apc, binderUid)) {
@@ -284,6 +297,69 @@
}
}
+ /**
+ * A map of uid to capture policy.
+ */
+ private final HashMap<Integer, Integer> mAllowedCapturePolicies =
+ new HashMap<Integer, Integer>();
+
+ /**
+ * Cache allowed capture policy, which specifies whether the audio played by the app may or may
+ * not be captured by other apps or the system.
+ *
+ * @param uid the uid of requested app
+ * @param capturePolicy one of
+ * {@link AudioAttributes#ALLOW_CAPTURE_BY_ALL},
+ * {@link AudioAttributes#ALLOW_CAPTURE_BY_SYSTEM},
+ * {@link AudioAttributes#ALLOW_CAPTURE_BY_NONE}.
+ */
+ public void setAllowedCapturePolicy(int uid, int capturePolicy) {
+ synchronized (mAllowedCapturePolicies) {
+ if (capturePolicy == AudioAttributes.ALLOW_CAPTURE_BY_ALL) {
+ // When the capture policy is ALLOW_CAPTURE_BY_ALL, it is okay to
+ // remove it from cached capture policy as it is the default value.
+ mAllowedCapturePolicies.remove(uid);
+ return;
+ } else {
+ mAllowedCapturePolicies.put(uid, capturePolicy);
+ }
+ }
+ synchronized (mPlayerLock) {
+ for (AudioPlaybackConfiguration apc : mPlayers.values()) {
+ if (apc.getClientUid() == uid) {
+ updateAllowedCapturePolicy(apc, capturePolicy);
+ }
+ }
+ }
+ }
+
+ /**
+ * Return the capture policy for given uid.
+ * @param uid the uid to query its cached capture policy.
+ * @return cached capture policy for given uid or AudioAttributes.ALLOW_CAPTURE_BY_ALL
+ * if there is not cached capture policy.
+ */
+ public int getAllowedCapturePolicy(int uid) {
+ return mAllowedCapturePolicies.getOrDefault(uid, AudioAttributes.ALLOW_CAPTURE_BY_ALL);
+ }
+
+ /**
+ * Return all cached capture policies.
+ */
+ public HashMap<Integer, Integer> getAllAllowedCapturePolicies() {
+ return mAllowedCapturePolicies;
+ }
+
+ private void updateAllowedCapturePolicy(AudioPlaybackConfiguration apc, int capturePolicy) {
+ AudioAttributes attr = apc.getAudioAttributes();
+ if (attr.getAllowedCapturePolicy() >= capturePolicy) {
+ return;
+ }
+ apc.handleAudioAttributesEvent(
+ new AudioAttributes.Builder(apc.getAudioAttributes())
+ .setAllowedCapturePolicy(capturePolicy).build());
+ }
+
// Implementation of AudioPlaybackConfiguration.PlayerDeathMonitor
@Override
public void playerDeath(int piid) {
@@ -331,6 +407,12 @@
// log
sEventLogger.dump(pw);
}
+ synchronized (mAllowedCapturePolicies) {
+ pw.println("\n allowed capture policies:");
+ for (HashMap.Entry<Integer, Integer> entry : mAllowedCapturePolicies.entrySet()) {
+ pw.println(" uid: " + entry.getKey() + " policy: " + entry.getValue());
+ }
+ }
}
/**
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index c4acff4..5011168 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -21260,6 +21260,11 @@
long token = Binder.clearCallingIdentity();
try {
if (getPackageInfo(packageName, MATCH_FACTORY_ONLY, UserHandle.USER_SYSTEM) == null) {
+ PackageInfo packageInfo = getPackageInfo(packageName, 0, UserHandle.USER_SYSTEM);
+ if (packageInfo != null) {
+ EventLog.writeEvent(0x534e4554, "145981139", packageInfo.applicationInfo.uid,
+ "");
+ }
return null;
}
} finally {
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java b/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java
index f78d263..add0b01 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java
@@ -19,8 +19,6 @@
import android.app.ActivityManager;
import android.content.Context;
import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.security.keystore.IKeystoreService;
import android.util.Slog;
import com.android.internal.policy.IKeyguardService;
@@ -53,16 +51,11 @@
private final LockPatternUtils mLockPatternUtils;
private final StateCallback mCallback;
- IKeystoreService mKeystoreService;
-
public KeyguardStateMonitor(Context context, IKeyguardService service, StateCallback callback) {
mLockPatternUtils = new LockPatternUtils(context);
mCurrentUserId = ActivityManager.getCurrentUser();
mCallback = callback;
- mKeystoreService = IKeystoreService.Stub.asInterface(ServiceManager
- .getService("android.security.keystore"));
-
try {
service.addStateMonitorCallback(this);
} catch (RemoteException e) {
@@ -95,23 +88,6 @@
mIsShowing = showing;
mCallback.onShowingChanged();
- int retry = 2;
- while (retry > 0) {
- try {
- mKeystoreService.onKeyguardVisibilityChanged(showing, mCurrentUserId);
- break;
- } catch (RemoteException e) {
- if (retry == 2) {
- Slog.w(TAG, "Error informing keystore of screen lock. Keystore may have died"
- + " -> refreshing service token and retrying");
- mKeystoreService = IKeystoreService.Stub.asInterface(ServiceManager
- .getService("android.security.keystore"));
- } else {
- Slog.e(TAG, "Error informing keystore of screen lock after retrying once", e);
- }
- --retry;
- }
- }
}
@Override // Binder interface
@@ -123,10 +99,6 @@
mCurrentUserId = userId;
}
- private synchronized int getCurrentUser() {
- return mCurrentUserId;
- }
-
@Override // Binder interface
public void onInputRestrictedStateChanged(boolean inputRestricted) {
mInputRestricted = inputRestricted;
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index ef54d04..2394baf 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -53,6 +53,7 @@
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
+import android.security.KeyStore;
import android.service.trust.TrustAgentService;
import android.text.TextUtils;
import android.util.ArrayMap;
@@ -135,6 +136,33 @@
@GuardedBy("mUserIsTrusted")
private final SparseBooleanArray mUserIsTrusted = new SparseBooleanArray();
+ /**
+ * Stores the locked state for users on the device. There are three different type of users
+ * which are handled slightly differently:
+ * <ul>
+ * <li> Users with real keyguard
+ * These are users who can be switched to ({@link UserInfo#supportsSwitchToByUser()}). Their
+ * locked state is derived by a combination of user secure state, keyguard state, trust agent
+ * decision and biometric authentication result. These are updated via
+ * {@link #refreshDeviceLockedForUser(int)} and result stored in {@link #mDeviceLockedForUser}.
+ * <li> Managed profiles with unified challenge
+ * Managed profile with unified challenge always shares the same locked state as their parent,
+ * so their locked state is not recorded in {@link #mDeviceLockedForUser}. Instead,
+ * {@link ITrustManager#isDeviceLocked(int)} always resolves their parent user handle and
+ * queries its locked state instead.
+ * <li> Managed profiles with separate challenge
+ * Locked state for profile with separate challenge is determined by other parts of the
+ * framework (mostly PowerManager) and pushed to TrustManagerService via
+ * {@link ITrustManager#setDeviceLockedForUser(int, boolean)}. Although in a corner case when
+ * the profile has a separate but empty challenge, setting its {@link #mDeviceLockedForUser} to
+ * {@code false} is actually done by {@link #refreshDeviceLockedForUser(int)}.
+ * </ul>
+ * TODO: Rename {@link ITrustManager#setDeviceLockedForUser(int, boolean)} to
+ * {@code setDeviceLockedForProfile} to better reflect its purpose. Unifying
+ * {@code setDeviceLockedForProfile} and {@link #setDeviceLockedForUser} would also be nice.
+ * At the moment they both update {@link #mDeviceLockedForUser} but have slightly different
+ * side-effects: one notifies trust agents while the other sends out a broadcast.
+ */
@GuardedBy("mDeviceLockedForUser")
private final SparseBooleanArray mDeviceLockedForUser = new SparseBooleanArray();
@@ -601,6 +629,10 @@
}
}
+ /**
+ * Update the user's locked state. Only applicable to users with a real keyguard
+ * ({@link UserInfo#supportsSwitchToByUser}) and unsecured managed profiles.
+ */
private void refreshDeviceLockedForUser(int userId) {
if (userId != UserHandle.USER_ALL && userId < UserHandle.USER_SYSTEM) {
Log.e(TAG, "refreshDeviceLockedForUser(userId=" + userId + "): Invalid user handle,"
@@ -661,6 +693,15 @@
}
if (changed) {
dispatchDeviceLocked(userId, locked);
+
+ KeyStore.getInstance().onUserLockedStateChanged(userId, locked);
+ // Also update the user's profiles who have unified challenge, since they
+ // share the same unlocked state (see {@link #isDeviceLocked(int)})
+ for (int profileHandle : mUserManager.getEnabledProfileIds(userId)) {
+ if (mLockPatternUtils.isManagedProfileWithUnifiedChallenge(profileHandle)) {
+ KeyStore.getInstance().onUserLockedStateChanged(profileHandle, locked);
+ }
+ }
}
}
@@ -1194,6 +1235,10 @@
return "0x" + Integer.toHexString(i);
}
+ /**
+ * Changes the lock status for the given user. This is only applicable to managed profiles,
+ * other users should be handled by Keyguard.
+ */
@Override
public void setDeviceLockedForUser(int userId, boolean locked) {
enforceReportPermission();
@@ -1204,6 +1249,9 @@
synchronized (mDeviceLockedForUser) {
mDeviceLockedForUser.put(userId, locked);
}
+
+ KeyStore.getInstance().onUserLockedStateChanged(userId, locked);
+
if (locked) {
try {
ActivityManager.getService().notifyLockedProfile(userId);
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index ed41642..88f2bb2 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -2113,15 +2113,23 @@
throw new IllegalStateException("Not an EAP network");
}
- return trimStringForKeyId(SSID) + "_" + keyMgmt + "_" +
- trimStringForKeyId(enterpriseConfig.getKeyId(current != null ?
- current.enterpriseConfig : null));
+ String keyId = trimStringForKeyId(SSID) + "_" + keyMgmt + "_"
+ + trimStringForKeyId(enterpriseConfig.getKeyId(current != null
+ ? current.enterpriseConfig : null));
+
+ if (!fromWifiNetworkSuggestion) {
+ return keyId;
+ }
+ return keyId + "_" + trimStringForKeyId(BSSID) + "_" + trimStringForKeyId(creatorName);
} catch (NullPointerException e) {
throw new IllegalStateException("Invalid config details");
}
}
private String trimStringForKeyId(String string) {
+ if (string == null) {
+ return "";
+ }
// Remove quotes and spaces
return string.replace("\"", "").replace(" ", "");
}
diff --git a/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java b/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java
index ba9fc78..f56cdc3 100644
--- a/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java
@@ -350,6 +350,67 @@
}
/**
+ * Verifies that getKeyIdForCredentials returns the expected string for Suggestion Enterprise
+ * networks
+ * @throws Exception
+ */
+ @Test
+ public void testGetKeyIdForCredentialsForSuggestion() throws Exception {
+ WifiConfiguration config = new WifiConfiguration();
+ final String mSsid = "TestAP";
+ final String packageName = "TestApp";
+ final String bSsid = MacAddress.createRandomUnicastAddress().toString();
+ String suggestionSuffix = "_" + bSsid + "_" + packageName;
+ config.SSID = mSsid;
+ config.fromWifiNetworkSuggestion = true;
+ config.creatorName = packageName;
+ config.BSSID = bSsid;
+
+ // Test various combinations
+ // EAP with TLS
+ config.allowedKeyManagement.set(KeyMgmt.WPA_EAP);
+ config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS);
+ config.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.NONE);
+ String keyId = config.getKeyIdForCredentials(config);
+ assertEquals(keyId, mSsid + "_WPA_EAP_TLS_NULL" + suggestionSuffix);
+
+ // EAP with TTLS & MSCHAPv2
+ config.allowedKeyManagement.set(KeyMgmt.WPA_EAP);
+ config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TTLS);
+ config.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.MSCHAPV2);
+ keyId = config.getKeyIdForCredentials(config);
+ assertEquals(keyId, mSsid + "_WPA_EAP_TTLS_MSCHAPV2" + suggestionSuffix);
+
+ // Suite-B 192 with PWD & GTC
+ config.allowedKeyManagement.clear();
+ config.allowedKeyManagement.set(KeyMgmt.SUITE_B_192);
+ config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.PWD);
+ config.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.GTC);
+ keyId = config.getKeyIdForCredentials(config);
+ assertEquals(keyId, mSsid + "_SUITE_B_192_PWD_GTC" + suggestionSuffix);
+
+ // IEEE8021X with SIM
+ config.allowedKeyManagement.clear();
+ config.allowedKeyManagement.set(KeyMgmt.IEEE8021X);
+ config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.SIM);
+ config.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.NONE);
+ keyId = config.getKeyIdForCredentials(config);
+ assertEquals(keyId, mSsid + "_IEEE8021X_SIM_NULL" + suggestionSuffix);
+
+ // Try calling this method with non-Enterprise network, expect an exception
+ boolean exceptionThrown = false;
+ try {
+ config.allowedKeyManagement.clear();
+ config.allowedKeyManagement.set(KeyMgmt.WPA2_PSK);
+ config.preSharedKey = "TestPsk";
+ keyId = config.getKeyIdForCredentials(config);
+ } catch (IllegalStateException e) {
+ exceptionThrown = true;
+ }
+ assertTrue(exceptionThrown);
+ }
+
+ /**
* Verifies that getSsidAndSecurityTypeString returns the correct String for networks of
* various different security types
*/