summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apct-tests/perftests/autofill/AndroidManifest.xml10
-rw-r--r--cmds/idmap2/OWNERS1
-rw-r--r--core/java/android/app/admin/DevicePolicyManagerInternal.java8
-rw-r--r--core/java/android/content/integrity/OWNERS2
-rw-r--r--core/java/android/content/om/OWNERS2
-rw-r--r--core/java/android/content/pm/OWNERS4
-rw-r--r--core/java/android/content/pm/dex/OWNERS2
-rw-r--r--core/java/android/content/pm/parsing/OWNERS1
-rw-r--r--core/java/android/content/pm/permission/OWNERS2
-rw-r--r--core/java/android/content/pm/split/OWNERS2
-rw-r--r--core/java/android/content/pm/verify/domain/OWNERS1
-rw-r--r--core/java/android/content/res/OWNERS2
-rw-r--r--core/java/android/hardware/OWNERS2
-rw-r--r--core/java/android/os/incremental/OWNERS1
-rw-r--r--core/java/android/view/ViewRootImpl.java36
-rw-r--r--core/java/android/window/SplashScreen.java3
-rw-r--r--core/java/android/window/SplashScreenView.java9
-rw-r--r--core/java/com/android/internal/infra/OWNERS6
-rw-r--r--core/java/com/android/internal/util/OWNERS1
-rw-r--r--core/java/com/android/internal/util/function/pooled/OWNERS1
-rw-r--r--core/java/com/android/server/OWNERS2
-rw-r--r--core/jni/OWNERS4
-rw-r--r--core/proto/OWNERS3
-rw-r--r--core/res/OWNERS1
-rw-r--r--data/etc/OWNERS2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java9
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java35
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java12
-rw-r--r--libs/androidfw/OWNERS1
-rw-r--r--media/java/android/media/IMediaRouterService.aidl1
-rw-r--r--media/java/android/media/MediaRouter.java3
-rw-r--r--mms/OWNERS1
-rw-r--r--native/android/OWNERS2
-rw-r--r--packages/CarrierDefaultApp/OWNERS1
-rw-r--r--packages/CtsShim/OWNERS1
-rw-r--r--packages/Shell/OWNERS1
-rw-r--r--packages/SystemUI/res/layout/internet_connectivity_dialog.xml40
-rw-r--r--packages/SystemUI/res/values/strings.xml2
-rw-r--r--packages/SystemUI/src/com/android/systemui/ScreenDecorations.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AnnotationLinkSpan.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java79
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java42
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogFactory.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt29
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java35
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java81
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java20
-rw-r--r--proto/src/metrics_constants/OWNERS1
-rw-r--r--services/OWNERS2
-rw-r--r--services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java52
-rw-r--r--services/core/java/com/android/server/am/OWNERS1
-rw-r--r--services/core/java/com/android/server/devicestate/OWNERS1
-rw-r--r--services/core/java/com/android/server/media/MediaRouterService.java19
-rw-r--r--services/core/java/com/android/server/om/OverlayManagerService.java18
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerService.java53
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerSession.java4
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java4
-rw-r--r--services/core/java/com/android/server/pm/verify/domain/OWNERS1
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java6
-rw-r--r--services/core/java/com/android/server/policy/WindowManagerPolicy.java14
-rw-r--r--services/core/java/com/android/server/stats/OWNERS1
-rw-r--r--services/core/java/com/android/server/wm/AppTransition.java4
-rw-r--r--services/core/java/com/android/server/wm/DisplayPolicy.java17
-rw-r--r--services/core/java/com/android/server/wm/RootWindowContainer.java3
-rw-r--r--services/core/java/com/android/server/wm/WallpaperController.java3
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java10
-rw-r--r--services/core/jni/stats/OWNERS2
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java7
-rw-r--r--services/incremental/OWNERS1
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/usage/UserUsageStatsServiceTest.java2
-rw-r--r--services/usage/java/com/android/server/usage/UsageStatsService.java26
-rw-r--r--services/usage/java/com/android/server/usage/UserUsageStatsService.java10
-rw-r--r--services/uwb/java/com/android/server/uwb/UwbServiceImpl.java2
-rw-r--r--telephony/OWNERS1
-rw-r--r--telephony/java/android/telephony/CarrierConfigManager.java16
-rw-r--r--tests/Codegen/OWNERS1
-rw-r--r--tools/aapt2/OWNERS1
-rw-r--r--tools/codegen/OWNERS1
81 files changed, 658 insertions, 158 deletions
diff --git a/apct-tests/perftests/autofill/AndroidManifest.xml b/apct-tests/perftests/autofill/AndroidManifest.xml
index 57595a213d20..de2a3f2c4bfc 100644
--- a/apct-tests/perftests/autofill/AndroidManifest.xml
+++ b/apct-tests/perftests/autofill/AndroidManifest.xml
@@ -16,6 +16,16 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.perftests.autofill">
+ <uses-permission android:name="android.permission.CONTROL_KEYGUARD" />
+ <uses-permission android:name="android.permission.DEVICE_POWER" />
+ <uses-permission android:name="android.permission.INSTALL_PACKAGES" />
+ <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
+ <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
+ <uses-permission android:name="android.permission.MANAGE_USERS" />
+ <uses-permission android:name="android.permission.REAL_GET_TASKS" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
+
<application>
<uses-library android:name="android.test.runner" />
<activity android:name="android.perftests.utils.PerfTestActivity"
diff --git a/cmds/idmap2/OWNERS b/cmds/idmap2/OWNERS
index def9f401e51f..062ffd41348a 100644
--- a/cmds/idmap2/OWNERS
+++ b/cmds/idmap2/OWNERS
@@ -1,3 +1,4 @@
set noparent
+toddke@google.com
patb@google.com
zyy@google.com
diff --git a/core/java/android/app/admin/DevicePolicyManagerInternal.java b/core/java/android/app/admin/DevicePolicyManagerInternal.java
index a0d2977cf09a..01875eda2eca 100644
--- a/core/java/android/app/admin/DevicePolicyManagerInternal.java
+++ b/core/java/android/app/admin/DevicePolicyManagerInternal.java
@@ -16,6 +16,7 @@
package android.app.admin;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.content.ComponentName;
@@ -77,6 +78,13 @@ public abstract class DevicePolicyManagerInternal {
OnCrossProfileWidgetProvidersChangeListener listener);
/**
+ * @param userHandle the handle of the user whose profile owner is being fetched.
+ * @return the configured supervision app if it exists and is the device owner or policy owner.
+ */
+ public abstract @Nullable ComponentName getProfileOwnerOrDeviceOwnerSupervisionComponent(
+ @NonNull UserHandle userHandle);
+
+ /**
* Checks if an app with given uid is an active device owner of its user.
*
* <p>This takes the DPMS lock. DO NOT call from PM/UM/AM with their lock held.
diff --git a/core/java/android/content/integrity/OWNERS b/core/java/android/content/integrity/OWNERS
index a1fe59c862d2..20c758aedd67 100644
--- a/core/java/android/content/integrity/OWNERS
+++ b/core/java/android/content/integrity/OWNERS
@@ -1,3 +1,5 @@
# Bug component: 722021
+toddke@android.com
+toddke@google.com
patb@google.com
diff --git a/core/java/android/content/om/OWNERS b/core/java/android/content/om/OWNERS
index 9c473360a46a..3669817e9844 100644
--- a/core/java/android/content/om/OWNERS
+++ b/core/java/android/content/om/OWNERS
@@ -1,4 +1,6 @@
# Bug component: 568631
+toddke@android.com
+toddke@google.com
patb@google.com
zyy@google.com
diff --git a/core/java/android/content/pm/OWNERS b/core/java/android/content/pm/OWNERS
index 128bfb99ccd4..4e674f6ec9a8 100644
--- a/core/java/android/content/pm/OWNERS
+++ b/core/java/android/content/pm/OWNERS
@@ -1,9 +1,11 @@
# Bug component: 36137
+toddke@android.com
+toddke@google.com
patb@google.com
per-file PackageParser.java = set noparent
-per-file PackageParser.java = chiuwinson@google.com,patb@google.com
+per-file PackageParser.java = chiuwinson@google.com,patb@google.com,toddke@google.com
per-file *Shortcut* = file:/core/java/android/content/pm/SHORTCUT_OWNERS
per-file AppSearchPerson.java = file:/core/java/android/content/pm/SHORTCUT_OWNERS
per-file *Launcher* = file:/core/java/android/content/pm/LAUNCHER_OWNERS
diff --git a/core/java/android/content/pm/dex/OWNERS b/core/java/android/content/pm/dex/OWNERS
index b590f659a5d4..267e5d58f9a6 100644
--- a/core/java/android/content/pm/dex/OWNERS
+++ b/core/java/android/content/pm/dex/OWNERS
@@ -1,5 +1,7 @@
# Bug component: 86431
+toddke@android.com
+toddke@google.com
patb@google.com
calin@google.com
ngeoffray@google.com
diff --git a/core/java/android/content/pm/parsing/OWNERS b/core/java/android/content/pm/parsing/OWNERS
index 445a8330037b..8049d5cb7fa2 100644
--- a/core/java/android/content/pm/parsing/OWNERS
+++ b/core/java/android/content/pm/parsing/OWNERS
@@ -2,3 +2,4 @@
chiuwinson@google.com
patb@google.com
+toddke@google.com
diff --git a/core/java/android/content/pm/permission/OWNERS b/core/java/android/content/pm/permission/OWNERS
index f9c51dd2ae58..cf7e6890876a 100644
--- a/core/java/android/content/pm/permission/OWNERS
+++ b/core/java/android/content/pm/permission/OWNERS
@@ -2,5 +2,7 @@
include platform/frameworks/base:/core/java/android/permission/OWNERS
+toddke@android.com
+toddke@google.com
patb@google.com
diff --git a/core/java/android/content/pm/split/OWNERS b/core/java/android/content/pm/split/OWNERS
index b8fa1a93ed78..3d126d297e60 100644
--- a/core/java/android/content/pm/split/OWNERS
+++ b/core/java/android/content/pm/split/OWNERS
@@ -1,3 +1,5 @@
# Bug component: 36137
+toddke@android.com
+toddke@google.com
patb@google.com
diff --git a/core/java/android/content/pm/verify/domain/OWNERS b/core/java/android/content/pm/verify/domain/OWNERS
index 445a8330037b..c669112e0512 100644
--- a/core/java/android/content/pm/verify/domain/OWNERS
+++ b/core/java/android/content/pm/verify/domain/OWNERS
@@ -2,3 +2,4 @@
chiuwinson@google.com
patb@google.com
+toddke@google.com \ No newline at end of file
diff --git a/core/java/android/content/res/OWNERS b/core/java/android/content/res/OWNERS
index 7460a14182e5..d12d920b2a54 100644
--- a/core/java/android/content/res/OWNERS
+++ b/core/java/android/content/res/OWNERS
@@ -1,4 +1,6 @@
# Bug component: 568761
+toddke@android.com
+toddke@google.com
patb@google.com
zyy@google.com
diff --git a/core/java/android/hardware/OWNERS b/core/java/android/hardware/OWNERS
index 75b42d4b64e1..2b4e4a106cec 100644
--- a/core/java/android/hardware/OWNERS
+++ b/core/java/android/hardware/OWNERS
@@ -1,5 +1,5 @@
# Camera
-per-file *Camera*=cychen@google.com,epeev@google.com,etalvala@google.com,shuzhenwang@google.com,zhijunhe@google.com,jchowdhary@google.com
+per-file *Camera*=cychen@google.com,epeev@google.com,etalvala@google.com,shuzhenwang@google.com,yinchiayeh@google.com,zhijunhe@google.com,jchowdhary@google.com
# Sensor Privacy
per-file *SensorPrivacy* = file:platform/frameworks/native:/libs/sensorprivacy/OWNERS
diff --git a/core/java/android/os/incremental/OWNERS b/core/java/android/os/incremental/OWNERS
index 363486905c93..47eee6406206 100644
--- a/core/java/android/os/incremental/OWNERS
+++ b/core/java/android/os/incremental/OWNERS
@@ -1,5 +1,6 @@
# Bug component: 554432
alexbuy@google.com
schfan@google.com
+toddke@google.com
zyy@google.com
patb@google.com
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 0ecd76f82a8a..5c09640e1785 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -800,11 +800,7 @@ public final class ViewRootImpl implements ViewParent,
context);
mCompatibleVisibilityInfo = new SystemUiVisibilityInfo();
mAccessibilityManager = AccessibilityManager.getInstance(context);
- mAccessibilityManager.addAccessibilityStateChangeListener(
- mAccessibilityInteractionConnectionManager, mHandler);
mHighContrastTextManager = new HighContrastTextManager();
- mAccessibilityManager.addHighTextContrastStateChangeListener(
- mHighContrastTextManager, mHandler);
mViewConfiguration = ViewConfiguration.get(context);
mDensity = context.getResources().getDisplayMetrics().densityDpi;
mNoncompatDensity = context.getResources().getDisplayMetrics().noncompatDensityDpi;
@@ -1004,8 +1000,6 @@ public final class ViewRootImpl implements ViewParent,
mView = view;
mAttachInfo.mDisplayState = mDisplay.getState();
- mDisplayManager.registerDisplayListener(mDisplayListener, mHandler);
-
mViewLayoutDirectionInitial = mView.getRawLayoutDirection();
mFallbackEventHandler.setView(view);
mWindowAttributes.copyFrom(attrs);
@@ -1198,6 +1192,7 @@ public final class ViewRootImpl implements ViewParent,
"Unable to add window -- unknown error code " + res);
}
+ registerListeners();
if ((res & WindowManagerGlobal.ADD_FLAG_USE_BLAST) != 0) {
mUseBLASTAdapter = true;
}
@@ -1254,6 +1249,28 @@ public final class ViewRootImpl implements ViewParent,
}
}
+ /**
+ * Register any kind of listeners if setView was success.
+ */
+ private void registerListeners() {
+ mAccessibilityManager.addAccessibilityStateChangeListener(
+ mAccessibilityInteractionConnectionManager, mHandler);
+ mAccessibilityManager.addHighTextContrastStateChangeListener(
+ mHighContrastTextManager, mHandler);
+ mDisplayManager.registerDisplayListener(mDisplayListener, mHandler);
+ }
+
+ /**
+ * Unregister all listeners while detachedFromWindow.
+ */
+ private void unregisterListeners() {
+ mAccessibilityManager.removeAccessibilityStateChangeListener(
+ mAccessibilityInteractionConnectionManager);
+ mAccessibilityManager.removeHighTextContrastStateChangeListener(
+ mHighContrastTextManager);
+ mDisplayManager.unregisterDisplayListener(mDisplayListener);
+ }
+
private void setTag() {
final String[] split = mWindowAttributes.getTitle().toString().split("\\.");
if (split.length > 0) {
@@ -4979,10 +4996,6 @@ public final class ViewRootImpl implements ViewParent,
}
mAccessibilityInteractionConnectionManager.ensureNoConnection();
- mAccessibilityManager.removeAccessibilityStateChangeListener(
- mAccessibilityInteractionConnectionManager);
- mAccessibilityManager.removeHighTextContrastStateChangeListener(
- mHighContrastTextManager);
removeSendWindowContentChangedCallback();
destroyHardwareRenderer();
@@ -5015,8 +5028,7 @@ public final class ViewRootImpl implements ViewParent,
mInputEventReceiver = null;
}
- mDisplayManager.unregisterDisplayListener(mDisplayListener);
-
+ unregisterListeners();
unscheduleTraversals();
}
diff --git a/core/java/android/window/SplashScreen.java b/core/java/android/window/SplashScreen.java
index 3e0075857402..0c4d273f6ce8 100644
--- a/core/java/android/window/SplashScreen.java
+++ b/core/java/android/window/SplashScreen.java
@@ -92,6 +92,9 @@ public interface SplashScreen {
* overrides and persists the theme used for the {@link SplashScreen} of this application.
* <p>
* To reset to the default theme, set this the themeId to {@link Resources#ID_NULL}.
+ * <p>
+ * <b>Note:</b> The theme name must be stable across versions, otherwise it won't be found
+ * after your application is updated.
*/
void setSplashScreenTheme(@StyleRes int themeId);
diff --git a/core/java/android/window/SplashScreenView.java b/core/java/android/window/SplashScreenView.java
index acf20d701eeb..6a875d1be65d 100644
--- a/core/java/android/window/SplashScreenView.java
+++ b/core/java/android/window/SplashScreenView.java
@@ -316,7 +316,8 @@ public final class SplashScreenView extends FrameLayout {
}
private SurfaceView createSurfaceView(@NonNull SplashScreenView view) {
- final SurfaceView surfaceView = new SurfaceView(view.getContext());
+ final Context viewContext = view.getContext();
+ final SurfaceView surfaceView = new SurfaceView(viewContext);
surfaceView.setPadding(0, 0, 0, 0);
surfaceView.setBackground(mIconBackground);
if (mSurfacePackage == null) {
@@ -326,10 +327,10 @@ public final class SplashScreenView extends FrameLayout {
+ Thread.currentThread().getId());
}
- SurfaceControlViewHost viewHost = new SurfaceControlViewHost(mContext,
- mContext.getDisplay(),
+ SurfaceControlViewHost viewHost = new SurfaceControlViewHost(viewContext,
+ viewContext.getDisplay(),
surfaceView.getHostToken());
- ImageView imageView = new ImageView(mContext);
+ ImageView imageView = new ImageView(viewContext);
imageView.setBackground(mIconDrawable);
viewHost.setView(imageView, mIconSize, mIconSize);
SurfaceControlViewHost.SurfacePackage surfacePackage = viewHost.getSurfacePackage();
diff --git a/core/java/com/android/internal/infra/OWNERS b/core/java/com/android/internal/infra/OWNERS
index e69de29bb2d1..45503582b2c5 100644
--- a/core/java/com/android/internal/infra/OWNERS
+++ b/core/java/com/android/internal/infra/OWNERS
@@ -0,0 +1,6 @@
+per-file AndroidFuture.java = eugenesusla@google.com
+per-file RemoteStream.java = eugenesusla@google.com
+per-file PerUser.java = eugenesusla@google.com
+per-file ServiceConnector.java = eugenesusla@google.com
+per-file AndroidFuture.aidl = eugenesusla@google.com
+per-file IAndroidFuture.aidl = eugenesusla@google.com \ No newline at end of file
diff --git a/core/java/com/android/internal/util/OWNERS b/core/java/com/android/internal/util/OWNERS
index 2b7f8b2749fd..100a605dc175 100644
--- a/core/java/com/android/internal/util/OWNERS
+++ b/core/java/com/android/internal/util/OWNERS
@@ -4,3 +4,4 @@ per-file *Notification* = file:/services/core/java/com/android/server/notificati
per-file *ContrastColor* = file:/services/core/java/com/android/server/notification/OWNERS
per-file Protocol* = etancohen@google.com, lorenzo@google.com
per-file State* = jchalard@google.com, lorenzo@google.com, satk@google.com
+per-file DataClass* = eugenesusla@google.com \ No newline at end of file
diff --git a/core/java/com/android/internal/util/function/pooled/OWNERS b/core/java/com/android/internal/util/function/pooled/OWNERS
index e69de29bb2d1..da723b3b67da 100644
--- a/core/java/com/android/internal/util/function/pooled/OWNERS
+++ b/core/java/com/android/internal/util/function/pooled/OWNERS
@@ -0,0 +1 @@
+eugenesusla@google.com \ No newline at end of file
diff --git a/core/java/com/android/server/OWNERS b/core/java/com/android/server/OWNERS
index 81bad6a4ba69..554e27890476 100644
--- a/core/java/com/android/server/OWNERS
+++ b/core/java/com/android/server/OWNERS
@@ -1 +1 @@
-per-file SystemConfig.java = patb@google.com
+per-file SystemConfig.java = toddke@google.com,patb@google.com
diff --git a/core/jni/OWNERS b/core/jni/OWNERS
index eef705420173..da896636aaa8 100644
--- a/core/jni/OWNERS
+++ b/core/jni/OWNERS
@@ -1,9 +1,9 @@
# Camera
per-file *Camera*,*camera* = cychen@google.com, epeev@google.com, etalvala@google.com
-per-file *Camera*,*camera* = shuzhenwang@google.com, zhijunhe@google.com
+per-file *Camera*,*camera* = shuzhenwang@google.com, yinchiayeh@google.com, zhijunhe@google.com
# Connectivity
-per-file android_net_* = jchalard@google.com, lorenzo@google.com, reminv@google.com, satk@google.com
+per-file android_net_* = codewiz@google.com, jchalard@google.com, lorenzo@google.com, reminv@google.com, satk@google.com
# CPU
per-file *Cpu* = file:/core/java/com/android/internal/os/CPU_OWNERS
diff --git a/core/proto/OWNERS b/core/proto/OWNERS
index 931ef4478098..78650ed34813 100644
--- a/core/proto/OWNERS
+++ b/core/proto/OWNERS
@@ -5,6 +5,7 @@ joeo@google.com
singhtejinder@google.com
yanmin@google.com
yaochen@google.com
+yro@google.com
zhouwenjie@google.com
# Frameworks
@@ -12,7 +13,7 @@ ogunwale@google.com
jjaggi@google.com
kwekua@google.com
roosa@google.com
-per-file package_item_info.proto = patb@google.com
+per-file package_item_info.proto = toddke@google.com,patb@google.com
per-file usagestatsservice.proto, usagestatsservice_v2.proto = file:/core/java/android/app/usage/OWNERS
per-file apphibernationservice.proto = file:/core/java/android/apphibernation/OWNERS
diff --git a/core/res/OWNERS b/core/res/OWNERS
index e241dd6e3615..165dcad896c9 100644
--- a/core/res/OWNERS
+++ b/core/res/OWNERS
@@ -22,6 +22,7 @@ patb@google.com
shanh@google.com
svetoslavganov@android.com
svetoslavganov@google.com
+toddke@google.com
tsuji@google.com
yamasani@google.com
diff --git a/data/etc/OWNERS b/data/etc/OWNERS
index 2c93d5abc155..ea23aba16d12 100644
--- a/data/etc/OWNERS
+++ b/data/etc/OWNERS
@@ -8,6 +8,8 @@ jsharkey@google.com
lorenzo@google.com
svetoslavganov@android.com
svetoslavganov@google.com
+toddke@android.com
+toddke@google.com
patb@google.com
yamasani@google.com
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
index 29326ec90e31..cdd745ff9794 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
@@ -50,6 +50,7 @@ import android.os.Trace;
import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.Slog;
+import android.view.ContextThemeWrapper;
import android.view.SurfaceControl;
import android.view.View;
import android.window.SplashScreenView;
@@ -299,6 +300,11 @@ public class SplashscreenContentDrawer {
}
}
+ /** Creates the wrapper with system theme to avoid unexpected styles from app. */
+ ContextThemeWrapper createViewContextWrapper(Context appContext) {
+ return new ContextThemeWrapper(appContext, mContext.getTheme());
+ }
+
/** The configuration of the splash screen window. */
public static class SplashScreenWindowAttrs {
private int mWindowBgResId = 0;
@@ -472,7 +478,8 @@ public class SplashscreenContentDrawer {
}
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "fillViewWithIcon");
- final SplashScreenView.Builder builder = new SplashScreenView.Builder(mContext)
+ final ContextThemeWrapper wrapper = createViewContextWrapper(mContext);
+ final SplashScreenView.Builder builder = new SplashScreenView.Builder(wrapper)
.setBackgroundColor(mThemeColor)
.setOverlayDrawable(mOverlayDrawable)
.setIconSize(iconSize)
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
index 147f5e30f9d6..4dae63485f8c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
@@ -137,24 +137,11 @@ public class StartingSurfaceDrawer {
private final SparseArray<SurfaceControlViewHost> mAnimatedSplashScreenSurfaceHosts =
new SparseArray<>(1);
- /** Obtain proper context for showing splash screen on the provided display. */
- private Context getDisplayContext(Context context, int displayId) {
- if (displayId == DEFAULT_DISPLAY) {
- // The default context fits.
- return context;
- }
-
- final Display targetDisplay = mDisplayManager.getDisplay(displayId);
- if (targetDisplay == null) {
- // Failed to obtain the non-default display where splash screen should be shown,
- // lets not show at all.
- return null;
- }
-
- return context.createDisplayContext(targetDisplay);
+ private Display getDisplay(int displayId) {
+ return mDisplayManager.getDisplay(displayId);
}
- private int getSplashScreenTheme(int splashScreenThemeResId, ActivityInfo activityInfo) {
+ int getSplashScreenTheme(int splashScreenThemeResId, ActivityInfo activityInfo) {
return splashScreenThemeResId != 0
? splashScreenThemeResId
: activityInfo.getThemeResource() != 0 ? activityInfo.getThemeResource()
@@ -177,7 +164,7 @@ public class StartingSurfaceDrawer {
final int displayId = taskInfo.displayId;
final int taskId = taskInfo.taskId;
- Context context = mContext;
+
// replace with the default theme if the application didn't set
final int theme = getSplashScreenTheme(windowInfo.splashScreenThemeResId, activityInfo);
if (DEBUG_SPLASH_SCREEN) {
@@ -186,13 +173,16 @@ public class StartingSurfaceDrawer {
+ " suggestType=" + suggestType);
}
- // Obtain proper context to launch on the right display.
- final Context displayContext = getDisplayContext(context, displayId);
- if (displayContext == null) {
+ final Display display = getDisplay(displayId);
+ if (display == null) {
// Can't show splash screen on requested display, so skip showing at all.
return;
}
- context = displayContext;
+ Context context = displayId == DEFAULT_DISPLAY
+ ? mContext : mContext.createDisplayContext(display);
+ if (context == null) {
+ return;
+ }
if (theme != context.getThemeResId()) {
try {
context = context.createPackageContextAsUser(activityInfo.packageName,
@@ -303,7 +293,8 @@ public class StartingSurfaceDrawer {
// Record whether create splash screen view success, notify to current thread after
// create splash screen view finished.
final SplashScreenViewSupplier viewSupplier = new SplashScreenViewSupplier();
- final FrameLayout rootLayout = new FrameLayout(context);
+ final FrameLayout rootLayout = new FrameLayout(
+ mSplashscreenContentDrawer.createViewContextWrapper(context));
rootLayout.setPadding(0, 0, 0, 0);
rootLayout.setFitsSystemWindows(false);
final Runnable setViewSynchronized = () -> {
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
index eef0d9bb268f..18b8faf4dbe6 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
@@ -30,6 +30,7 @@ import static org.junit.Assert.assertNotEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -101,7 +102,6 @@ public class StartingSurfaceDrawerTests {
static final class TestStartingSurfaceDrawer extends StartingSurfaceDrawer{
int mAddWindowForTask = 0;
- int mViewThemeResId;
TestStartingSurfaceDrawer(Context context, ShellExecutor splashScreenExecutor,
TransactionPool pool) {
@@ -113,7 +113,6 @@ public class StartingSurfaceDrawerTests {
View view, WindowManager wm, WindowManager.LayoutParams params, int suggestType) {
// listen for addView
mAddWindowForTask = taskId;
- mViewThemeResId = view.getContext().getThemeResId();
// Do not wait for background color
return false;
}
@@ -183,12 +182,15 @@ public class StartingSurfaceDrawerTests {
final int taskId = 1;
final StartingWindowInfo windowInfo =
createWindowInfo(taskId, 0);
+ final int[] theme = new int[1];
+ doAnswer(invocation -> theme[0] = (Integer) invocation.callRealMethod())
+ .when(mStartingSurfaceDrawer).getSplashScreenTheme(eq(0), any());
+
mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo, mBinder,
STARTING_WINDOW_TYPE_SPLASH_SCREEN);
waitHandlerIdle(mTestHandler);
- verify(mStartingSurfaceDrawer).addWindow(eq(taskId), eq(mBinder), any(), any(), any(),
- eq(STARTING_WINDOW_TYPE_SPLASH_SCREEN));
- assertNotEquals(mStartingSurfaceDrawer.mViewThemeResId, 0);
+ verify(mStartingSurfaceDrawer).getSplashScreenTheme(eq(0), any());
+ assertNotEquals(theme[0], 0);
}
@Test
diff --git a/libs/androidfw/OWNERS b/libs/androidfw/OWNERS
index 38b642501fcd..17f5164cf417 100644
--- a/libs/androidfw/OWNERS
+++ b/libs/androidfw/OWNERS
@@ -1,4 +1,5 @@
set noparent
+toddke@google.com
zyy@google.com
patb@google.com
diff --git a/media/java/android/media/IMediaRouterService.aidl b/media/java/android/media/IMediaRouterService.aidl
index 48289ecde9e0..25b582d2fc8d 100644
--- a/media/java/android/media/IMediaRouterService.aidl
+++ b/media/java/android/media/IMediaRouterService.aidl
@@ -39,6 +39,7 @@ interface IMediaRouterService {
MediaRouterClientState getState(IMediaRouterClient client);
boolean isPlaybackActive(IMediaRouterClient client);
+ void setBluetoothA2dpOn(IMediaRouterClient client, boolean on);
void setDiscoveryRequest(IMediaRouterClient client, int routeTypes, boolean activeScan);
void setSelectedRoute(IMediaRouterClient client, String routeId, boolean explicit);
void requestSetVolume(IMediaRouterClient client, String routeId, int volume);
diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java
index 2986f7c75f4d..dfdfeacb065a 100644
--- a/media/java/android/media/MediaRouter.java
+++ b/media/java/android/media/MediaRouter.java
@@ -1070,7 +1070,8 @@ public class MediaRouter {
&& (types & ROUTE_TYPE_LIVE_AUDIO) != 0
&& (route.isBluetooth() || route.isDefault())) {
try {
- sStatic.mAudioService.setBluetoothA2dpOn(route.isBluetooth());
+ sStatic.mMediaRouterService.setBluetoothA2dpOn(sStatic.mClient,
+ route.isBluetooth());
} catch (RemoteException e) {
Log.e(TAG, "Error changing Bluetooth A2DP state", e);
}
diff --git a/mms/OWNERS b/mms/OWNERS
index f56845ed80c7..2e419c1e529c 100644
--- a/mms/OWNERS
+++ b/mms/OWNERS
@@ -3,6 +3,7 @@ set noparent
tgunn@google.com
breadley@google.com
rgreenwalt@google.com
+amitmahajan@google.com
fionaxu@google.com
jackyu@google.com
jminjie@google.com
diff --git a/native/android/OWNERS b/native/android/OWNERS
index 8b35f8d38691..02dfd393a0b7 100644
--- a/native/android/OWNERS
+++ b/native/android/OWNERS
@@ -1,7 +1,7 @@
jreck@google.com
per-file libandroid_net.map.txt, net.c = set noparent
-per-file libandroid_net.map.txt, net.c = jchalard@google.com, junyulai@google.com
+per-file libandroid_net.map.txt, net.c = codewiz@google.com, jchalard@google.com, junyulai@google.com
per-file libandroid_net.map.txt, net.c = lorenzo@google.com, reminv@google.com, satk@google.com
per-file system_fonts.cpp = file:/graphics/java/android/graphics/fonts/OWNERS
diff --git a/packages/CarrierDefaultApp/OWNERS b/packages/CarrierDefaultApp/OWNERS
index b9de5a3919f5..a2352e20f841 100644
--- a/packages/CarrierDefaultApp/OWNERS
+++ b/packages/CarrierDefaultApp/OWNERS
@@ -2,6 +2,7 @@ set noparent
tgunn@google.com
breadley@google.com
rgreenwalt@google.com
+amitmahajan@google.com
fionaxu@google.com
jackyu@google.com
jminjie@google.com
diff --git a/packages/CtsShim/OWNERS b/packages/CtsShim/OWNERS
index eb631bc7cbcf..94197715150d 100644
--- a/packages/CtsShim/OWNERS
+++ b/packages/CtsShim/OWNERS
@@ -1,2 +1,3 @@
ioffe@google.com
+toddke@google.com
patb@google.com \ No newline at end of file
diff --git a/packages/Shell/OWNERS b/packages/Shell/OWNERS
index 80bb307749ed..177f86b08864 100644
--- a/packages/Shell/OWNERS
+++ b/packages/Shell/OWNERS
@@ -6,6 +6,7 @@ nandana@google.com
svetoslavganov@google.com
hackbod@google.com
yamasani@google.com
+toddke@google.com
patb@google.com
cbrubaker@google.com
omakoto@google.com
diff --git a/packages/SystemUI/res/layout/internet_connectivity_dialog.xml b/packages/SystemUI/res/layout/internet_connectivity_dialog.xml
index 918635d666fa..c88e95f07f12 100644
--- a/packages/SystemUI/res/layout/internet_connectivity_dialog.xml
+++ b/packages/SystemUI/res/layout/internet_connectivity_dialog.xml
@@ -323,6 +323,46 @@
</FrameLayout>
</LinearLayout>
+ <LinearLayout
+ android:id="@+id/wifi_scan_notify_layout"
+ style="@style/InternetDialog.Network"
+ android:orientation="vertical"
+ android:layout_height="wrap_content"
+ android:paddingBottom="4dp"
+ android:clickable="false"
+ android:focusable="false">
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:minWidth="56dp"
+ android:gravity="start|top"
+ android:orientation="horizontal"
+ android:paddingEnd="12dp"
+ android:paddingTop="16dp"
+ android:paddingBottom="4dp">
+ <ImageView
+ android:src="@drawable/ic_info_outline"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:tint="?android:attr/textColorTertiary"/>
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+ <TextView
+ android:id="@+id/wifi_scan_notify_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingTop="16dp"
+ android:paddingBottom="8dp"
+ android:textColor="?android:attr/textColorSecondary"
+ android:clickable="true"/>
+ </LinearLayout>
+ </LinearLayout>
+
<FrameLayout
android:id="@+id/done_layout"
android:layout_width="67dp"
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 7aacb702b75a..4ad4fa9d0854 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -3033,4 +3033,6 @@
<string name="see_all_networks">See all</string>
<!-- Summary for warning to disconnect ethernet first then switch to other networks. [CHAR LIMIT=60] -->
<string name="to_switch_networks_disconnect_ethernet">To switch networks, disconnect ethernet</string>
+ <!-- Message to describe "Wi-Fi scan always available feature" when Wi-Fi is off and Wi-Fi scanning is on. [CHAR LIMIT=NONE] -->
+ <string name="wifi_scan_notify_message">To improve device experience, apps and services can still scan for Wi\u2011Fi networks at any time, even when Wi\u2011Fi is off. You can change this in Wi\u2011Fi scanning settings. <annotation id="link">Change</annotation></string>
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
index e9c565377530..2c0b52638d2f 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
@@ -496,6 +496,9 @@ public class ScreenDecorations extends SystemUI implements Tunable {
lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS
| WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
+ // FLAG_SLIPPERY can only be set by trusted overlays
+ lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY;
+
if (!DEBUG_SCREENSHOT_ROUNDED_CORNERS) {
lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY;
}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AnnotationLinkSpan.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AnnotationLinkSpan.java
index d8e80fe99331..0d7551ff66e9 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AnnotationLinkSpan.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AnnotationLinkSpan.java
@@ -30,7 +30,7 @@ import java.util.Optional;
/**
* A span that turns the text wrapped by annotation tag into the clickable link text.
*/
-class AnnotationLinkSpan extends ClickableSpan {
+public class AnnotationLinkSpan extends ClickableSpan {
private final Optional<View.OnClickListener> mClickListener;
private AnnotationLinkSpan(View.OnClickListener listener) {
@@ -50,7 +50,7 @@ class AnnotationLinkSpan extends ClickableSpan {
* @param linkInfos used to attach the click action into the corresponding span
* @return the text attached with the span
*/
- static CharSequence linkify(CharSequence text, LinkInfo... linkInfos) {
+ public static CharSequence linkify(CharSequence text, LinkInfo... linkInfos) {
final SpannableString msg = new SpannableString(text);
final Annotation[] spans =
msg.getSpans(/* queryStart= */ 0, msg.length(), Annotation.class);
@@ -78,12 +78,12 @@ class AnnotationLinkSpan extends ClickableSpan {
/**
* Data class to store the annotation and the click action.
*/
- static class LinkInfo {
- static final String DEFAULT_ANNOTATION = "link";
+ public static class LinkInfo {
+ public static final String DEFAULT_ANNOTATION = "link";
private final Optional<String> mAnnotation;
private final Optional<View.OnClickListener> mListener;
- LinkInfo(@NonNull String annotation, View.OnClickListener listener) {
+ public LinkInfo(@NonNull String annotation, View.OnClickListener listener) {
mAnnotation = Optional.of(annotation);
mListener = Optional.ofNullable(listener);
}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java
index 37a6cfaabb5e..0a9329845b23 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java
@@ -330,7 +330,7 @@ public class BrightLineFalsingManager implements FalsingManager {
|| mTestHarness
|| mDataProvider.isJustUnlockedWithFace()
|| mDataProvider.isDocked()
- || mAccessibilityManager.isEnabled();
+ || mAccessibilityManager.isTouchExplorationEnabled();
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
index dc54e1b52f2e..d0271f72153e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
@@ -36,6 +36,7 @@ import android.telephony.TelephonyDisplayInfo;
import android.telephony.TelephonyManager;
import android.text.Html;
import android.text.TextUtils;
+import android.text.method.LinkMovementMethod;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
@@ -63,12 +64,15 @@ import com.android.internal.logging.UiEvent;
import com.android.internal.logging.UiEventLogger;
import com.android.systemui.Prefs;
import com.android.systemui.R;
+import com.android.systemui.accessibility.floatingmenu.AnnotationLinkSpan;
import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.statusbar.phone.SystemUIDialog;
import com.android.wifitrackerlib.WifiEntry;
import java.util.List;
+import java.util.concurrent.Executor;
/**
* Dialog for showing mobile network, connected Wi-Fi network and Wi-Fi networks.
@@ -82,6 +86,7 @@ public class InternetDialog extends SystemUIDialog implements
static final long PROGRESS_DELAY_MS = 2000L;
private final Handler mHandler;
+ private final Executor mBackgroundExecutor;
private final LinearLayoutManager mLayoutManager;
@VisibleForTesting
@@ -110,6 +115,8 @@ public class InternetDialog extends SystemUIDialog implements
private LinearLayout mTurnWifiOnLayout;
private LinearLayout mEthernetLayout;
private TextView mWifiToggleTitleText;
+ private LinearLayout mWifiScanNotifyLayout;
+ private TextView mWifiScanNotifyText;
private LinearLayout mSeeAllLayout;
private RecyclerView mWifiRecyclerView;
private ImageView mConnectedWifiIcon;
@@ -154,13 +161,14 @@ public class InternetDialog extends SystemUIDialog implements
public InternetDialog(Context context, InternetDialogFactory internetDialogFactory,
InternetDialogController internetDialogController, boolean canConfigMobileData,
boolean canConfigWifi, boolean aboveStatusBar, UiEventLogger uiEventLogger,
- @Main Handler handler) {
+ @Main Handler handler, @Background Executor executor) {
super(context, R.style.Theme_SystemUI_Dialog_Internet);
if (DEBUG) {
Log.d(TAG, "Init InternetDialog");
}
mContext = context;
mHandler = handler;
+ mBackgroundExecutor = executor;
mInternetDialogFactory = internetDialogFactory;
mInternetDialogController = internetDialogController;
mSubscriptionManager = mInternetDialogController.getSubscriptionManager();
@@ -220,6 +228,8 @@ public class InternetDialog extends SystemUIDialog implements
mMobileNetworkLayout = mDialogView.requireViewById(R.id.mobile_network_layout);
mTurnWifiOnLayout = mDialogView.requireViewById(R.id.turn_on_wifi_layout);
mWifiToggleTitleText = mDialogView.requireViewById(R.id.wifi_toggle_title);
+ mWifiScanNotifyLayout = mDialogView.requireViewById(R.id.wifi_scan_notify_layout);
+ mWifiScanNotifyText = mDialogView.requireViewById(R.id.wifi_scan_notify_text);
mConnectedWifListLayout = mDialogView.requireViewById(R.id.wifi_connected_layout);
mConnectedWifiIcon = mDialogView.requireViewById(R.id.wifi_connected_icon);
mConnectedWifiTitleText = mDialogView.requireViewById(R.id.wifi_connected_title);
@@ -293,7 +303,13 @@ public class InternetDialog extends SystemUIDialog implements
dismiss();
}
- void updateDialog() {
+ /**
+ * Update the internet dialog when receiving the callback.
+ *
+ * @param shouldUpdateMobileNetwork {@code true} for update the mobile network layout,
+ * otherwise {@code false}.
+ */
+ void updateDialog(boolean shouldUpdateMobileNetwork) {
if (DEBUG) {
Log.d(TAG, "updateDialog");
}
@@ -303,8 +319,10 @@ public class InternetDialog extends SystemUIDialog implements
mInternetDialogSubTitle.setText(getSubtitleText());
}
updateEthernet();
- setMobileDataLayout(mInternetDialogController.activeNetworkIsCellular()
- || mInternetDialogController.isCarrierNetworkActive());
+ if (shouldUpdateMobileNetwork) {
+ setMobileDataLayout(mInternetDialogController.activeNetworkIsCellular()
+ || mInternetDialogController.isCarrierNetworkActive());
+ }
if (!mCanConfigWifi) {
return;
@@ -313,8 +331,10 @@ public class InternetDialog extends SystemUIDialog implements
showProgressBar();
final boolean isDeviceLocked = mInternetDialogController.isDeviceLocked();
final boolean isWifiEnabled = mWifiManager.isWifiEnabled();
+ final boolean isWifiScanEnabled = mInternetDialogController.isWifiScanEnabled();
updateWifiToggle(isWifiEnabled, isDeviceLocked);
updateConnectedWifi(isWifiEnabled, isDeviceLocked);
+ updateWifiScanNotify(isWifiEnabled, isWifiScanEnabled, isDeviceLocked);
final int visibility = (isDeviceLocked || !isWifiEnabled || mWifiEntriesCount <= 0)
? View.GONE : View.VISIBLE;
@@ -371,7 +391,13 @@ public class InternetDialog extends SystemUIDialog implements
} else {
mMobileSummaryText.setVisibility(View.GONE);
}
- mSignalIcon.setImageDrawable(getSignalStrengthDrawable());
+
+ mBackgroundExecutor.execute(() -> {
+ Drawable drawable = getSignalStrengthDrawable();
+ mHandler.post(() -> {
+ mSignalIcon.setImageDrawable(drawable);
+ });
+ });
mMobileTitleText.setTextAppearance(isCarrierNetworkConnected
? R.style.TextAppearance_InternetDialog_Active
: R.style.TextAppearance_InternetDialog);
@@ -411,6 +437,24 @@ public class InternetDialog extends SystemUIDialog implements
mContext.getColor(R.color.connected_network_primary_color));
}
+ @MainThread
+ private void updateWifiScanNotify(boolean isWifiEnabled, boolean isWifiScanEnabled,
+ boolean isDeviceLocked) {
+ if (isWifiEnabled || !isWifiScanEnabled || isDeviceLocked) {
+ mWifiScanNotifyLayout.setVisibility(View.GONE);
+ return;
+ }
+ if (TextUtils.isEmpty(mWifiScanNotifyText.getText())) {
+ final AnnotationLinkSpan.LinkInfo linkInfo = new AnnotationLinkSpan.LinkInfo(
+ AnnotationLinkSpan.LinkInfo.DEFAULT_ANNOTATION,
+ v -> mInternetDialogController.launchWifiScanningSetting());
+ mWifiScanNotifyText.setText(AnnotationLinkSpan.linkify(
+ getContext().getText(R.string.wifi_scan_notify_message), linkInfo));
+ mWifiScanNotifyText.setMovementMethod(LinkMovementMethod.getInstance());
+ }
+ mWifiScanNotifyLayout.setVisibility(View.VISIBLE);
+ }
+
void onClickConnectedWifi() {
if (mConnectedWifiEntry == null) {
return;
@@ -508,52 +552,57 @@ public class InternetDialog extends SystemUIDialog implements
@Override
public void onRefreshCarrierInfo() {
- mHandler.post(() -> updateDialog());
+ mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */));
}
@Override
public void onSimStateChanged() {
- mHandler.post(() -> updateDialog());
+ mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */));
}
@Override
@WorkerThread
public void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) {
- mHandler.post(() -> updateDialog());
+ mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */));
}
@Override
@WorkerThread
public void onLost(Network network) {
- mHandler.post(() -> updateDialog());
+ mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */));
}
@Override
public void onSubscriptionsChanged(int defaultDataSubId) {
mDefaultDataSubId = defaultDataSubId;
mTelephonyManager = mTelephonyManager.createForSubscriptionId(mDefaultDataSubId);
- mHandler.post(() -> updateDialog());
+ mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */));
+ }
+
+ @Override
+ public void onUserMobileDataStateChanged(boolean enabled) {
+ mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */));
}
@Override
public void onServiceStateChanged(ServiceState serviceState) {
- mHandler.post(() -> updateDialog());
+ mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */));
}
@Override
@WorkerThread
public void onDataConnectionStateChanged(int state, int networkType) {
- mHandler.post(() -> updateDialog());
+ mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */));
}
@Override
public void onSignalStrengthsChanged(SignalStrength signalStrength) {
- mHandler.post(() -> updateDialog());
+ mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */));
}
@Override
public void onDisplayInfoChanged(TelephonyDisplayInfo telephonyDisplayInfo) {
- mHandler.post(() -> updateDialog());
+ mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */));
}
@Override
@@ -565,7 +614,7 @@ public class InternetDialog extends SystemUIDialog implements
mAdapter.setWifiEntries(wifiEntries, mWifiEntriesCount);
mHandler.post(() -> {
mAdapter.notifyDataSetChanged();
- updateDialog();
+ updateDialog(false /* shouldUpdateMobileNetwork */);
});
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
index aaba5efc92f6..67e34113bebb 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
@@ -76,6 +76,7 @@ import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.statusbar.policy.LocationController;
import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.NetworkController.AccessPointController;
import com.android.systemui.toast.SystemUIToast;
@@ -103,6 +104,8 @@ public class InternetDialogController implements WifiEntry.DisconnectCallback,
private static final String TAG = "InternetDialogController";
private static final String ACTION_NETWORK_PROVIDER_SETTINGS =
"android.settings.NETWORK_PROVIDER_SETTINGS";
+ private static final String ACTION_WIFI_SCANNING_SETTINGS =
+ "android.settings.WIFI_SCANNING_SETTINGS";
private static final String EXTRA_CHOSEN_WIFI_ENTRY_KEY = "key_chosen_wifientry_key";
public static final Drawable EMPTY_DRAWABLE = new ColorDrawable(Color.TRANSPARENT);
public static final int NO_CELL_DATA_TYPE_ICON = 0;
@@ -147,6 +150,8 @@ public class InternetDialogController implements WifiEntry.DisconnectCallback,
private ConnectivityManager.NetworkCallback mConnectivityManagerNetworkCallback;
private WindowManager mWindowManager;
private ToastFactory mToastFactory;
+ private SignalDrawable mSignalDrawable;
+ private LocationController mLocationController;
@VisibleForTesting
static final float TOAST_PARAMS_HORIZONTAL_WEIGHT = 1.0f;
@@ -196,7 +201,8 @@ public class InternetDialogController implements WifiEntry.DisconnectCallback,
GlobalSettings globalSettings, KeyguardStateController keyguardStateController,
WindowManager windowManager, ToastFactory toastFactory,
@Background Handler workerHandler,
- CarrierConfigTracker carrierConfigTracker) {
+ CarrierConfigTracker carrierConfigTracker,
+ LocationController locationController) {
if (DEBUG) {
Log.d(TAG, "Init InternetDialogController");
}
@@ -223,6 +229,8 @@ public class InternetDialogController implements WifiEntry.DisconnectCallback,
mConnectivityManagerNetworkCallback = new DataConnectivityListener();
mWindowManager = windowManager;
mToastFactory = toastFactory;
+ mSignalDrawable = new SignalDrawable(mContext);
+ mLocationController = locationController;
}
void onStart(@NonNull InternetDialogCallback callback, boolean canConfigWifi) {
@@ -429,10 +437,7 @@ public class InternetDialogController implements WifiEntry.DisconnectCallback,
Drawable getSignalStrengthIcon(Context context, int level, int numLevels,
int iconType, boolean cutOut) {
- Log.d(TAG, "getSignalStrengthIcon");
- final SignalDrawable signalDrawable = new SignalDrawable(context);
- signalDrawable.setLevel(
- SignalDrawable.getState(level, numLevels, cutOut));
+ mSignalDrawable.setLevel(SignalDrawable.getState(level, numLevels, cutOut));
// Make the network type drawable
final Drawable networkDrawable =
@@ -441,7 +446,7 @@ public class InternetDialogController implements WifiEntry.DisconnectCallback,
: context.getResources().getDrawable(iconType, context.getTheme());
// Overlay the two drawables
- final Drawable[] layers = {networkDrawable, signalDrawable};
+ final Drawable[] layers = {networkDrawable, mSignalDrawable};
final int iconSize =
context.getResources().getDimensionPixelSize(R.dimen.signal_strength_icon_size);
@@ -603,6 +608,13 @@ public class InternetDialogController implements WifiEntry.DisconnectCallback,
}
}
+ void launchWifiScanningSetting() {
+ mCallback.dismissDialog();
+ final Intent intent = new Intent(ACTION_WIFI_SCANNING_SETTINGS);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ mActivityStarter.postStartActivityDismissingKeyguard(intent, 0);
+ }
+
void connectCarrierNetwork() {
final MergedCarrierEntry mergedCarrierEntry =
mAccessPointController.getMergedCarrierEntry();
@@ -780,6 +792,14 @@ public class InternetDialogController implements WifiEntry.DisconnectCallback,
return false;
}
+ @WorkerThread
+ boolean isWifiScanEnabled() {
+ if (!mLocationController.isLocationEnabled()) {
+ return false;
+ }
+ return mWifiManager.isScanAlwaysAvailable();
+ }
+
static class WifiEntryConnectCallback implements WifiEntry.ConnectCallback {
final ActivityStarter mActivityStarter;
final WifiEntry mWifiEntry;
@@ -883,7 +903,8 @@ public class InternetDialogController implements WifiEntry.DisconnectCallback,
TelephonyCallback.DataConnectionStateListener,
TelephonyCallback.DisplayInfoListener,
TelephonyCallback.ServiceStateListener,
- TelephonyCallback.SignalStrengthsListener {
+ TelephonyCallback.SignalStrengthsListener,
+ TelephonyCallback.UserMobileDataStateListener {
@Override
public void onServiceStateChanged(@NonNull ServiceState serviceState) {
@@ -905,6 +926,11 @@ public class InternetDialogController implements WifiEntry.DisconnectCallback,
mTelephonyDisplayInfo = telephonyDisplayInfo;
mCallback.onDisplayInfoChanged(telephonyDisplayInfo);
}
+
+ @Override
+ public void onUserMobileDataStateChanged(boolean enabled) {
+ mCallback.onUserMobileDataStateChanged(enabled);
+ }
}
private class InternetOnSubscriptionChangedListener
@@ -1009,6 +1035,8 @@ public class InternetDialogController implements WifiEntry.DisconnectCallback,
void onSignalStrengthsChanged(SignalStrength signalStrength);
+ void onUserMobileDataStateChanged(boolean enabled);
+
void onDisplayInfoChanged(TelephonyDisplayInfo telephonyDisplayInfo);
void dismissDialog();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogFactory.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogFactory.kt
index 11c6980678b1..ea5df17bca58 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogFactory.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogFactory.kt
@@ -20,7 +20,9 @@ import android.os.Handler
import android.util.Log
import com.android.internal.logging.UiEventLogger
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main
+import java.util.concurrent.Executor
import javax.inject.Inject
private const val TAG = "InternetDialogFactory"
@@ -32,6 +34,7 @@ private val DEBUG = Log.isLoggable(TAG, Log.DEBUG)
@SysUISingleton
class InternetDialogFactory @Inject constructor(
@Main private val handler: Handler,
+ @Background private val executor: Executor,
private val internetDialogController: InternetDialogController,
private val context: Context,
private val uiEventLogger: UiEventLogger
@@ -49,7 +52,8 @@ class InternetDialogFactory @Inject constructor(
return
} else {
internetDialog = InternetDialog(context, this, internetDialogController,
- canConfigMobileData, canConfigWifi, aboveStatusBar, uiEventLogger, handler)
+ canConfigMobileData, canConfigWifi, aboveStatusBar, uiEventLogger, handler,
+ executor)
internetDialog?.show()
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 1e3e47b75d8a..9a2ebcfeea98 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -899,7 +899,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
@Override
public boolean bouncerIsOrWillBeShowing() {
- return mBouncer.isShowing() || mBouncer.getShowingSoon();
+ return isBouncerShowing() || mBouncer.getShowingSoon();
}
public boolean isFullscreenBouncer() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
index 143aaba648da..e3f4b03dc4f2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
@@ -145,22 +145,27 @@ class UnlockedScreenOffAnimationController @Inject constructor(
.setDuration(duration.toLong())
.setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
.alpha(1f)
- .withEndAction {
- aodUiAnimationPlaying = false
+ .setListener(object : AnimatorListenerAdapter() {
+ override fun onAnimationEnd(animation: Animator?) {
+ aodUiAnimationPlaying = false
- // Lock the keyguard if it was waiting for the screen off animation to end.
- keyguardViewMediatorLazy.get().maybeHandlePendingLock()
+ // Lock the keyguard if it was waiting for the screen off animation to end.
+ keyguardViewMediatorLazy.get().maybeHandlePendingLock()
- // Tell the StatusBar to become keyguard for real - we waited on that since it
- // is slow and would have caused the animation to jank.
- statusBar.updateIsKeyguard()
+ // Tell the StatusBar to become keyguard for real - we waited on that since
+ // it is slow and would have caused the animation to jank.
+ statusBar.updateIsKeyguard()
- // Run the callback given to us by the KeyguardVisibilityHelper.
- after.run()
+ // Run the callback given to us by the KeyguardVisibilityHelper.
+ after.run()
- // Done going to sleep, reset this flag.
- decidedToAnimateGoingToSleep = null
- }
+ // Done going to sleep, reset this flag.
+ decidedToAnimateGoingToSleep = null
+
+ // We need to unset the listener. These are persistent for future animators
+ keyguardView.animate().setListener(null)
+ }
+ })
.start()
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java
index c4f480d7e7aa..55ee433c8d9d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java
@@ -91,7 +91,7 @@ public class BrightLineFalsingManagerTest extends SysuiTestCase {
@Test
public void testA11yDisablesGesture() {
assertThat(mBrightLineFalsingManager.isFalseTap(1)).isTrue();
- when(mAccessibilityManager.isEnabled()).thenReturn(true);
+ when(mAccessibilityManager.isTouchExplorationEnabled()).thenReturn(true);
assertThat(mBrightLineFalsingManager.isFalseTap(1)).isFalse();
}
@@ -99,7 +99,7 @@ public class BrightLineFalsingManagerTest extends SysuiTestCase {
@Test
public void testA11yDisablesTap() {
assertThat(mBrightLineFalsingManager.isFalseTouch(Classifier.GENERIC)).isTrue();
- when(mAccessibilityManager.isEnabled()).thenReturn(true);
+ when(mAccessibilityManager.isTouchExplorationEnabled()).thenReturn(true);
assertThat(mBrightLineFalsingManager.isFalseTouch(Classifier.GENERIC)).isFalse();
}
@@ -107,7 +107,7 @@ public class BrightLineFalsingManagerTest extends SysuiTestCase {
@Test
public void testA11yDisablesDoubleTap() {
assertThat(mBrightLineFalsingManager.isFalseDoubleTap()).isTrue();
- when(mAccessibilityManager.isEnabled()).thenReturn(true);
+ when(mAccessibilityManager.isTouchExplorationEnabled()).thenReturn(true);
assertThat(mBrightLineFalsingManager.isFalseDoubleTap()).isFalse();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java
index f9d5be6c4807..663edc7b373b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java
@@ -49,6 +49,7 @@ import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.statusbar.policy.LocationController;
import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.NetworkController.AccessPointController;
import com.android.systemui.toast.SystemUIToast;
@@ -135,6 +136,8 @@ public class InternetDialogControllerTest extends SysuiTestCase {
private Animator mAnimator;
@Mock
private CarrierConfigTracker mCarrierConfigTracker;
+ @Mock
+ private LocationController mLocationController;
private TestableResources mTestableResources;
private MockInternetDialogController mInternetDialogController;
@@ -170,7 +173,8 @@ public class InternetDialogControllerTest extends SysuiTestCase {
mSubscriptionManager, mTelephonyManager, mWifiManager,
mock(ConnectivityManager.class), mHandler, mExecutor, mBroadcastDispatcher,
mock(KeyguardUpdateMonitor.class), mGlobalSettings, mKeyguardStateController,
- mWindowManager, mToastFactory, mWorkerHandler, mCarrierConfigTracker);
+ mWindowManager, mToastFactory, mWorkerHandler, mCarrierConfigTracker,
+ mLocationController);
mSubscriptionManager.addOnSubscriptionsChangedListener(mExecutor,
mInternetDialogController.mOnSubscriptionsChangedListener);
mInternetDialogController.onStart(mInternetDialogCallback, true);
@@ -602,6 +606,30 @@ public class InternetDialogControllerTest extends SysuiTestCase {
verify(mMergedCarrierEntry).setEnabled(false);
}
+ @Test
+ public void isWifiScanEnabled_locationOff_returnFalse() {
+ when(mLocationController.isLocationEnabled()).thenReturn(false);
+ when(mWifiManager.isScanAlwaysAvailable()).thenReturn(false);
+
+ assertThat(mInternetDialogController.isWifiScanEnabled()).isFalse();
+
+ when(mWifiManager.isScanAlwaysAvailable()).thenReturn(true);
+
+ assertThat(mInternetDialogController.isWifiScanEnabled()).isFalse();
+ }
+
+ @Test
+ public void isWifiScanEnabled_locationOn_returnIsScanAlwaysAvailable() {
+ when(mLocationController.isLocationEnabled()).thenReturn(true);
+ when(mWifiManager.isScanAlwaysAvailable()).thenReturn(false);
+
+ assertThat(mInternetDialogController.isWifiScanEnabled()).isFalse();
+
+ when(mWifiManager.isScanAlwaysAvailable()).thenReturn(true);
+
+ assertThat(mInternetDialogController.isWifiScanEnabled()).isTrue();
+ }
+
private String getResourcesString(String name) {
return mContext.getResources().getString(getResourcesId(name));
}
@@ -625,12 +653,13 @@ public class InternetDialogControllerTest extends SysuiTestCase {
KeyguardUpdateMonitor keyguardUpdateMonitor, GlobalSettings globalSettings,
KeyguardStateController keyguardStateController, WindowManager windowManager,
ToastFactory toastFactory, Handler workerHandler,
- CarrierConfigTracker carrierConfigTracker) {
+ CarrierConfigTracker carrierConfigTracker,
+ LocationController locationController) {
super(context, uiEventLogger, starter, accessPointController, subscriptionManager,
telephonyManager, wifiManager, connectivityManager, handler, mainExecutor,
broadcastDispatcher, keyguardUpdateMonitor, globalSettings,
keyguardStateController, windowManager, toastFactory, workerHandler,
- carrierConfigTracker);
+ carrierConfigTracker, locationController);
mGlobalSettings = globalSettings;
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java
index c42b64a09985..5e1fea512d55 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java
@@ -19,6 +19,7 @@ import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.view.View;
import android.widget.LinearLayout;
+import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView;
import androidx.test.filters.SmallTest;
@@ -26,6 +27,8 @@ import androidx.test.filters.SmallTest;
import com.android.internal.logging.UiEventLogger;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.util.concurrency.FakeExecutor;
+import com.android.systemui.util.time.FakeSystemClock;
import com.android.wifitrackerlib.WifiEntry;
import org.junit.After;
@@ -64,6 +67,7 @@ public class InternetDialogTest extends SysuiTestCase {
@Mock
private InternetDialogController mInternetDialogController;
+ private FakeExecutor mBgExecutor = new FakeExecutor(new FakeSystemClock());
private InternetDialog mInternetDialog;
private View mDialogView;
private View mSubTitle;
@@ -73,6 +77,7 @@ public class InternetDialogTest extends SysuiTestCase {
private LinearLayout mConnectedWifi;
private RecyclerView mWifiList;
private LinearLayout mSeeAll;
+ private LinearLayout mWifiScanNotify;
@Before
public void setUp() {
@@ -91,7 +96,8 @@ public class InternetDialogTest extends SysuiTestCase {
when(mInternetDialogController.getWifiManager()).thenReturn(mWifiManager);
mInternetDialog = new InternetDialog(mContext, mock(InternetDialogFactory.class),
- mInternetDialogController, true, true, true, mock(UiEventLogger.class), mHandler);
+ mInternetDialogController, true, true, true, mock(UiEventLogger.class), mHandler,
+ mBgExecutor);
mInternetDialog.mAdapter = mInternetAdapter;
mInternetDialog.onAccessPointsChanged(mWifiEntries, mInternetWifiEntry);
mInternetDialog.show();
@@ -104,6 +110,7 @@ public class InternetDialogTest extends SysuiTestCase {
mConnectedWifi = mDialogView.requireViewById(R.id.wifi_connected_layout);
mWifiList = mDialogView.requireViewById(R.id.wifi_list_layout);
mSeeAll = mDialogView.requireViewById(R.id.see_all_layout);
+ mWifiScanNotify = mDialogView.requireViewById(R.id.wifi_scan_notify_layout);
}
@After
@@ -126,7 +133,7 @@ public class InternetDialogTest extends SysuiTestCase {
public void updateDialog_withApmOn_internetDialogSubTitleGone() {
when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(true);
- mInternetDialog.updateDialog();
+ mInternetDialog.updateDialog(true);
assertThat(mSubTitle.getVisibility()).isEqualTo(View.GONE);
}
@@ -135,7 +142,7 @@ public class InternetDialogTest extends SysuiTestCase {
public void updateDialog_withApmOff_internetDialogSubTitleVisible() {
when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(false);
- mInternetDialog.updateDialog();
+ mInternetDialog.updateDialog(true);
assertThat(mSubTitle.getVisibility()).isEqualTo(View.VISIBLE);
}
@@ -145,7 +152,7 @@ public class InternetDialogTest extends SysuiTestCase {
when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(false);
when(mInternetDialogController.hasEthernet()).thenReturn(true);
- mInternetDialog.updateDialog();
+ mInternetDialog.updateDialog(true);
assertThat(mEthernet.getVisibility()).isEqualTo(View.VISIBLE);
}
@@ -155,7 +162,7 @@ public class InternetDialogTest extends SysuiTestCase {
when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(false);
when(mInternetDialogController.hasEthernet()).thenReturn(false);
- mInternetDialog.updateDialog();
+ mInternetDialog.updateDialog(true);
assertThat(mEthernet.getVisibility()).isEqualTo(View.GONE);
}
@@ -165,7 +172,7 @@ public class InternetDialogTest extends SysuiTestCase {
when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(true);
when(mInternetDialogController.hasEthernet()).thenReturn(true);
- mInternetDialog.updateDialog();
+ mInternetDialog.updateDialog(true);
assertThat(mEthernet.getVisibility()).isEqualTo(View.VISIBLE);
}
@@ -175,7 +182,7 @@ public class InternetDialogTest extends SysuiTestCase {
when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(true);
when(mInternetDialogController.hasEthernet()).thenReturn(false);
- mInternetDialog.updateDialog();
+ mInternetDialog.updateDialog(true);
assertThat(mEthernet.getVisibility()).isEqualTo(View.GONE);
}
@@ -184,7 +191,7 @@ public class InternetDialogTest extends SysuiTestCase {
public void updateDialog_withApmOn_mobileDataLayoutGone() {
when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(true);
- mInternetDialog.updateDialog();
+ mInternetDialog.updateDialog(true);
assertThat(mMobileDataToggle.getVisibility()).isEqualTo(View.GONE);
}
@@ -194,7 +201,7 @@ public class InternetDialogTest extends SysuiTestCase {
// The preconditions WiFi ON and Internet WiFi are already in setUp()
doReturn(false).when(mInternetDialogController).activeNetworkIsCellular();
- mInternetDialog.updateDialog();
+ mInternetDialog.updateDialog(false);
assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.VISIBLE);
}
@@ -205,7 +212,7 @@ public class InternetDialogTest extends SysuiTestCase {
mInternetDialog.onAccessPointsChanged(mWifiEntries, null /* connectedEntry*/);
doReturn(false).when(mInternetDialogController).activeNetworkIsCellular();
- mInternetDialog.updateDialog();
+ mInternetDialog.updateDialog(false);
assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.GONE);
}
@@ -215,7 +222,7 @@ public class InternetDialogTest extends SysuiTestCase {
// The precondition WiFi ON is already in setUp()
mInternetDialog.onAccessPointsChanged(null /* wifiEntries */, mInternetWifiEntry);
- mInternetDialog.updateDialog();
+ mInternetDialog.updateDialog(false);
assertThat(mWifiList.getVisibility()).isEqualTo(View.GONE);
assertThat(mSeeAll.getVisibility()).isEqualTo(View.GONE);
@@ -225,7 +232,7 @@ public class InternetDialogTest extends SysuiTestCase {
public void updateDialog_wifiOnAndHasWifiList_showWifiListAndSeeAll() {
// The preconditions WiFi ON and WiFi entries are already in setUp()
- mInternetDialog.updateDialog();
+ mInternetDialog.updateDialog(false);
assertThat(mWifiList.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mSeeAll.getVisibility()).isEqualTo(View.VISIBLE);
@@ -236,7 +243,7 @@ public class InternetDialogTest extends SysuiTestCase {
// The preconditions WiFi ON and Internet WiFi are already in setUp()
when(mInternetDialogController.isDeviceLocked()).thenReturn(true);
- mInternetDialog.updateDialog();
+ mInternetDialog.updateDialog(false);
assertThat(mWifiToggle.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mWifiToggle.getBackground()).isNotNull();
@@ -247,7 +254,7 @@ public class InternetDialogTest extends SysuiTestCase {
// The preconditions WiFi ON and Internet WiFi are already in setUp()
when(mInternetDialogController.isDeviceLocked()).thenReturn(true);
- mInternetDialog.updateDialog();
+ mInternetDialog.updateDialog(false);
assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.GONE);
}
@@ -257,13 +264,57 @@ public class InternetDialogTest extends SysuiTestCase {
// The preconditions WiFi entries are already in setUp()
when(mInternetDialogController.isDeviceLocked()).thenReturn(true);
- mInternetDialog.updateDialog();
+ mInternetDialog.updateDialog(false);
assertThat(mWifiList.getVisibility()).isEqualTo(View.GONE);
assertThat(mSeeAll.getVisibility()).isEqualTo(View.GONE);
}
@Test
+ public void updateDialog_wifiOn_hideWifiScanNotify() {
+ // The preconditions WiFi ON and Internet WiFi are already in setUp()
+
+ mInternetDialog.updateDialog(false);
+
+ assertThat(mWifiScanNotify.getVisibility()).isEqualTo(View.GONE);
+ }
+
+ @Test
+ public void updateDialog_wifiOffAndWifiScanOff_hideWifiScanNotify() {
+ when(mWifiManager.isWifiEnabled()).thenReturn(false);
+ when(mInternetDialogController.isWifiScanEnabled()).thenReturn(false);
+
+ mInternetDialog.updateDialog(false);
+
+ assertThat(mWifiScanNotify.getVisibility()).isEqualTo(View.GONE);
+ }
+
+ @Test
+ public void updateDialog_wifiOffAndWifiScanOnAndDeviceLocked_hideWifiScanNotify() {
+ when(mWifiManager.isWifiEnabled()).thenReturn(false);
+ when(mInternetDialogController.isWifiScanEnabled()).thenReturn(true);
+ when(mInternetDialogController.isDeviceLocked()).thenReturn(true);
+
+ mInternetDialog.updateDialog(false);
+
+ assertThat(mWifiScanNotify.getVisibility()).isEqualTo(View.GONE);
+ }
+
+ @Test
+ public void updateDialog_wifiOffAndWifiScanOnAndDeviceUnlocked_showWifiScanNotify() {
+ when(mWifiManager.isWifiEnabled()).thenReturn(false);
+ when(mInternetDialogController.isWifiScanEnabled()).thenReturn(true);
+ when(mInternetDialogController.isDeviceLocked()).thenReturn(false);
+
+ mInternetDialog.updateDialog(false);
+
+ assertThat(mWifiScanNotify.getVisibility()).isEqualTo(View.VISIBLE);
+ TextView wifiScanNotifyText = mDialogView.requireViewById(R.id.wifi_scan_notify_text);
+ assertThat(wifiScanNotifyText.getText().length()).isNotEqualTo(0);
+ assertThat(wifiScanNotifyText.getMovementMethod()).isNotNull();
+ }
+
+ @Test
public void onClickSeeMoreButton_clickSeeAll_verifyLaunchNetworkSetting() {
mSeeAll.performClick();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
index 2b569f31e916..5ed69853e40f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
@@ -102,6 +102,8 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
@Mock
private UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController;
@Mock
+ private StatusBarKeyguardViewManager.AlternateAuthInterceptor mAlternateAuthInterceptor;
+ @Mock
private KeyguardMessageArea mKeyguardMessageArea;
private WakefulnessLifecycle mWakefulnessLifecycle;
@@ -287,6 +289,24 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
}
@Test
+ public void testShowing_whenAlternateAuthShowing() {
+ mStatusBarKeyguardViewManager.setAlternateAuthInterceptor(mAlternateAuthInterceptor);
+ when(mBouncer.isShowing()).thenReturn(false);
+ when(mAlternateAuthInterceptor.isShowingAlternateAuthBouncer()).thenReturn(true);
+ assertTrue("Is showing not accurate when alternative auth showing",
+ mStatusBarKeyguardViewManager.isShowing());
+ }
+
+ @Test
+ public void testWillBeShowing_whenAlternateAuthShowing() {
+ mStatusBarKeyguardViewManager.setAlternateAuthInterceptor(mAlternateAuthInterceptor);
+ when(mBouncer.isShowing()).thenReturn(false);
+ when(mAlternateAuthInterceptor.isShowingAlternateAuthBouncer()).thenReturn(true);
+ assertTrue("Is or will be showing not accurate when alternative auth showing",
+ mStatusBarKeyguardViewManager.bouncerIsOrWillBeShowing());
+ }
+
+ @Test
public void testUpdateResources_delegatesToBouncer() {
mStatusBarKeyguardViewManager.updateResources();
diff --git a/proto/src/metrics_constants/OWNERS b/proto/src/metrics_constants/OWNERS
index 274d0d6323cf..7009282b66e1 100644
--- a/proto/src/metrics_constants/OWNERS
+++ b/proto/src/metrics_constants/OWNERS
@@ -1,3 +1,4 @@
cwren@android.com
yanglu@google.com
yaochen@google.com
+yro@google.com
diff --git a/services/OWNERS b/services/OWNERS
index b3bf5dcd2292..a08331996556 100644
--- a/services/OWNERS
+++ b/services/OWNERS
@@ -3,5 +3,5 @@ per-file Android.bp = file:platform/build/soong:/OWNERS
# art-team@ manages the system server profile
per-file art-profile* = calin@google.com, ngeoffray@google.com, vmarko@google.com
-per-file java/com/android/server/* = patb@google.com
+per-file java/com/android/server/* = toddke@google.com,patb@google.com
per-file tests/servicestests/src/com/android/server/systemconfig/* = patb@google.com
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
index 8a42ddfdc19d..757f1aeb275f 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
@@ -1072,26 +1072,18 @@ public final class ContentCaptureManagerService extends
ParcelFileDescriptor sourceOut = servicePipe.second;
ParcelFileDescriptor sinkOut = servicePipe.first;
- mParentService.mPackagesWithShareRequests.add(mDataShareRequest.getPackageName());
-
- try {
- mClientAdapter.write(sourceIn);
- } catch (RemoteException e) {
- Slog.e(TAG, "Failed to call write() the client operation", e);
- sendErrorSignal(mClientAdapter, serviceAdapter,
- ContentCaptureManager.DATA_SHARE_ERROR_UNKNOWN);
- logServiceEvent(
- CONTENT_CAPTURE_SERVICE_EVENTS__EVENT__DATA_SHARE_ERROR_CLIENT_PIPE_FAIL);
- return;
+ synchronized (mParentService.mLock) {
+ mParentService.mPackagesWithShareRequests.add(mDataShareRequest.getPackageName());
}
- try {
- serviceAdapter.start(sinkOut);
- } catch (RemoteException e) {
- Slog.e(TAG, "Failed to call start() the service operation", e);
+
+ if (!setUpSharingPipeline(mClientAdapter, serviceAdapter, sourceIn, sinkOut)) {
sendErrorSignal(mClientAdapter, serviceAdapter,
ContentCaptureManager.DATA_SHARE_ERROR_UNKNOWN);
- logServiceEvent(
- CONTENT_CAPTURE_SERVICE_EVENTS__EVENT__DATA_SHARE_ERROR_SERVICE_PIPE_FAIL);
+ bestEffortCloseFileDescriptors(sourceIn, sinkIn, sourceOut, sinkOut);
+ synchronized (mParentService.mLock) {
+ mParentService.mPackagesWithShareRequests
+ .remove(mDataShareRequest.getPackageName());
+ }
return;
}
@@ -1184,6 +1176,32 @@ public final class ContentCaptureManagerService extends
}
}
+ private boolean setUpSharingPipeline(
+ IDataShareWriteAdapter clientAdapter,
+ IDataShareReadAdapter serviceAdapter,
+ ParcelFileDescriptor sourceIn,
+ ParcelFileDescriptor sinkOut) {
+ try {
+ clientAdapter.write(sourceIn);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to call write() the client operation", e);
+ logServiceEvent(
+ CONTENT_CAPTURE_SERVICE_EVENTS__EVENT__DATA_SHARE_ERROR_CLIENT_PIPE_FAIL);
+ return false;
+ }
+
+ try {
+ serviceAdapter.start(sinkOut);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to call start() the service operation", e);
+ logServiceEvent(
+ CONTENT_CAPTURE_SERVICE_EVENTS__EVENT__DATA_SHARE_ERROR_SERVICE_PIPE_FAIL);
+ return false;
+ }
+
+ return true;
+ }
+
private void enforceDataSharingTtl(ParcelFileDescriptor sourceIn,
ParcelFileDescriptor sinkIn,
ParcelFileDescriptor sourceOut,
diff --git a/services/core/java/com/android/server/am/OWNERS b/services/core/java/com/android/server/am/OWNERS
index a5cfc4a62c96..c4efbd7e8f51 100644
--- a/services/core/java/com/android/server/am/OWNERS
+++ b/services/core/java/com/android/server/am/OWNERS
@@ -19,6 +19,7 @@ ogunwale@google.com
# Permissions & Packages
svetoslavganov@google.com
+toddke@google.com
patb@google.com
# Battery Stats
diff --git a/services/core/java/com/android/server/devicestate/OWNERS b/services/core/java/com/android/server/devicestate/OWNERS
index 7708505ae2dd..ae79fc0e2c2d 100644
--- a/services/core/java/com/android/server/devicestate/OWNERS
+++ b/services/core/java/com/android/server/devicestate/OWNERS
@@ -1,2 +1,3 @@
ogunwale@google.com
akulian@google.com
+darryljohnson@google.com
diff --git a/services/core/java/com/android/server/media/MediaRouterService.java b/services/core/java/com/android/server/media/MediaRouterService.java
index a57d7db0ec54..7502afc8cd82 100644
--- a/services/core/java/com/android/server/media/MediaRouterService.java
+++ b/services/core/java/com/android/server/media/MediaRouterService.java
@@ -338,6 +338,25 @@ public final class MediaRouterService extends IMediaRouterService.Stub
// Binder call
@Override
+ public void setBluetoothA2dpOn(IMediaRouterClient client, boolean on) {
+ if (client == null) {
+ throw new IllegalArgumentException("client must not be null");
+ }
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ mAudioService.setBluetoothA2dpOn(on);
+ }
+ } catch (RemoteException ex) {
+ Slog.w(TAG, "RemoteException while calling setBluetoothA2dpOn. on=" + on);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ // Binder call
+ @Override
public void setDiscoveryRequest(IMediaRouterClient client,
int routeTypes, boolean activeScan) {
if (client == null) {
diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
index 27b164830572..ee0b3d52eb3d 100644
--- a/services/core/java/com/android/server/om/OverlayManagerService.java
+++ b/services/core/java/com/android/server/om/OverlayManagerService.java
@@ -71,6 +71,7 @@ import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.AtomicFile;
+import android.util.EventLog;
import android.util.Slog;
import android.util.SparseArray;
@@ -81,7 +82,6 @@ import com.android.server.FgThread;
import com.android.server.LocalServices;
import com.android.server.SystemConfig;
import com.android.server.SystemService;
-
import com.android.server.pm.UserManagerService;
import com.android.server.pm.parsing.pkg.AndroidPackage;
@@ -285,6 +285,12 @@ public final class OverlayManagerService extends SystemService {
restoreSettings();
+ // Wipe all shell overlays on boot, to recover from a potentially broken device
+ String shellPkgName = TextUtils.emptyIfNull(
+ getContext().getString(android.R.string.config_systemShell));
+ mSettings.removeIf(overlayInfo -> overlayInfo.isFabricated
+ && shellPkgName.equals(overlayInfo.packageName));
+
initIfNeeded();
onSwitchUser(UserHandle.USER_SYSTEM);
@@ -891,6 +897,16 @@ public final class OverlayManagerService extends SystemService {
throw new IllegalArgumentException(request.typeToString()
+ " unsupported for user " + request.userId);
}
+
+ // Normal apps are blocked from accessing OMS via SELinux, so to block non-root,
+ // non privileged callers, a simple check against the shell UID is sufficient, since
+ // that's the only exception from the other categories. This is enough while OMS
+ // is not a public API, but this will have to be changed if it's ever exposed.
+ if (callingUid == Process.SHELL_UID) {
+ EventLog.writeEvent(0x534e4554, "202768292", -1, "");
+ throw new IllegalArgumentException("Non-root shell cannot fabricate overlays");
+ }
+
realUserId = UserHandle.USER_ALL;
// Enforce that the calling process can only register and unregister fabricated
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 00e54b1f6846..99f4a595ae8f 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -135,6 +135,8 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
private static final long MAX_ACTIVE_SESSIONS_NO_PERMISSION = 50;
/** Upper bound on number of historical sessions for a UID */
private static final long MAX_HISTORICAL_SESSIONS = 1048576;
+ /** Destroy sessions older than this on storage free request */
+ private static final long MAX_SESSION_AGE_ON_LOW_STORAGE_MILLIS = 8 * DateUtils.HOUR_IN_MILLIS;
/**
* Allow verification-skipping if it's a development app installed through ADB with
@@ -338,22 +340,28 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
@GuardedBy("mSessions")
private void reconcileStagesLocked(String volumeUuid) {
- final File stagingDir = getTmpSessionDir(volumeUuid);
- final ArraySet<File> unclaimedStages = newArraySet(
- stagingDir.listFiles(sStageFilter));
-
- // We also need to clean up orphaned staging directory for staged sessions
- final File stagedSessionStagingDir = Environment.getDataStagingDirectory(volumeUuid);
- unclaimedStages.addAll(newArraySet(stagedSessionStagingDir.listFiles()));
-
+ final ArraySet<File> unclaimedStages = getStagingDirsOnVolume(volumeUuid);
// Ignore stages claimed by active sessions
for (int i = 0; i < mSessions.size(); i++) {
final PackageInstallerSession session = mSessions.valueAt(i);
unclaimedStages.remove(session.stageDir);
}
+ removeStagingDirs(unclaimedStages);
+ }
+
+ private ArraySet<File> getStagingDirsOnVolume(String volumeUuid) {
+ final File stagingDir = getTmpSessionDir(volumeUuid);
+ final ArraySet<File> stagingDirs = newArraySet(stagingDir.listFiles(sStageFilter));
+
+ // We also need to clean up orphaned staging directory for staged sessions
+ final File stagedSessionStagingDir = Environment.getDataStagingDirectory(volumeUuid);
+ stagingDirs.addAll(newArraySet(stagedSessionStagingDir.listFiles()));
+ return stagingDirs;
+ }
+ private void removeStagingDirs(ArraySet<File> stagingDirsToRemove) {
// Clean up orphaned staging directories
- for (File stage : unclaimedStages) {
+ for (File stage : stagingDirsToRemove) {
Slog.w(TAG, "Deleting orphan stage " + stage);
synchronized (mPm.mInstallLock) {
mPm.removeCodePathLI(stage);
@@ -367,6 +375,33 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
}
}
+ /**
+ * Called to free up some storage space from obsolete installation files
+ */
+ public void freeStageDirs(String volumeUuid) {
+ final ArraySet<File> unclaimedStagingDirsOnVolume = getStagingDirsOnVolume(volumeUuid);
+ final long currentTimeMillis = System.currentTimeMillis();
+ synchronized (mSessions) {
+ for (int i = 0; i < mSessions.size(); i++) {
+ final PackageInstallerSession session = mSessions.valueAt(i);
+ if (!unclaimedStagingDirsOnVolume.contains(session.stageDir)) {
+ // Only handles sessions stored on the target volume
+ continue;
+ }
+ final long age = currentTimeMillis - session.createdMillis;
+ if (age >= MAX_SESSION_AGE_ON_LOW_STORAGE_MILLIS) {
+ // Aggressively close old sessions because we are running low on storage
+ // Their staging dirs will be removed too
+ session.abandon();
+ } else {
+ // Session is new enough, so it deserves to be kept even on low storage
+ unclaimedStagingDirsOnVolume.remove(session.stageDir);
+ }
+ }
+ }
+ removeStagingDirs(unclaimedStagingDirsOnVolume);
+ }
+
public static boolean isStageName(String name) {
final boolean isFile = name.startsWith("vmdl") && name.endsWith(".tmp");
final boolean isContainer = name.startsWith("smdl") && name.endsWith(".tmp");
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 542948491dc8..d0e445749698 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -673,7 +673,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
final Runnable r;
synchronized (mLock) {
assertNotChildLocked("StagedSession#abandon");
- assertCallerIsOwnerOrRoot();
+ assertCallerIsOwnerOrRootOrSystem();
if (isInTerminalState()) {
// We keep the session in the database if it's in a finalized state. It will be
// removed by PackageInstallerService when the last update time is old enough.
@@ -3704,7 +3704,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
private void abandonNonStaged() {
synchronized (mLock) {
assertNotChildLocked("abandonNonStaged");
- assertCallerIsOwnerOrRoot();
+ assertCallerIsOwnerOrRootOrSystem();
if (mRelinquished) {
if (LOGD) Slog.d(TAG, "Ignoring abandon after commit relinquished control");
return;
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 3e0a7fdd51ef..bc28cffbcbfc 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -9305,6 +9305,10 @@ public class PackageManagerService extends IPackageManager.Stub
if (freeBytesRequired > 0) {
smInternal.freeCache(volumeUuid, freeBytesRequired);
}
+
+ // 12. Clear temp install session files
+ mInstallerService.freeStageDirs(volumeUuid);
+
if (file.getUsableSpace() >= bytes) return;
} else {
try {
diff --git a/services/core/java/com/android/server/pm/verify/domain/OWNERS b/services/core/java/com/android/server/pm/verify/domain/OWNERS
index 445a8330037b..c669112e0512 100644
--- a/services/core/java/com/android/server/pm/verify/domain/OWNERS
+++ b/services/core/java/com/android/server/pm/verify/domain/OWNERS
@@ -2,3 +2,4 @@
chiuwinson@google.com
patb@google.com
+toddke@google.com \ No newline at end of file
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index e05f7ef135fa..34a49ccd8040 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -4668,6 +4668,12 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return mKeyguardDelegate.isInputRestricted();
}
+ /** {@inheritDoc} */
+ @Override
+ public boolean isKeyguardUnoccluding() {
+ return keyguardOn() && !mWindowManagerFuncs.isAppTransitionStateIdle();
+ }
+
@Override
public void dismissKeyguardLw(IKeyguardDismissCallback callback, CharSequence message) {
if (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()) {
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index 78b03b2b88e7..510ab93e1af5 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -367,6 +367,12 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants {
* as the top display.
*/
void moveDisplayToTop(int displayId);
+
+ /**
+ * Return whether the app transition state is idle.
+ * @return {@code true} if app transition state is idle on the default display.
+ */
+ boolean isAppTransitionStateIdle();
}
/**
@@ -974,6 +980,14 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants {
public boolean isKeyguardOccluded();
/**
+ * Return whether the keyguard is unoccluding.
+ * @return {@code true} if the keyguard is unoccluding.
+ */
+ default boolean isKeyguardUnoccluding() {
+ return false;
+ }
+
+ /**
* @return true if in keyguard is on.
*/
boolean isKeyguardShowing();
diff --git a/services/core/java/com/android/server/stats/OWNERS b/services/core/java/com/android/server/stats/OWNERS
index 2450dbb6bfcd..174ad3ad2e25 100644
--- a/services/core/java/com/android/server/stats/OWNERS
+++ b/services/core/java/com/android/server/stats/OWNERS
@@ -8,3 +8,4 @@ sharaienko@google.com
singhtejinder@google.com
tsaichristine@google.com
yaochen@google.com
+yro@google.com
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index c1b287ff8077..c61cfeeac917 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -365,6 +365,10 @@ public class AppTransition implements Dump {
setAppTransitionState(APP_STATE_IDLE);
}
+ boolean isIdle() {
+ return mAppTransitionState == APP_STATE_IDLE;
+ }
+
boolean isTimeout() {
return mAppTransitionState == APP_STATE_TIMEOUT;
}
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index d0457b08aa34..b87d6f4fdf57 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -56,6 +56,7 @@ import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
+import static android.view.WindowManager.LayoutParams.FLAG_SLIPPERY;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
@@ -848,6 +849,20 @@ public class DisplayPolicy {
}
/**
+ * Only trusted overlays are allowed to use FLAG_SLIPPERY.
+ */
+ static int sanitizeFlagSlippery(int flags, int privateFlags, String name) {
+ if ((flags & FLAG_SLIPPERY) == 0) {
+ return flags;
+ }
+ if ((privateFlags & PRIVATE_FLAG_TRUSTED_OVERLAY) != 0) {
+ return flags;
+ }
+ Slog.w(TAG, "Removing FLAG_SLIPPERY for non-trusted overlay " + name);
+ return flags & ~FLAG_SLIPPERY;
+ }
+
+ /**
* Sanitize the layout parameters coming from a client. Allows the policy
* to do things like ensure that windows of a specific type can't take
* input focus.
@@ -927,6 +942,8 @@ public class DisplayPolicy {
if (mExtraNavBarAlt == win) {
mExtraNavBarAltPosition = getAltBarPosition(attrs);
}
+
+ attrs.flags = sanitizeFlagSlippery(attrs.flags, attrs.privateFlags, win.getName());
}
/**
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index bd688a618c63..52da4b80a75d 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -2125,6 +2125,9 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
final Task rootTask;
if (singleActivity) {
rootTask = task;
+
+ // Apply the last recents animation leash transform to the task entering PIP
+ rootTask.maybeApplyLastRecentsAnimationTransaction();
} else {
// In the case of multiple activities, we will create a new task for it and then
// move the PIP activity into the task. Note that we explicitly defer the task
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
index 4ff6d3c9a5f2..1f2a9a29932c 100644
--- a/services/core/java/com/android/server/wm/WallpaperController.java
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -159,7 +159,8 @@ class WallpaperController {
boolean needsShowWhenLockedWallpaper = false;
if ((w.mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0
&& mService.mPolicy.isKeyguardLocked()
- && mService.mPolicy.isKeyguardOccluded()) {
+ && (mService.mPolicy.isKeyguardOccluded()
+ || mService.mPolicy.isKeyguardUnoccluding())) {
// The lowest show when locked window decides whether we need to put the wallpaper
// behind.
needsShowWhenLockedWallpaper = !isFullscreen(w.mAttrs)
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 68e85c85b995..56bc1d80e9ec 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -56,6 +56,7 @@ import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
+import static android.view.WindowManager.LayoutParams.FLAG_SLIPPERY;
import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL;
import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE;
import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
@@ -3081,6 +3082,11 @@ public class WindowManagerService extends IWindowManager.Stub
syncInputTransactions(true /* waitForAnimations */);
}
+ @Override
+ public boolean isAppTransitionStateIdle() {
+ return getDefaultDisplayContentLocked().mAppTransition.isIdle();
+ }
+
/**
* Notifies activity manager that some Keyguard flags have changed and that it needs to
* reevaluate the visibilities of the activities.
@@ -8267,8 +8273,10 @@ public class WindowManagerService extends IWindowManager.Stub
h.token = channelToken;
h.name = name;
+ flags = DisplayPolicy.sanitizeFlagSlippery(flags, privateFlags, name);
+
final int sanitizedFlags = flags & (LayoutParams.FLAG_NOT_TOUCHABLE
- | LayoutParams.FLAG_SLIPPERY | LayoutParams.FLAG_NOT_FOCUSABLE);
+ | FLAG_SLIPPERY | LayoutParams.FLAG_NOT_FOCUSABLE);
h.layoutParamsFlags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | sanitizedFlags;
h.layoutParamsType = type;
h.dispatchingTimeoutMillis = DEFAULT_DISPATCHING_TIMEOUT_MILLIS;
diff --git a/services/core/jni/stats/OWNERS b/services/core/jni/stats/OWNERS
index 552cc0d31304..2611e5b6cee2 100644
--- a/services/core/jni/stats/OWNERS
+++ b/services/core/jni/stats/OWNERS
@@ -1,6 +1,8 @@
jeffreyhuang@google.com
jtnguyen@google.com
muhammadq@google.com
+sharaieko@google.com
singhtejinder@google.com
tsaichristine@google.com
yaochen@google.com
+yro@google.com
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 9ceabce398ed..0792d9bde4b4 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -12648,6 +12648,13 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
@Override
+ public @Nullable ComponentName getProfileOwnerOrDeviceOwnerSupervisionComponent(
+ @NonNull UserHandle userHandle) {
+ return DevicePolicyManagerService.this.getProfileOwnerOrDeviceOwnerSupervisionComponent(
+ userHandle);
+ }
+
+ @Override
public boolean isActiveDeviceOwner(int uid) {
return isDeviceOwner(new CallerIdentity(uid, null, null));
}
diff --git a/services/incremental/OWNERS b/services/incremental/OWNERS
index fe8c253aa793..7ebb962c8feb 100644
--- a/services/incremental/OWNERS
+++ b/services/incremental/OWNERS
@@ -3,5 +3,6 @@ include /services/core/java/com/android/server/pm/OWNERS
alexbuy@google.com
schfan@google.com
+toddke@google.com
zyy@google.com
patb@google.com
diff --git a/services/tests/mockingservicestests/src/com/android/server/usage/UserUsageStatsServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/usage/UserUsageStatsServiceTest.java
index 24c58f49bed6..7358551d1bc5 100644
--- a/services/tests/mockingservicestests/src/com/android/server/usage/UserUsageStatsServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/usage/UserUsageStatsServiceTest.java
@@ -72,7 +72,7 @@ public class UserUsageStatsServiceTest {
HashMap<String, Long> installedPkgs = new HashMap<>();
installedPkgs.put(TEST_PACKAGE_NAME, System.currentTimeMillis());
- mService.init(System.currentTimeMillis(), installedPkgs);
+ mService.init(System.currentTimeMillis(), installedPkgs, true);
}
@After
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 1b8492722c10..ac1fcce20dc0 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -380,6 +380,7 @@ public class UsageStatsService extends SystemService implements
if (userId == UserHandle.USER_SYSTEM) {
UsageStatsIdleService.scheduleUpdateMappingsJob(getContext());
}
+ final boolean deleteObsoleteData = shouldDeleteObsoleteData(UserHandle.of(userId));
synchronized (mLock) {
// This should be safe to add this early. Other than reportEventOrAddToQueue, every
// other user grabs the lock before accessing
@@ -402,7 +403,7 @@ public class UsageStatsService extends SystemService implements
boolean needToFlush = !pendingEvents.isEmpty();
initializeUserUsageStatsServiceLocked(userId, System.currentTimeMillis(),
- installedPackages);
+ installedPackages, deleteObsoleteData);
final UserUsageStatsService userService = getUserUsageStatsServiceLocked(userId);
if (userService == null) {
Slog.i(TAG, "Attempted to unlock stopped or removed user " + userId);
@@ -596,13 +597,13 @@ public class UsageStatsService extends SystemService implements
* when the user is initially unlocked.
*/
private void initializeUserUsageStatsServiceLocked(int userId, long currentTimeMillis,
- HashMap<String, Long> installedPackages) {
+ HashMap<String, Long> installedPackages, boolean deleteObsoleteData) {
final File usageStatsDir = new File(Environment.getDataSystemCeDirectory(userId),
"usagestats");
final UserUsageStatsService service = new UserUsageStatsService(getContext(), userId,
usageStatsDir, this);
try {
- service.init(currentTimeMillis, installedPackages);
+ service.init(currentTimeMillis, installedPackages, deleteObsoleteData);
mUserState.put(userId, service);
} catch (Exception e) {
if (mUserManager.isUserUnlocked(userId)) {
@@ -1165,6 +1166,10 @@ public class UsageStatsService extends SystemService implements
* Called by the Binder stub.
*/
private boolean updatePackageMappingsData() {
+ // don't update the mappings if a profile user is defined
+ if (!shouldDeleteObsoleteData(UserHandle.SYSTEM)) {
+ return true; // return true so job scheduler doesn't reschedule the job
+ }
// fetch the installed packages outside the lock so it doesn't block package manager.
final HashMap<String, Long> installedPkgs = getInstalledPackages(UserHandle.USER_SYSTEM);
synchronized (mLock) {
@@ -1309,6 +1314,13 @@ public class UsageStatsService extends SystemService implements
}
}
+ private boolean shouldDeleteObsoleteData(UserHandle userHandle) {
+ final DevicePolicyManagerInternal dpmInternal = getDpmInternal();
+ // If a profile owner is not defined for the given user, obsolete data should be deleted
+ return dpmInternal == null
+ || dpmInternal.getProfileOwnerOrDeviceOwnerSupervisionComponent(userHandle) == null;
+ }
+
private String buildFullToken(String packageName, String token) {
final StringBuilder sb = new StringBuilder(packageName.length() + token.length() + 1);
sb.append(packageName);
@@ -2532,8 +2544,12 @@ public class UsageStatsService extends SystemService implements
private class MyPackageMonitor extends PackageMonitor {
@Override
public void onPackageRemoved(String packageName, int uid) {
- mHandler.obtainMessage(MSG_PACKAGE_REMOVED, getChangingUserId(), 0, packageName)
- .sendToTarget();
+ final int changingUserId = getChangingUserId();
+ // Only remove the package's data if a profile owner is not defined for the user
+ if (shouldDeleteObsoleteData(UserHandle.of(changingUserId))) {
+ mHandler.obtainMessage(MSG_PACKAGE_REMOVED, changingUserId, 0, packageName)
+ .sendToTarget();
+ }
super.onPackageRemoved(packageName, uid);
}
}
diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
index 36d8c857ca21..fee4a47fd6ff 100644
--- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
@@ -115,8 +115,9 @@ class UserUsageStatsService {
mSystemTimeSnapshot = System.currentTimeMillis();
}
- void init(final long currentTimeMillis, HashMap<String, Long> installedPackages) {
- readPackageMappingsLocked(installedPackages);
+ void init(final long currentTimeMillis, HashMap<String, Long> installedPackages,
+ boolean deleteObsoleteData) {
+ readPackageMappingsLocked(installedPackages, deleteObsoleteData);
mDatabase.init(currentTimeMillis);
if (mDatabase.wasUpgradePerformed()) {
mDatabase.prunePackagesDataOnUpgrade(installedPackages);
@@ -180,12 +181,13 @@ class UserUsageStatsService {
return mDatabase.onPackageRemoved(packageName, timeRemoved);
}
- private void readPackageMappingsLocked(HashMap<String, Long> installedPackages) {
+ private void readPackageMappingsLocked(HashMap<String, Long> installedPackages,
+ boolean deleteObsoleteData) {
mDatabase.readMappingsLocked();
// Package mappings for the system user are updated after 24 hours via a job scheduled by
// UsageStatsIdleService to ensure restored data is not lost on first boot. Additionally,
// this makes user service initialization a little quicker on subsequent boots.
- if (mUserId != UserHandle.USER_SYSTEM) {
+ if (mUserId != UserHandle.USER_SYSTEM && deleteObsoleteData) {
updatePackageMappingsLocked(installedPackages);
}
}
diff --git a/services/uwb/java/com/android/server/uwb/UwbServiceImpl.java b/services/uwb/java/com/android/server/uwb/UwbServiceImpl.java
index 70d6aab542a2..889e182af46b 100644
--- a/services/uwb/java/com/android/server/uwb/UwbServiceImpl.java
+++ b/services/uwb/java/com/android/server/uwb/UwbServiceImpl.java
@@ -356,7 +356,7 @@ public class UwbServiceImpl extends IUwbAdapter.Stub implements IBinder.DeathRec
private void handleAirplaneModeEvent() {
try {
getVendorUwbAdapter().setEnabled(isEnabled());
- } catch (RemoteException e) {
+ } catch (RemoteException | IllegalStateException e) {
Log.e(TAG, "Unable to set UWB Adapter state.", e);
}
}
diff --git a/telephony/OWNERS b/telephony/OWNERS
index 4016ba7de379..f248fd52db83 100644
--- a/telephony/OWNERS
+++ b/telephony/OWNERS
@@ -1,5 +1,6 @@
set noparent
+amitmahajan@google.com
breadley@google.com
fionaxu@google.com
jackyu@google.com
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 5ffe45f8c489..0445efad864f 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -964,6 +964,21 @@ public class CarrierConfigManager {
= "carrier_use_ims_first_for_emergency_bool";
/**
+ * When {@code true}, the determination of whether to place a call as an emergency call will be
+ * based on the known {@link android.telephony.emergency.EmergencyNumber}s for the SIM on which
+ * the call is being placed. In a dual SIM scenario, if Sim A has the emergency numbers
+ * 123, 456 and Sim B has the emergency numbers 789, and the user places a call on SIM A to 789,
+ * it will not be treated as an emergency call in this case.
+ * When {@code false}, the determination is based on the emergency numbers from all device SIMs,
+ * regardless of which SIM the call is being placed on. If Sim A has the emergency numbers
+ * 123, 456 and Sim B has the emergency numbers 789, and the user places a call on SIM A to 789,
+ * the call will be dialed as an emergency number, but with an unspecified routing.
+ * @hide
+ */
+ public static final String KEY_USE_ONLY_DIALED_SIM_ECC_LIST_BOOL =
+ "use_only_dialed_sim_ecc_list_bool";
+
+ /**
* When IMS instant lettering is available for a carrier (see
* {@link #KEY_CARRIER_INSTANT_LETTERING_AVAILABLE_BOOL}), determines the list of characters
* which may not be contained in messages. Should be specified as a regular expression suitable
@@ -5328,6 +5343,7 @@ public class CarrierConfigManager {
sDefaults.putBoolean(KEY_CARRIER_IMS_GBA_REQUIRED_BOOL, false);
sDefaults.putBoolean(KEY_CARRIER_INSTANT_LETTERING_AVAILABLE_BOOL, false);
sDefaults.putBoolean(KEY_CARRIER_USE_IMS_FIRST_FOR_EMERGENCY_BOOL, true);
+ sDefaults.putBoolean(KEY_USE_ONLY_DIALED_SIM_ECC_LIST_BOOL, false);
sDefaults.putString(KEY_CARRIER_NETWORK_SERVICE_WWAN_PACKAGE_OVERRIDE_STRING, "");
sDefaults.putString(KEY_CARRIER_NETWORK_SERVICE_WLAN_PACKAGE_OVERRIDE_STRING, "");
sDefaults.putString(KEY_CARRIER_QUALIFIED_NETWORKS_SERVICE_PACKAGE_OVERRIDE_STRING, "");
diff --git a/tests/Codegen/OWNERS b/tests/Codegen/OWNERS
index e69de29bb2d1..da723b3b67da 100644
--- a/tests/Codegen/OWNERS
+++ b/tests/Codegen/OWNERS
@@ -0,0 +1 @@
+eugenesusla@google.com \ No newline at end of file
diff --git a/tools/aapt2/OWNERS b/tools/aapt2/OWNERS
index a96d15ea8233..4f655e54a7c2 100644
--- a/tools/aapt2/OWNERS
+++ b/tools/aapt2/OWNERS
@@ -1,3 +1,4 @@
set noparent
+toddke@google.com
zyy@google.com
patb@google.com \ No newline at end of file
diff --git a/tools/codegen/OWNERS b/tools/codegen/OWNERS
index e69de29bb2d1..da723b3b67da 100644
--- a/tools/codegen/OWNERS
+++ b/tools/codegen/OWNERS
@@ -0,0 +1 @@
+eugenesusla@google.com \ No newline at end of file