From 9841b9006104a2109016c0d6a82e761b54bf35fd Mon Sep 17 00:00:00 2001 From: Yimin Li Date: Tue, 22 Sep 2020 21:17:56 +0000 Subject: Revert "Merge commit '973dd92cab00df73a6bdd1ac637a311b5d02a856' into manual_merge_973dd92cab00df73a6bdd1ac637a311b5d02a856" This reverts commit 56822cc786ec291d488a69c67ce47f9144db176e. Reason for revert: Change-Id: I87d1335864a58eef80a34a95ddceb33b252e4467 --- .../com/android/systemui/statusbar/policy/BatteryController.java | 4 ++-- .../android/systemui/statusbar/policy/BatteryControllerImpl.java | 8 -------- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java index 94b2f5215264..b9168e3c2223 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java @@ -53,9 +53,9 @@ public interface BatteryController extends DemoMode, Dumpable, boolean isAodPowerSave(); /** - * Returns {@code true} if the device is currently in wireless charging mode. + * Initializes the class. */ - default boolean isWirelessCharging() { return false; }6 + default void init() { } /** * Returns {@code true} if reverse is supported. diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java index d30f01a658f6..8bd236681594 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java @@ -73,7 +73,6 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC private boolean mCharged; protected boolean mPowerSave; private boolean mAodPowerSave; - protected boolean mWirelessCharging; private boolean mTestmode = false; @VisibleForTesting boolean mHasReceivedBattery = false; @@ -165,8 +164,6 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC BatteryManager.BATTERY_STATUS_UNKNOWN); mCharged = status == BatteryManager.BATTERY_STATUS_FULL; mCharging = mCharged || status == BatteryManager.BATTERY_STATUS_CHARGING; - mWirelessCharging = mCharging && intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) - == BatteryManager.BATTERY_PLUGGED_WIRELESS; fireBatteryLevelChanged(); } else if (action.equals(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED)) { @@ -221,11 +218,6 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC return mAodPowerSave; } - @Override - public boolean isWirelessCharging() { - return mWirelessCharging; - } - @Override public void getEstimatedTimeRemainingString(EstimateFetchCompletion completion) { // Need to fetch or refresh the estimate, but it may involve binder calls so offload the -- cgit v1.2.3 From b6c83e5f98f5db624dbe4201398c3025fa18d5df Mon Sep 17 00:00:00 2001 From: Yimin Li Date: Tue, 22 Sep 2020 21:23:51 +0000 Subject: Revert "Revert "Merge commit '973dd92cab00df73a6bdd1ac637a311b5d02a856' into manual_merge_973dd92cab00df73a6bdd1ac637a311b5d02a856"" This reverts commit 9841b9006104a2109016c0d6a82e761b54bf35fd. Reason for revert: Change-Id: I1a82feb29d1e9313a07d5495f64950d58eebc59b --- .../com/android/systemui/statusbar/policy/BatteryController.java | 4 ++-- .../android/systemui/statusbar/policy/BatteryControllerImpl.java | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java index b9168e3c2223..94b2f5215264 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java @@ -53,9 +53,9 @@ public interface BatteryController extends DemoMode, Dumpable, boolean isAodPowerSave(); /** - * Initializes the class. + * Returns {@code true} if the device is currently in wireless charging mode. */ - default void init() { } + default boolean isWirelessCharging() { return false; }6 /** * Returns {@code true} if reverse is supported. diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java index 8bd236681594..d30f01a658f6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java @@ -73,6 +73,7 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC private boolean mCharged; protected boolean mPowerSave; private boolean mAodPowerSave; + protected boolean mWirelessCharging; private boolean mTestmode = false; @VisibleForTesting boolean mHasReceivedBattery = false; @@ -164,6 +165,8 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC BatteryManager.BATTERY_STATUS_UNKNOWN); mCharged = status == BatteryManager.BATTERY_STATUS_FULL; mCharging = mCharged || status == BatteryManager.BATTERY_STATUS_CHARGING; + mWirelessCharging = mCharging && intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) + == BatteryManager.BATTERY_PLUGGED_WIRELESS; fireBatteryLevelChanged(); } else if (action.equals(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED)) { @@ -218,6 +221,11 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC return mAodPowerSave; } + @Override + public boolean isWirelessCharging() { + return mWirelessCharging; + } + @Override public void getEstimatedTimeRemainingString(EstimateFetchCompletion completion) { // Need to fetch or refresh the estimate, but it may involve binder calls so offload the -- cgit v1.2.3 From 63c78bcc4187102083a23527d31fe21cf2465333 Mon Sep 17 00:00:00 2001 From: Yimin Li Date: Tue, 22 Sep 2020 16:18:19 -0700 Subject: Changes to be committed: modified: packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java Change-Id: I01a4b490f0b2bfca625b7425bf549fc123dc5210 --- .../src/com/android/systemui/statusbar/policy/BatteryController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java index 94b2f5215264..21e2e580df4a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java @@ -55,7 +55,7 @@ public interface BatteryController extends DemoMode, Dumpable, /** * Returns {@code true} if the device is currently in wireless charging mode. */ - default boolean isWirelessCharging() { return false; }6 + default boolean isWirelessCharging() { return false; } /** * Returns {@code true} if reverse is supported. -- cgit v1.2.3 From 111d61551cbaddf772520b1f6b21a72824a41a05 Mon Sep 17 00:00:00 2001 From: Yimin Li Date: Thu, 24 Sep 2020 21:36:06 -0700 Subject: Changes to be committed: new file: telephony/framework-telephony-jarjar-rules.txt Change-Id: I7416dea95fce8abc25c3fa245337f997ead56f5d --- telephony/framework-telephony-jarjar-rules.txt | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 telephony/framework-telephony-jarjar-rules.txt diff --git a/telephony/framework-telephony-jarjar-rules.txt b/telephony/framework-telephony-jarjar-rules.txt new file mode 100644 index 000000000000..212eba153a15 --- /dev/null +++ b/telephony/framework-telephony-jarjar-rules.txt @@ -0,0 +1,9 @@ +rule android.telephony.Annotation* android.telephony.framework.Annotation@1 +rule android.util.RecurrenceRule* android.telephony.RecurrenceRule@1 +rule com.android.i18n.phonenumbers.** com.android.telephony.framework.phonenumbers.@1 +rule com.android.internal.os.SomeArgs* android.telephony.SomeArgs@1 +rule com.android.internal.util.BitwiseInputStream* android.telephony.BitwiseInputStream@1 +rule com.android.internal.util.BitwiseOutputStream* android.telephony.BitwiseOutputStream@1 +rule com.android.internal.util.Preconditions* android.telephony.Preconditions@1 +rule com.android.internal.util.IndentingPrintWriter* android.telephony.IndentingPrintWriter@1 +rule com.android.internal.util.HexDump* android.telephony.HexDump@1 -- cgit v1.2.3 From a6edc2fdb12cf9a5a37662ebcb854970d906ca74 Mon Sep 17 00:00:00 2001 From: Yimin Li Date: Thu, 8 Oct 2020 13:44:41 -0700 Subject: Solve Merge Errors Change-Id: Iacd7b1878320c460b2aa03b025e8b33f820a6a7c --- .../src/com/android/systemui/doze/DozeFactory.java | 1 - .../src/com/android/systemui/doze/DozeSensors.java | 56 +++++++++------ .../com/android/systemui/doze/DozeTriggers.java | 83 ++++++++++++++++++++-- .../systemui/util/sensors/ProximitySensor.java | 15 ++-- 4 files changed, 118 insertions(+), 37 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java index 6aa221b46c4e..3bac196ca59f 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java @@ -70,7 +70,6 @@ public class DozeFactory { DockManager dockManager, @Nullable IWallpaperManager wallpaperManager, ProximitySensor proximitySensor, ProximitySensor.ProximityCheck proximityCheck, DelayedWakeLock.Builder delayedWakeLockBuilder, @Main Handler handler, - @Main DelayableExecutor delayableExecutor, BiometricUnlockController biometricUnlockController, BroadcastDispatcher broadcastDispatcher, DozeHost dozeHost) { mFalsingManager = falsingManager; diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java index 4c9f28799583..aebf41b884c4 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java @@ -42,6 +42,9 @@ import android.view.Display; import androidx.annotation.VisibleForTesting; import com.android.internal.logging.MetricsLogger; +import com.android.internal.logging.UiEvent; +import com.android.internal.logging.UiEventLogger; +import com.android.internal.logging.UiEventLoggerImpl; import com.android.internal.logging.nano.MetricsProto; import com.android.systemui.plugins.SensorManagerPlugin; import com.android.systemui.statusbar.phone.DozeParameters; @@ -57,14 +60,13 @@ import java.util.function.Consumer; public class DozeSensors { private static final boolean DEBUG = DozeService.DEBUG; - private static final String TAG = "DozeSensors"; + private static final UiEventLogger UI_EVENT_LOGGER = new UiEventLoggerImpl(); private final Context mContext; private final AlarmManager mAlarmManager; private final AsyncSensorManager mSensorManager; private final ContentResolver mResolver; - private final TriggerSensor mPickupSensor; private final DozeParameters mDozeParameters; private final AmbientDisplayConfiguration mConfig; private final WakeLock mWakeLock; @@ -78,7 +80,23 @@ public class DozeSensors { private long mDebounceFrom; private boolean mSettingRegistered; private boolean mListening; - private boolean mPaused; + + @VisibleForTesting + public enum DozeSensorsUiEvent implements UiEventLogger.UiEventEnum { + @UiEvent(doc = "User performs pickup gesture that activates the ambient display") + ACTION_AMBIENT_GESTURE_PICKUP(459); + + private final int mId; + + DozeSensorsUiEvent(int id) { + mId = id; + } + + @Override + public int getId() { + return mId; + } + } public DozeSensors(Context context, AlarmManager alarmManager, AsyncSensorManager sensorManager, DozeParameters dozeParameters, AmbientDisplayConfiguration config, WakeLock wakeLock, @@ -93,6 +111,7 @@ public class DozeSensors { mProxCallback = proxCallback; mResolver = mContext.getContentResolver(); mCallback = callback; + mProximitySensor = proximitySensor; boolean alwaysOn = mConfig.alwaysOnEnabled(UserHandle.USER_CURRENT); mSensors = new TriggerSensor[] { @@ -102,7 +121,7 @@ public class DozeSensors { dozeParameters.getPulseOnSigMotion(), DozeLog.PULSE_REASON_SENSOR_SIGMOTION, false /* touchCoords */, false /* touchscreen */, dozeLog), - mPickupSensor = new TriggerSensor( + new TriggerSensor( mSensorManager.getDefaultSensor(Sensor.TYPE_PICK_UP_GESTURE), Settings.Secure.DOZE_PICK_UP_GESTURE, true /* settingDef */, @@ -155,7 +174,6 @@ public class DozeSensors { dozeLog), }; - mProximitySensor = proximitySensor; setProxListening(false); // Don't immediately start listening when we register. mProximitySensor.register( proximityEvent -> { @@ -165,6 +183,17 @@ public class DozeSensors { }); } + /** + * Unregister any sensors. + */ + public void destroy() { + // Unregisters everything, which is enough to allow gc. + for (TriggerSensor triggerSensor : mSensors) { + triggerSensor.setListening(false); + } + mProximitySensor.pause(); + } + /** * Temporarily disable some sensors to avoid turning on the device while the user is * turning it off. @@ -201,18 +230,6 @@ public class DozeSensors { updateListening(); } - /** - * Unregister sensors, when listening, unless they are prox gated. - * @see #setListening(boolean) - */ - public void setPaused(boolean paused) { - if (mPaused == paused) { - return; - } - mPaused = paused; - updateListening(); - } - /** * Registers/unregisters sensors based on internal state. */ @@ -281,10 +298,6 @@ public class DozeSensors { } }; - public void setDisableSensorsInterferingWithProximity(boolean disable) { - mPickupSensor.setDisabled(disable); - } - /** Ignore the setting value of only the sensors that require the touchscreen. */ public void ignoreTouchScreenSensorsSettingInterferingWithDocking(boolean ignore) { for (TriggerSensor sensor : mSensors) { @@ -414,6 +427,7 @@ public class DozeSensors { MetricsLogger.action( mContext, MetricsProto.MetricsEvent.ACTION_AMBIENT_GESTURE, subType); + UI_EVENT_LOGGER.log(DozeSensorsUiEvent.ACTION_AMBIENT_GESTURE_PICKUP); } mRegistered = false; diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java index b8c770fd05f5..cbf8f578744c 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java @@ -26,7 +26,6 @@ import android.content.IntentFilter; import android.content.res.Configuration; import android.hardware.display.AmbientDisplayConfiguration; import android.metrics.LogMaker; -import android.os.Handler; import android.os.SystemClock; import android.os.UserHandle; import android.text.format.Formatter; @@ -35,6 +34,9 @@ import android.view.Display; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.logging.MetricsLogger; +import com.android.internal.logging.UiEvent; +import com.android.internal.logging.UiEventLogger; +import com.android.internal.logging.UiEventLoggerImpl; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.systemui.Dependency; import com.android.systemui.broadcast.BroadcastDispatcher; @@ -46,6 +48,7 @@ import com.android.systemui.util.sensors.ProximitySensor; import com.android.systemui.util.wakelock.WakeLock; import java.io.PrintWriter; +import java.util.Optional; import java.util.function.Consumer; /** @@ -59,6 +62,8 @@ public class DozeTriggers implements DozeMachine.Part { /** adb shell am broadcast -a com.android.systemui.doze.pulse com.android.systemui */ private static final String PULSE_ACTION = "com.android.systemui.doze.pulse"; + private static final UiEventLogger UI_EVENT_LOGGER = new UiEventLoggerImpl(); + /** * Last value sent by the wake-display sensor. * Assuming that the screen should start on. @@ -92,12 +97,68 @@ public class DozeTriggers implements DozeMachine.Part { private boolean mWantSensors; private boolean mWantTouchScreenSensors; + @VisibleForTesting + public enum DozingUpdateUiEvent implements UiEventLogger.UiEventEnum { + @UiEvent(doc = "Dozing updated due to notification.") + DOZING_UPDATE_NOTIFICATION(433), + + @UiEvent(doc = "Dozing updated due to sigmotion.") + DOZING_UPDATE_SIGMOTION(434), + + @UiEvent(doc = "Dozing updated because sensor was picked up.") + DOZING_UPDATE_SENSOR_PICKUP(435), + + @UiEvent(doc = "Dozing updated because sensor was double tapped.") + DOZING_UPDATE_SENSOR_DOUBLE_TAP(436), + + @UiEvent(doc = "Dozing updated because sensor was long squeezed.") + DOZING_UPDATE_SENSOR_LONG_SQUEEZE(437), + + @UiEvent(doc = "Dozing updated due to docking.") + DOZING_UPDATE_DOCKING(438), + + @UiEvent(doc = "Dozing updated because sensor woke up.") + DOZING_UPDATE_SENSOR_WAKEUP(439), + + @UiEvent(doc = "Dozing updated because sensor woke up the lockscreen.") + DOZING_UPDATE_SENSOR_WAKE_LOCKSCREEN(440), + + @UiEvent(doc = "Dozing updated because sensor was tapped.") + DOZING_UPDATE_SENSOR_TAP(441); + + private final int mId; + + DozingUpdateUiEvent(int id) { + mId = id; + } + + @Override + public int getId() { + return mId; + } + + static DozingUpdateUiEvent fromReason(int reason) { + switch (reason) { + case 1: return DOZING_UPDATE_NOTIFICATION; + case 2: return DOZING_UPDATE_SIGMOTION; + case 3: return DOZING_UPDATE_SENSOR_PICKUP; + case 4: return DOZING_UPDATE_SENSOR_DOUBLE_TAP; + case 5: return DOZING_UPDATE_SENSOR_LONG_SQUEEZE; + case 6: return DOZING_UPDATE_DOCKING; + case 7: return DOZING_UPDATE_SENSOR_WAKEUP; + case 8: return DOZING_UPDATE_SENSOR_WAKE_LOCKSCREEN; + case 9: return DOZING_UPDATE_SENSOR_TAP; + default: return null; + } + } + } + public DozeTriggers(Context context, DozeMachine machine, DozeHost dozeHost, AlarmManager alarmManager, AmbientDisplayConfiguration config, - DozeParameters dozeParameters, AsyncSensorManager sensorManager, Handler handler, + DozeParameters dozeParameters, AsyncSensorManager sensorManager, WakeLock wakeLock, boolean allowPulseTriggers, DockManager dockManager, - ProximitySensor proximitySensor, DozeLog dozeLog, - BroadcastDispatcher broadcastDispatcher) { + ProximitySensor proximitySensor, ProximitySensor.ProximityCheck proxCheck, + DozeLog dozeLog, BroadcastDispatcher broadcastDispatcher) { mContext = context; mMachine = machine; mDozeHost = dozeHost; @@ -107,15 +168,19 @@ public class DozeTriggers implements DozeMachine.Part { mWakeLock = wakeLock; mAllowPulseTriggers = allowPulseTriggers; mDozeSensors = new DozeSensors(context, alarmManager, mSensorManager, dozeParameters, - config, wakeLock, this::onSensor, this::onProximityFar, dozeLog, - proximitySensor); + config, wakeLock, this::onSensor, this::onProximityFar, dozeLog, proximitySensor); mUiModeManager = mContext.getSystemService(UiModeManager.class); mDockManager = dockManager; - mProxCheck = new ProximitySensor.ProximityCheck(proximitySensor, handler); + mProxCheck = proxCheck; mDozeLog = dozeLog; mBroadcastDispatcher = broadcastDispatcher; } + @Override + public void destroy() { + mDozeSensors.destroy(); + } + private void onNotification(Runnable onPulseSuppressedListener) { if (DozeMachine.DEBUG) { Log.d(TAG, "requestNotificationPulse"); @@ -224,6 +289,8 @@ public class DozeTriggers implements DozeMachine.Part { mMetricsLogger.write(new LogMaker(MetricsEvent.DOZING) .setType(MetricsEvent.TYPE_UPDATE) .setSubtype(reason)); + Optional.ofNullable(DozingUpdateUiEvent.fromReason(reason)) + .ifPresent(UI_EVENT_LOGGER::log); if (mDozeParameters.getDisplayNeedsBlanking()) { // Let's prepare the display to wake-up by drawing black. // This will cover the hardware wake-up sequence, where the display @@ -419,6 +486,8 @@ public class DozeTriggers implements DozeMachine.Part { // Logs request pulse reason on AOD screen. mMetricsLogger.write(new LogMaker(MetricsEvent.DOZING) .setType(MetricsEvent.TYPE_UPDATE).setSubtype(reason)); + Optional.ofNullable(DozingUpdateUiEvent.fromReason(reason)) + .ifPresent(UI_EVENT_LOGGER::log); } private boolean canPulse() { diff --git a/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java b/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java index 6e65b01e790e..06806d0e6ab6 100644 --- a/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java +++ b/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java @@ -17,7 +17,6 @@ package com.android.systemui.util.sensors; import android.hardware.SensorManager; -import android.os.Handler; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; @@ -27,6 +26,7 @@ import com.android.systemui.util.concurrency.DelayableExecutor; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Consumer; import javax.inject.Inject; @@ -64,11 +64,12 @@ public class ProximitySensor implements ThresholdSensor { private final DelayableExecutor mDelayableExecutor; private final List mListeners = new ArrayList<>(); private String mTag = null; + @VisibleForTesting protected boolean mPaused; private ThresholdSensorEvent mLastPrimaryEvent; @VisibleForTesting ThresholdSensorEvent mLastEvent; - private boolean mPaused; private boolean mRegistered; + private final AtomicBoolean mAlerting = new AtomicBoolean(); private Runnable mCancelSecondaryRunnable; private boolean mInitializedListeners = false; private boolean mSecondarySafe = false; @@ -252,7 +253,7 @@ public class ProximitySensor implements ThresholdSensor { /** Update all listeners with the last value this class received from the sensor. */ public void alertListeners() { Assert.isMainThread(); - if (mLastEvent == null) { + if (mAlerting.getAndSet(true)) { return; } if (mLastEvent != null) { @@ -262,9 +263,7 @@ public class ProximitySensor implements ThresholdSensor { proximitySensorListener.onThresholdCrossed(lastEvent)); } - List listeners = new ArrayList<>(mListeners); - listeners.forEach(proximitySensorListener -> - proximitySensorListener.onThresholdCrossed(mLastEvent)); + mAlerting.set(false); } private void onPrimarySensorEvent(ThresholdSensorEvent event) { @@ -318,13 +317,13 @@ public class ProximitySensor implements ThresholdSensor { public static class ProximityCheck implements Runnable { private final ProximitySensor mSensor; - private final Handler mHandler; + private final DelayableExecutor mDelayableExecutor; private List> mCallbacks = new ArrayList<>(); private final ThresholdSensor.Listener mListener; private final AtomicBoolean mRegistered = new AtomicBoolean(); @Inject - public ProximityCheck(ProximitySensor sensor, Handler handler) { + public ProximityCheck(ProximitySensor sensor, @Main DelayableExecutor delayableExecutor) { mSensor = sensor; mSensor.setTag("prox_check"); mDelayableExecutor = delayableExecutor; -- cgit v1.2.3 From 2c95dd9bc7edee231cd8e1e6d524d9771d2c7c41 Mon Sep 17 00:00:00 2001 From: Yimin Li Date: Wed, 24 Mar 2021 12:38:20 -0700 Subject: Merge rvc-qpr3-release Change-Id: I6afda73753503b4fa7c98128f77f1fbc2dd6b7d1 --- .../server/utils/DeviceConfigInterface.java | 121 +++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 services/core/java/com/android/server/utils/DeviceConfigInterface.java diff --git a/services/core/java/com/android/server/utils/DeviceConfigInterface.java b/services/core/java/com/android/server/utils/DeviceConfigInterface.java new file mode 100644 index 000000000000..ff609031b57c --- /dev/null +++ b/services/core/java/com/android/server/utils/DeviceConfigInterface.java @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.utils; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.provider.DeviceConfig; + +import java.util.concurrent.Executor; + +/** + * Abstraction around {@link DeviceConfig} to allow faking device configuration in tests. + */ +public interface DeviceConfigInterface { + /** + * @see DeviceConfig#getProperty + */ + @Nullable + String getProperty(@NonNull String namespace, @NonNull String name); + + /** + * @see DeviceConfig#getString + */ + @NonNull + String getString(@NonNull String namespace, @NonNull String name, @NonNull String defaultValue); + + /** + * @see DeviceConfig#getInt + */ + int getInt(@NonNull String namespace, @NonNull String name, int defaultValue); + + /** + * @see DeviceConfig#getLong + */ + long getLong(@NonNull String namespace, @NonNull String name, long defaultValue); + + /** + * @see DeviceConfig#getBoolean + */ + boolean getBoolean(@NonNull String namespace, @NonNull String name, boolean defaultValue); + + /** + * @see DeviceConfig#getFloat + */ + float getFloat(@NonNull String namespace, @NonNull String name, float defaultValue); + + /** + * @see DeviceConfig#addOnPropertiesChangedListener + */ + void addOnPropertiesChangedListener(@NonNull String namespace, @NonNull Executor executor, + @NonNull DeviceConfig.OnPropertiesChangedListener listener); + + /** + * @see DeviceConfig#removeOnPropertiesChangedListener + */ + void removeOnPropertiesChangedListener( + @NonNull DeviceConfig.OnPropertiesChangedListener listener); + + /** + * Calls through to the real {@link DeviceConfig}. + */ + DeviceConfigInterface REAL = new DeviceConfigInterface() { + @Override + public String getProperty(String namespace, String name) { + return DeviceConfig.getProperty(namespace, name); + } + + @Override + public String getString(String namespace, String name, String defaultValue) { + return DeviceConfig.getString(namespace, name, defaultValue); + } + + @Override + public int getInt(String namespace, String name, int defaultValue) { + return DeviceConfig.getInt(namespace, name, defaultValue); + } + + @Override + public long getLong(String namespace, String name, long defaultValue) { + return DeviceConfig.getLong(namespace, name, defaultValue); + } + + @Override + public boolean getBoolean(@NonNull String namespace, @NonNull String name, + boolean defaultValue) { + return DeviceConfig.getBoolean(namespace, name, defaultValue); + } + + @Override + public float getFloat(@NonNull String namespace, @NonNull String name, + float defaultValue) { + return DeviceConfig.getFloat(namespace, name, defaultValue); + } + + @Override + public void addOnPropertiesChangedListener(String namespace, Executor executor, + DeviceConfig.OnPropertiesChangedListener listener) { + DeviceConfig.addOnPropertiesChangedListener(namespace, executor, listener); + } + + @Override + public void removeOnPropertiesChangedListener( + DeviceConfig.OnPropertiesChangedListener listener) { + DeviceConfig.removeOnPropertiesChangedListener(listener); + } + }; +} -- cgit v1.2.3 From 91604e3513d450bd4f08ea69d5dc40f7d5b3e7a7 Mon Sep 17 00:00:00 2001 From: Yimin Li Date: Wed, 24 Mar 2021 13:38:05 -0700 Subject: git add xml for config_highAmbientBrightnessThresholdsOfFixedRefreshRate and config_highAmbientBrightnessThresholdsOfFixedRefreshRate Change-Id: I3d2bb291c22c56cf64b1df7b45d8ce48db99ac5d --- core/res/res/values/config.xml | 29 +++++++++++++++++++++++++++++ core/res/res/values/symbols.xml | 5 +++++ 2 files changed, 34 insertions(+) diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 550601af0faa..5f02eb6a6a37 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -4138,6 +4138,35 @@ If non-positive, then the refresh rate is unchanged even if thresholds are configured. --> 0 + + + + + + + + + + + 0 + diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index ee4c6941d6c5..3ef0a8dc9daa 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -3784,6 +3784,11 @@ + + + + + -- cgit v1.2.3 From 8184ee5478188142dfa67cd076de6b1191910c0a Mon Sep 17 00:00:00 2001 From: Yimin Li Date: Wed, 24 Mar 2021 13:50:12 -0700 Subject: git add core/java/android/hardware/display/DisplayManager.java for rvc-qpr3-release merge Change-Id: Ife19fbb3c8f50532c84b278f2a5764c8a0cfb62e --- .../android/hardware/display/DisplayManager.java | 55 ++++++++++++++++++---- 1 file changed, 47 insertions(+), 8 deletions(-) diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java index c1ba2094d3cf..0fa4ca8a574b 100644 --- a/core/java/android/hardware/display/DisplayManager.java +++ b/core/java/android/hardware/display/DisplayManager.java @@ -875,37 +875,76 @@ public final class DisplayManager { public interface DeviceConfig { /** - * Key for refresh rate in the zone defined by thresholds. + * Key for refresh rate in the low zone defined by thresholds. * + * Note that the name and value don't match because they were added before we had a high + * zone to consider. * @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER * @see android.R.integer#config_defaultZoneBehavior */ - String KEY_REFRESH_RATE_IN_ZONE = "refresh_rate_in_zone"; + String KEY_REFRESH_RATE_IN_LOW_ZONE = "refresh_rate_in_zone"; /** - * Key for accessing the display brightness thresholds for the configured refresh rate zone. + * Key for accessing the low display brightness thresholds for the configured refresh + * rate zone. * The value will be a pair of comma separated integers representing the minimum and maximum * thresholds of the zone, respectively, in display backlight units (i.e. [0, 255]). * + * Note that the name and value don't match because they were added before we had a high + * zone to consider. + * * @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER * @see android.R.array#config_brightnessThresholdsOfPeakRefreshRate * @hide */ - String KEY_PEAK_REFRESH_RATE_DISPLAY_BRIGHTNESS_THRESHOLDS = + String KEY_FIXED_REFRESH_RATE_LOW_DISPLAY_BRIGHTNESS_THRESHOLDS = "peak_refresh_rate_brightness_thresholds"; /** - * Key for accessing the ambient brightness thresholds for the configured refresh rate zone. - * The value will be a pair of comma separated integers representing the minimum and maximum - * thresholds of the zone, respectively, in lux. + * Key for accessing the low ambient brightness thresholds for the configured refresh + * rate zone. The value will be a pair of comma separated integers representing the minimum + * and maximum thresholds of the zone, respectively, in lux. + * + * Note that the name and value don't match because they were added before we had a high + * zone to consider. * * @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER * @see android.R.array#config_ambientThresholdsOfPeakRefreshRate * @hide */ - String KEY_PEAK_REFRESH_RATE_AMBIENT_BRIGHTNESS_THRESHOLDS = + String KEY_FIXED_REFRESH_RATE_LOW_AMBIENT_BRIGHTNESS_THRESHOLDS = "peak_refresh_rate_ambient_thresholds"; + /** + * Key for refresh rate in the high zone defined by thresholds. + * + * @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER + * @see android.R.integer#config_fixedRefreshRateInHighZone + */ + String KEY_REFRESH_RATE_IN_HIGH_ZONE = "refresh_rate_in_high_zone"; + /** + * Key for accessing the display brightness thresholds for the configured refresh rate zone. + * The value will be a pair of comma separated integers representing the minimum and maximum + * thresholds of the zone, respectively, in display backlight units (i.e. [0, 255]). + * + * @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER + * @see android.R.array#config_brightnessHighThresholdsOfFixedRefreshRate + * @hide + */ + String KEY_FIXED_REFRESH_RATE_HIGH_DISPLAY_BRIGHTNESS_THRESHOLDS = + "fixed_refresh_rate_high_display_brightness_thresholds"; + + /** + * Key for accessing the ambient brightness thresholds for the configured refresh rate zone. + * The value will be a pair of comma separated integers representing the minimum and maximum + * thresholds of the zone, respectively, in lux. + * + * @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER + * @see android.R.array#config_ambientHighThresholdsOfFixedRefreshRate + * @hide + */ + String KEY_FIXED_REFRESH_RATE_HIGH_AMBIENT_BRIGHTNESS_THRESHOLDS = + "fixed_refresh_rate_high_ambient_brightness_thresholds"; /** * Key for default peak refresh rate * -- cgit v1.2.3 From 38006e1efb3b4beee6c83bebc7937f9ecb1fa0d4 Mon Sep 17 00:00:00 2001 From: Paul Scovanner Date: Tue, 30 Mar 2021 21:06:32 +0000 Subject: Revert "Limit maximum allowed size for a status bar icon" This reverts commit 3a62e9ffaad2d81bf176decb7b60266bd6005301. Reason for revert: Regression (eg: b/183696500) caused by security fix. Revert needed to respin May MPR build. Change-Id: If9e34a0120121ed851b911c8a8bd2bbe0e0f9e34 (cherry picked from commit 2455fc526470713c22b3a0a8d7f4a3ec910fa61c) (cherry picked from commit 024b57030326ee8c6a0a2d96db83136ea549acbd) --- .../src/com/android/systemui/statusbar/StatusBarIconView.java | 10 ---------- .../com/android/systemui/statusbar/StatusBarIconViewTest.java | 10 ---------- 2 files changed, 20 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java index 25ae5c2dadef..8cf8a2299922 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java @@ -83,9 +83,6 @@ public class StatusBarIconView extends AnimatedImageView implements StatusIconDi public static final int STATE_DOT = 1; public static final int STATE_HIDDEN = 2; - /** Maximum allowed width or height for an icon drawable */ - private static final int MAX_IMAGE_SIZE = 500; - private static final String TAG = "StatusBarIconView"; private static final Property ICON_APPEAR_AMOUNT = new FloatProperty("iconAppearAmount") { @@ -381,13 +378,6 @@ public class StatusBarIconView extends AnimatedImageView implements StatusIconDi Log.w(TAG, "No icon for slot " + mSlot + "; " + mIcon.icon); return false; } - - if (drawable.getIntrinsicWidth() > MAX_IMAGE_SIZE - || drawable.getIntrinsicHeight() > MAX_IMAGE_SIZE) { - Log.w(TAG, "Drawable is too large " + mIcon); - return false; - } - if (withClear) { setImageDrawable(null); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarIconViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarIconViewTest.java index daa805a8f6e6..9971e0cf81a3 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarIconViewTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarIconViewTest.java @@ -35,7 +35,6 @@ import android.content.ContextWrapper; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.res.Resources; -import android.graphics.Bitmap; import android.graphics.Color; import android.graphics.drawable.Icon; import android.os.UserHandle; @@ -124,13 +123,4 @@ public class StatusBarIconViewTest extends SysuiTestCase { assertEquals("Transparent backgrounds should fallback to drawable color", color, mIconView.getStaticDrawableColor()); } - - @Test - public void testGiantImageNotAllowed() { - Bitmap largeBitmap = Bitmap.createBitmap(1000, 1000, Bitmap.Config.ARGB_8888); - Icon icon = Icon.createWithBitmap(largeBitmap); - StatusBarIcon largeIcon = new StatusBarIcon(UserHandle.ALL, "mockPackage", - icon, 0, 0, ""); - assertFalse(mIconView.set(largeIcon)); - } } \ No newline at end of file -- cgit v1.2.3 From 372088d7721f4c8cb7260d8e9fdaf498c5a30464 Mon Sep 17 00:00:00 2001 From: Jorim Jaggi Date: Thu, 20 May 2021 18:35:30 +0200 Subject: Fix race condition between lockNow() and updateLockscreenTimeout If updateLockscreenTimeout gets called before the Runnable queued from lockNow gets executed, lockNow request will be ignored. Fix this by not clearing out the runnable if it's pending lock request. Test: Switch user, ensure lockscreen comes up Bug: 161149543 Change-Id: Ie486396fd7328edf8ca0912df92524bb82a1fb7f (cherry picked from commit 875fa991aac0f3bbd5c66327408ceae60a24a6b3) Merged-In: Ie486396fd7328edf8ca0912df92524bb82a1fb7f (cherry picked from commit 9c8b1512a532478dea055d82ad6a49d53a9f31b1) --- .../java/com/android/server/policy/PhoneWindowManager.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index f0439a3db4fc..b65a310c55ba 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -608,6 +608,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { private int mPowerButtonSuppressionDelayMillis = POWER_BUTTON_SUPPRESSION_DELAY_DEFAULT_MILLIS; + private boolean mLockNowPending = false; + private static final int MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK = 3; private static final int MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK = 4; private static final int MSG_KEYGUARD_DRAWN_COMPLETE = 5; @@ -4941,6 +4943,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { mKeyguardDelegate.doKeyguardTimeout(options); } mLockScreenTimerActive = false; + mLockNowPending = false; options = null; } } @@ -4950,7 +4953,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } - ScreenLockTimeout mScreenLockTimeout = new ScreenLockTimeout(); + final ScreenLockTimeout mScreenLockTimeout = new ScreenLockTimeout(); @Override public void lockNow(Bundle options) { @@ -4962,6 +4965,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { mScreenLockTimeout.setLockOptions(options); } mHandler.post(mScreenLockTimeout); + synchronized (mScreenLockTimeout) { + mLockNowPending = true; + } } // TODO (b/113840485): Move this logic to DisplayPolicy when lockscreen supports multi-display. @@ -4977,6 +4983,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { private void updateLockScreenTimeout() { synchronized (mScreenLockTimeout) { + if (mLockNowPending) { + Log.w(TAG, "lockNow pending, ignore updating lockscreen timeout"); + return; + } final boolean enable = !mAllowLockscreenWhenOnDisplays.isEmpty() && mDefaultDisplayPolicy.isAwake() && mKeyguardDelegate != null && mKeyguardDelegate.isSecure(mCurrentUserId); -- cgit v1.2.3 From 49cb41f9d7d2ec741bc2ec27717283dc560a9060 Mon Sep 17 00:00:00 2001 From: Winson Date: Tue, 22 Jun 2021 12:38:56 -0700 Subject: Remove ParsedIntentInfo CREATOR Its existence allows implicit readParcelable calls to invoke a Parcel operation with mismatched read/write data sizes, allowing someone to swap out the data on a reparcel. Internal classes will use writeIntentInfoToParcel, so this is safe to remove. Bug: 191055353 Test: atest com.android.server.pm.test.parsing.parcelling Change-Id: I44faa635faf8a77894a3dda8adf89c10064e53f1 (cherry picked from commit 75214cc510c62f936a713c2da3d0a54db9405957) --- .../content/pm/parsing/component/ParsedIntentInfo.java | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/core/java/android/content/pm/parsing/component/ParsedIntentInfo.java b/core/java/android/content/pm/parsing/component/ParsedIntentInfo.java index 0ba92cc4fef7..504a7bd5a320 100644 --- a/core/java/android/content/pm/parsing/component/ParsedIntentInfo.java +++ b/core/java/android/content/pm/parsing/component/ParsedIntentInfo.java @@ -19,7 +19,6 @@ package android.content.pm.parsing.component; import android.annotation.Nullable; import android.content.IntentFilter; import android.os.Parcel; -import android.os.Parcelable; import android.util.Pair; import com.android.internal.util.DataClass; @@ -168,19 +167,6 @@ public final class ParsedIntentInfo extends IntentFilter { + '}'; } - public static final Parcelable.Creator CREATOR = - new Parcelable.Creator() { - @Override - public ParsedIntentInfo createFromParcel(Parcel source) { - return new ParsedIntentInfo(source); - } - - @Override - public ParsedIntentInfo[] newArray(int size) { - return new ParsedIntentInfo[size]; - } - }; - public boolean isHasDefault() { return hasDefault; } -- cgit v1.2.3 From 7f39ba09b8ccad2ae50874d3643cdc93746391ea Mon Sep 17 00:00:00 2001 From: Hai Zhang Date: Wed, 16 Jun 2021 00:20:52 +0000 Subject: DO NOT MERGE Add cross-user check for getDefaultSmsPackage(). Bug: 177927831 Test: atest RoleSecurityTest Change-Id: I1254804fb72a299e782d45f938acdf979a82f904 (cherry picked from commit cf1bd25a37123624688f9965608a48d362ab4eb0) --- services/core/java/com/android/server/role/RoleManagerService.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/services/core/java/com/android/server/role/RoleManagerService.java b/services/core/java/com/android/server/role/RoleManagerService.java index 392792dbae69..b75bce833e04 100644 --- a/services/core/java/com/android/server/role/RoleManagerService.java +++ b/services/core/java/com/android/server/role/RoleManagerService.java @@ -662,6 +662,12 @@ public class RoleManagerService extends SystemService implements RoleUserState.C @Override public String getDefaultSmsPackage(int userId) { + userId = handleIncomingUser(userId, false, "getDefaultSmsPackage"); + if (!mUserManagerInternal.exists(userId)) { + Slog.e(LOG_TAG, "user " + userId + " does not exist"); + return null; + } + long identity = Binder.clearCallingIdentity(); try { return CollectionUtils.firstOrNull( -- cgit v1.2.3 From 4241ab5ee435ee3c5e6496c001b2cf5bc827cfc4 Mon Sep 17 00:00:00 2001 From: Christopher Tate Date: Mon, 7 Jun 2021 15:02:45 -0700 Subject: Fix side effects of trace-ipc and dumpheap commands These shell commands were implicitly deleting any client-named file for which the system uid had deletion capability. They no longer do this, instead using only the client's own capabilities and file manipulation modes. Bug: 185398942 Test: manual "adb shell cmd activity dumpheap system_server /data/system/last-fstrim" Test: atest CtsPermissionTestCases:ShellCommandPermissionTest Change-Id: Ie61ab2c3f4bfbd04de09ca99c1116d1129461e8f (cherry picked from commit 76e8e04703cb49a4984145a18f4552c4bcf72172) --- .../com/android/server/am/ActivityManagerShellCommand.java | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java index 149e3baa90e7..122af56bd575 100644 --- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java +++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java @@ -94,7 +94,6 @@ import com.android.internal.util.MemInfoReader; import com.android.server.compat.PlatformCompat; import java.io.BufferedReader; -import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -787,8 +786,7 @@ final class ActivityManagerShellCommand extends ShellCommand { return -1; } - File file = new File(filename); - file.delete(); + // Writes an error message to stderr on failure ParcelFileDescriptor fd = openFileForSystem(filename, "w"); if (fd == null) { return -1; @@ -942,16 +940,16 @@ final class ActivityManagerShellCommand extends ShellCommand { String logNameTimeString = LOG_NAME_TIME_FORMATTER.format(localDateTime); heapFile = "/data/local/tmp/heapdump-" + logNameTimeString + ".prof"; } - pw.println("File: " + heapFile); - pw.flush(); - File file = new File(heapFile); - file.delete(); + // Writes an error message to stderr on failure ParcelFileDescriptor fd = openFileForSystem(heapFile, "w"); if (fd == null) { return -1; } + pw.println("File: " + heapFile); + pw.flush(); + final CountDownLatch latch = new CountDownLatch(1); final RemoteCallback finishCallback = new RemoteCallback(new OnResultListener() { -- cgit v1.2.3 From ed0c637a311d98426ff29cecd96aa429b53544dc Mon Sep 17 00:00:00 2001 From: Seigo Nonaka Date: Fri, 4 Jun 2021 16:07:23 -0700 Subject: Improve ellipsize performance Instead of iterate all ellipsized characters, only iterate the necessary ranges for copying. Bug: 188913943 Test: atest CtsTextTestCases CtsGraphicsTestCases CtsWidgetTestCases Change-Id: I3d03b1e3897e427c23fbe51315f412c57a4ce9e9 (cherry picked from commit 2c6121f3e3c52965ae33317e4fe7a273fd1742c6) (cherry picked from commit 40d7a4535aba93073264bf8998daf588f0923986) --- core/java/android/text/Layout.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java index 8a4497a0f0ce..6baea1aea471 100644 --- a/core/java/android/text/Layout.java +++ b/core/java/android/text/Layout.java @@ -2350,7 +2350,10 @@ public abstract class Layout { final int ellipsisStringLen = ellipsisString.length(); // Use the ellipsis string only if there are that at least as many characters to replace. final boolean useEllipsisString = ellipsisCount >= ellipsisStringLen; - for (int i = 0; i < ellipsisCount; i++) { + final int min = Math.max(0, start - ellipsisStart - lineStart); + final int max = Math.min(ellipsisCount, end - ellipsisStart - lineStart); + + for (int i = min; i < max; i++) { final char c; if (useEllipsisString && i < ellipsisStringLen) { c = ellipsisString.charAt(i); @@ -2359,9 +2362,7 @@ public abstract class Layout { } final int a = i + ellipsisStart + lineStart; - if (start <= a && a < end) { - dest[destoff + a - start] = c; - } + dest[destoff + a - start] = c; } } -- cgit v1.2.3 From ba984d1c0c0270b6c704189abf4faa808c2038bf Mon Sep 17 00:00:00 2001 From: Louis Chang Date: Mon, 21 Jun 2021 00:33:10 +0800 Subject: Avoid locking profile task when it is already lock WorkLockActivity was started repeatedly on top of the task that contains work apps when turning screen on and off over and over. So, lots of the WorkLockActivity instances were created and added in the task, which caused system sluggish. Bug: 177457096 Test: manually test work challenges Test: RootWindowContainerTests Change-Id: Iac345471ef3badad6b9e5c0cc2873c60938663eb Merged-In: Iac345471ef3badad6b9e5c0cc2873c60938663eb (cherry picked from commit 805585ed1baa0ddeeab07aa1f77819333a73c93d) (cherry picked from commit db7d06c52903b8dccb7e8d9976a23c366430a42e) --- .../com/android/server/wm/RootWindowContainer.java | 10 +++++++++ .../server/wm/RootWindowContainerTests.java | 25 ++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index ddad1dbd9b3d..1c1360f6f389 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -17,6 +17,7 @@ package com.android.server.wm; import static android.app.ActivityTaskManager.INVALID_TASK_ID; +import static android.app.KeyguardManager.ACTION_CONFIRM_DEVICE_CREDENTIAL_WITH_USER; import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT; import static android.app.WindowConfiguration.ACTIVITY_TYPE_DREAM; import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; @@ -3381,6 +3382,15 @@ class RootWindowContainer extends WindowContainer mService.deferWindowLayout(); try { forAllLeafTasks(task -> { + final ActivityRecord top = task.topRunningActivity(); + if (top != null && !top.finishing + && ACTION_CONFIRM_DEVICE_CREDENTIAL_WITH_USER.equals(top.intent.getAction()) + && top.packageName.equals( + mService.getSysUiServiceComponentLocked().getPackageName())) { + // Do nothing since the task is already secure by sysui. + return; + } + if (task.getActivity(activity -> !activity.finishing && activity.mUserId == userId) != null) { mService.getTaskChangeNotificationController().notifyTaskProfileLocked( diff --git a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java index 1aff8a7b5382..e5c5bf54b0e6 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java @@ -16,6 +16,7 @@ package com.android.server.wm; +import static android.app.KeyguardManager.ACTION_CONFIRM_DEVICE_CREDENTIAL_WITH_USER; import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.view.Display.DEFAULT_DISPLAY; @@ -25,6 +26,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE; import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR; import static android.view.WindowManager.LayoutParams.TYPE_TOAST; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.server.wm.ActivityStack.ActivityState.FINISHING; import static com.android.server.wm.ActivityStack.ActivityState.PAUSED; @@ -37,11 +39,15 @@ import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.clearInvocations; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import android.app.WindowConfiguration; import android.content.ComponentName; +import android.content.Intent; import android.content.pm.ActivityInfo; import android.os.UserHandle; import android.platform.test.annotations.Presubmit; @@ -194,6 +200,8 @@ public class RootWindowContainerTests extends WindowTestsBase { .setUid(UserHandle.PER_USER_RANGE + 1) .setTask(task) .build(); + doReturn(true).when(topActivity).okToShowLocked(); + topActivity.intent.setAction(Intent.ACTION_MAIN); // Make sure the listeners will be notified for putting the task to locked state TaskChangeNotificationController controller = @@ -201,6 +209,23 @@ public class RootWindowContainerTests extends WindowTestsBase { spyOn(controller); mWm.mRoot.lockAllProfileTasks(0); verify(controller).notifyTaskProfileLocked(eq(task.mTaskId), eq(0)); + + // Create the work lock activity on top of the task + final ActivityRecord workLockActivity = + new ActivityTestsBase.ActivityBuilder(mWm.mAtmService) + .setStack(stack) + .setUid(UserHandle.PER_USER_RANGE + 1) + .setTask(task) + .build(); + doReturn(true).when(workLockActivity).okToShowLocked(); + workLockActivity.intent.setAction(ACTION_CONFIRM_DEVICE_CREDENTIAL_WITH_USER); + doReturn(workLockActivity.mActivityComponent).when( + mWm.mAtmService).getSysUiServiceComponentLocked(); + + // Make sure the listener won't be notified again. + clearInvocations(controller); + mWm.mRoot.lockAllProfileTasks(0); + verify(controller, never()).notifyTaskProfileLocked(eq(task.mTaskId), anyInt()); } } -- cgit v1.2.3 From d5b1cf4978be922dd87255312eb345453aa56ebf Mon Sep 17 00:00:00 2001 From: Hui Yu Date: Fri, 25 Jun 2021 17:32:20 +0000 Subject: Merge "BG-FGS-start while-in-use permission restriction improvement." into rvc-dev am: e51f884f6a Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/15081994 Bug: 183147114 Bug: 183204439 Test: atest cts/tests/app/src/android/app/cts/ActivityManagerFgsBgStartTest.java#testStartForegroundTimeout Test: atest cts/tests/app/src/android/app/cts/ActivityManagerFgsBgStartTest.java#testSecondStartForeground Change-Id: Ieaaa70884cd11cfa460ec2be6db5e40856ffccef Merged-In: Idc88f274c7a323d175d65bb47eca041772ae9bb7 (cherry picked from commit fd02546e52841dcd0ec194f70baa58cc377505ec) --- .../java/com/android/server/am/ActiveServices.java | 103 ++++++++++++++++----- .../server/am/ActivityManagerConstants.java | 20 ++++ .../java/com/android/server/am/ServiceRecord.java | 6 ++ 3 files changed, 107 insertions(+), 22 deletions(-) diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 5abb87cedc71..1cd7115f8edc 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -734,11 +734,8 @@ public final class ActiveServices { } ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting); - if (!r.mAllowWhileInUsePermissionInFgs) { - r.mAllowWhileInUsePermissionInFgs = - shouldAllowWhileInUsePermissionInFgsLocked(callingPackage, callingPid, - callingUid, service, r, allowBackgroundActivityStarts); - } + setFgsRestrictionLocked(callingPackage, callingPid, callingUid, r, + allowBackgroundActivityStarts); return cmp; } @@ -1411,14 +1408,6 @@ public final class ActiveServices { + String.format("0x%08X", manifestType) + " in service element of manifest file"); } - // If the foreground service is not started from TOP process, do not allow it to - // have while-in-use location/camera/microphone access. - if (!r.mAllowWhileInUsePermissionInFgs) { - Slog.w(TAG, - "Foreground service started from background can not have " - + "location/camera/microphone access: service " - + r.shortInstanceName); - } } boolean alreadyStartedOp = false; boolean stopProcStatsOp = false; @@ -1466,6 +1455,57 @@ public final class ActiveServices { ignoreForeground = true; } + if (!ignoreForeground) { + if (r.mStartForegroundCount == 0) { + /* + If the service was started with startService(), not + startForegroundService(), and if startForeground() isn't called within + mFgsStartForegroundTimeoutMs, then we check the state of the app + (who owns the service, which is the app that called startForeground()) + again. If the app is in the foreground, or in any other cases where + FGS-starts are allowed, then we still allow the FGS to be started. + Otherwise, startForeground() would fail. + + If the service was started with startForegroundService(), then the service + must call startForeground() within a timeout anyway, so we don't need this + check. + */ + if (!r.fgRequired) { + final long delayMs = SystemClock.elapsedRealtime() - r.createRealTime; + if (delayMs > mAm.mConstants.mFgsStartForegroundTimeoutMs) { + resetFgsRestrictionLocked(r); + setFgsRestrictionLocked(r.serviceInfo.packageName, r.app.pid, + r.appInfo.uid, r, false); + EventLog.writeEvent(0x534e4554, "183147114", + r.appInfo.uid, + "call setFgsRestrictionLocked again due to " + + "startForegroundTimeout"); + } + } + } else if (r.mStartForegroundCount >= 1) { + // The second or later time startForeground() is called after service is + // started. Check for app state again. + final long delayMs = SystemClock.elapsedRealtime() - + r.mLastSetFgsRestrictionTime; + if (delayMs > mAm.mConstants.mFgsStartForegroundTimeoutMs) { + resetFgsRestrictionLocked(r); + setFgsRestrictionLocked(r.serviceInfo.packageName, r.app.pid, + r.appInfo.uid, r, false); + EventLog.writeEvent(0x534e4554, "183147114", r.appInfo.uid, + "call setFgsRestrictionLocked for " + + (r.mStartForegroundCount + 1) + "th startForeground"); + } + } + // If the foreground service is not started from TOP process, do not allow it to + // have while-in-use location/camera/microphone access. + if (!r.mAllowWhileInUsePermissionInFgs) { + Slog.w(TAG, + "Foreground service started from background can not have " + + "location/camera/microphone access: service " + + r.shortInstanceName); + } + } + // Apps under strict background restrictions simply don't get to have foreground // services, so now that we've enforced the startForegroundService() contract // we only do the machinery of making the service foreground when the app @@ -1501,6 +1541,7 @@ public final class ActiveServices { active.mNumActive++; } r.isForeground = true; + r.mStartForegroundCount++; if (!stopProcStatsOp) { ServiceState stracker = r.getTracker(); if (stracker != null) { @@ -1559,6 +1600,7 @@ public final class ActiveServices { decActiveForegroundAppLocked(smap, r); } r.isForeground = false; + resetFgsRestrictionLocked(r); ServiceState stracker = r.getTracker(); if (stracker != null) { stracker.setForeground(false, mAm.mProcessStats.getMemFactorLocked(), @@ -2118,12 +2160,7 @@ public final class ActiveServices { } } - if (!s.mAllowWhileInUsePermissionInFgs) { - s.mAllowWhileInUsePermissionInFgs = - shouldAllowWhileInUsePermissionInFgsLocked(callingPackage, - callingPid, callingUid, - service, s, false); - } + setFgsRestrictionLocked(callingPackage, callingPid, callingUid, s, false); if (s.app != null) { if ((flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) { @@ -3419,7 +3456,7 @@ public final class ActiveServices { r.isForeground = false; r.foregroundId = 0; r.foregroundNoti = null; - r.mAllowWhileInUsePermissionInFgs = false; + resetFgsRestrictionLocked(r); // Clear start entries. r.clearDeliveredStartsLocked(); @@ -4900,7 +4937,7 @@ public final class ActiveServices { * @return true if allow, false otherwise. */ private boolean shouldAllowWhileInUsePermissionInFgsLocked(String callingPackage, - int callingPid, int callingUid, Intent intent, ServiceRecord r, + int callingPid, int callingUid, ServiceRecord r, boolean allowBackgroundActivityStarts) { // Is the background FGS start restriction turned on? if (!mAm.mConstants.mFlagBackgroundFgsStartRestrictionEnabled) { @@ -4986,6 +5023,28 @@ public final class ActiveServices { boolean canAllowWhileInUsePermissionInFgsLocked(int callingPid, int callingUid, String callingPackage) { return shouldAllowWhileInUsePermissionInFgsLocked( - callingPackage, callingPid, callingUid, null, null, false); + callingPackage, callingPid, callingUid, null, false); + } + + /** + * In R, mAllowWhileInUsePermissionInFgs is to allow while-in-use permissions in foreground + * service or not. while-in-use permissions in FGS started from background might be restricted. + * @param callingPackage caller app's package name. + * @param callingUid caller app's uid. + * @param r the service to start. + * @return true if allow, false otherwise. + */ + private void setFgsRestrictionLocked(String callingPackage, + int callingPid, int callingUid, ServiceRecord r, + boolean allowBackgroundActivityStarts) { + r.mLastSetFgsRestrictionTime = SystemClock.elapsedRealtime(); + if (!r.mAllowWhileInUsePermissionInFgs) { + r.mAllowWhileInUsePermissionInFgs = shouldAllowWhileInUsePermissionInFgsLocked( + callingPackage, callingPid, callingUid, r, allowBackgroundActivityStarts); + } + } + + private void resetFgsRestrictionLocked(ServiceRecord r) { + r.mAllowWhileInUsePermissionInFgs = false; } } diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java index 7be843f17863..00d8208ea118 100644 --- a/services/core/java/com/android/server/am/ActivityManagerConstants.java +++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java @@ -88,6 +88,7 @@ final class ActivityManagerConstants extends ContentObserver { static final String KEY_PROCESS_START_ASYNC = "process_start_async"; static final String KEY_MEMORY_INFO_THROTTLE_TIME = "memory_info_throttle_time"; static final String KEY_TOP_TO_FGS_GRACE_DURATION = "top_to_fgs_grace_duration"; + static final String KEY_FGS_START_FOREGROUND_TIMEOUT = "fgs_start_foreground_timeout"; static final String KEY_PENDINGINTENT_WARNING_THRESHOLD = "pendingintent_warning_threshold"; private static final int DEFAULT_MAX_CACHED_PROCESSES = 32; @@ -121,6 +122,7 @@ final class ActivityManagerConstants extends ContentObserver { private static final boolean DEFAULT_PROCESS_START_ASYNC = true; private static final long DEFAULT_MEMORY_INFO_THROTTLE_TIME = 5*60*1000; private static final long DEFAULT_TOP_TO_FGS_GRACE_DURATION = 15 * 1000; + private static final int DEFAULT_FGS_START_FOREGROUND_TIMEOUT_MS = 10 * 1000; private static final int DEFAULT_PENDINGINTENT_WARNING_THRESHOLD = 2000; // Flag stored in the DeviceConfig API. @@ -273,6 +275,12 @@ final class ActivityManagerConstants extends ContentObserver { // this long. public long TOP_TO_FGS_GRACE_DURATION = DEFAULT_TOP_TO_FGS_GRACE_DURATION; + /** + * When service started from background, before the timeout it can be promoted to FGS by calling + * Service.startForeground(). + */ + volatile long mFgsStartForegroundTimeoutMs = DEFAULT_FGS_START_FOREGROUND_TIMEOUT_MS; + // Indicates whether the activity starts logging is enabled. // Controlled by Settings.Global.ACTIVITY_STARTS_LOGGING_ENABLED volatile boolean mFlagActivityStartsLoggingEnabled; @@ -421,6 +429,9 @@ final class ActivityManagerConstants extends ContentObserver { case KEY_MIN_ASSOC_LOG_DURATION: updateMinAssocLogDuration(); break; + case KEY_FGS_START_FOREGROUND_TIMEOUT: + updateFgsStartForegroundTimeout(); + break; default: break; } @@ -697,6 +708,13 @@ final class ActivityManagerConstants extends ContentObserver { /* defaultValue */ DEFAULT_MIN_ASSOC_LOG_DURATION); } + private void updateFgsStartForegroundTimeout() { + mFgsStartForegroundTimeoutMs = DeviceConfig.getLong( + DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, + KEY_FGS_START_FOREGROUND_TIMEOUT, + DEFAULT_FGS_START_FOREGROUND_TIMEOUT_MS); + } + void dump(PrintWriter pw) { pw.println("ACTIVITY MANAGER SETTINGS (dumpsys activity settings) " + Settings.Global.ACTIVITY_MANAGER_CONSTANTS + ":"); @@ -769,6 +787,8 @@ final class ActivityManagerConstants extends ContentObserver { pw.println(Arrays.toString(IMPERCEPTIBLE_KILL_EXEMPT_PACKAGES.toArray())); pw.print(" "); pw.print(KEY_MIN_ASSOC_LOG_DURATION); pw.print("="); pw.println(MIN_ASSOC_LOG_DURATION); + pw.print(" "); pw.print(KEY_FGS_START_FOREGROUND_TIMEOUT); pw.print("="); + pw.println(mFgsStartForegroundTimeoutMs); pw.println(); if (mOverrideMaxCachedProcesses >= 0) { diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java index 1b65dbac2294..0e628289a09f 100644 --- a/services/core/java/com/android/server/am/ServiceRecord.java +++ b/services/core/java/com/android/server/am/ServiceRecord.java @@ -142,6 +142,10 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN // allow while-in-use permissions in foreground service or not. // while-in-use permissions in FGS started from background might be restricted. boolean mAllowWhileInUsePermissionInFgs; + // The number of times Service.startForeground() is called; + int mStartForegroundCount; + // Last time mAllowWhileInUsePermissionInFgs is set. + long mLastSetFgsRestrictionTime; // the most recent package that start/bind this service. String mRecentCallingPackage; @@ -406,6 +410,8 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN } pw.print(prefix); pw.print("allowWhileInUsePermissionInFgs="); pw.println(mAllowWhileInUsePermissionInFgs); + pw.print(prefix); pw.print("startForegroundCount="); + pw.println(mStartForegroundCount); pw.print(prefix); pw.print("recentCallingPackage="); pw.println(mRecentCallingPackage); if (delayed) { -- cgit v1.2.3 From 5f2616cce92192fdf529117a63c7946087ce9979 Mon Sep 17 00:00:00 2001 From: Steve Elliott Date: Tue, 22 Jun 2021 13:58:48 -0400 Subject: Don't attach private Notification to A11yEvent when user locked Fixes: 159624555 Test: manual, atest Change-Id: Ib44f1d3695d2b31bee4f8ccae3f948c83f3b40b6 Merged-In: Ib44f1d3695d2b31bee4f8ccae3f948c83f3b40b6 (cherry picked from commit 54fbccc2934eae844550d851480d5448c2542f1d) (cherry picked from commit 40574b32076bc1de5ef1a29daf693c3673e96ba1) --- .../notification/NotificationManagerService.java | 35 ++++++-- .../server/notification/BuzzBeepBlinkTest.java | 93 ++++++++++++++++++++++ 2 files changed, 121 insertions(+), 7 deletions(-) diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 97dc3b2b89fd..dc551e14b970 100755 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -123,6 +123,7 @@ import android.app.INotificationManager; import android.app.ITransientNotification; import android.app.ITransientNotificationCallback; import android.app.IUriGrantsManager; +import android.app.KeyguardManager; import android.app.Notification; import android.app.NotificationChannel; import android.app.NotificationChannelGroup; @@ -479,6 +480,8 @@ public class NotificationManagerService extends SystemService { final ArrayMap> mDelayedCancelations = new ArrayMap<>(); + private KeyguardManager mKeyguardManager; + // The last key in this list owns the hardware. ArrayList mLights = new ArrayList<>(); @@ -1725,6 +1728,11 @@ public class NotificationManagerService extends SystemService { mAudioManager = audioMananger; } + @VisibleForTesting + void setKeyguardManager(KeyguardManager keyguardManager) { + mKeyguardManager = keyguardManager; + } + @VisibleForTesting ShortcutHelper getShortcutHelper() { return mShortcutHelper; @@ -2330,6 +2338,7 @@ public class NotificationManagerService extends SystemService { mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE); mAudioManagerInternal = getLocalService(AudioManagerInternal.class); mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class); + mKeyguardManager = getContext().getSystemService(KeyguardManager.class); mZenModeHelper.onSystemReady(); mRoleObserver = new RoleObserver(getContext().getSystemService(RoleManager.class), mPackageManager, getContext().getMainExecutor()); @@ -6902,7 +6911,6 @@ public class NotificationManagerService extends SystemService { boolean beep = false; boolean blink = false; - final Notification notification = record.getSbn().getNotification(); final String key = record.getKey(); // Should this notification make noise, vibe, or use the LED? @@ -6924,7 +6932,7 @@ public class NotificationManagerService extends SystemService { if (!record.isUpdate && record.getImportance() > IMPORTANCE_MIN && !suppressedByDnd) { - sendAccessibilityEvent(notification, record.getSbn().getPackageName()); + sendAccessibilityEvent(record); sentAccessibilityEvent = true; } @@ -6946,7 +6954,7 @@ public class NotificationManagerService extends SystemService { boolean hasAudibleAlert = hasValidSound || hasValidVibrate; if (hasAudibleAlert && !shouldMuteNotificationLocked(record)) { if (!sentAccessibilityEvent) { - sendAccessibilityEvent(notification, record.getSbn().getPackageName()); + sendAccessibilityEvent(record); sentAccessibilityEvent = true; } if (DBG) Slog.v(TAG, "Interrupting!"); @@ -7659,17 +7667,30 @@ public class NotificationManagerService extends SystemService { return (x < low) ? low : ((x > high) ? high : x); } - void sendAccessibilityEvent(Notification notification, CharSequence packageName) { + void sendAccessibilityEvent(NotificationRecord record) { if (!mAccessibilityManager.isEnabled()) { return; } - AccessibilityEvent event = + final Notification notification = record.getNotification(); + final CharSequence packageName = record.getSbn().getPackageName(); + final AccessibilityEvent event = AccessibilityEvent.obtain(AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED); event.setPackageName(packageName); event.setClassName(Notification.class.getName()); - event.setParcelableData(notification); - CharSequence tickerText = notification.tickerText; + final int visibilityOverride = record.getPackageVisibilityOverride(); + final int notifVisibility = visibilityOverride == NotificationManager.VISIBILITY_NO_OVERRIDE + ? notification.visibility : visibilityOverride; + final int userId = record.getUser().getIdentifier(); + final boolean needPublic = userId >= 0 && mKeyguardManager.isDeviceLocked(userId); + if (needPublic && notifVisibility != Notification.VISIBILITY_PUBLIC) { + // Emit the public version if we're on the lockscreen and this notification isn't + // publicly visible. + event.setParcelableData(notification.publicVersion); + } else { + event.setParcelableData(notification); + } + final CharSequence tickerText = notification.tickerText; if (!TextUtils.isEmpty(tickerText)) { event.getText().add(tickerText); } diff --git a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java index cfda07c55208..a21bfda58529 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java @@ -46,6 +46,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.ActivityManager; +import android.app.KeyguardManager; import android.app.Notification; import android.app.Notification.Builder; import android.app.NotificationChannel; @@ -103,6 +104,8 @@ public class BuzzBeepBlinkTest extends UiServiceTestCase { NotificationUsageStats mUsageStats; @Mock IAccessibilityManager mAccessibilityService; + @Mock + KeyguardManager mKeyguardManager; NotificationRecordLoggerFake mNotificationRecordLogger = new NotificationRecordLoggerFake(); private InstanceIdSequence mNotificationInstanceIdSequence = new InstanceIdSequenceFake( 1 << 30); @@ -147,6 +150,7 @@ public class BuzzBeepBlinkTest extends UiServiceTestCase { when(mAudioManager.getStreamVolume(anyInt())).thenReturn(10); when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL); when(mUsageStats.isAlertRateLimited(any())).thenReturn(false); + when(mKeyguardManager.isDeviceLocked(anyInt())).thenReturn(false); long serviceReturnValue = IntPair.of( AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED, @@ -168,6 +172,7 @@ public class BuzzBeepBlinkTest extends UiServiceTestCase { mService.setFallbackVibrationPattern(FALLBACK_VIBRATION_PATTERN); mService.setUsageStats(mUsageStats); mService.setAccessibilityManager(accessibilityManager); + mService.setKeyguardManager(mKeyguardManager); mService.mScreenOn = false; mService.mInCallStateOffHook = false; mService.mNotificationPulseEnabled = true; @@ -483,6 +488,94 @@ public class BuzzBeepBlinkTest extends UiServiceTestCase { assertNotEquals(-1, r.getLastAudiblyAlertedMs()); } + @Test + public void testLockedPrivateA11yRedaction() throws Exception { + NotificationRecord r = getBeepyNotification(); + r.setPackageVisibilityOverride(NotificationManager.VISIBILITY_NO_OVERRIDE); + r.getNotification().visibility = Notification.VISIBILITY_PRIVATE; + when(mKeyguardManager.isDeviceLocked(anyInt())).thenReturn(true); + AccessibilityManager accessibilityManager = Mockito.mock(AccessibilityManager.class); + when(accessibilityManager.isEnabled()).thenReturn(true); + mService.setAccessibilityManager(accessibilityManager); + + mService.buzzBeepBlinkLocked(r); + + ArgumentCaptor eventCaptor = + ArgumentCaptor.forClass(AccessibilityEvent.class); + + verify(accessibilityManager, times(1)) + .sendAccessibilityEvent(eventCaptor.capture()); + + AccessibilityEvent event = eventCaptor.getValue(); + assertEquals(r.getNotification().publicVersion, event.getParcelableData()); + } + + @Test + public void testLockedOverridePrivateA11yRedaction() throws Exception { + NotificationRecord r = getBeepyNotification(); + r.setPackageVisibilityOverride(Notification.VISIBILITY_PRIVATE); + r.getNotification().visibility = Notification.VISIBILITY_PUBLIC; + when(mKeyguardManager.isDeviceLocked(anyInt())).thenReturn(true); + AccessibilityManager accessibilityManager = Mockito.mock(AccessibilityManager.class); + when(accessibilityManager.isEnabled()).thenReturn(true); + mService.setAccessibilityManager(accessibilityManager); + + mService.buzzBeepBlinkLocked(r); + + ArgumentCaptor eventCaptor = + ArgumentCaptor.forClass(AccessibilityEvent.class); + + verify(accessibilityManager, times(1)) + .sendAccessibilityEvent(eventCaptor.capture()); + + AccessibilityEvent event = eventCaptor.getValue(); + assertEquals(r.getNotification().publicVersion, event.getParcelableData()); + } + + @Test + public void testLockedPublicA11yNoRedaction() throws Exception { + NotificationRecord r = getBeepyNotification(); + r.setPackageVisibilityOverride(NotificationManager.VISIBILITY_NO_OVERRIDE); + r.getNotification().visibility = Notification.VISIBILITY_PUBLIC; + when(mKeyguardManager.isDeviceLocked(anyInt())).thenReturn(true); + AccessibilityManager accessibilityManager = Mockito.mock(AccessibilityManager.class); + when(accessibilityManager.isEnabled()).thenReturn(true); + mService.setAccessibilityManager(accessibilityManager); + + mService.buzzBeepBlinkLocked(r); + + ArgumentCaptor eventCaptor = + ArgumentCaptor.forClass(AccessibilityEvent.class); + + verify(accessibilityManager, times(1)) + .sendAccessibilityEvent(eventCaptor.capture()); + + AccessibilityEvent event = eventCaptor.getValue(); + assertEquals(r.getNotification(), event.getParcelableData()); + } + + @Test + public void testUnlockedPrivateA11yNoRedaction() throws Exception { + NotificationRecord r = getBeepyNotification(); + r.setPackageVisibilityOverride(NotificationManager.VISIBILITY_NO_OVERRIDE); + r.getNotification().visibility = Notification.VISIBILITY_PRIVATE; + when(mKeyguardManager.isDeviceLocked(anyInt())).thenReturn(false); + AccessibilityManager accessibilityManager = Mockito.mock(AccessibilityManager.class); + when(accessibilityManager.isEnabled()).thenReturn(true); + mService.setAccessibilityManager(accessibilityManager); + + mService.buzzBeepBlinkLocked(r); + + ArgumentCaptor eventCaptor = + ArgumentCaptor.forClass(AccessibilityEvent.class); + + verify(accessibilityManager, times(1)) + .sendAccessibilityEvent(eventCaptor.capture()); + + AccessibilityEvent event = eventCaptor.getValue(); + assertEquals(r.getNotification(), event.getParcelableData()); + } + @Test public void testBeepInsistently() throws Exception { NotificationRecord r = getInsistentBeepyNotification(); -- cgit v1.2.3 From e9a6ebf59258a4ca14f83b74f10113aaddaf2b33 Mon Sep 17 00:00:00 2001 From: Kweku Adams Date: Thu, 3 Jun 2021 16:07:56 -0700 Subject: Don't export HeapDumpProvider. Stop exporting HeapDumpProvider so apps can only access generated dumps when the user explicitly shares them. Bug: 184046948 Test: capture system heap dump in developer options and confirm test app get SecurityException if it tries to access the dump directly, but gets access when the dump is shared through the notification flow Change-Id: Ibdca7cde4f563baa39163869289da5b79fc3a6db (cherry picked from commit a60c62bcb74e0146820f75f1da49581d1709b63c) (cherry picked from commit 260d0a85ddf986d41340980ef5abf0a878d65d9c) --- packages/Shell/AndroidManifest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index 570c2ab3efd1..3e820c39665c 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -346,7 +346,7 @@ + android:exported="false" /> Date: Fri, 25 Jun 2021 09:59:32 -0700 Subject: Use IntentFilter CREATOR directly for serializing ParsedIntentInfo ParsedIntentInfo's CRFEATOR was removed because it exposes a reparcelling vulnerability. This adjusts a system API that relied on the implicit parcelling read to instead use IntentFilter directly, ignoring the fields contained in the subclass. Bug: 192050390 Bug: 191055353 Test: manual, cannot repro crash after patch Merged-In: Ib12e0a959eb5a5d73d5832ff2eee26a30eed5ded Change-Id: Ib12e0a959eb5a5d73d5832ff2eee26a30eed5ded (cherry picked from commit 7ac9b1da731bdf6ed2f34e22d5da7030bc0f7d21) --- .../java/com/android/server/pm/PackageManagerService.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index c643307c5f51..cde249fe2a72 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -14252,9 +14252,15 @@ public class PackageManagerService extends IPackageManager.Stub return new ParceledListSlice(result) { @Override protected void writeElement(IntentFilter parcelable, Parcel dest, int callFlags) { - // IntentFilter has final Parcelable methods, so redirect to the subclass - ((ParsedIntentInfo) parcelable).writeIntentInfoToParcel(dest, - callFlags); + parcelable.writeToParcel(dest, callFlags); + } + + @Override + protected void writeParcelableCreator(IntentFilter parcelable, Parcel dest) { + // All Parcel#writeParcelableCreator does is serialize the class name to + // access via reflection to grab its CREATOR. This does that manually, pointing + // to the parent IntentFilter so that all of the subclass fields are ignored. + dest.writeString(IntentFilter.class.getName()); } }; } -- cgit v1.2.3 From 1d2d942b765f842c7002ef948611a126bc87bd06 Mon Sep 17 00:00:00 2001 From: Paul Scovanner Date: Sat, 19 Jun 2021 04:56:21 +0000 Subject: Revert "Detects all activities for whether showing work challenge" This reverts commit 87fa64ebe46f1b3273e1e42c99ef2a09f19145a8. Reason for revert: b/191385314 Change-Id: I87ac32c9aa6a8d2a43533f7512d5b6ea85fdeb36 (cherry picked from commit bbdd0f043c714c62b45abd39d9078a049db70ef9) (cherry picked from commit 2992a1dac025074726364d522cf9eac586f3d2c3) --- .../com/android/server/wm/RootWindowContainer.java | 40 +++++++++++++++++----- .../server/wm/RootWindowContainerTests.java | 33 ------------------ 2 files changed, 32 insertions(+), 41 deletions(-) diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index ddad1dbd9b3d..eaf76938e2e8 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -3372,7 +3372,7 @@ class RootWindowContainer extends WindowContainer } /** - * Find all task stacks containing {@param userId} and intercept them with an activity + * Find all visible task stacks containing {@param userId} and intercept them with an activity * to block out the contents and possibly start a credential-confirming intent. * * @param userId user handle for the locked managed profile. @@ -3380,18 +3380,42 @@ class RootWindowContainer extends WindowContainer void lockAllProfileTasks(@UserIdInt int userId) { mService.deferWindowLayout(); try { - forAllLeafTasks(task -> { - if (task.getActivity(activity -> !activity.finishing && activity.mUserId == userId) - != null) { - mService.getTaskChangeNotificationController().notifyTaskProfileLocked( - task.mTaskId, userId); - } - }, true /* traverseTopToBottom */); + final PooledConsumer c = PooledLambda.obtainConsumer( + RootWindowContainer::taskTopActivityIsUser, this, PooledLambda.__(Task.class), + userId); + forAllLeafTasks(c, true /* traverseTopToBottom */); + c.recycle(); } finally { mService.continueWindowLayout(); } } + /** + * Detects whether we should show a lock screen in front of this task for a locked user. + *

+ * We'll do this if either of the following holds: + *

    + *
  • The top activity explicitly belongs to {@param userId}.
  • + *
  • The top activity returns a result to an activity belonging to {@param userId}.
  • + *
+ * + * @return {@code true} if the top activity looks like it belongs to {@param userId}. + */ + private void taskTopActivityIsUser(Task task, @UserIdInt int userId) { + // To handle the case that work app is in the task but just is not the top one. + final ActivityRecord activityRecord = task.getTopNonFinishingActivity(); + final ActivityRecord resultTo = (activityRecord != null ? activityRecord.resultTo : null); + + // Check the task for a top activity belonging to userId, or returning a + // result to an activity belonging to userId. Example case: a document + // picker for personal files, opened by a work app, should still get locked. + if ((activityRecord != null && activityRecord.mUserId == userId) + || (resultTo != null && resultTo.mUserId == userId)) { + mService.getTaskChangeNotificationController().notifyTaskProfileLocked( + task.mTaskId, userId); + } + } + void cancelInitializingActivities() { for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) { final DisplayContent display = getChildAt(displayNdx); diff --git a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java index 1aff8a7b5382..35d1b17d5822 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java @@ -25,7 +25,6 @@ import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE; import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR; import static android.view.WindowManager.LayoutParams.TYPE_TOAST; -import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.server.wm.ActivityStack.ActivityState.FINISHING; import static com.android.server.wm.ActivityStack.ActivityState.PAUSED; import static com.android.server.wm.ActivityStack.ActivityState.PAUSING; @@ -37,13 +36,10 @@ import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.verify; import android.app.WindowConfiguration; import android.content.ComponentName; import android.content.pm.ActivityInfo; -import android.os.UserHandle; import android.platform.test.annotations.Presubmit; import androidx.test.filters.SmallTest; @@ -173,34 +169,5 @@ public class RootWindowContainerTests extends WindowTestsBase { activity.setState(FINISHING, "test FINISHING"); assertThat(mWm.mRoot.allPausedActivitiesComplete()).isTrue(); } - - @Test - public void testLockAllProfileTasks() { - // Make an activity visible with the user id set to 0 - DisplayContent displayContent = mWm.mRoot.getDisplayContent(DEFAULT_DISPLAY); - TaskDisplayArea taskDisplayArea = displayContent.getTaskDisplayAreaAt(0); - final ActivityStack stack = createTaskStackOnDisplay(WINDOWING_MODE_FULLSCREEN, - ACTIVITY_TYPE_STANDARD, displayContent); - final ActivityRecord activity = new ActivityTestsBase.ActivityBuilder(stack.mAtmService) - .setStack(stack) - .setUid(0) - .setCreateTask(true) - .build(); - - // Create another activity on top and the user id is 1 - Task task = activity.getTask(); - final ActivityRecord topActivity = new ActivityTestsBase.ActivityBuilder(mWm.mAtmService) - .setStack(stack) - .setUid(UserHandle.PER_USER_RANGE + 1) - .setTask(task) - .build(); - - // Make sure the listeners will be notified for putting the task to locked state - TaskChangeNotificationController controller = - mWm.mAtmService.getTaskChangeNotificationController(); - spyOn(controller); - mWm.mRoot.lockAllProfileTasks(0); - verify(controller).notifyTaskProfileLocked(eq(task.mTaskId), eq(0)); - } } -- cgit v1.2.3 From 4ebfedd7f870e181a62daa2ab70b9d9155492bac Mon Sep 17 00:00:00 2001 From: Dmitry Dementyev Date: Thu, 17 Jun 2021 13:16:38 -0700 Subject: Change ownership of the account request notification. Add "Permission requested by Application..." string. Test: manual Bug: 179338675 Change-Id: Ib66ccc1b39bd1f3f8fa3b1efc38a9d413b72a321 (cherry picked from commit 26de0c231ffb9fd8d22e80ca120c766c26276779) --- core/res/res/values/strings.xml | 2 ++ core/res/res/values/symbols.xml | 1 + .../server/accounts/AccountManagerService.java | 21 +++++++++++++++------ 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index d6ee28b93f92..5c659123b027 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -3780,6 +3780,8 @@ Deny Permission requested Permission requested\nfor account %s. + + Permission requested by %1$s\nfor account %2$s. You\'re using this app outside of your work profile diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 3ef0a8dc9daa..3c2aa621864b 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -548,6 +548,7 @@ + diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java index 2e04f9c2bcd1..db3c25a7e43a 100644 --- a/services/core/java/com/android/server/accounts/AccountManagerService.java +++ b/services/core/java/com/android/server/accounts/AccountManagerService.java @@ -449,7 +449,7 @@ public class AccountManagerService if (!checkAccess || hasAccountAccess(account, packageName, UserHandle.getUserHandleForUid(uid))) { cancelNotification(getCredentialPermissionNotificationId(account, - AccountManager.ACCOUNT_ACCESS_TOKEN_TYPE, uid), packageName, + AccountManager.ACCOUNT_ACCESS_TOKEN_TYPE, uid), UserHandle.getUserHandleForUid(uid)); } } @@ -3051,8 +3051,8 @@ public class AccountManagerService String authTokenType = intent.getStringExtra( GrantCredentialsPermissionActivity.EXTRAS_AUTH_TOKEN_TYPE); final String titleAndSubtitle = - mContext.getString(R.string.permission_request_notification_with_subtitle, - account.name); + mContext.getString(R.string.permission_request_notification_for_app_with_subtitle, + getApplicationLabel(packageName), account.name); final int index = titleAndSubtitle.indexOf('\n'); String title = titleAndSubtitle; String subtitle = ""; @@ -3075,7 +3075,16 @@ public class AccountManagerService null, user)) .build(); installNotification(getCredentialPermissionNotificationId( - account, authTokenType, uid), n, packageName, user.getIdentifier()); + account, authTokenType, uid), n, "android", user.getIdentifier()); + } + + private String getApplicationLabel(String packageName) { + try { + return mPackageManager.getApplicationLabel( + mPackageManager.getApplicationInfo(packageName, 0)).toString(); + } catch (PackageManager.NameNotFoundException e) { + return packageName; + } } private Intent newGrantCredentialsPermissionIntent(Account account, String packageName, @@ -3111,7 +3120,7 @@ public class AccountManagerService nId = accounts.credentialsPermissionNotificationIds.get(key); if (nId == null) { String tag = TAG + ":" + SystemMessage.NOTE_ACCOUNT_CREDENTIAL_PERMISSION - + ":" + account.hashCode() + ":" + authTokenType.hashCode(); + + ":" + account.hashCode() + ":" + authTokenType.hashCode() + ":" + uid; int id = SystemMessage.NOTE_ACCOUNT_CREDENTIAL_PERMISSION; nId = new NotificationId(tag, id); accounts.credentialsPermissionNotificationIds.put(key, nId); @@ -4064,7 +4073,7 @@ public class AccountManagerService private void handleAuthenticatorResponse(boolean accessGranted) throws RemoteException { cancelNotification(getCredentialPermissionNotificationId(account, - AccountManager.ACCOUNT_ACCESS_TOKEN_TYPE, uid), packageName, + AccountManager.ACCOUNT_ACCESS_TOKEN_TYPE, uid), UserHandle.getUserHandleForUid(uid)); if (callback != null) { Bundle result = new Bundle(); -- cgit v1.2.3 From 4eba7e65cd0cc2f2c87b001fb34b9f28ee7c70ab Mon Sep 17 00:00:00 2001 From: Bernardo Rufino Date: Wed, 26 May 2021 16:25:39 +0100 Subject: Fix background bypass via notifications This is a CP of ag/14736230 to qt-dev. Apps were able to bypass BAL and BG-FGS restrictions by retrieving their own notifications and firing their PI since those were allowlisted for those operations. Now we strip the token that granted them that ability from notifications returned via NM.getActiveNotifications(), which returns the notifications of the caller. Notifications returned via notification listener APIs still contain such token, as they should. Bug: 185388103 Bug: 169821287 Test: Manually tested Change-Id: I2ede0d639a560f6acacec3864a0a7d23af152ba5 Merged-In: I2ede0d639a560f6acacec3864a0a7d23af152ba5 (cherry picked from commit 5fbeff59df3ea1441c3843aa1834616876ef1985) (cherry picked from commit 14c1c7b4a732c517ba18f5dd0598adb9f3b72221) --- core/java/android/app/Notification.java | 13 +++++++++++++ .../server/notification/NotificationManagerService.java | 8 +++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index c273cf08d03b..132afabe82d1 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -3028,6 +3028,19 @@ public class Notification implements Parcelable builder.build(); // callers expect this notification to be ready to use } + /** + * Sets the token used for background operations for the pending intents associated with this + * notification. + * + * This token is automatically set during deserialization for you, you usually won't need to + * call this unless you want to change the existing token, if any. + * + * @hide + */ + public void setAllowlistToken(@Nullable IBinder token) { + mWhitelistToken = token; + } + /** * @hide */ diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index dc551e14b970..629a918584fe 100755 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -3859,6 +3859,7 @@ public class NotificationManagerService extends SystemService { } } + /** Notifications returned here will have allowlistToken stripped from them. */ private StatusBarNotification sanitizeSbn(String pkg, int userId, StatusBarNotification sbn) { if (sbn.getUserId() == userId) { @@ -3866,11 +3867,16 @@ public class NotificationManagerService extends SystemService { // We could pass back a cloneLight() but clients might get confused and // try to send this thing back to notify() again, which would not work // very well. + Notification notification = sbn.getNotification().clone(); + // Remove background token before returning notification to untrusted app, this + // ensures the app isn't able to perform background operations that are + // associated with notification interactions. + notification.setAllowlistToken(null); return new StatusBarNotification( sbn.getPackageName(), sbn.getOpPkg(), sbn.getId(), sbn.getTag(), sbn.getUid(), sbn.getInitialPid(), - sbn.getNotification().clone(), + notification, sbn.getUser(), sbn.getOverrideGroupKey(), sbn.getPostTime()); } } -- cgit v1.2.3 From 0c4bc631f2e09ccd0712da39b3e1a6c4eaf52a65 Mon Sep 17 00:00:00 2001 From: John Reck Date: Thu, 22 Apr 2021 16:55:09 -0400 Subject: Fix a potential thread safety issue in VectorDrawable Bug: 158839504 Bug: 185178568 Test: speculative Change-Id: Id9f229f08fe5897dda25441fbaa15c98f8130de9 (cherry picked from commit 304f3af54526f3d80cc037e18f4cf89f1053737c) --- graphics/java/android/graphics/drawable/VectorDrawable.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java index e6fa866df3ab..a831bb86009c 100644 --- a/graphics/java/android/graphics/drawable/VectorDrawable.java +++ b/graphics/java/android/graphics/drawable/VectorDrawable.java @@ -348,15 +348,19 @@ public class VectorDrawable extends Drawable { private final Rect mTmpBounds = new Rect(); public VectorDrawable() { - this(new VectorDrawableState(null), null); + this(null, null); } /** * The one constructor to rule them all. This is called by all public * constructors to set the state and initialize local properties. */ - private VectorDrawable(@NonNull VectorDrawableState state, @Nullable Resources res) { - mVectorState = state; + private VectorDrawable(@Nullable VectorDrawableState state, @Nullable Resources res) { + // As the mutable, not-thread-safe native instance is stored in VectorDrawableState, we + // need to always do a defensive copy even if mutate() isn't called. Otherwise + // draw() being called on 2 different VectorDrawable instances could still hit the same + // underlying native object. + mVectorState = new VectorDrawableState(state); updateLocalState(res); } -- cgit v1.2.3 From 42c16edc958fa196e934e361205f74727db8285b Mon Sep 17 00:00:00 2001 From: Dave Mankoff Date: Wed, 21 Jul 2021 10:08:04 -0400 Subject: Guard DISABLE_PLUGIN with PLUGIN permission. Fixes a p0 security bug. We already have the plugin permission defined in our manifest. Ensure that senders of the DISABLE_PLUGIN broadcast have that permission. Bug: 193444889 Test: manual Change-Id: Iebaba435c17c5644c5357c0683858447f5ffb897 Merged-In: Iebaba435c17c5644c5357c0683858447f5ffb897 (cherry picked from commit c2c2fa79ffae28d40d0d8bfb29f25b6ede6bd55b) --- .../src/com/android/systemui/shared/plugins/PluginManagerImpl.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManagerImpl.java b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManagerImpl.java index 4d1fb38329e9..a687bb89fd75 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManagerImpl.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManagerImpl.java @@ -195,9 +195,12 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage filter.addAction(Intent.ACTION_PACKAGE_CHANGED); filter.addAction(Intent.ACTION_PACKAGE_REPLACED); filter.addAction(Intent.ACTION_PACKAGE_REMOVED); + filter.addDataScheme("package"); + mContext.registerReceiver(this, filter); filter.addAction(PLUGIN_CHANGED); filter.addAction(DISABLE_PLUGIN); filter.addDataScheme("package"); + mContext.registerReceiver(this, filter, PluginInstanceManager.PLUGIN_PERMISSION, null); mContext.registerReceiver(this, filter); filter = new IntentFilter(Intent.ACTION_USER_UNLOCKED); mContext.registerReceiver(this, filter); -- cgit v1.2.3 From bfad9c3e8e1e920b03c06beae0cb0fa77af81126 Mon Sep 17 00:00:00 2001 From: Sudheer Shanka Date: Tue, 11 May 2021 17:01:11 -0700 Subject: Send targeted broadcasts to prevent other apps from receiving them. When sending broadcasts ACTION_SNOOZE_WARNING in NPMS, which may contain sensitive information, explicitly set the package name that should receive it to prevent other apps from receiving them. Bug: 177931370 Test: manual Change-Id: I11d736771d859d2af27d5c84a502ab038974e2e2 Merged-In: I11d736771d859d2af27d5c84a502ab038974e2e2 (cherry picked from commit 1494979a6ac772fa49a26748f047a4c3d64baf51) (cherry picked from commit 16732a1253294866c588ca040416c48be734490b) --- .../com/android/server/net/NetworkPolicyManagerService.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java index 42bd8c512806..4873440b53c1 100644 --- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java @@ -1370,7 +1370,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { builder.setSmallIcon(R.drawable.stat_notify_error); - final Intent snoozeIntent = buildSnoozeWarningIntent(policy.template); + final Intent snoozeIntent = buildSnoozeWarningIntent(policy.template, + mContext.getPackageName()); builder.setDeleteIntent(PendingIntent.getBroadcast( mContext, 0, snoozeIntent, PendingIntent.FLAG_UPDATE_CURRENT)); @@ -1456,7 +1457,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { builder.setSmallIcon(R.drawable.stat_notify_error); - final Intent snoozeIntent = buildSnoozeRapidIntent(policy.template); + final Intent snoozeIntent = buildSnoozeRapidIntent(policy.template, + mContext.getPackageName()); builder.setDeleteIntent(PendingIntent.getBroadcast( mContext, 0, snoozeIntent, PendingIntent.FLAG_UPDATE_CURRENT)); @@ -5061,17 +5063,19 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { return new Intent(ACTION_ALLOW_BACKGROUND); } - private static Intent buildSnoozeWarningIntent(NetworkTemplate template) { + private static Intent buildSnoozeWarningIntent(NetworkTemplate template, String targetPackage) { final Intent intent = new Intent(ACTION_SNOOZE_WARNING); intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); intent.putExtra(EXTRA_NETWORK_TEMPLATE, template); + intent.setPackage(targetPackage); return intent; } - private static Intent buildSnoozeRapidIntent(NetworkTemplate template) { + private static Intent buildSnoozeRapidIntent(NetworkTemplate template, String targetPackage) { final Intent intent = new Intent(ACTION_SNOOZE_RAPID); intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); intent.putExtra(EXTRA_NETWORK_TEMPLATE, template); + intent.setPackage(targetPackage); return intent; } -- cgit v1.2.3 From efdcec1e29a4179aeb5df314321bb1d5e1ba0bee Mon Sep 17 00:00:00 2001 From: Rhed Jao Date: Fri, 30 Jul 2021 15:52:05 +0800 Subject: DO NOT MERGE Apply a maximum char count to the load label api The system is overwhelmed by an enormous label string returned by the load label api. This cl truncates the label string if it exceeds the maximum safe length. Bug: 67013844 Test: atest PackageManagerTest Change-Id: Ia4d768cc93a47cfb8b6f7c4b6dc73abd801809bd Merged-in: Ia4d768cc93a47cfb8b6f7c4b6dc73abd801809bd (cherry picked from commit 3c26a24644feaf2860892809929dec816f354bae) --- core/java/android/content/pm/PackageItemInfo.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/core/java/android/content/pm/PackageItemInfo.java b/core/java/android/content/pm/PackageItemInfo.java index 65ce1e7ef079..9cd568fe2aaf 100644 --- a/core/java/android/content/pm/PackageItemInfo.java +++ b/core/java/android/content/pm/PackageItemInfo.java @@ -207,7 +207,9 @@ public class PackageItemInfo { return loadSafeLabel(pm, DEFAULT_MAX_LABEL_SIZE_PX, SAFE_STRING_FLAG_TRIM | SAFE_STRING_FLAG_FIRST_LINE); } else { - return loadUnsafeLabel(pm); + // Trims the label string to the MAX_SAFE_LABEL_LENGTH. This is to prevent that the + // system is overwhelmed by an enormous string returned by the application. + return TextUtils.trimToSize(loadUnsafeLabel(pm), MAX_SAFE_LABEL_LENGTH); } } -- cgit v1.2.3 From 0974700666a209e3495510eb2f6a2579ea0d8a04 Mon Sep 17 00:00:00 2001 From: lucaslin Date: Thu, 29 Jul 2021 13:26:35 +0800 Subject: Make sure that only the owner can call stopVpnProfile() In stopVpnProfile(), it doesn't check if the caller's package name is the same as the given one, so any app has chance to stop the VPN profile of other apps. Bug: 191382886 Test: atest FrameworksNetTests CtsNetTestCases \ CtsHostsideNetworkTests:HostsideVpnTests Change-Id: Ib0a6e9ed191ff8c8bd55ce9902d894b6a339ace2 Merged-In: I254ffd1c08ec058d594b4ea55cbae5505f8497cc (cherry picked from commit f3072fcd46112bad7c5f6ddd4cc35d2c67f00d11) --- .../com/android/server/ConnectivityService.java | 28 ++++++++++++++++++++-- .../android/server/ConnectivityServiceTest.java | 18 ++++++++++++++ 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index a1cbd00e360f..9a3ab4403831 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -73,6 +73,7 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.Configuration; import android.database.ContentObserver; import android.net.CaptivePortal; @@ -4609,6 +4610,25 @@ public class ConnectivityService extends IConnectivityManager.Stub } } + private int getAppUid(final String app, final int userId) { + final PackageManager pm = mContext.getPackageManager(); + final long token = Binder.clearCallingIdentity(); + try { + return pm.getPackageUidAsUser(app, userId); + } catch (NameNotFoundException e) { + return -1; + } finally { + Binder.restoreCallingIdentity(token); + } + } + + private void verifyCallingUidAndPackage(String packageName, int callingUid) { + final int userId = UserHandle.getUserId(callingUid); + if (getAppUid(packageName, userId) != callingUid) { + throw new SecurityException(packageName + " does not belong to uid " + callingUid); + } + } + /** * Starts the VPN based on the stored profile for the given package * @@ -4620,7 +4640,9 @@ public class ConnectivityService extends IConnectivityManager.Stub */ @Override public void startVpnProfile(@NonNull String packageName) { - final int user = UserHandle.getUserId(Binder.getCallingUid()); + final int callingUid = Binder.getCallingUid(); + verifyCallingUidAndPackage(packageName, callingUid); + final int user = UserHandle.getUserId(callingUid); synchronized (mVpns) { throwIfLockdownEnabled(); mVpns.get(user).startVpnProfile(packageName, mKeyStore); @@ -4637,7 +4659,9 @@ public class ConnectivityService extends IConnectivityManager.Stub */ @Override public void stopVpnProfile(@NonNull String packageName) { - final int user = UserHandle.getUserId(Binder.getCallingUid()); + final int callingUid = Binder.getCallingUid(); + verifyCallingUidAndPackage(packageName, callingUid); + final int user = UserHandle.getUserId(callingUid); synchronized (mVpns) { mVpns.get(user).stopVpnProfile(packageName); } diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index a5554c740e7f..e9301d1dea9d 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -1224,6 +1224,9 @@ public class ConnectivityServiceTest { Arrays.asList(new UserInfo[] { new UserInfo(VPN_USER, "", 0), })); + final int userId = UserHandle.getCallingUserId(); + final UserInfo primaryUser = new UserInfo(userId, "", UserInfo.FLAG_PRIMARY); + doReturn(primaryUser).when(mUserManager).getUserInfo(eq(userId)); final ApplicationInfo applicationInfo = new ApplicationInfo(); applicationInfo.targetSdkVersion = Build.VERSION_CODES.Q; when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), any())) @@ -1368,6 +1371,9 @@ public class ConnectivityServiceTest { buildPackageInfo(/* SYSTEM */ false, APP2_UID), buildPackageInfo(/* SYSTEM */ false, VPN_UID) })); + final int userId = UserHandle.getCallingUserId(); + when(mPackageManager.getPackageUidAsUser(TEST_PACKAGE_NAME, userId)) + .thenReturn(Process.myUid()); } private void verifyActiveNetwork(int transport) { @@ -7068,6 +7074,18 @@ public class ConnectivityServiceTest { assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID); } + @Test + public void testStartVpnProfileFromDiffPackage() throws Exception { + final String notMyVpnPkg = "com.not.my.vpn"; + assertThrows(SecurityException.class, () -> mService.startVpnProfile(notMyVpnPkg)); + } + + @Test + public void testStopVpnProfileFromDiffPackage() throws Exception { + final String notMyVpnPkg = "com.not.my.vpn"; + assertThrows(SecurityException.class, () -> mService.stopVpnProfile(notMyVpnPkg)); + } + @Test public void testUidUpdateChangesInterfaceFilteringRule() throws Exception { LinkProperties lp = new LinkProperties(); -- cgit v1.2.3 From 4474f794d8c019463328d2c0f48667438cc3ec5f Mon Sep 17 00:00:00 2001 From: Jayant Chowdhary Date: Wed, 9 Jun 2021 14:34:54 -0700 Subject: camera2: Fix exception swallowing in params classes createFromParcel Do not catch exceptions when we attempt to create the following classes from a parcel - OutputConfiguration - VendorTagDescriptor - VendorTagDescriptorCache - SessionConfiguration This could cause subsequent parcel information to be read incorrectly. Bug: 188675581 Test: Sample app which tries to write invalid data into an OutputConfiguration parcel to send in an intent via Broadcast. When read by the receiving app, gets an exception (not swallowed). Merged-In: I745ca49daa6ca36b1020d518e9f346b52684f2b1 Change-Id: I745ca49daa6ca36b1020d518e9f346b52684f2b1 Signed-off-by: Jayant Chowdhary (cherry picked from commit 6b0bcd60c81003e6a193aeccf44ee03f188e3984) (cherry picked from commit 7bf30cb92ab213c07241ad22def6816ae201dbab) --- .../java/android/hardware/camera2/params/OutputConfiguration.java | 8 +------- .../android/hardware/camera2/params/SessionConfiguration.java | 8 +------- .../java/android/hardware/camera2/params/VendorTagDescriptor.java | 8 +------- .../android/hardware/camera2/params/VendorTagDescriptorCache.java | 8 +------- 4 files changed, 4 insertions(+), 28 deletions(-) diff --git a/core/java/android/hardware/camera2/params/OutputConfiguration.java b/core/java/android/hardware/camera2/params/OutputConfiguration.java index 226b8e549a9e..c062f8c13d75 100644 --- a/core/java/android/hardware/camera2/params/OutputConfiguration.java +++ b/core/java/android/hardware/camera2/params/OutputConfiguration.java @@ -631,13 +631,7 @@ public final class OutputConfiguration implements Parcelable { new Parcelable.Creator() { @Override public OutputConfiguration createFromParcel(Parcel source) { - try { - OutputConfiguration outputConfiguration = new OutputConfiguration(source); - return outputConfiguration; - } catch (Exception e) { - Log.e(TAG, "Exception creating OutputConfiguration from parcel", e); - return null; - } + return new OutputConfiguration(source); } @Override diff --git a/core/java/android/hardware/camera2/params/SessionConfiguration.java b/core/java/android/hardware/camera2/params/SessionConfiguration.java index 47a897cb2c55..010b083633f5 100644 --- a/core/java/android/hardware/camera2/params/SessionConfiguration.java +++ b/core/java/android/hardware/camera2/params/SessionConfiguration.java @@ -143,13 +143,7 @@ public final class SessionConfiguration implements Parcelable { new Parcelable.Creator () { @Override public SessionConfiguration createFromParcel(Parcel source) { - try { - SessionConfiguration sessionConfiguration = new SessionConfiguration(source); - return sessionConfiguration; - } catch (Exception e) { - Log.e(TAG, "Exception creating SessionConfiguration from parcel", e); - return null; - } + return new SessionConfiguration(source); } @Override diff --git a/core/java/android/hardware/camera2/params/VendorTagDescriptor.java b/core/java/android/hardware/camera2/params/VendorTagDescriptor.java index 4845ec3e3bd8..c62f6da012c1 100644 --- a/core/java/android/hardware/camera2/params/VendorTagDescriptor.java +++ b/core/java/android/hardware/camera2/params/VendorTagDescriptor.java @@ -36,13 +36,7 @@ public final class VendorTagDescriptor implements Parcelable { new Parcelable.Creator() { @Override public VendorTagDescriptor createFromParcel(Parcel source) { - try { - VendorTagDescriptor vendorDescriptor = new VendorTagDescriptor(source); - return vendorDescriptor; - } catch (Exception e) { - Log.e(TAG, "Exception creating VendorTagDescriptor from parcel", e); - return null; - } + return new VendorTagDescriptor(source); } @Override diff --git a/core/java/android/hardware/camera2/params/VendorTagDescriptorCache.java b/core/java/android/hardware/camera2/params/VendorTagDescriptorCache.java index 450b70bcdcdc..8d7615c98662 100644 --- a/core/java/android/hardware/camera2/params/VendorTagDescriptorCache.java +++ b/core/java/android/hardware/camera2/params/VendorTagDescriptorCache.java @@ -36,13 +36,7 @@ public final class VendorTagDescriptorCache implements Parcelable { new Parcelable.Creator() { @Override public VendorTagDescriptorCache createFromParcel(Parcel source) { - try { - VendorTagDescriptorCache vendorDescriptorCache = new VendorTagDescriptorCache(source); - return vendorDescriptorCache; - } catch (Exception e) { - Log.e(TAG, "Exception creating VendorTagDescriptorCache from parcel", e); - return null; - } + return new VendorTagDescriptorCache(source); } @Override -- cgit v1.2.3 From 37e59f5ca2974761bf09f579d14de775b610e991 Mon Sep 17 00:00:00 2001 From: Winson Date: Fri, 18 Jun 2021 11:17:50 -0700 Subject: Fix parsing code parcelling errors Address problems reading/writing: - ParsingPackageImpl mKeySetMapping - ParsingPackageImpl mQueriesIntent Bug: 187043377 Bug: 195962697 Test: atest com.android.server.pm.test.parsing.parcelling Merged-In: I5b33315f8248d5fcbdef2cc04ecf77cc18dbd7b6 Change-Id: I5b33315f8248d5fcbdef2cc04ecf77cc18dbd7b6 (cherry picked from commit f93af7ef7ebe9d139a34e615b97393a41ebabb56) (cherry picked from commit 37a0b6de89f7fb321fbeac02ec1a012817b8e682) --- .../content/pm/parsing/ParsingPackageImpl.java | 6 +-- .../content/pm/parsing/ParsingPackageUtils.java | 63 ++++++++++++++++++++++ 2 files changed, 66 insertions(+), 3 deletions(-) diff --git a/core/java/android/content/pm/parsing/ParsingPackageImpl.java b/core/java/android/content/pm/parsing/ParsingPackageImpl.java index 2da93ca34019..295107a06f99 100644 --- a/core/java/android/content/pm/parsing/ParsingPackageImpl.java +++ b/core/java/android/content/pm/parsing/ParsingPackageImpl.java @@ -1007,7 +1007,7 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable { sForInternedStringList.parcel(this.requestedPermissions, dest, flags); sForInternedStringList.parcel(this.implicitPermissions, dest, flags); sForStringSet.parcel(this.upgradeKeySets, dest, flags); - dest.writeMap(this.keySetMapping); + ParsingPackageUtils.writeKeySetMapping(dest, this.keySetMapping); sForInternedStringList.parcel(this.protectedBroadcasts, dest, flags); dest.writeTypedList(this.activities); dest.writeTypedList(this.receivers); @@ -1026,7 +1026,7 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable { dest.writeBoolean(this.use32BitAbi); dest.writeBoolean(this.visibleToInstantApps); dest.writeBoolean(this.forceQueryable); - dest.writeParcelableList(this.queriesIntents, flags); + dest.writeTypedList(this.queriesIntents, flags); sForInternedStringList.parcel(this.queriesPackages, dest, flags); sForInternedStringSet.parcel(this.queriesProviders, dest, flags); dest.writeString(this.appComponentFactory); @@ -1169,7 +1169,7 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable { this.requestedPermissions = sForInternedStringList.unparcel(in); this.implicitPermissions = sForInternedStringList.unparcel(in); this.upgradeKeySets = sForStringSet.unparcel(in); - this.keySetMapping = in.readHashMap(boot); + this.keySetMapping = ParsingPackageUtils.readKeySetMapping(in); this.protectedBroadcasts = sForInternedStringList.unparcel(in); this.activities = in.createTypedArrayList(ParsedActivity.CREATOR); diff --git a/core/java/android/content/pm/parsing/ParsingPackageUtils.java b/core/java/android/content/pm/parsing/ParsingPackageUtils.java index ab0ed51fb909..a56a3ea9b2f6 100644 --- a/core/java/android/content/pm/parsing/ParsingPackageUtils.java +++ b/core/java/android/content/pm/parsing/ParsingPackageUtils.java @@ -84,6 +84,7 @@ import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.FileUtils; +import android.os.Parcel; import android.os.RemoteException; import android.os.Trace; import android.os.ext.SdkExtensions; @@ -2834,6 +2835,68 @@ public class ParsingPackageUtils { return sa.getNonResourceString(index); } + /** + * Writes the keyset mapping to the provided package. {@code null} mappings are permitted. + */ + public static void writeKeySetMapping(@NonNull Parcel dest, + @NonNull Map> keySetMapping) { + if (keySetMapping == null) { + dest.writeInt(-1); + return; + } + + final int N = keySetMapping.size(); + dest.writeInt(N); + + for (String key : keySetMapping.keySet()) { + dest.writeString(key); + ArraySet keys = keySetMapping.get(key); + if (keys == null) { + dest.writeInt(-1); + continue; + } + + final int M = keys.size(); + dest.writeInt(M); + for (int j = 0; j < M; j++) { + dest.writeSerializable(keys.valueAt(j)); + } + } + } + + /** + * Reads a keyset mapping from the given parcel at the given data position. May return + * {@code null} if the serialized mapping was {@code null}. + */ + @NonNull + public static ArrayMap> readKeySetMapping(@NonNull Parcel in) { + final int N = in.readInt(); + if (N == -1) { + return null; + } + + ArrayMap> keySetMapping = new ArrayMap<>(); + for (int i = 0; i < N; ++i) { + String key = in.readString(); + final int M = in.readInt(); + if (M == -1) { + keySetMapping.put(key, null); + continue; + } + + ArraySet keys = new ArraySet<>(M); + for (int j = 0; j < M; ++j) { + PublicKey pk = (PublicKey) in.readSerializable(); + keys.add(pk); + } + + keySetMapping.put(key, keys); + } + + return keySetMapping; + } + + /** * Callback interface for retrieving information that may be needed while parsing * a package. -- cgit v1.2.3 From 609a8da0ba5ce448ca7b70c5265ec3048259febf Mon Sep 17 00:00:00 2001 From: Hansong Zhang Date: Wed, 18 Aug 2021 16:35:00 -0700 Subject: Bluetooth: Fix formatting in getAlias() Bug: 180747689 Test: manual Change-Id: Ic309f4aad116fd424d5d0d0e2016d61be8826b78 (cherry picked from commit 3c4a917cb9481f4b70c26b6a06e798e65e5895ce) --- core/java/android/bluetooth/BluetoothDevice.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java index 594e5ffa77a7..ffdd356e333f 100644 --- a/core/java/android/bluetooth/BluetoothDevice.java +++ b/core/java/android/bluetooth/BluetoothDevice.java @@ -1081,7 +1081,10 @@ public final class BluetoothDevice implements Parcelable { if (alias == null) { return getName(); } - return alias; + return alias + .replace('\t', ' ') + .replace('\n', ' ') + .replace('\r', ' '); } catch (RemoteException e) { Log.e(TAG, "", e); } -- cgit v1.2.3 From 82b4d4e0ad8bde0a45bbfd747842cab43b21ac6e Mon Sep 17 00:00:00 2001 From: Evan Chen Date: Thu, 2 Sep 2021 22:12:15 +0000 Subject: Backporting the change of ag/15629060 to rvc-qpr-dev Bug: 172251622 Bug: 197035186 Change-Id: I5aceab7697ef7a40bc08b0e9a79ed1284259797a Merged-In: I7e2f95fd85e18127dc481f188ace8ad6effc4831 Test: Manual (cherry picked from commit 0608e87c9204a01ad6ddbb11f5b3812aa19546ac) --- .../com/android/companiondevicemanager/DeviceChooserActivity.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java index 5ac059be2010..ac15164c4174 100644 --- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java +++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java @@ -66,8 +66,8 @@ public class DeviceChooserActivity extends Activity { final DeviceFilterPair selectedDevice = getService().mDevicesFound.get(0); setTitle(Html.fromHtml(getString( R.string.confirmation_title, - getCallingAppName(), - selectedDevice.getDisplayName()), 0)); + Html.escapeHtml(getCallingAppName()), + Html.escapeHtml(selectedDevice.getDisplayName())), 0)); mPairButton = findViewById(R.id.button_pair); mPairButton.setOnClickListener(v -> onDeviceConfirmed(getService().mSelectedDevice)); getService().mSelectedDevice = selectedDevice; @@ -76,7 +76,8 @@ public class DeviceChooserActivity extends Activity { setContentView(R.layout.device_chooser); mPairButton = findViewById(R.id.button_pair); mPairButton.setVisibility(View.GONE); - setTitle(Html.fromHtml(getString(R.string.chooser_title, getCallingAppName()), 0)); + setTitle(Html.fromHtml(getString(R.string.chooser_title, + Html.escapeHtml(getCallingAppName())), 0)); mDeviceListView = findViewById(R.id.device_list); final DeviceDiscoveryService.DevicesAdapter adapter = getService().mDevicesAdapter; mDeviceListView.setAdapter(adapter); -- cgit v1.2.3 From e75253ea061d14dfdcd817c0eb967c069139e0b5 Mon Sep 17 00:00:00 2001 From: kholoud mohamed Date: Tue, 4 May 2021 16:33:54 +0100 Subject: Changed INTERACT_ACROSS_PROFILES appop to be set per UID In some cases, enforceCrossUserOrProfilePermission fails for packages which have INTERACT_ACROSS_PROFILE appop granted if it shares the uid with another package that doesn't hold the permission, this is because getPackagesForUid is used to get the callingPackage which could return either packages randomly. I've changed setting the appop to be per uid instead of per package, Test: manual testing Bug: 183188804 Bug: 183730243 Bug: 195630721 Change-Id: I7a72c1d3abd1f83924865326797630ded2f2040f Merged-In: I7a72c1d3abd1f83924865326797630ded2f2040f (cherry picked from commit 4670d1d855a853852980148d99b190171db4ec79) (cherry picked from commit f5e0e80312e1b9c99e36f3775a5da2b8b93fd3de) --- .../server/pm/CrossProfileAppsServiceImpl.java | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java index 3e9e45e59b95..c3733c4c12fb 100644 --- a/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java +++ b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java @@ -482,16 +482,16 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub { // this particular app-op to be modified without the broader app-op permissions. mInjector.withCleanCallingIdentity(() -> mInjector.getAppOpsManager() - .setMode(OP_INTERACT_ACROSS_PROFILES, uid, packageName, newMode)); + .setUidMode(OP_INTERACT_ACROSS_PROFILES, uid, newMode)); } else { mInjector.getAppOpsManager() - .setMode(OP_INTERACT_ACROSS_PROFILES, uid, packageName, newMode); + .setUidMode(OP_INTERACT_ACROSS_PROFILES, uid, newMode); } // Kill the UID before sending the broadcast to ensure that apps can be informed when // their app-op has been revoked. maybeKillUid(packageName, uid, hadPermission); - sendCanInteractAcrossProfilesChangedBroadcast(packageName, uid, UserHandle.of(profileId)); - maybeLogSetInteractAcrossProfilesAppOp(packageName, newMode, logMetrics, uid); + sendCanInteractAcrossProfilesChangedBroadcast(packageName, UserHandle.of(profileId)); + maybeLogSetInteractAcrossProfilesAppOp(packageName, newMode, logMetrics); } /** @@ -509,7 +509,7 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub { } private void maybeLogSetInteractAcrossProfilesAppOp( - String packageName, @Mode int newMode, boolean logMetrics, int uid) { + String packageName, @Mode int newMode, boolean logMetrics) { if (!logMetrics) { return; } @@ -517,7 +517,7 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub { .createEvent(DevicePolicyEnums.SET_INTERACT_ACROSS_PROFILES_APP_OP) .setStrings(packageName) .setInt(newMode) - .setBoolean(appDeclaresCrossProfileAttribute(uid)) + .setBoolean(appDeclaresCrossProfileAttribute(packageName)) .write(); } @@ -533,10 +533,10 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub { } private void sendCanInteractAcrossProfilesChangedBroadcast( - String packageName, int uid, UserHandle userHandle) { + String packageName, UserHandle userHandle) { final Intent intent = new Intent(ACTION_CAN_INTERACT_ACROSS_PROFILES_CHANGED).setPackage(packageName); - if (appDeclaresCrossProfileAttribute(uid)) { + if (appDeclaresCrossProfileAttribute(packageName)) { intent.addFlags( Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND | Intent.FLAG_RECEIVER_FOREGROUND); } else { @@ -553,8 +553,8 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub { .queryBroadcastReceiversAsUser(intent, /* flags= */ 0, userHandle); } - private boolean appDeclaresCrossProfileAttribute(int uid) { - return mInjector.getPackageManagerInternal().getPackage(uid).isCrossProfile(); + private boolean appDeclaresCrossProfileAttribute(String packageName) { + return mInjector.getPackageManagerInternal().getPackage(packageName).isCrossProfile(); } @Override -- cgit v1.2.3 From 015e38aedf6358a08ce2c1374ac32c2eb95f6a1f Mon Sep 17 00:00:00 2001 From: Yimin Li Date: Tue, 2 Nov 2021 22:07:37 +0000 Subject: resolve Coastguard cherrypick merge conflict for change: 16174904 Change-Id: Ia82254a2716ee7e67dd79532d57279e75901fb8c (cherry picked from commit 441d4d7d1bb38dd2af42d947700489bfe45e69c4) --- core/res/res/values-af/strings.xml | 1 + core/res/res/values-am/strings.xml | 1 + core/res/res/values-ar/strings.xml | 1 + core/res/res/values-as/strings.xml | 1 + core/res/res/values-az/strings.xml | 1 + core/res/res/values-b+sr+Latn/strings.xml | 1 + core/res/res/values-be/strings.xml | 1 + core/res/res/values-bg/strings.xml | 1 + core/res/res/values-bn/strings.xml | 1 + core/res/res/values-bs/strings.xml | 1 + core/res/res/values-ca/strings.xml | 1 + core/res/res/values-cs/strings.xml | 1 + core/res/res/values-da/strings.xml | 1 + core/res/res/values-de/strings.xml | 1 + core/res/res/values-el/strings.xml | 1 + core/res/res/values-en-rAU/strings.xml | 1 + core/res/res/values-en-rCA/strings.xml | 1 + core/res/res/values-en-rGB/strings.xml | 1 + core/res/res/values-en-rIN/strings.xml | 1 + core/res/res/values-en-rXC/strings.xml | 1 + core/res/res/values-es-rUS/strings.xml | 1 + core/res/res/values-es/strings.xml | 1 + core/res/res/values-et/strings.xml | 1 + core/res/res/values-eu/strings.xml | 1 + core/res/res/values-fa/strings.xml | 1 + core/res/res/values-fi/strings.xml | 1 + core/res/res/values-fr-rCA/strings.xml | 1 + core/res/res/values-fr/strings.xml | 1 + core/res/res/values-gl/strings.xml | 1 + core/res/res/values-gu/strings.xml | 1 + core/res/res/values-hi/strings.xml | 1 + core/res/res/values-hr/strings.xml | 1 + core/res/res/values-hu/strings.xml | 1 + core/res/res/values-hy/strings.xml | 1 + core/res/res/values-in/strings.xml | 1 + core/res/res/values-is/strings.xml | 1 + core/res/res/values-it/strings.xml | 1 + core/res/res/values-iw/strings.xml | 1 + core/res/res/values-ja/strings.xml | 1 + core/res/res/values-ka/strings.xml | 1 + core/res/res/values-kk/strings.xml | 1 + core/res/res/values-km/strings.xml | 1 + core/res/res/values-kn/strings.xml | 1 + core/res/res/values-ko/strings.xml | 1 + core/res/res/values-ky/strings.xml | 1 + core/res/res/values-lo/strings.xml | 1 + core/res/res/values-lt/strings.xml | 1 + core/res/res/values-lv/strings.xml | 1 + core/res/res/values-mk/strings.xml | 1 + core/res/res/values-ml/strings.xml | 1 + core/res/res/values-mn/strings.xml | 1 + core/res/res/values-mr/strings.xml | 1 + core/res/res/values-ms/strings.xml | 1 + core/res/res/values-my/strings.xml | 1 + core/res/res/values-nb/strings.xml | 1 + core/res/res/values-ne/strings.xml | 1 + core/res/res/values-nl/strings.xml | 1 + core/res/res/values-or/strings.xml | 1 + core/res/res/values-pa/strings.xml | 1 + core/res/res/values-pl/strings.xml | 1 + core/res/res/values-pt-rBR/strings.xml | 1 + core/res/res/values-pt-rPT/strings.xml | 1 + core/res/res/values-pt/strings.xml | 1 + core/res/res/values-ro/strings.xml | 1 + core/res/res/values-ru/strings.xml | 1 + core/res/res/values-si/strings.xml | 1 + core/res/res/values-sk/strings.xml | 1 + core/res/res/values-sl/strings.xml | 1 + core/res/res/values-sq/strings.xml | 1 + core/res/res/values-sr/strings.xml | 1 + core/res/res/values-sv/strings.xml | 1 + core/res/res/values-sw/strings.xml | 1 + core/res/res/values-ta/strings.xml | 1 + core/res/res/values-te/strings.xml | 1 + core/res/res/values-th/strings.xml | 1 + core/res/res/values-tl/strings.xml | 1 + core/res/res/values-tr/strings.xml | 1 + core/res/res/values-uk/strings.xml | 1 + core/res/res/values-ur/strings.xml | 1 + core/res/res/values-uz/strings.xml | 1 + core/res/res/values-vi/strings.xml | 1 + core/res/res/values-zh-rCN/strings.xml | 1 + core/res/res/values-zh-rHK/strings.xml | 1 + core/res/res/values-zh-rTW/strings.xml | 1 + core/res/res/values-zu/strings.xml | 1 + 85 files changed, 85 insertions(+) diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml index 7d773d902bbe..55329e07ba91 100644 --- a/core/res/res/values-af/strings.xml +++ b/core/res/res/values-af/strings.xml @@ -1413,6 +1413,7 @@ "Weier" "Toestemming versoek" "Toestemming versoek\nvir rekening %s." + "Toestemming versoek deur %1$s\nvir rekening %2$s" "Jy gebruik hierdie program buite jou werkprofiel" "Jy gebruik tans hierdie program in jou werkprofiel" "Invoermetode" diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml index d41868e8c478..670b64e010f0 100644 --- a/core/res/res/values-am/strings.xml +++ b/core/res/res/values-am/strings.xml @@ -1413,6 +1413,7 @@ "ያስተባብሉ" "ፈቃድ ተጠይቋል" \n" ለ%s መለያ ፈቃድ ተጠይቋል" + "ለመለያ %2$s\nበ%1$s የተጠየቀ ፈቃድ።" "ከስራ መገለጫዎ ውጪ ሆነው መተግበሪያ እየተጠቀሙ ነው" "ይህን መተግበሪያ በእርስዎ የስራ መገለጫ ላይ እየተጠቀሙበት ነው" "ግቤት ስልት" diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml index 4a99ec8021e8..7e5460160a7d 100644 --- a/core/res/res/values-ar/strings.xml +++ b/core/res/res/values-ar/strings.xml @@ -1493,6 +1493,7 @@ "رفض" "الإذن مطلوب" "الإذن مطلوب\nللحساب %s." + "طلب تطبيق %1$s الإذن بالدخول\nإلى حساب %2$s." "أنت تستخدم هذا التطبيق خارج ملفك الشخصي للعمل" "أنت تستخدم هذا التطبيق في ملفك الشخصي للعمل" "طريقة الإرسال" diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml index 2ca98b4c5f22..3573ff5d6eb9 100644 --- a/core/res/res/values-as/strings.xml +++ b/core/res/res/values-as/strings.xml @@ -1413,6 +1413,7 @@ "প্ৰত্যাখ্যান কৰক" "অনুমতি বিচাৰি অনুৰোধ কৰা হৈছে" "%s একাউণ্টৰ বাবে\nঅনুমতি বিচাৰি অনুৰোধ কৰা হৈছে।" + "%1$s%2$s একাউণ্টটো এক্সেছৰ \nঅনুমতি বিচাৰি অনুৰোধ জনাইছে।" "আপুনি আপোনাৰ কৰ্মস্থানৰ প্ৰ\'ফাইলৰ বাহিৰত এই এপটো ব্যৱহাৰ কৰি আছে" "আপুনি আপোনাৰ কৰ্মস্থানৰ প্ৰ\'ফাইলৰ ভিতৰত এই এপটো ব্যৱহাৰ কৰি আছে" "ইনপুট পদ্ধতি" diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml index 36c293c491c6..52c57cdcd112 100644 --- a/core/res/res/values-az/strings.xml +++ b/core/res/res/values-az/strings.xml @@ -1413,6 +1413,7 @@ "Rədd et" "İcazə tələb olunur" \n" hesabı üçün%s icazə sorğusu göndərildi." + "%1$s\ntərəfindən %2$s hesabı üçün icazə tələb edilib." "Bu tətbiqi iş profilinizdən kənarda istifadə edirsiniz" "Bu tətbiqi iş profilinizdə istifadə edirsiniz" "Daxiletmə metodu" diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml index daec63a9d5a5..1399c8fb9f37 100644 --- a/core/res/res/values-b+sr+Latn/strings.xml +++ b/core/res/res/values-b+sr+Latn/strings.xml @@ -1433,6 +1433,7 @@ "Odbij" "Zatražena je dozvola" "Zatražena je dozvola\nza nalog %s" + "%1$s traži dozvolu \nza nalog %2$s." "Koristite ovu aplikaciju izvan poslovnog profila" "Koristite ovu aplikaciju na poslovnom profilu" "Metod unosa" diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml index 220c3520a1db..bd35a675d814 100644 --- a/core/res/res/values-be/strings.xml +++ b/core/res/res/values-be/strings.xml @@ -1453,6 +1453,7 @@ "Адмовіць" "Дазвол запытаны" "Запытаны дазвол\nдля ўліковага запісу %s" + "Праграма \"%1$s\" запытвае дазвол\nдля ўліковага запісу %2$s." "Вы выкарыстоўваеце гэту праграму па-за межамі свайго працоўнага профілю" "Вы выкарыстоўваеце гэту праграму ў сваім працоўным профілі" "Метад уводу" diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml index 8d3a23c99e3b..5a4dc99e3845 100644 --- a/core/res/res/values-bg/strings.xml +++ b/core/res/res/values-bg/strings.xml @@ -1413,6 +1413,7 @@ "Отказване" "Иска се разрешение" "Иска се разрешение\nза профила %s." + "Поискано е разрешение от %1$s\nза профила %2$s." "Използвате това приложение извън служебния си потребителски профил" "Използвате това приложение в служебния си потребителски профил" "Метод на въвеждане" diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml index 9462be3f2f44..b91868e8f147 100644 --- a/core/res/res/values-bn/strings.xml +++ b/core/res/res/values-bn/strings.xml @@ -1413,6 +1413,7 @@ "অস্বীকার করুন" "অনুমতির অনুরোধ করা হয়েছে" "%sঅ্যাকাউন্টের জন্য\nঅনুমতির অনুরোধ করা হয়েছে৷" + "%2$s অ্যাকাউন্টের জন্য %1$s\n থেকে অনুমতি চাওয়া হয়েছে।" "আপনি এই অ্যাপ্লিকেশানটি আপনার কর্মস্থলের প্রোফাইলের বাইরে ব্যবহার করছেন" "আপনি এই অ্যাপ্লিকেশানটি আপনার কর্মস্থলের প্রোফাইলে ব্যবহার করছেন" "ইনপুট পদ্ধতি" diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml index 7511455fc0ee..2c4f91ee339c 100644 --- a/core/res/res/values-bs/strings.xml +++ b/core/res/res/values-bs/strings.xml @@ -1433,6 +1433,7 @@ "Odbij" "Upućen zahtjev za odobrenje" "Upućen zahtjev za dozvolu\nza račun %s." + "Odobrenje je zatražila aplikacija %1$s\nza račun %2$s." "Aplikaciju koristite van poslovnog profila" "Aplikaciju koristite u poslovnom profilu" "Način unosa" diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml index ca45c00fb8b3..2b18f3f8a731 100644 --- a/core/res/res/values-ca/strings.xml +++ b/core/res/res/values-ca/strings.xml @@ -1413,6 +1413,7 @@ "Denega" "Permís sol·licitat" "S\'ha sol·licitat permís\nper al compte %s." + "%1$s ha sol·licitat permís\nper accedir al compte %2$s." "Estàs utilitzant aquesta aplicació fora del perfil de treball." "Estàs utilitzant l\'aplicació al perfil de treball." "Mètode d\'introducció de text" diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml index a5f421390d44..fdbf1f80719c 100644 --- a/core/res/res/values-cs/strings.xml +++ b/core/res/res/values-cs/strings.xml @@ -1453,6 +1453,7 @@ "Odepřít" "Požadováno oprávnění" "Požadováno oprávnění\npro účet %s." + "Aplikace %1$s požádala o přístup\nk účtu %2$s." "Tuto aplikaci používáte mimo svůj pracovní profil." "Tuto aplikaci používáte v pracovním profilu" "Metoda zadávání dat" diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml index 09e2ea20cd92..70dfcb2fb354 100644 --- a/core/res/res/values-da/strings.xml +++ b/core/res/res/values-da/strings.xml @@ -1413,6 +1413,7 @@ "Afvis" "Der er anmodet om tilladelse" "Der er anmodet om tilladelse\nfor kontoen %s." + "%1$s har anmodet om tilladelse\nfor kontoen %2$s." "Du bruger denne app uden for din arbejdsprofil" "Du bruger denne app i din arbejdsprofil" "Inputmetode" diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml index 627a3ab6a4fd..dfe712e9f42a 100644 --- a/core/res/res/values-de/strings.xml +++ b/core/res/res/values-de/strings.xml @@ -1413,6 +1413,7 @@ "Ablehnen" "Berechtigung angefordert" "Berechtigung angefordert\nfür Konto %s" + "Berechtigung wurde angefordert von %1$s\nfür das Konto %2$s." "Du verwendest diese App außerhalb deines Arbeitsprofils" "Du verwendest diese App in deinem Arbeitsprofil." "Eingabemethode" diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml index 9435d34b562e..a8ac541b9840 100644 --- a/core/res/res/values-el/strings.xml +++ b/core/res/res/values-el/strings.xml @@ -1413,6 +1413,7 @@ "Άρνηση" "Απαιτείται άδεια" "Ζητήθηκε άδεια\nγια τον λογαριασμό %s." + "Ζητήθηκε άδεια από την εφαρμογή %1$s\nγια πρόσβαση στον λογαριασμό %2$s." "Χρησιμοποιείτε αυτήν την εφαρμογή εκτός του προφίλ εργασίας σας" "Χρησιμοποιείτε αυτήν την εφαρμογή στο προφίλ εργασίας" "Μέθοδος εισόδου" diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml index c748cc80cb23..a0a64c9c1999 100644 --- a/core/res/res/values-en-rAU/strings.xml +++ b/core/res/res/values-en-rAU/strings.xml @@ -1413,6 +1413,7 @@ "Deny" "Permission requested" "Permission requested\nfor account %s." + "Permission requested by %1$s\nfor account %2$s." "You\'re using this app outside of your work profile" "You\'re using this app in your work profile" "Input Method" diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml index d6faf46ee74a..3a82c601090f 100644 --- a/core/res/res/values-en-rCA/strings.xml +++ b/core/res/res/values-en-rCA/strings.xml @@ -1413,6 +1413,7 @@ "Deny" "Permission requested" "Permission requested\nfor account %s." + "Permission requested by %1$s\nfor account %2$s." "You\'re using this app outside of your work profile" "You\'re using this app in your work profile" "Input Method" diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml index 695ddb0e4e4e..bdeee0a9809f 100644 --- a/core/res/res/values-en-rGB/strings.xml +++ b/core/res/res/values-en-rGB/strings.xml @@ -1413,6 +1413,7 @@ "Deny" "Permission requested" "Permission requested\nfor account %s." + "Permission requested by %1$s\nfor account %2$s." "You\'re using this app outside of your work profile" "You\'re using this app in your work profile" "Input Method" diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml index 596d4b658769..d1302d304a72 100644 --- a/core/res/res/values-en-rIN/strings.xml +++ b/core/res/res/values-en-rIN/strings.xml @@ -1413,6 +1413,7 @@ "Deny" "Permission requested" "Permission requested\nfor account %s." + "Permission requested by %1$s\nfor account %2$s." "You\'re using this app outside of your work profile" "You\'re using this app in your work profile" "Input Method" diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml index 2cd891f57281..920808b9b492 100644 --- a/core/res/res/values-en-rXC/strings.xml +++ b/core/res/res/values-en-rXC/strings.xml @@ -1413,6 +1413,7 @@ "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‎‎‎‎‎‎‏‎‏‎‏‎‎‎‎‏‎‏‎‏‎‏‎‎‎‎‎‏‏‏‎‏‎‎‎‎‎‏‎‎‎‏‏‏‎‎‎‏‏‎‏‎‎‏‏‏‎‎‎Deny‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‏‎‎‎‏‏‏‏‎‏‎‎‎‎‎‎‎‏‏‏‏‏‏‎‎‏‎‎‎‏‏‎‏‎‏‎‏‏‎‎‎‏‏‏‏‎‎‎‎‏‏‎‏‎‎‎‏‎Permission requested‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‏‏‏‏‏‎‎‏‏‎‏‎‎‏‎‏‎‏‎‏‏‏‎‎‎‎‎‏‏‏‎‎‎‏‎‏‎‏‎‏‎‎‎‏‎‏‏‏‏‎‎‎‏‎‎‏‎‎Permission requested‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎for account ‎‏‎‎‏‏‎%s‎‏‎‎‏‏‏‎.‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‎‎‎‎‎‎‏‎‏‏‏‏‎‏‏‎‎‎‏‏‎‏‎‎‏‏‎‎‏‎‎‏‎‎‎‎‏‎‏‎‏‎‏‎‏‏‏‏‎‏‎‎‏‎‏‏‎‎Permission requested by ‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎for account ‎‏‎‎‏‏‎%2$s‎‏‎‎‏‏‏‎.‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‎‎‎‎‏‏‏‏‎‏‏‎‏‎‎‎‎‎‎‎‏‎‎‎‎‏‎‎‎‏‎‏‎‏‎‏‎‎‏‎‏‏‎‎‏‏‏‎‎‎‏‏‎‎‏‏‏‎You\'re using this app outside of your work profile‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‎‎‎‏‏‏‏‎‏‏‏‎‎‎‎‎‏‎‏‏‏‏‎‏‎‎‎‎‏‏‎‎‏‏‎‏‎‎‎‏‎‏‏‎‏‏‎‏‏‏‎‎‏‏‏‏‏‎You\'re using this app in your work profile‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‎‎‎‏‏‎‎‎‏‎‎‎‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‎‎‏‏‎‎‏‏‎‏‏‏‎‎‏‎‎‎‎‎‏‎‏‎‏‎‏‎‎‎‎Input method‎‏‎‎‏‎" diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml index 5b216612430e..8ad378d3ecd8 100644 --- a/core/res/res/values-es-rUS/strings.xml +++ b/core/res/res/values-es-rUS/strings.xml @@ -1413,6 +1413,7 @@ "Denegar" "Permiso solicitado" "Permiso solicitado\npara la cuenta %s" + "%1$s solicitó permiso\npara acceder a la cuenta %2$s." "Estás utilizando esta aplicación fuera del perfil de trabajo." "Estás utilizando esta aplicación en tu perfil de trabajo." "Método de entrada" diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml index 13f1b5613169..4f6dc6414a97 100644 --- a/core/res/res/values-es/strings.xml +++ b/core/res/res/values-es/strings.xml @@ -1413,6 +1413,7 @@ "Denegar" "Permiso solicitado" "Permiso solicitado\npara la cuenta %s" + "Permiso solicitado por %1$s\npara acceder a la cuenta%2$s." "Estás usando esta aplicación fuera del perfil de trabajo" "Estás usando esta aplicación en tu perfil de trabajo" "Método de introducción de texto" diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml index ea6fabe0556f..e58422ab4fee 100644 --- a/core/res/res/values-et/strings.xml +++ b/core/res/res/values-et/strings.xml @@ -1413,6 +1413,7 @@ "Keela" "Taotletud luba" "Luba on taotletud\nkontole %s." + "Rakendus %1$s nõuab luba\nkontole %2$s juurdepääsemiseks." "Kasutate rakendust väljaspool tööprofiili" "Kasutate seda rakendust oma tööprofiilil" "Sisestusmeetod" diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml index 99012924a3e2..7bd4bfc56949 100644 --- a/core/res/res/values-eu/strings.xml +++ b/core/res/res/values-eu/strings.xml @@ -1413,6 +1413,7 @@ "Ukatu" "Baimena eskatu da" "Baimena eskatu da \n%s konturako." + "%1$s aplikazioak %2$s kontua atzitzeko baimena\neskatu du." "Laneko profiletik kanpo ari zara aplikazioa erabiltzen" "Laneko profilean ari zara aplikazioa erabiltzen" "Idazketa-metodoa" diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml index 3dd8173ae4e1..ff775bcab8eb 100644 --- a/core/res/res/values-fa/strings.xml +++ b/core/res/res/values-fa/strings.xml @@ -1413,6 +1413,7 @@ "مجاز نبودن" "مجوز درخواست شد" "مجوز\nبرای حساب %s درخواست شد." + "%1$s برای دسترسی به حساب %2$s\nدرخواست اجازه کرد." "شما از این برنامه در خارج از نمایه کاری‌تان استفاده می‌کنید" "از این برنامه در نمایه کاری‌تان استفاده می‌کنید" "روش ورودی" diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml index 527d5a6a8087..87cc6af3b34c 100644 --- a/core/res/res/values-fi/strings.xml +++ b/core/res/res/values-fi/strings.xml @@ -1413,6 +1413,7 @@ "Kiellä" "Lupa pyydetty" "Pyydetään lupaa\ntilille %s." + "%1$s pyytänyt pääsyä\ntilille %2$s." "Käytät sovellusta muulla kuin työprofiililla" "Käytät sovellusta työprofiililla" "Syöttötapa" diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml index 8002080a1005..f46e648232e2 100644 --- a/core/res/res/values-fr-rCA/strings.xml +++ b/core/res/res/values-fr-rCA/strings.xml @@ -1413,6 +1413,7 @@ "Refuser" "Autorisation demandée" "Autorisation demandée\npour le compte \"%s\"" + "Autorisation demandée par %1$s\npour le compte %2$s." "Vous utilisez cette application en dehors de votre profil professionnel" "Vous utilisez cette application dans votre profil professionnel" "Mode de saisie" diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml index 7d777542e6f4..6355e621e8e9 100644 --- a/core/res/res/values-fr/strings.xml +++ b/core/res/res/values-fr/strings.xml @@ -1413,6 +1413,7 @@ "Refuser" "Autorisation demandée" "Autorisation demandée\npour le compte \"%s\"" + "Autorisation demandée par %1$s\npour le compte %2$s." "Vous utilisez cette application en dehors de votre profil professionnel." "Vous utilisez cette application dans votre profil professionnel." "Mode de saisie" diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml index 7cc6f6934901..86915dd2bb09 100644 --- a/core/res/res/values-gl/strings.xml +++ b/core/res/res/values-gl/strings.xml @@ -1413,6 +1413,7 @@ "Rexeitar" "Permiso solicitado" "Permiso solicitado\npara a conta %s." + "%1$s solicitou permiso\npara acceder á conta %2$s." "Estás usando esta aplicación fóra do teu perfil de traballo" "Estás usando esta aplicación no teu perfil de traballo" "Método de introdución de texto" diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml index 758b2a014633..d1bea9bc507b 100644 --- a/core/res/res/values-gu/strings.xml +++ b/core/res/res/values-gu/strings.xml @@ -1413,6 +1413,7 @@ "નકારો" "પરવાનગીની વિનંતી કરી" "એકાઉન્ટ %s માટે\nપરવાનગીની વિનંતી કરી." + "%2$s એકાઉન્ટ માટે\n%1$s દ્વારા પરવાનગીની વિનંતી કરવામાં આવી." "તમે તમારી કાર્ય પ્રોફાઇલની બહાર આ એપ્લિકેશનનો ઉપયોગ કરી રહ્યાં છો" "તમે તમારી કાર્ય પ્રોફાઇલમાં આ એપ્લિકેશનનો ઉપયોગ કરી રહ્યાં છો" "ઇનપુટ પદ્ધતિ" diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml index 7fdbb8a60989..481a9deb9ed1 100644 --- a/core/res/res/values-hi/strings.xml +++ b/core/res/res/values-hi/strings.xml @@ -1413,6 +1413,7 @@ "अस्वीकारें" "अनुमति अनुरोधित" "%s खाते के लिए अनुमति\nका अनुरोध किया गया." + "%1$s ने %2$s खाते को ऐक्सेस\nकरने की अनुमति का अनुरोध किया है." "आप इस ऐप्स का उपयोग अपनी वर्क प्रोफ़ाइल से बाहर कर रहे हैं" "आप इस ऐप्स का उपयोग अपनी वर्क प्रोफ़ाइल में कर रहे हैं" "इनपुट विधि" diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml index 5d4905fb5680..18327375a156 100644 --- a/core/res/res/values-hr/strings.xml +++ b/core/res/res/values-hr/strings.xml @@ -1433,6 +1433,7 @@ "Odbij" "Zatražena je dozvola" "Zatražena je dozvola\nza račun %s." + "Aplikacija %1$s zatražila je dopuštenje\nza račun %2$s." "Ovu aplikaciju upotrebljavate izvan svog radnog profila" "Upotrebljavate tu aplikaciju u radnom profilu" "Način unosa" diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml index 4492eec7d8be..f9c55767e1ca 100644 --- a/core/res/res/values-hu/strings.xml +++ b/core/res/res/values-hu/strings.xml @@ -1413,6 +1413,7 @@ "Elutasítás" "Az engedélykérés megtörtént" "Az engedélykérés megtörtént\na(z) %s fiók számára." + "A(z) %1$s alkalmazás által kért engedély\na következő fiók számára: %2$s." "Ezt az alkalmazást munkaprofilján kívül használja" "Munkaprofiljában már használja az alkalmazást" "Beviteli mód" diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml index 2288e68d7b1b..986c3e7259ad 100644 --- a/core/res/res/values-hy/strings.xml +++ b/core/res/res/values-hy/strings.xml @@ -1413,6 +1413,7 @@ "Մերժել" "Թույլտվության հարցում է արված" "Թույլտվության հարցում է արված\n%s հաշվի համար:" + "Հայցվում է թույլտվություն %1$s հավելվածի կողմից\n%2$s հաշվի համար" "Դուք օգտագործում եք այս հավելվածը ձեր աշխատանքային պրոֆիլից դուրս" "Դուք օգտագործում եք այս հավելվածը ձեր աշխատանքային պրոֆիլում" "Ներածման եղանակը" diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml index 12d479d95e8e..43238dc2c92b 100644 --- a/core/res/res/values-in/strings.xml +++ b/core/res/res/values-in/strings.xml @@ -1413,6 +1413,7 @@ "Tolak" "Izin dimintakan" "Izin dimintakan\nuntuk akun %s." + "%1$s meminta izin\nuntuk akun %2$s." "Anda menggunakan aplikasi ini di luar profil kerja" "Anda menggunakan aplikasi ini di profil kerja" "Metode masukan" diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml index 1ca4e619b66c..dde1424f3379 100644 --- a/core/res/res/values-is/strings.xml +++ b/core/res/res/values-is/strings.xml @@ -1413,6 +1413,7 @@ "Hafna" "Beðið um heimild" "Beðið um heimild\nfyrir reikninginn %s." + "Beiðni um heimild frá %1$s\nfyrir reikninginn %2$s." "Þú ert að nota þetta forrit utan vinnusniðsins" "Þú ert að nota þetta forrit á vinnusniðinu þínu" "Innsláttaraðferð" diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml index 054344ebabe5..83a7ee88d2ac 100644 --- a/core/res/res/values-it/strings.xml +++ b/core/res/res/values-it/strings.xml @@ -1413,6 +1413,7 @@ "Rifiuta" "Autorizzazione richiesta" "Autorizzazione richiesta\nper l\'account %s." + "Autorizzazione richiesta da %1$s\nper l\'account %2$s." "Stai utilizzando l\'app al di fuori del tuo profilo di lavoro" "Stai utilizzando l\'app nel tuo profilo di lavoro" "Metodo inserimento" diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml index 757041c4d397..c2f78a4921d6 100644 --- a/core/res/res/values-iw/strings.xml +++ b/core/res/res/values-iw/strings.xml @@ -1453,6 +1453,7 @@ "עדיף שלא" "בקשת הרשאה" "נדרשת הרשאה\nלחשבון %s." + "התבקשה הרשאה על ידי %1$s\nלחשבון %2$s." "אתה משתמש באפליקציה זו מחוץ לפרופיל העבודה שלך" "אתה משתמש באפליקציה זו בפרופיל העבודה שלך" "שיטת קלט" diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml index 4a8179142c5b..526d9226d6ee 100644 --- a/core/res/res/values-ja/strings.xml +++ b/core/res/res/values-ja/strings.xml @@ -1413,6 +1413,7 @@ "拒否" "権限がリクエストされました" "次のアカウントにアクセスする権限が\nリクエストされました: %s" + "アカウント %2$s へのアクセス権限が\n%1$s からリクエストされました。" "仕事用プロファイルの外部でこのアプリを使用しています" "仕事用プロファイルでこのアプリを使用しています" "入力方法" diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml index 7365b05ee513..8102f353a83d 100644 --- a/core/res/res/values-ka/strings.xml +++ b/core/res/res/values-ka/strings.xml @@ -1413,6 +1413,7 @@ "აკრძალვა" "მოთხოვნილია ნებართვა" "მოთხოვნილია ნებრათვა \nანგარიშისთვის: %s" + "ნებართვა მოთხოვნილია %1$s-ის მიერ\nანგარიშისთვის %2$s." "იყენებთ ამ აპს თქვენს სამუშაო პროფილს მიღმა" "ამ აპს თქვენს სამუშაო პროფილში იყენებთ" "შეყვანის მეთოდი" diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml index 18476482fa42..e4c354a6b7b6 100644 --- a/core/res/res/values-kk/strings.xml +++ b/core/res/res/values-kk/strings.xml @@ -1413,6 +1413,7 @@ "Бас тарту" "Рұқсат өтінілді" "Рұқсат \nесептік жазба үшін %s өтінілді." + "%2$s аккаунты үшін %1$s\nқолданбасы арқылы рұқсат сұралды." "Осы қолданбаны жұмыс профиліңізден тыс пайдаланып жатырсыз" "Осы қолданбаны жұмыс профиліңізде пайдаланып жатырсыз" "Енгізу әдісі" diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml index 95b253f25d78..692f8b0b4d3d 100644 --- a/core/res/res/values-km/strings.xml +++ b/core/res/res/values-km/strings.xml @@ -1413,6 +1413,7 @@ "បដិសេធ" "បាន​ស្នើ​សិទ្ធិ" "បាន​ស្នើ​សិទ្ធិ\nសម្រាប់​គណនី %s ។" + "ការអនុញ្ញាត​ដែលស្នើដោយ %1$s\nសម្រាប់គណនី %2$s។" "អ្នក​កំពុង​ប្រើ​កម្មវិធី​នេះ​នៅ​ខាងក្រៅ​ប្រវត្តិរូប​​ការងារ​របស់​អ្នក" "អ្នក​កំពុង​ប្រើ​កម្មវិធី​នេះ​ក្នុង​ប្រវត្តិរូប​ការងារ​របស់​អ្នក" "វិធីសាស្ត្រ​បញ្ចូល" diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml index 37d20495cbde..019e6777d9fe 100644 --- a/core/res/res/values-kn/strings.xml +++ b/core/res/res/values-kn/strings.xml @@ -1413,6 +1413,7 @@ "ನಿರಾಕರಿಸಿ" "ಅನುಮತಿ ವಿನಂತಿಸಲಾಗಿದೆ" "%s ಖಾತೆಗಾಗಿ\n ಅನುಮತಿಯನ್ನು ವಿನಂತಿಸಲಾಗಿದೆ." + "%2$s ಖಾತೆಗಾಗಿ \n %1$s ನಿಂದ ಅನುಮತಿಯನ್ನು ವಿನಂತಿಸಲಾಗಿದೆ." "ನಿಮ್ಮ ಕೆಲಸದ ಪ್ರೊಫೈಲ್‌ನ ಹೊರಗೆ ನೀವು ಈ ಅಪ್ಲಿಕೇಶನ್‌ ಅನ್ನು ಬಳಸುತ್ತಿರುವಿರಿ" "ನಿಮ್ಮ ಕೆಲಸದ ಪ್ರೊಫೈಲ್‌ನಲ್ಲಿ ನೀವು ಈ ಅಪ್ಲಿಕೇಶನ್‌ ಅನ್ನು ಬಳಸುತ್ತಿರುವಿರಿ" "ಇನ್‌ಪುಟ್ ವಿಧಾನ" diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml index 7dcbaa00c476..6b390a0c6a78 100644 --- a/core/res/res/values-ko/strings.xml +++ b/core/res/res/values-ko/strings.xml @@ -1413,6 +1413,7 @@ "거부" "권한 요청됨" "%s 계정에 대해\n권한 요청" + "%1$s에서 %2$s 계정에 대한\n권한을 요청했습니다" "직장 프로필 외부에서 이 앱을 사용 중입니다." "직장 프로필에서 이 앱을 사용 중입니다." "입력 방법" diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml index 6420e45fe02e..1eb107152bfe 100644 --- a/core/res/res/values-ky/strings.xml +++ b/core/res/res/values-ky/strings.xml @@ -1413,6 +1413,7 @@ "Уруксат берилбейт" "Уруксат талап кылуу" "Кийинки эсепке\nуруксат талап кылынууда: %s." + "%1$s колдонмосу\n%2$s аккаунтуна кирүүгө уруксат сурады." "Бул колдонмо жумуш профилиңиздин сыртында колдонулуп жатат" "Бул колдонмону жумуш профилиңизде пайдаланып жатасыз" "Киргизүү ыкмасы" diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml index 47bd5a8da60e..57acf482dd1d 100644 --- a/core/res/res/values-lo/strings.xml +++ b/core/res/res/values-lo/strings.xml @@ -1413,6 +1413,7 @@ "ປະ​ຕິ​ເສດ" "ຕ້ອງການການອະນຸຍາດ" "ຮ້ອງຂໍການກຳນົດສິດ\nສຳລັບບັນຊີ %s ແລ້ວ." + "ຮ້ອງຂໍການອະນຸຍາດໂດຍ %1$s\nສຳລັບບັນຊີ %2$s." "​ທ່ານ​ກຳ​ລັງ​ໃຊ້​ແອັບຯ​ນີ້ນອກ​ໂປຣ​ໄຟລ໌​ບ່ອນ​ເຮັດ​ວຽກ​ຂອງ​ທ່ານ" "​ທ່ານ​ກຳ​ລັງ​ໃຊ້​ແອັບຯ​ນີ້​ໃນ​ໂປຣ​ໄຟລ໌​​ບ່ອນ​ເຮັດ​ວຽກ​ຂອງ​ທ່ານ" "ວິທີການປ້ອນຂໍ້ມູນ" diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml index 6a4958219732..cb69d1ab99d0 100644 --- a/core/res/res/values-lt/strings.xml +++ b/core/res/res/values-lt/strings.xml @@ -1453,6 +1453,7 @@ "Atmesti" "Pateikta užklausa dėl leidimo" "Pateikta leidimo užklausa\ndėl %s paskyros" + "Programai „%1$s“ reikalingas leidimas\n, susijęs su paskyra %2$s." "Šią programą naudojate ne darbo profilyje" "Šią programą naudojate darbo profilyje" "Įvesties būdas" diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml index 8e67568e1718..d5caa65e5187 100644 --- a/core/res/res/values-lv/strings.xml +++ b/core/res/res/values-lv/strings.xml @@ -1433,6 +1433,7 @@ "Noraidīt" "Atļauja ir pieprasīta." "Atļauja kontam %s\nir pieprasīta." + "Lietotne %1$s pieprasīja atļauju piekļūt \nkontam %2$s." "Šo lietotni izmantojat ārpus sava darba profila" "Jūs izmantojat šo lietotni no sava darba profila." "Ievades metode" diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml index 92d8e36fbe6b..32ba34c6a89d 100644 --- a/core/res/res/values-mk/strings.xml +++ b/core/res/res/values-mk/strings.xml @@ -1413,6 +1413,7 @@ "Одбиј" "Побарана е дозвола" "Побарана е дозвола\nза сметка %s." + "%1$s побара дозвола\nза сметката %2$s." "Ја користите апликацијата надвор од работниот профил" "Ја користите апликацијата во работниот профил" "Метод на внес" diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml index 4a62f7286e63..ab631e9a5f4f 100644 --- a/core/res/res/values-ml/strings.xml +++ b/core/res/res/values-ml/strings.xml @@ -1413,6 +1413,7 @@ "നിരസിക്കുക" "അനുമതി ആവശ്യമാണ്" "%s എന്ന അക്കൗണ്ടിനായി\nഅനുമതി അഭ്യർത്ഥിച്ചു." + "%2$s അക്കൗണ്ട് ആക്സസ് ചെയ്യാൻ \n%1$s അനുമതി അഭ്യർത്ഥിച്ചു." "നിങ്ങളുടെ ഔദ്യോഗിക പ്രൊഫൈലിന് പുറത്ത് ഈ അപ്ലിക്കേഷൻ ഉപയോഗിക്കുന്നു" "നിങ്ങളുടെ ഔദ്യോഗിക പ്രൊഫൈലിൽ ഈ അപ്ലിക്കേഷൻ ഉപയോഗിക്കുന്നു" "ടൈപ്പുചെയ്യൽ രീതി" diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml index ed77e86a2ad1..768b8cd3a30f 100644 --- a/core/res/res/values-mn/strings.xml +++ b/core/res/res/values-mn/strings.xml @@ -1413,6 +1413,7 @@ "Татгалзах" "Зөвшөөрөл хүсэв" "%s бүртгэл зөвшөөрөл \n хүссэн" + "%1$s\n нь %2$s бүртгэлд зөвшөөрөл хүссэн." "Та энэ апп-г өөрийн ажлын профайлаас гадуур ашиглаж байна" "Та энэ апп-г өөрийн ажлын профайл дотор ашиглаж байна" "Оруулах арга" diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml index 46057eea940e..80c490b78712 100644 --- a/core/res/res/values-mr/strings.xml +++ b/core/res/res/values-mr/strings.xml @@ -1413,6 +1413,7 @@ "नकार द्या" "परवानगीची विनंती केली" "%s खात्यासाठी\nपरवानगीची विनंती केली." + "%1$s ने तुमचे \n%2$s खाते ॲक्सेस करण्यासाठी परवानगीची विनंती केली आहे." "तुम्ही हा अ‍ॅप आपल्‍या कार्य प्रोफाईलच्या बाहेर वापरत आहात" "तुम्ही हा अ‍ॅप आपल्या कार्य प्रोफाईलमध्‍ये वापरत आहात" "इनपुट पद्धत" diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml index f8efcfd5216a..cf91addc0b9d 100644 --- a/core/res/res/values-ms/strings.xml +++ b/core/res/res/values-ms/strings.xml @@ -1413,6 +1413,7 @@ "Nafi" "Kebenaran diminta" "Kebenaran diminta\nuntuk akaun %s." + "Kebenaran diminta oleh %1$s\nuntuk akaun %2$s." "Anda menggunakan apl ini di luar profil kerja anda" "Anda menggunakan apl ini dalam profil kerja anda" "Kaedah input" diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml index c0e3fb9a30fb..675c1837dd75 100644 --- a/core/res/res/values-my/strings.xml +++ b/core/res/res/values-my/strings.xml @@ -1413,6 +1413,7 @@ "ငြင်းပယ်ရန်" "ခွင့်ပြုချက် တောင်းခံထားခြင်း" "အကောင့် %s အတွက် \n ခွင့်ပြုချက် တောင်းခံထားပြီး" + "%2$s အကောင့်အတွက်\n%1$s က ခွင့်ပြုချက် တောင်းခံထားသည်။" "သင်သည် ဒီအက်ပ်ကို သင့်အလုပ်ပရိုဖိုင် ပြင်ပတွင် အသုံးပြုနေ၏" "သင်သည် ဒီအက်ပ်ကို သင်၏ အလုပ် ပရိုဖိုင် ထဲမှာ အသုံးပြုနေသည်" "ထည့်သွင်းရန်နည်းလမ်း" diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml index 4a89f37af147..7b99ec98ec51 100644 --- a/core/res/res/values-nb/strings.xml +++ b/core/res/res/values-nb/strings.xml @@ -1413,6 +1413,7 @@ "Avslå" "Tillatelse forespurt" "Tillatelse forespurt\nfor kontoen %s." + "Tillatelse forespurt av %1$s\nfor kontoen %2$s." "Du bruker denne appen utenfor arbeidsprofilen" "Du bruker denne appen i jobbprofilen din" "Inndatametode" diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml index 343d0b22e4d4..ba55cc3b7521 100644 --- a/core/res/res/values-ne/strings.xml +++ b/core/res/res/values-ne/strings.xml @@ -1413,6 +1413,7 @@ "अस्वीकार गर्नुहोस्" "अनुरोध गरिएको अनुमति" \n"खाता %sको लागि अनुरोध गरिएको अनुमति।" + "%1$s ले %2$s खाता चलाउने\nअनुमति मागेको छ।" "तपाईं तपाईंको कार्य प्रोफाइल बाहिर यो एप प्रयोग गरिरहनु भएको छ" "तपाईं आफ्नो कार्य प्रोफाइलमा यो एप प्रयोग गरिरहनु भएको छ" "इनपुट विधि" diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml index 1a8ce28e3561..867f84d7f70c 100644 --- a/core/res/res/values-nl/strings.xml +++ b/core/res/res/values-nl/strings.xml @@ -1413,6 +1413,7 @@ "Weigeren" "Rechten gevraagd" "Rechten gevraagd\nvoor account %s." + "Toegang gevraagd door %1$s\nvoor account %2$s." "Je gebruikt deze app buiten je werkprofiel" "U gebruikt deze app in je werkprofiel" "Invoermethode" diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml index 386d9e05124d..9af7cf3a69be 100644 --- a/core/res/res/values-or/strings.xml +++ b/core/res/res/values-or/strings.xml @@ -1413,6 +1413,7 @@ "ଅଗ୍ରାହ୍ୟ କରନ୍ତୁ" "ଅନୁମତି ଅନୁରୋଧ କରାଯାଇଛି" "%s ଆକାଉଣ୍ଟ ପାଇଁ ଅନୁମତି\n ଅନୁରୋଧ କରାଯାଇଛି।" + "%2$s ଆକାଉଣ୍ଟକୁ ଆକ୍ସେସ୍ ପାଇଁ\n%1$s ଦ୍ୱାରା ଅନୁମତି ନିମନ୍ତେ ଅନୁରୋଧ କରାଯାଇଛି।" "ଆପଣ ନିଜର ୱର୍କ ପ୍ରୋଫାଇଲ୍‌ ବାହାରେ ଏହି ଆପ୍‌ର ପ୍ରୟୋଗ କରୁଛନ୍ତି" "ଆପଣ ନିଜ ୱର୍କ ପ୍ରୋଫାଇଲ୍‌ରେ ଏହି ଆପ୍‌ର ବ୍ୟବହାର କରୁଛନ୍ତି" "ଇନପୁଟ୍ ପଦ୍ଧତି" diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml index 77aceb7264f4..caded7e6a008 100644 --- a/core/res/res/values-pa/strings.xml +++ b/core/res/res/values-pa/strings.xml @@ -1413,6 +1413,7 @@ "ਅਸਵੀਕਾਰ ਕਰੋ" "ਅਨੁਮਤੀ ਦੀ ਬੇਨਤੀ ਕੀਤੀ" "%s ਖਾਤੇ ਲਈ ਅਨੁਮਤੀ ਦੀ ਬੇਨਤੀ ਕੀਤੀ\n।" + "%1$s ਨੇ %2$s ਖਾਤੇ ਤੱਕ ਪਹੁੰਚ ਕਰਨ\nਦੀ ਇਜਾਜ਼ਤ ਲਈ ਬੇਨਤੀ ਕੀਤੀ।" "ਤੁਸੀਂ ਇਹ ਐਪ ਆਪਣੀ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਦੇ ਬਾਹਰ ਵਰਤ ਰਹੇ ਹੋ" "ਤੁਸੀਂ ਇਹ ਐਪ ਆਪਣੀ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਵਿੱਚ ਵਰਤ ਰਹੇ ਹੋ" "ਇਨਪੁੱਟ ਵਿਧੀ" diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml index 9b6edd21b6ac..b423089751f7 100644 --- a/core/res/res/values-pl/strings.xml +++ b/core/res/res/values-pl/strings.xml @@ -1453,6 +1453,7 @@ "Odmów" "Prośba o pozwolenie" "Prośba o pozwolenie\ndotyczące konta %s" + "Aplikacja %1$s prosi o uprawnienia\ndotyczące konta %2$s." "Używasz tej aplikacji poza profilem służbowym" "Używasz tej aplikacji w swoim profilu służbowym" "Sposób wprowadzania tekstu" diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml index ec34e4e6f8c8..35ccbdb06e5a 100644 --- a/core/res/res/values-pt-rBR/strings.xml +++ b/core/res/res/values-pt-rBR/strings.xml @@ -1413,6 +1413,7 @@ "Negar" "Permissão solicitada" "Permissão solicitada\npara a conta %s." + "Permissão solicitada pelo app %1$s\npara a conta %2$s." "Este app está sendo usado fora de seu perfil de trabalho" "Você está usando este app em seu perfil de trabalho" "Método de entrada" diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml index 6de3cdffefae..387d9a79db94 100644 --- a/core/res/res/values-pt-rPT/strings.xml +++ b/core/res/res/values-pt-rPT/strings.xml @@ -1413,6 +1413,7 @@ "Recusar" "Permissão solicitada" "Permissão solicitada\npara a conta %s." + "Autorização solicitada pela app %1$s\npara a conta %2$s." "Está a utilizar esta app fora do seu perfil de trabalho" "Está a utilizar esta app no seu perfil de trabalho" "Método de entrada" diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml index ec34e4e6f8c8..35ccbdb06e5a 100644 --- a/core/res/res/values-pt/strings.xml +++ b/core/res/res/values-pt/strings.xml @@ -1413,6 +1413,7 @@ "Negar" "Permissão solicitada" "Permissão solicitada\npara a conta %s." + "Permissão solicitada pelo app %1$s\npara a conta %2$s." "Este app está sendo usado fora de seu perfil de trabalho" "Você está usando este app em seu perfil de trabalho" "Método de entrada" diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml index bffa4570ef2a..b77851b76cf6 100644 --- a/core/res/res/values-ro/strings.xml +++ b/core/res/res/values-ro/strings.xml @@ -1433,6 +1433,7 @@ "Refuzați" "Permisiune solicitată" "Permisiune solicitată\npentru contul %s." + "Permisiune solicitată de %1$s\npentru contul %2$s." "Utilizați această aplicație în afara profilului de serviciu" "Utilizați această aplicație în profilul de serviciu" "Metodă de intrare" diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml index 20407b131907..2fab14de573d 100644 --- a/core/res/res/values-ru/strings.xml +++ b/core/res/res/values-ru/strings.xml @@ -1453,6 +1453,7 @@ "Отклонить" "Разрешение запрошено" "Требуется разрешение\nдля аккаунта %s." + "Разрешение запрошено приложением \"%1$s\"\nдля аккаунта %2$s." "Это приложение используется в личном профиле" "Вы перешли в рабочий профиль" "Способ ввода" diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml index dc8f723af411..825fdfa3af0b 100644 --- a/core/res/res/values-si/strings.xml +++ b/core/res/res/values-si/strings.xml @@ -1413,6 +1413,7 @@ "ප්‍රතික්ෂේප කරන්න" "අවසර ඉල්ලා සිටී" "%s ගිණුම සඳහා\nඅවසර ඉල්ලන ලදි." + "%2$s ගිණුම සඳහා %1$s\n විසින් ඉල්ලූ අවසරය" "මෙම යෙදුම ඔබගේ කාර්යාල පැතිකඩින් පිට දී ඔබ භාවිතා කරයි" "මෙම යෙදුම ඔබගේ පුද්ගලික කොටසේ ඔබ භාවිතා කරයි" "ආදාන ක්‍රමය" diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml index 624d55492603..cfc5f394150e 100644 --- a/core/res/res/values-sk/strings.xml +++ b/core/res/res/values-sk/strings.xml @@ -1453,6 +1453,7 @@ "Zamietnuť" "Vyžaduje sa povolenie" "Vyžaduje sa oprávnenie\npre účet %s" + "Povolenia, ktoré aplikácia %1$s požaduje\npre účet %2$s." "Túto aplikáciu používate mimo svojho pracovného profilu" "Túto aplikáciu používate vo svojom pracovnom profile" "Metóda vstupu" diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml index 32cfb18501d2..0c681ec9a49f 100644 --- a/core/res/res/values-sl/strings.xml +++ b/core/res/res/values-sl/strings.xml @@ -1453,6 +1453,7 @@ "Zavrni" "Zahtevano je dovoljenje" "Zahtevano je dovoljenje\nza račun %s." + "Aplikacija %1$s je zahtevala dovoljenje\nza račun %2$s." "Aplikacijo uporabljate zunaj delovnega profila" "To aplikacijo uporabljate v delovnem profilu" "Način vnosa" diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml index 0c2b143bc808..6e0436ed8884 100644 --- a/core/res/res/values-sq/strings.xml +++ b/core/res/res/values-sq/strings.xml @@ -1413,6 +1413,7 @@ "Moho" "Kërkohet leje" "Kërkohet leje\npër llogarinë %s." + "Kërkohet leja nga %1$s\npër llogarinë %2$s." "Po e përdor këtë aplikacion jashtë profilit tënd të punës" "Këtë aplikacion po e përdor në profilin tënd të punës" "Metoda e hyrjeve" diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml index d2e78651ef22..d69ed48f09e5 100644 --- a/core/res/res/values-sr/strings.xml +++ b/core/res/res/values-sr/strings.xml @@ -1433,6 +1433,7 @@ "Одбиј" "Затражена је дозвола" "Затражена је дозвола\nза налог %s" + "%1$s тражи дозволу \nза налог %2$s." "Користите ову апликацију изван пословног профила" "Користите ову апликацију на пословном профилу" "Метод уноса" diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml index 66bf9c2d8030..6688fe210b9b 100644 --- a/core/res/res/values-sv/strings.xml +++ b/core/res/res/values-sv/strings.xml @@ -1413,6 +1413,7 @@ "Neka" "Begärd behörighet" "Begärd behörighet\nför kontot %s." + "Behörighet har begärts av %1$s\nför kontot %2$s." "Du använder den här appen i din jobbprofil" "Du använder den här appen i din jobbprofil" "Indatametod" diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml index 8aca7d259c30..ef35a6fe4420 100644 --- a/core/res/res/values-sw/strings.xml +++ b/core/res/res/values-sw/strings.xml @@ -1413,6 +1413,7 @@ "Kataza" "Idhini imeitishwa" "Idhini imeombwa\nya akaunti%s." + "%1$s imeombwa ruhusa\nkwenye akaunti ya %2$s." "Unatumia programu hii nje ya wasifu wako wa kazini" "Unatumia programu hii kwenye wasifu wako wa kazini" "Mbinu ya uingizaji" diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml index 2eb628c7afb0..d6410beb93cd 100644 --- a/core/res/res/values-ta/strings.xml +++ b/core/res/res/values-ta/strings.xml @@ -1413,6 +1413,7 @@ "நிராகரி" "அனுமதிக் கோரப்பட்டது" "%s கணக்கிற்கான அனுமதி\nகோரப்பட்டது." + "%1$s ஆப்ஸ்\n%2$s கணக்கிற்கான அனுமதியைக் கோருகிறது." "இந்தப் பயன்பாட்டைப் பணிக் கணக்கிற்கு வெளியே பயன்படுத்துகிறீர்கள்" "பணிக் கணக்கில் பயன்பாட்டைப் பயன்படுத்துகிறீர்கள்" "உள்ளீட்டு முறை" diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml index f379214734c9..fb715953b7df 100644 --- a/core/res/res/values-te/strings.xml +++ b/core/res/res/values-te/strings.xml @@ -1413,6 +1413,7 @@ "తిరస్కరించండి" "అనుమతి అభ్యర్థించబడింది" "ఖాతా %s కోసం\nఅనుమతి అభ్యర్థించబడింది." + "%1$s ద్వారా అనుమతి రిక్వెస్ట్ చేయబడింది\nఖాతా %2$s కోసం." "మీరు మీ కార్యాలయ ప్రొఫైల్‌కు వెలుపల ఈ యాప్‌ను ఉపయోగిస్తున్నారు" "మీరు మీ కార్యాలయ ప్రొఫైల్‌లో ఈ యాప్‌ను ఉపయోగిస్తున్నారు" "ఇన్‌పుట్ పద్ధతి" diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml index 4c6be820d4ff..08718ffd614f 100644 --- a/core/res/res/values-th/strings.xml +++ b/core/res/res/values-th/strings.xml @@ -1413,6 +1413,7 @@ "ปฏิเสธ" "การอนุญาตที่ขอ" "การอนุญาตที่ขอ\nสำหรับบัญชี %s" + "สิทธิ์ที่ %1$s ขอ\nสำหรับบัญชี %2$s" "คุณกำลังใช้แอปนี้นอกโปรไฟล์งานของคุณ" "คุณกำลังใช้แอปนี้ในโปรไฟล์งานของคุณ" "วิธีป้อนข้อมูล" diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml index 0bd750f1aa33..0a7aa0e7ab14 100644 --- a/core/res/res/values-tl/strings.xml +++ b/core/res/res/values-tl/strings.xml @@ -1413,6 +1413,7 @@ "Tanggihan" "Hiniling ang pahintulot" "Hiniling ang pahintulot\npara sa account na %s." + "Humiling ang %1$s ng pahintulot\npara sa account na %2$s." "Ginagamit mo ang app na ito sa labas ng iyong profile sa trabaho" "Ginagamit mo ang app na ito sa iyong profile sa trabaho" "Pamamaraan ng pag-input" diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml index 87d97599a9bb..a44882498142 100644 --- a/core/res/res/values-tr/strings.xml +++ b/core/res/res/values-tr/strings.xml @@ -1413,6 +1413,7 @@ "Reddet" "İzin istendi" "%s hesabı için\nizin isteğinde bulunuldu." + "%1$s uygulaması, %2$s hesabı\niçin izin istedi" "Bu uygulamayı iş profilinizin dışında kullanıyorsunuz" "Bu uygulamayı iş profilinizde kullanıyorsunuz" "Giriş yöntemi" diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml index 067045aa0860..4605db387a44 100644 --- a/core/res/res/values-uk/strings.xml +++ b/core/res/res/values-uk/strings.xml @@ -1453,6 +1453,7 @@ "Забор." "Потрібен дозвіл" "Запитано дозвіл\nдля облікового запису %s." + "Додаток %1$s запитує дозвіл\nна доступ до облікового запису %2$s." "Ви використовуєте цей додаток за межами робочого профілю" "Ви використовуєте цей додаток у своєму робочому профілі" "Метод введення" diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml index 04800531784e..06dc0751e76e 100644 --- a/core/res/res/values-ur/strings.xml +++ b/core/res/res/values-ur/strings.xml @@ -1413,6 +1413,7 @@ "مسترد کریں" "اجازت طلب کی گئی" "اکاؤنٹ %s کیلئے\nاجازت طلب کی گئی۔" + "%2$s اکاؤنٹ کیلئے\n%1$s نے اجازت کی درخواست کی۔" "آپ اس ایپ کا استعمال اپنے دفتری پروفائل کے باہر کر رہے ہیں" "آپ اس ایپ کو اپنے دفتری پروفائل میں استعمال کر رہے ہیں" "اندراج کا طریقہ" diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml index e3ed7829f1ec..f09aaa67c43a 100644 --- a/core/res/res/values-uz/strings.xml +++ b/core/res/res/values-uz/strings.xml @@ -1413,6 +1413,7 @@ "Rad etish" "Ruxsat so‘raldi" "%s hisobi uchun\nruxsat so‘raldi" + "Ruxsat %1$s ilovasi tomonidan \n%2$s hisobi uchun soʻralgan." "Siz ushbu ilovadan ishchi profilingizdan tashqarida foydalanmoqdasiz" "Siz ushbu ilovadan ishchi profilingizda foydalanmoqdasiz" "Kiritish uslubi" diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml index 8e0cc2ead613..d19ecf567c54 100644 --- a/core/res/res/values-vi/strings.xml +++ b/core/res/res/values-vi/strings.xml @@ -1413,6 +1413,7 @@ "Từ chối" "Đã yêu cầu quyền" "Đã yêu cầu quyền\ncho tài khoản %s." + "Quyền do %1$s\nyêu cầu cho tài khoản %2$s." "Bạn đang sử dụng ứng dụng này bên ngoài hồ sơ công việc của mình" "Bạn đang sử dụng ứng dụng này trong hồ sơ công việc của mình" "Phương thức nhập" diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml index a645cd7db90a..74dde0ec4550 100644 --- a/core/res/res/values-zh-rCN/strings.xml +++ b/core/res/res/values-zh-rCN/strings.xml @@ -1413,6 +1413,7 @@ "拒绝" "权限请求" "应用对帐号 %s\n 提出权限请求。" + "“%1$s”请求获得以下帐号的访问权限:\n%2$s。" "您目前是在工作资料之外使用此应用" "您目前是在工作资料内使用此应用" "输入法" diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml index 9eef703670ef..6cae6439ffd3 100644 --- a/core/res/res/values-zh-rHK/strings.xml +++ b/core/res/res/values-zh-rHK/strings.xml @@ -1413,6 +1413,7 @@ "拒絕" "已要求權限" "%s 帳戶的\n權限要求。" + "「%1$s」要求帳戶 %2$s\n的權限" "您目前並未透過公司檔案使用這個應用程式" "您目前透過公司檔案使用這個應用程式" "輸入法" diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml index c4f5dc8d3661..58af46e65f60 100644 --- a/core/res/res/values-zh-rTW/strings.xml +++ b/core/res/res/values-zh-rTW/strings.xml @@ -1413,6 +1413,7 @@ "拒絕" "已要求權限" "帳戶 %s 已提出\n權限要求。" + "「%1$s」要求授予\n%2$s 帳戶的權限。" "你目前並非透過工作資料夾使用這個應用程式" "你目前透過工作設定檔使用這個應用程式" "輸入法" diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml index bb5360edb0b8..c84b44720467 100644 --- a/core/res/res/values-zu/strings.xml +++ b/core/res/res/values-zu/strings.xml @@ -1413,6 +1413,7 @@ "Yala" "Imvume Iceliwe" "Imvume Iceliwe \n ye-akhawunti %s" + "Imvume ecelwe yi-%1$s\nye-akhawunti ye-%2$s." "Usebenzisa lolu hlelo lokusebenza ngaphandle kwephrofayela yakho yomsebenzi" "Usebenzisa lolu hlelo lokusebenza kuphrofayela yakho yomsebenzi" "Indlela yokufakwayo" -- cgit v1.2.3 From f587d95c7307de3dd0e01f709582e1feb4a91cb0 Mon Sep 17 00:00:00 2001 From: Yu-Han Yang Date: Tue, 21 Sep 2021 12:29:34 -0700 Subject: Fix serialization bug in GpsNavigationMessage Bug: 196970023 Test: presubmits passing. Change-Id: I69f51eb2faac0cf2ee9f7a5f94f7100925f7221c (cherry picked from commit aa03fae4523684d6fbb85e1ec3e088bfce16ea74) --- location/java/android/location/GpsNavigationMessage.java | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/location/java/android/location/GpsNavigationMessage.java b/location/java/android/location/GpsNavigationMessage.java index dc1e99fd6a4f..2b978f759a13 100644 --- a/location/java/android/location/GpsNavigationMessage.java +++ b/location/java/android/location/GpsNavigationMessage.java @@ -262,12 +262,8 @@ public class GpsNavigationMessage implements Parcelable { parcel.readByteArray(data); navigationMessage.setData(data); - if (parcel.dataAvail() >= Integer.SIZE) { - int status = parcel.readInt(); - navigationMessage.setStatus((short) status); - } else { - navigationMessage.setStatus(STATUS_UNKNOWN); - } + int status = parcel.readInt(); + navigationMessage.setStatus((short) status); return navigationMessage; } -- cgit v1.2.3 From 838263ffbd5b3018368e6017bbbcbd62f76b2c98 Mon Sep 17 00:00:00 2001 From: cnchen Date: Mon, 6 Jul 2020 19:58:44 +0800 Subject: Fix NPE on getTitle() Bug: 199922685 Test: make RunSettingsLibRoboTests -j40 Change-Id: I35bf6f5911dc0ee56e43af7faddaceb479362863 (cherry picked from commit f00f2203b578e919e56f21f3a4119a974b942243) Merged-In: I35bf6f5911dc0ee56e43af7faddaceb479362863 (cherry picked from commit af6f9ab235fa08f773715539c7178cb47afcb85e) --- .../src/com/android/settingslib/wifi/AccessPoint.java | 10 ++++++---- .../src/com/android/settingslib/wifi/AccessPointTest.java | 11 +++++++++++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java index 8968340b65f4..c5e66bef9653 100644 --- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java +++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java @@ -1117,14 +1117,16 @@ public class AccessPoint implements Comparable { * Returns the display title for the AccessPoint, such as for an AccessPointPreference's title. */ public String getTitle() { - if (isPasspoint()) { + if (isPasspoint() && !TextUtils.isEmpty(mConfig.providerFriendlyName)) { return mConfig.providerFriendlyName; - } else if (isPasspointConfig()) { + } else if (isPasspointConfig() && !TextUtils.isEmpty(mProviderFriendlyName)) { return mProviderFriendlyName; - } else if (isOsuProvider()) { + } else if (isOsuProvider() && !TextUtils.isEmpty(mOsuProvider.getFriendlyName())) { return mOsuProvider.getFriendlyName(); - } else { + } else if (!TextUtils.isEmpty(getSsidStr())) { return getSsidStr(); + } else { + return ""; } } diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java index bcabec858487..46ecbd45a860 100644 --- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java +++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java @@ -147,6 +147,17 @@ public class AccessPointTest { assertThat(ssid instanceof SpannableString).isFalse(); } + @Test + public void testCompareTo_GivesNull() { + WifiConfiguration spyConfig = spy(new WifiConfiguration()); + + when(spyConfig.isPasspoint()).thenReturn(true); + spyConfig.providerFriendlyName = null; + AccessPoint passpointAp = new AccessPoint(mContext, spyConfig); + + assertThat(passpointAp.getTitle()).isEqualTo(""); + } + @Test public void testCompareTo_GivesActiveBeforeInactive() { AccessPoint activeAp = new TestAccessPointBuilder(mContext).setActive(true).build(); -- cgit v1.2.3 From 40ef6c0341e89fff99602fb570033f2fc8945bd8 Mon Sep 17 00:00:00 2001 From: Jeff DeCew Date: Fri, 17 Sep 2021 16:32:58 -0400 Subject: Do not show the notification footer until the user is set up. Bug: 193149550 Test: follow repro steps Merged-In: I49e2b8bcec7b2ce0a9776ff30a64c07f24949da7 Change-Id: I49e2b8bcec7b2ce0a9776ff30a64c07f24949da7 (cherry picked from commit 42e8c45e8c48530d7d0b4624add65c72b9961485) --- .../stack/NotificationStackScrollLayout.java | 39 ++++++++++++++++++++++ .../stack/NotificationStackScrollLayoutTest.java | 33 +++++++++++++++--- 2 files changed, 68 insertions(+), 4 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java index a4a58194a46b..6986ad754596 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java @@ -157,6 +157,8 @@ import com.android.systemui.statusbar.phone.ShadeController; import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener; +import com.android.systemui.statusbar.policy.DeviceProvisionedController; +import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener; import com.android.systemui.statusbar.policy.HeadsUpUtil; import com.android.systemui.statusbar.policy.ScrollAdapter; import com.android.systemui.statusbar.policy.ZenModeController; @@ -300,6 +302,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd private boolean mExpandedInThisMotion; private boolean mShouldShowShelfOnly; protected boolean mScrollingEnabled; + private boolean mIsCurrentUserSetup; protected FooterView mFooterView; protected EmptyShadeView mEmptyShadeView; private boolean mDismissAllInProgress; @@ -508,6 +511,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd private final NotifPipeline mNotifPipeline; private final NotifCollection mNotifCollection; private final NotificationEntryManager mEntryManager; + private final DeviceProvisionedController mDeviceProvisionedController = + Dependency.get(DeviceProvisionedController.class); private final IStatusBarService mBarService = IStatusBarService.Stub.asInterface( ServiceManager.getService(Context.STATUS_BAR_SERVICE)); @VisibleForTesting @@ -648,6 +653,29 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd }, HIGH_PRIORITY, Settings.Secure.NOTIFICATION_DISMISS_RTL, Settings.Secure.NOTIFICATION_HISTORY_ENABLED); + mDeviceProvisionedController.addCallback( + new DeviceProvisionedListener() { + @Override + public void onDeviceProvisionedChanged() { + updateCurrentUserIsSetup(); + } + + @Override + public void onUserSwitched() { + updateCurrentUserIsSetup(); + } + + @Override + public void onUserSetupChanged() { + updateCurrentUserIsSetup(); + } + + private void updateCurrentUserIsSetup() { + setCurrentUserSetup(mDeviceProvisionedController.isCurrentUserSetup()); + } + }); + + mFeatureFlags = featureFlags; mNotifPipeline = notifPipeline; mEntryManager = entryManager; @@ -772,6 +800,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd } boolean showDismissView = mClearAllEnabled && hasActiveClearableNotifications(ROWS_ALL); boolean showFooterView = (showDismissView || hasActiveNotifications()) + && mIsCurrentUserSetup // see: b/193149550 && mStatusBarState != StatusBarState.KEYGUARD && !mRemoteInputManager.getController().isRemoteInputActive(); boolean showHistory = Settings.Secure.getIntForUser(mContext.getContentResolver(), @@ -5923,6 +5952,16 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd return MathUtils.smoothStep(0, totalDistance, dragDownAmount); } + /** + * Sets whether the current user is set up, which is required to show the footer (b/193149550) + */ + public void setCurrentUserSetup(boolean isCurrentUserSetup) { + if (mIsCurrentUserSetup != isCurrentUserSetup) { + mIsCurrentUserSetup = isCurrentUserSetup; + updateFooter(); + } + } + /** * A listener that is notified when the empty space below the notifications is clicked on */ diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java index 2ae4caeca963..710a6c84a63e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java @@ -110,8 +110,6 @@ import org.mockito.junit.MockitoRule; import java.util.ArrayList; import java.util.List; -import dagger.Lazy; - /** * Tests for {@link NotificationStackScrollLayout}. */ @@ -143,7 +141,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { @Mock private NotificationSection mNotificationSection; @Mock private NotificationLockscreenUserManager mLockscreenUserManager; @Mock private FeatureFlags mFeatureFlags; - @Mock private Lazy mBubbleControllerLazy; + @Mock private BubbleController mBubbleController; private UserChangedListener mUserChangedListener; private NotificationEntryManager mEntryManager; private int mOriginalInterruptionModelSetting; @@ -194,7 +192,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { () -> mock(NotificationRowBinder.class), () -> mRemoteInputManager, mock(LeakDetector.class), - mBubbleControllerLazy, + () -> mBubbleController, mock(ForegroundServiceDismissalFeatureController.class) ); mEntryManager.setUpWithPresenter(mock(NotificationPresenter.class)); @@ -354,6 +352,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { @Test public void testUpdateFooter_noNotifications() { setBarStateForTest(StatusBarState.SHADE); + mStackScroller.setCurrentUserSetup(true); assertEquals(0, mEntryManager.getActiveNotificationsCount()); FooterView view = mock(FooterView.class); @@ -365,6 +364,8 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { @Test public void testUpdateFooter_remoteInput() { setBarStateForTest(StatusBarState.SHADE); + mStackScroller.setCurrentUserSetup(true); + ArrayList entries = new ArrayList<>(); entries.add(new NotificationEntryBuilder().build()); addEntriesToEntryManager(entries); @@ -384,6 +385,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { @Test public void testUpdateFooter_oneClearableNotification() { setBarStateForTest(StatusBarState.SHADE); + mStackScroller.setCurrentUserSetup(true); ArrayList entries = new ArrayList<>(); entries.add(new NotificationEntryBuilder().build()); @@ -400,9 +402,30 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { verify(mStackScroller).updateFooterView(true, true, true); } + @Test + public void testUpdateFooter_oneClearableNotification_beforeUserSetup() { + setBarStateForTest(StatusBarState.SHADE); + mStackScroller.setCurrentUserSetup(false); + + ArrayList entries = new ArrayList<>(); + entries.add(new NotificationEntryBuilder().build()); + addEntriesToEntryManager(entries); + + ExpandableNotificationRow row = mock(ExpandableNotificationRow.class); + when(row.canViewBeDismissed()).thenReturn(true); + when(mStackScroller.getChildCount()).thenReturn(1); + when(mStackScroller.getChildAt(anyInt())).thenReturn(row); + + FooterView view = mock(FooterView.class); + mStackScroller.setFooterView(view); + mStackScroller.updateFooter(); + verify(mStackScroller).updateFooterView(false, true, true); + } + @Test public void testUpdateFooter_oneNonClearableNotification() { setBarStateForTest(StatusBarState.SHADE); + mStackScroller.setCurrentUserSetup(true); ArrayList entries = new ArrayList<>(); entries.add(new NotificationEntryBuilder().build()); @@ -416,6 +439,8 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { @Test public void testUpdateFooter_atEnd() { + mStackScroller.setCurrentUserSetup(true); + // add footer mStackScroller.inflateFooterView(); -- cgit v1.2.3 From 9654eca69f91b407259a368926d1af16d54cbc4d Mon Sep 17 00:00:00 2001 From: Janis Danisevskis Date: Thu, 23 Sep 2021 16:56:06 -0700 Subject: DO NOT MERGE KeyStore ChunkedStreamer must tolerate update consuming 0 bytes. Some older versions of Keymster do not consume any data in certain block modes unless a full block of data was presented. Bug: 199032140 Bug: 200041882 Test: CtsKeyStoreTestcases with KM1.0 backend. Merged-In: Ic2da6e5c12628f11603f51c7a3408aad70947d95 Change-Id: Ic2da6e5c12628f11603f51c7a3408aad70947d95 (cherry picked from commit 395e56a71c87d3748ca280f235da04983069de87) --- .../KeyStoreCryptoOperationChunkedStreamer.java | 28 +++++++++++++++------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/keystore/java/android/security/keystore/KeyStoreCryptoOperationChunkedStreamer.java b/keystore/java/android/security/keystore/KeyStoreCryptoOperationChunkedStreamer.java index 2c0f40d528d2..cedc4d2fb8e6 100644 --- a/keystore/java/android/security/keystore/KeyStoreCryptoOperationChunkedStreamer.java +++ b/keystore/java/android/security/keystore/KeyStoreCryptoOperationChunkedStreamer.java @@ -126,8 +126,8 @@ class KeyStoreCryptoOperationChunkedStreamer implements KeyStoreCryptoOperationS if (mChunkLength > mChunkSizeMax) { throw new KeyStoreException(KeymasterDefs.KM_ERROR_INVALID_INPUT_LENGTH, - "Chunk size exceeded max chunk size. Max: " + mChunkSizeMax - + " Actual: " + mChunkLength); + "Chunk size exceeded max chunk size. Max: " + mChunkSizeMax + + " Actual: " + mChunkLength); } if (mChunkLength >= mChunkSizeThreshold) { @@ -139,18 +139,28 @@ class KeyStoreCryptoOperationChunkedStreamer implements KeyStoreCryptoOperationS } else if (opResult.resultCode != KeyStore.NO_ERROR) { throw KeyStore.getKeyStoreException(opResult.resultCode); } - if (opResult.inputConsumed <= 0) { - throw new KeyStoreException(KeymasterDefs.KM_ERROR_INVALID_INPUT_LENGTH, - "Keystore consumed 0 of " + mChunkLength + " bytes provided."); - } else if (opResult.inputConsumed > mChunkLength) { + if (opResult.inputConsumed == 0) { + // Some KM implementations do not consume data in certain block modes unless a + // full block of data was presented. + if (inputLength > 0) { + // More input is available, but it wasn't included into the previous chunk + // because the chunk reached its maximum permitted size. + // Shouldn't have happened. + throw new KeyStoreException(KeymasterDefs.KM_ERROR_INVALID_INPUT_LENGTH, + "Keystore consumed nothing from max-sized chunk: " + mChunkLength + + " bytes"); + } + } else if (opResult.inputConsumed > mChunkLength || opResult.inputConsumed < 0) { throw new KeyStoreException(KeymasterDefs.KM_ERROR_UNKNOWN_ERROR, - "Keystore consumed more input than provided. Provided: " - + mChunkLength + ", consumed: " + opResult.inputConsumed); + "Keystore consumed more input than provided (or inputConsumed was " + + "negative." + + " Provided: " + mChunkLength + + ", consumed: " + opResult.inputConsumed); } mChunkLength -= opResult.inputConsumed; if (mChunkLength > 0) { - // Partialy consumed, shift chunk contents + // Partially consumed, shift chunk contents ArrayUtils.copy(mChunk, opResult.inputConsumed, mChunk, 0, mChunkLength); } -- cgit v1.2.3 From 64f77dcd575cbab66f1c63f80e5ce2445155b2c1 Mon Sep 17 00:00:00 2001 From: Collin Fijalkovich Date: Mon, 5 Oct 2020 13:10:33 -0700 Subject: Disallow overlays for ResolverActivity Prevents non-system apps from placing a window over the app selection screen. Bug: 143559931 Test: Installed test app and attempted to overlay Change-Id: Ied05088a5007e0f10cd3e1abd8d7da8ffeb3b674 Merged-In: Ied05088a5007e0f10cd3e1abd8d7da8ffeb3b674 (cherry picked from commit 34534e1fd2057ea6d858ce82f8505cbdb1026d9a) (cherry picked from commit 718c60bea7b9f8858306705aa60d8d5206271696) --- core/java/com/android/internal/app/ResolverActivity.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java index fadc15912dc1..24bbe749aaef 100644 --- a/core/java/com/android/internal/app/ResolverActivity.java +++ b/core/java/com/android/internal/app/ResolverActivity.java @@ -19,6 +19,7 @@ package com.android.internal.app; import static android.Manifest.permission.INTERACT_ACROSS_PROFILES; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; import static android.content.PermissionChecker.PID_UNKNOWN; +import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; import android.annotation.Nullable; import android.annotation.StringRes; @@ -69,7 +70,9 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; +import android.view.Window; import android.view.WindowInsets; +import android.view.WindowManager; import android.widget.AbsListView; import android.widget.AdapterView; import android.widget.Button; @@ -101,7 +104,6 @@ import java.util.List; import java.util.Objects; import java.util.Set; - /** * This activity is displayed when the system attempts to start an Intent for * which there is more than one matching activity, allowing the user to decide @@ -822,6 +824,8 @@ public class ResolverActivity extends Activity implements @Override protected void onStart() { super.onStart(); + + this.getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); if (shouldShowTabs()) { mWorkProfileStateReceiver = createWorkProfileStateReceiver(); registerWorkProfileStateReceiver(); @@ -849,6 +853,12 @@ public class ResolverActivity extends Activity implements @Override protected void onStop() { super.onStop(); + + final Window window = this.getWindow(); + final WindowManager.LayoutParams attrs = window.getAttributes(); + attrs.privateFlags &= ~SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; + window.setAttributes(attrs); + if (mRegistered) { mPersonalPackageMonitor.unregister(); if (mWorkPackageMonitor != null) { -- cgit v1.2.3 From 3bd0157135e4633c2bbb70808d726c84e4966cf9 Mon Sep 17 00:00:00 2001 From: Aseem Kumar Date: Mon, 17 May 2021 09:25:03 +0000 Subject: Prevent apps from spamming addAccountExplicitly. See comment here for the discussion on solution https://b.corp.google.com/issues/169762606#comment14 Change-Id: If212df3a3b7be1de0fb26b8e88b2fcbb8077c253 Bug: 169762606 (cherry picked from commit 11053c17b397db67b20e96ce769508766cef7db9) Change-Id: Ic65162df3415275514f6277891a9412865e2315b Merged-In: If212df3a3b7be1de0fb26b8e88b2fcbb8077c253 (cherry picked from commit 9050942832acdf93faea1803b82ebededa2e1372) Merged-In:Ic65162df3415275514f6277891a9412865e2315b --- core/java/android/accounts/Account.java | 7 +++++++ .../java/com/android/server/accounts/AccountManagerService.java | 5 +++++ 2 files changed, 12 insertions(+) diff --git a/core/java/android/accounts/Account.java b/core/java/android/accounts/Account.java index 9a18880a353b..965b6e0a02cd 100644 --- a/core/java/android/accounts/Account.java +++ b/core/java/android/accounts/Account.java @@ -30,6 +30,7 @@ import android.util.Log; import com.android.internal.annotations.GuardedBy; +import java.util.Objects; import java.util.Set; /** @@ -85,6 +86,12 @@ public class Account implements Parcelable { if (TextUtils.isEmpty(type)) { throw new IllegalArgumentException("the type must not be empty: " + type); } + if (name.length() > 200) { + throw new IllegalArgumentException("account name is longer than 200 characters"); + } + if (type.length() > 200) { + throw new IllegalArgumentException("account type is longer than 200 characters"); + } this.name = name; this.type = type; this.accessId = accessId; diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java index db3c25a7e43a..90dc03642a86 100644 --- a/services/core/java/com/android/server/accounts/AccountManagerService.java +++ b/services/core/java/com/android/server/accounts/AccountManagerService.java @@ -1820,6 +1820,11 @@ public class AccountManagerService + ", skipping since the account already exists"); return false; } + if (accounts.accountsDb.findAllDeAccounts().size() > 100) { + Log.w(TAG, "insertAccountIntoDatabase: " + account.toSafeString() + + ", skipping since more than 50 accounts on device exist"); + return false; + } long accountId = accounts.accountsDb.insertCeAccount(account, password); if (accountId < 0) { Log.w(TAG, "insertAccountIntoDatabase: " + account.toSafeString() -- cgit v1.2.3 From 40421407ca923073b7386b8fb9cb56ea53424fb6 Mon Sep 17 00:00:00 2001 From: Jeff DeCew Date: Thu, 21 Oct 2021 19:48:19 +0000 Subject: Allow forcing status bar state changes and do so when the screen turns off. This adds a force flag, which we will use when turning the screen off to make sure that all UI components are reset to the SHADE state regardless. Bug: 189575031 Test: make a call; lock screen; pull down shade Merged-In: I79baeb71ac5d1ed45602ac55cdca996b3bed0ac3 Change-Id: I79baeb71ac5d1ed45602ac55cdca996b3bed0ac3 (cherry picked from commit 9be6207510c2e39e2899a9ce7a93fb09f83134c6) Merged-In:I79baeb71ac5d1ed45602ac55cdca996b3bed0ac3 --- .../systemui/statusbar/StatusBarStateControllerImpl.java | 4 ++-- .../systemui/statusbar/SysuiStatusBarStateController.java | 14 +++++++++++++- .../com/android/systemui/statusbar/phone/StatusBar.java | 13 +++++++++---- .../android/systemui/statusbar/phone/StatusBarTest.java | 6 ++++-- 4 files changed, 28 insertions(+), 9 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java index 2bef355d59f3..e0e603f7514d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java @@ -134,11 +134,11 @@ public class StatusBarStateControllerImpl implements SysuiStatusBarStateControll } @Override - public boolean setState(int state) { + public boolean setState(int state, boolean force) { if (state > MAX_STATE || state < MIN_STATE) { throw new IllegalArgumentException("Invalid state " + state); } - if (state == mState) { + if (!force && state == mState) { return false; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SysuiStatusBarStateController.java b/packages/SystemUI/src/com/android/systemui/statusbar/SysuiStatusBarStateController.java index 07b35502478f..fc40077810ff 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/SysuiStatusBarStateController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/SysuiStatusBarStateController.java @@ -58,7 +58,19 @@ public interface SysuiStatusBarStateController extends StatusBarStateController * @param state see {@link StatusBarState} for valid options * @return {@code true} if the state changed, else {@code false} */ - boolean setState(int state); + default boolean setState(int state) { + return setState(state, false /* force */); + } + + /** + * Update the status bar state + * @param state see {@link StatusBarState} for valid options + * @param force whether to set the state even if it's the same as the current state. This will + * dispatch the state to all StatusBarStateListeners, ensuring that all listening + * components are reset to this state. + * @return {@code true} if the state was changed or set forcefully + */ + boolean setState(int state, boolean force); /** * Update the dozing state from {@link StatusBar}'s perspective diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index f125b7d10035..0b98f1a60a97 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -3186,6 +3186,10 @@ public class StatusBar extends SystemUI implements DemoMode, } boolean updateIsKeyguard() { + return updateIsKeyguard(false /* force */); + } + + boolean updateIsKeyguard(boolean force) { boolean wakeAndUnlocking = mBiometricUnlockController.getMode() == BiometricUnlockController.MODE_WAKE_AND_UNLOCK; @@ -3208,7 +3212,7 @@ public class StatusBar extends SystemUI implements DemoMode, showKeyguardImpl(); } } else { - return hideKeyguardImpl(); + return hideKeyguardImpl(force); } return false; } @@ -3339,11 +3343,11 @@ public class StatusBar extends SystemUI implements DemoMode, /** * @return true if we would like to stay in the shade, false if it should go away entirely */ - public boolean hideKeyguardImpl() { + public boolean hideKeyguardImpl(boolean force) { mIsKeyguard = false; Trace.beginSection("StatusBar#hideKeyguard"); boolean staying = mStatusBarStateController.leaveOpenOnKeyguardHide(); - if (!(mStatusBarStateController.setState(StatusBarState.SHADE))) { + if (!(mStatusBarStateController.setState(StatusBarState.SHADE, force))) { //TODO: StatusBarStateController should probably know about hiding the keyguard and // notify listeners. @@ -3770,7 +3774,8 @@ public class StatusBar extends SystemUI implements DemoMode, // is correct. mHandler.post(() -> onCameraLaunchGestureDetected(mLastCameraLaunchSource)); } - updateIsKeyguard(); + // When finished going to sleep, force the status bar state to avoid stale state. + updateIsKeyguard(true /* force */); } @Override diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java index 5a08c9ca017b..d528f209cd1c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java @@ -809,12 +809,14 @@ public class StatusBarTest extends SysuiTestCase { // By default, showKeyguardImpl sets state to KEYGUARD. mStatusBar.showKeyguardImpl(); - verify(mStatusBarStateController).setState(eq(StatusBarState.KEYGUARD)); + verify(mStatusBarStateController).setState( + eq(StatusBarState.KEYGUARD), eq(false) /* force */); // If useFullscreenUserSwitcher is true, state is set to FULLSCREEN_USER_SWITCHER. when(mUserSwitcherController.useFullscreenUserSwitcher()).thenReturn(true); mStatusBar.showKeyguardImpl(); - verify(mStatusBarStateController).setState(eq(StatusBarState.FULLSCREEN_USER_SWITCHER)); + verify(mStatusBarStateController).setState( + eq(StatusBarState.FULLSCREEN_USER_SWITCHER), eq(false) /* force */); } @Test -- cgit v1.2.3 From 05db60d4e8b0a14297e6b167140a9965a9f1b1b7 Mon Sep 17 00:00:00 2001 From: Songchun Fan Date: Thu, 14 Oct 2021 09:12:44 -0700 Subject: Revert "Revert "[pm] remove old stage dirs on low storage"" This reverts commit b45ebca772a77bf3fd269d0dcfc1a7af7c73861d. Reason for revert: adding the fix for system to abandon sessions BUG: 67862680 Test: manual Change-Id: I5b762a29d12f62b516a59a85530386236259308b Merged-In: I91170ba399b3a596320b3bd9c8188912e5c4f1be (cherry picked from commit 4006041d55db50a1db640e7f85accd58d23e71b8) Merged-In:I5b762a29d12f62b516a59a85530386236259308b --- .../android/server/pm/PackageInstallerService.java | 54 ++++++++++++++++++---- .../android/server/pm/PackageInstallerSession.java | 8 +--- .../android/server/pm/PackageManagerService.java | 4 ++ 3 files changed, 51 insertions(+), 15 deletions(-) diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java index f8115d39b375..d88a8364f316 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerService.java +++ b/services/core/java/com/android/server/pm/PackageInstallerService.java @@ -134,6 +134,9 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements /** 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 * disable verification flag specified. @@ -295,22 +298,29 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements @GuardedBy("mSessions") private void reconcileStagesLocked(String volumeUuid) { - final File stagingDir = getTmpSessionDir(volumeUuid); - final ArraySet 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 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 getStagingDirsOnVolume(String volumeUuid) { + final File stagingDir = getTmpSessionDir(volumeUuid); + final ArraySet 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 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); @@ -318,6 +328,34 @@ 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 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 void onPrivateVolumeMounted(String volumeUuid) { synchronized (mSessions) { reconcileStagesLocked(volumeUuid); diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java index d690ae9e70f1..a253b509abb9 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerSession.java +++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java @@ -2638,14 +2638,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { List childSessions = getChildSessionsNotLocked(); synchronized (mLock) { - if (params.isStaged && mDestroyed) { - // If a user abandons staged session in an unsafe state, then system will try to - // abandon the destroyed staged session when it is safe on behalf of the user. - assertCallerIsOwnerOrRootOrSystemLocked(); - } else { - assertCallerIsOwnerOrRootLocked(); - } + assertCallerIsOwnerOrRootOrSystemLocked(); if (isStagedAndInTerminalState()) { // 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. diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 6658d14a2a10..a344d4993c80 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -5142,6 +5142,10 @@ public class PackageManagerService extends IPackageManager.Stub InstantAppRegistry.DEFAULT_UNINSTALLED_INSTANT_APP_MIN_CACHE_PERIOD))) { return; } + + // 12. Clear temp install session files + mInstallerService.freeStageDirs(volumeUuid); + } else { try { mInstaller.freeCache(volumeUuid, bytes, 0, 0); -- cgit v1.2.3 From 5fac63153e993f1b696e8c4dc78c61cbb158ae97 Mon Sep 17 00:00:00 2001 From: Varun Shah Date: Fri, 12 Nov 2021 01:02:20 +0000 Subject: Merge "Update deletion conditions for a package's UsageStats." into rvc-dev am: 06c5973697 Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/16222704 Bug: 206039322 Change-Id: I8f02f4bce0661eaea6ae1e72c05f6fcafdc49884 Merged-In: I94a8e3dfca8ef4c7616f77944d61726e06043b85 (cherry picked from commit a7174fa6dbfcb54f3f39a86d755ae1c16bc7d772) Merged-In:I8f02f4bce0661eaea6ae1e72c05f6fcafdc49884 --- .../app/admin/DevicePolicyManagerInternal.java | 8 +++++++ .../devicepolicy/DevicePolicyManagerService.java | 7 ++++++ .../android/server/usage/UsageStatsService.java | 26 +++++++++++++++++----- .../server/usage/UserUsageStatsService.java | 10 +++++---- 4 files changed, 42 insertions(+), 9 deletions(-) diff --git a/core/java/android/app/admin/DevicePolicyManagerInternal.java b/core/java/android/app/admin/DevicePolicyManagerInternal.java index d24694faff93..60cb563cca3d 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; @@ -76,6 +77,13 @@ public abstract class DevicePolicyManagerInternal { public abstract void addOnCrossProfileWidgetProvidersChangeListener( 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 admin of its user and has the policy * specified. diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index ae354a953eec..2550f0282c4f 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -12481,6 +12481,13 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } } + @Override + public @Nullable ComponentName getProfileOwnerOrDeviceOwnerSupervisionComponent( + @NonNull UserHandle userHandle) { + return DevicePolicyManagerService.this.getProfileOwnerOrDeviceOwnerSupervisionComponent( + userHandle); + } + @Override public boolean isActiveAdminWithPolicy(int uid, int reqPolicy) { synchronized (getLockObject()) { diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java index a5b676012ea9..a54f263c32ae 100644 --- a/services/usage/java/com/android/server/usage/UsageStatsService.java +++ b/services/usage/java/com/android/server/usage/UsageStatsService.java @@ -339,6 +339,7 @@ public class UsageStatsService extends SystemService implements if (userId == UserHandle.USER_SYSTEM) { UsageStatsIdleService.scheduleUpdateMappingsJob(getContext()); } + final boolean deleteObsoleteData = shouldDeleteObsoleteData(UserHandle.of(userId)); synchronized (mLock) { // Create a user unlocked event to report final Event unlockEvent = new Event(USER_UNLOCKED, SystemClock.elapsedRealtime()); @@ -356,7 +357,7 @@ public class UsageStatsService extends SystemService implements boolean needToFlush = !pendingEvents.isEmpty(); initializeUserUsageStatsServiceLocked(userId, System.currentTimeMillis(), - installedPackages); + installedPackages, deleteObsoleteData); mUserUnlockedStates.put(userId, true); final UserUsageStatsService userService = getUserUsageStatsServiceLocked(userId); if (userService == null) { @@ -551,13 +552,13 @@ public class UsageStatsService extends SystemService implements * when the user is initially unlocked. */ private void initializeUserUsageStatsServiceLocked(int userId, long currentTimeMillis, - HashMap installedPackages) { + HashMap 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)) { @@ -1029,6 +1030,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 installedPkgs = getInstalledPackages(UserHandle.USER_SYSTEM); synchronized (mLock) { @@ -1154,6 +1159,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); @@ -2324,8 +2336,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 26de11af6f4e..0a5adc8e61d4 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 installedPackages) { - readPackageMappingsLocked(installedPackages); + void init(final long currentTimeMillis, HashMap 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 installedPackages) { + private void readPackageMappingsLocked(HashMap 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); } } -- cgit v1.2.3 From 33f94a437587030bd0e84f78279fa7c6f71e2daf Mon Sep 17 00:00:00 2001 From: Miranda Kephart Date: Wed, 17 Nov 2021 13:32:42 -0500 Subject: Dispose of input event reciever along with monitor Explicitly store a reference to the input event receiver so that we can dispose of it at the same time as the input monitor. Bug: 206809961 Fix: 206809961 Test: manual Change-Id: Id201891ffd546119b18b18b692dd87008f6735c2 --- .../src/com/android/systemui/screenshot/ScreenshotView.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java index ca63ec269bf4..0d11070fd220 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java @@ -86,6 +86,7 @@ import androidx.constraintlayout.widget.ConstraintLayout; import com.android.internal.logging.UiEventLogger; import com.android.systemui.R; import com.android.systemui.screenshot.ScreenshotController.SavedImageData.ActionTransition; +import com.android.systemui.shared.system.InputChannelCompat; import com.android.systemui.shared.system.InputMonitorCompat; import com.android.systemui.shared.system.QuickStepContract; @@ -162,6 +163,7 @@ public class ScreenshotView extends FrameLayout implements private GestureDetector mSwipeDetector; private SwipeDismissHandler mSwipeDismissHandler; private InputMonitorCompat mInputMonitor; + private InputChannelCompat.InputEventReceiver mInputEventReceiver; private boolean mShowScrollablePreview; private String mPackageName = ""; @@ -302,8 +304,8 @@ public class ScreenshotView extends FrameLayout implements private void startInputListening() { stopInputListening(); mInputMonitor = new InputMonitorCompat("Screenshot", Display.DEFAULT_DISPLAY); - mInputMonitor.getInputReceiver(Looper.getMainLooper(), Choreographer.getInstance(), - ev -> { + mInputEventReceiver = mInputMonitor.getInputReceiver( + Looper.getMainLooper(), Choreographer.getInstance(), ev -> { if (ev instanceof MotionEvent) { MotionEvent event = (MotionEvent) ev; if (event.getActionMasked() == MotionEvent.ACTION_DOWN @@ -320,6 +322,10 @@ public class ScreenshotView extends FrameLayout implements mInputMonitor.dispose(); mInputMonitor = null; } + if (mInputEventReceiver != null) { + mInputEventReceiver.dispose(); + mInputEventReceiver = null; + } } @Override // ViewGroup -- cgit v1.2.3 From 694cab06a044f1b40aa57dbac2460d88a0b9e483 Mon Sep 17 00:00:00 2001 From: Hung-ying Tyan Date: Mon, 6 Dec 2021 13:51:56 +0800 Subject: Revert "Merge "Update deletion conditions for a package's UsageStats." into rvc-dev am: 06c5973697" This reverts commit 5fac63153e993f1b696e8c4dc78c61cbb158ae97. Reason for revert: causing issues in running CTS-on-GSI Bug: 208892267 Test: TH Change-Id: I9c56b82ff28f0c530a0646365db595bca5e3413a (cherry picked from commit 6983aed6838752448db2bf38085dbc355eab7565) Merged-In:I9c56b82ff28f0c530a0646365db595bca5e3413a --- .../app/admin/DevicePolicyManagerInternal.java | 8 ------- .../devicepolicy/DevicePolicyManagerService.java | 7 ------ .../android/server/usage/UsageStatsService.java | 26 +++++----------------- .../server/usage/UserUsageStatsService.java | 10 ++++----- 4 files changed, 9 insertions(+), 42 deletions(-) diff --git a/core/java/android/app/admin/DevicePolicyManagerInternal.java b/core/java/android/app/admin/DevicePolicyManagerInternal.java index 60cb563cca3d..d24694faff93 100644 --- a/core/java/android/app/admin/DevicePolicyManagerInternal.java +++ b/core/java/android/app/admin/DevicePolicyManagerInternal.java @@ -16,7 +16,6 @@ package android.app.admin; -import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; import android.content.ComponentName; @@ -77,13 +76,6 @@ public abstract class DevicePolicyManagerInternal { public abstract void addOnCrossProfileWidgetProvidersChangeListener( 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 admin of its user and has the policy * specified. diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 2550f0282c4f..ae354a953eec 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -12481,13 +12481,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } } - @Override - public @Nullable ComponentName getProfileOwnerOrDeviceOwnerSupervisionComponent( - @NonNull UserHandle userHandle) { - return DevicePolicyManagerService.this.getProfileOwnerOrDeviceOwnerSupervisionComponent( - userHandle); - } - @Override public boolean isActiveAdminWithPolicy(int uid, int reqPolicy) { synchronized (getLockObject()) { diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java index a54f263c32ae..a5b676012ea9 100644 --- a/services/usage/java/com/android/server/usage/UsageStatsService.java +++ b/services/usage/java/com/android/server/usage/UsageStatsService.java @@ -339,7 +339,6 @@ public class UsageStatsService extends SystemService implements if (userId == UserHandle.USER_SYSTEM) { UsageStatsIdleService.scheduleUpdateMappingsJob(getContext()); } - final boolean deleteObsoleteData = shouldDeleteObsoleteData(UserHandle.of(userId)); synchronized (mLock) { // Create a user unlocked event to report final Event unlockEvent = new Event(USER_UNLOCKED, SystemClock.elapsedRealtime()); @@ -357,7 +356,7 @@ public class UsageStatsService extends SystemService implements boolean needToFlush = !pendingEvents.isEmpty(); initializeUserUsageStatsServiceLocked(userId, System.currentTimeMillis(), - installedPackages, deleteObsoleteData); + installedPackages); mUserUnlockedStates.put(userId, true); final UserUsageStatsService userService = getUserUsageStatsServiceLocked(userId); if (userService == null) { @@ -552,13 +551,13 @@ public class UsageStatsService extends SystemService implements * when the user is initially unlocked. */ private void initializeUserUsageStatsServiceLocked(int userId, long currentTimeMillis, - HashMap installedPackages, boolean deleteObsoleteData) { + HashMap installedPackages) { final File usageStatsDir = new File(Environment.getDataSystemCeDirectory(userId), "usagestats"); final UserUsageStatsService service = new UserUsageStatsService(getContext(), userId, usageStatsDir, this); try { - service.init(currentTimeMillis, installedPackages, deleteObsoleteData); + service.init(currentTimeMillis, installedPackages); mUserState.put(userId, service); } catch (Exception e) { if (mUserManager.isUserUnlocked(userId)) { @@ -1030,10 +1029,6 @@ 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 installedPkgs = getInstalledPackages(UserHandle.USER_SYSTEM); synchronized (mLock) { @@ -1159,13 +1154,6 @@ 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); @@ -2336,12 +2324,8 @@ public class UsageStatsService extends SystemService implements private class MyPackageMonitor extends PackageMonitor { @Override public void onPackageRemoved(String packageName, int uid) { - 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(); - } + mHandler.obtainMessage(MSG_PACKAGE_REMOVED, getChangingUserId(), 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 0a5adc8e61d4..26de11af6f4e 100644 --- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java +++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java @@ -115,9 +115,8 @@ class UserUsageStatsService { mSystemTimeSnapshot = System.currentTimeMillis(); } - void init(final long currentTimeMillis, HashMap installedPackages, - boolean deleteObsoleteData) { - readPackageMappingsLocked(installedPackages, deleteObsoleteData); + void init(final long currentTimeMillis, HashMap installedPackages) { + readPackageMappingsLocked(installedPackages); mDatabase.init(currentTimeMillis); if (mDatabase.wasUpgradePerformed()) { mDatabase.prunePackagesDataOnUpgrade(installedPackages); @@ -181,13 +180,12 @@ class UserUsageStatsService { return mDatabase.onPackageRemoved(packageName, timeRemoved); } - private void readPackageMappingsLocked(HashMap installedPackages, - boolean deleteObsoleteData) { + private void readPackageMappingsLocked(HashMap installedPackages) { 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 && deleteObsoleteData) { + if (mUserId != UserHandle.USER_SYSTEM) { updatePackageMappingsLocked(installedPackages); } } -- cgit v1.2.3 From 285732a9aee7988eec14b4cee6884785374c8066 Mon Sep 17 00:00:00 2001 From: Yimin Li Date: Thu, 16 Dec 2021 05:38:38 +0000 Subject: resolve Coastguard cherrypick merge conflict for change: 16485739 Change-Id: If398ac883f366463f674042cfce6e344a84d0c87 (cherry picked from commit d4b490a8d6e15f8573b879d896a9959df1c53b4b) Merged-In:If398ac883f366463f674042cfce6e344a84d0c87 --- .../app/admin/DevicePolicyManagerInternal.java | 8 +++++++ .../devicepolicy/DevicePolicyManagerService.java | 7 ++++++ .../android/server/usage/UsageStatsService.java | 26 +++++++++++++++++----- .../server/usage/UserUsageStatsService.java | 10 +++++---- 4 files changed, 42 insertions(+), 9 deletions(-) diff --git a/core/java/android/app/admin/DevicePolicyManagerInternal.java b/core/java/android/app/admin/DevicePolicyManagerInternal.java index d24694faff93..60cb563cca3d 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; @@ -76,6 +77,13 @@ public abstract class DevicePolicyManagerInternal { public abstract void addOnCrossProfileWidgetProvidersChangeListener( 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 admin of its user and has the policy * specified. diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index ae354a953eec..2550f0282c4f 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -12481,6 +12481,13 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } } + @Override + public @Nullable ComponentName getProfileOwnerOrDeviceOwnerSupervisionComponent( + @NonNull UserHandle userHandle) { + return DevicePolicyManagerService.this.getProfileOwnerOrDeviceOwnerSupervisionComponent( + userHandle); + } + @Override public boolean isActiveAdminWithPolicy(int uid, int reqPolicy) { synchronized (getLockObject()) { diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java index a5b676012ea9..a54f263c32ae 100644 --- a/services/usage/java/com/android/server/usage/UsageStatsService.java +++ b/services/usage/java/com/android/server/usage/UsageStatsService.java @@ -339,6 +339,7 @@ public class UsageStatsService extends SystemService implements if (userId == UserHandle.USER_SYSTEM) { UsageStatsIdleService.scheduleUpdateMappingsJob(getContext()); } + final boolean deleteObsoleteData = shouldDeleteObsoleteData(UserHandle.of(userId)); synchronized (mLock) { // Create a user unlocked event to report final Event unlockEvent = new Event(USER_UNLOCKED, SystemClock.elapsedRealtime()); @@ -356,7 +357,7 @@ public class UsageStatsService extends SystemService implements boolean needToFlush = !pendingEvents.isEmpty(); initializeUserUsageStatsServiceLocked(userId, System.currentTimeMillis(), - installedPackages); + installedPackages, deleteObsoleteData); mUserUnlockedStates.put(userId, true); final UserUsageStatsService userService = getUserUsageStatsServiceLocked(userId); if (userService == null) { @@ -551,13 +552,13 @@ public class UsageStatsService extends SystemService implements * when the user is initially unlocked. */ private void initializeUserUsageStatsServiceLocked(int userId, long currentTimeMillis, - HashMap installedPackages) { + HashMap 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)) { @@ -1029,6 +1030,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 installedPkgs = getInstalledPackages(UserHandle.USER_SYSTEM); synchronized (mLock) { @@ -1154,6 +1159,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); @@ -2324,8 +2336,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 26de11af6f4e..0a5adc8e61d4 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 installedPackages) { - readPackageMappingsLocked(installedPackages); + void init(final long currentTimeMillis, HashMap 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 installedPackages) { + private void readPackageMappingsLocked(HashMap 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); } } -- cgit v1.2.3 From 1add3fc7c4bd9e04bac9865b796b29157c477e22 Mon Sep 17 00:00:00 2001 From: Dave Mankoff Date: Mon, 15 Nov 2021 19:21:44 +0000 Subject: RESTRICT AUTOMERGE Remove line of code that was mistakently left in. This line was removed in O, S, & P, but somehow survived in the Q and R branches. Bug: 193444889 Change-Id: I56589865427b10e2eab68e1ed2e7c290572a9edc (cherry picked from commit daba01ddf8686ef0299bac01c6d39ea78029d942) Merged-In:I56589865427b10e2eab68e1ed2e7c290572a9edc --- .../src/com/android/systemui/shared/plugins/PluginManagerImpl.java | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManagerImpl.java b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManagerImpl.java index a687bb89fd75..5c742f25209e 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManagerImpl.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManagerImpl.java @@ -201,7 +201,6 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage filter.addAction(DISABLE_PLUGIN); filter.addDataScheme("package"); mContext.registerReceiver(this, filter, PluginInstanceManager.PLUGIN_PERMISSION, null); - mContext.registerReceiver(this, filter); filter = new IntentFilter(Intent.ACTION_USER_UNLOCKED); mContext.registerReceiver(this, filter); } -- cgit v1.2.3 From 03021ef050c2e8afc1892109b8c1b884b6df4ee2 Mon Sep 17 00:00:00 2001 From: Wu Ahan Date: Thu, 2 Dec 2021 08:23:26 +0000 Subject: DO NOT MERGE: Decode the input of both setStream and setResource calls first The size of the input of both setStream and setResource may very big that system server got oom while handling it, so we try to decode it first before copying it to the wallpaper path, if the decoding fails, we treat the input as an invalid input. Bug: 204087139 Test: Manually set wallpaper, no PDoS observed. Change-Id: I014cf461954992782b3dfa0dde67c98a572cc770 (cherry picked from commit fa9c73975e1d2b5bf6335e1e387130890d787b15) Merged-In:I014cf461954992782b3dfa0dde67c98a572cc770 --- core/java/android/app/WallpaperManager.java | 40 +++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java index c5d343d168ca..6d4489e99e6f 100644 --- a/core/java/android/app/WallpaperManager.java +++ b/core/java/android/app/WallpaperManager.java @@ -1275,18 +1275,27 @@ public class WallpaperManager { mContext.getUserId()); if (fd != null) { FileOutputStream fos = null; - boolean ok = false; + final Bitmap tmp = BitmapFactory.decodeStream(resources.openRawResource(resid)); try { - fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd); - copyStreamToWallpaperFile(resources.openRawResource(resid), fos); - // The 'close()' is the trigger for any server-side image manipulation, - // so we must do that before waiting for completion. - fos.close(); - completion.waitForCompletion(); + // If the stream can't be decoded, treat it as an invalid input. + if (tmp != null) { + fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd); + tmp.compress(Bitmap.CompressFormat.PNG, 100, fos); + // The 'close()' is the trigger for any server-side image manipulation, + // so we must do that before waiting for completion. + fos.close(); + completion.waitForCompletion(); + } else { + throw new IllegalArgumentException( + "Resource 0x" + Integer.toHexString(resid) + " is invalid"); + } } finally { // Might be redundant but completion shouldn't wait unless the write // succeeded; this is a fallback if it threw past the close+wait. IoUtils.closeQuietly(fos); + if (tmp != null) { + tmp.recycle(); + } } } } catch (RemoteException e) { @@ -1528,13 +1537,22 @@ public class WallpaperManager { result, which, completion, mContext.getUserId()); if (fd != null) { FileOutputStream fos = null; + final Bitmap tmp = BitmapFactory.decodeStream(bitmapData); try { - fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd); - copyStreamToWallpaperFile(bitmapData, fos); - fos.close(); - completion.waitForCompletion(); + // If the stream can't be decoded, treat it as an invalid input. + if (tmp != null) { + fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd); + tmp.compress(Bitmap.CompressFormat.PNG, 100, fos); + fos.close(); + completion.waitForCompletion(); + } else { + throw new IllegalArgumentException("InputStream is invalid"); + } } finally { IoUtils.closeQuietly(fos); + if (tmp != null) { + tmp.recycle(); + } } } } catch (RemoteException e) { -- cgit v1.2.3 From d20633ffbc80e5a9ea5b3b965d1c6040fc45919a Mon Sep 17 00:00:00 2001 From: Matt Pietal Date: Mon, 4 Oct 2021 15:33:14 -0400 Subject: [DO NOT MERGE] Controls - Do not recreate intent Recreating the control's intent in SystemUI can be exploited to launch Intent's with SystemUI's privileges, rather than what is limited to the application. Use the fillInIntent parameter to supply additional parameters to the application. Bug: 193445603 Test: Follow directions in bug to retest Change-Id: Ib2b0342af85679c0514fb4d88530376b58e6e12a Merged-In: (cherry picked from commit 0e120a5d4f8998e343f3c8106081037017613082) (cherry picked from commit d7b16dd2a56035b2feec9f39d6d461fd551317eb) Merged-In:Ib2b0342af85679c0514fb4d88530376b58e6e12a --- .../controls/ui/ControlActionCoordinatorImpl.kt | 13 ++-- .../android/systemui/controls/ui/DetailDialog.kt | 32 ++++++---- .../systemui/controls/ui/DetailDialogTest.kt | 74 ++++++++++++++++++++++ 3 files changed, 102 insertions(+), 17 deletions(-) create mode 100644 packages/SystemUI/tests/src/com/android/systemui/controls/ui/DetailDialogTest.kt diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt index e15380b42a78..f6b420ba57f3 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt @@ -17,6 +17,7 @@ package com.android.systemui.controls.ui import android.app.Dialog +import android.app.PendingIntent import android.content.Context import android.content.Intent import android.content.pm.PackageManager @@ -74,7 +75,7 @@ class ControlActionCoordinatorImpl @Inject constructor( bouncerOrRun(Action(cvh.cws.ci.controlId, { cvh.layout.performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK) if (cvh.usePanel()) { - showDialog(cvh, control.getAppIntent().getIntent()) + showDetail(cvh, control.getAppIntent()) } else { cvh.action(CommandAction(templateId)) } @@ -100,7 +101,7 @@ class ControlActionCoordinatorImpl @Inject constructor( // Long press snould only be called when there is valid control state, otherwise ignore cvh.cws.control?.let { cvh.layout.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS) - showDialog(cvh, it.getAppIntent().getIntent()) + showDetail(cvh, it.getAppIntent()) } }, false /* blockable */)) } @@ -155,17 +156,17 @@ class ControlActionCoordinatorImpl @Inject constructor( bgExecutor.execute { vibrator.vibrate(effect) } } - private fun showDialog(cvh: ControlViewHolder, intent: Intent) { + private fun showDetail(cvh: ControlViewHolder, pendingIntent: PendingIntent) { bgExecutor.execute { - val activities: List = cvh.context.packageManager.queryIntentActivities( - intent, + val activities: List = context.packageManager.queryIntentActivities( + pendingIntent.getIntent(), PackageManager.MATCH_DEFAULT_ONLY ) uiExecutor.execute { // make sure the intent is valid before attempting to open the dialog if (activities.isNotEmpty()) { - dialog = DetailDialog(cvh, intent).also { + dialog = DetailDialog(cvh, pendingIntent).also { it.setOnDismissListener { _ -> dialog = null } it.show() } diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt index 9ec14523a809..a7f7eb7ffb44 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt @@ -16,8 +16,11 @@ package com.android.systemui.controls.ui +import android.app.ActivityOptions import android.app.ActivityView +import android.app.PendingIntent import android.app.Dialog +import android.content.ComponentName import android.content.Intent import android.provider.Settings import android.view.View @@ -37,9 +40,8 @@ import com.android.systemui.R */ class DetailDialog( val cvh: ControlViewHolder, - val intent: Intent + val pendingIntent: PendingIntent ) : Dialog(cvh.context, R.style.Theme_SystemUI_Dialog_Control_DetailPanel) { - companion object { private const val PANEL_TOP_OFFSET = "systemui.controls_panel_top_offset" /* @@ -49,18 +51,19 @@ class DetailDialog( private const val EXTRA_USE_PANEL = "controls.DISPLAY_IN_PANEL" } + private val fillInIntent = Intent().apply { + putExtra(EXTRA_USE_PANEL, true) + + // Apply flags to make behaviour match documentLaunchMode=always. + addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT) + addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK) + } + var activityView = ActivityView(context, null, 0, false) val stateCallback: ActivityView.StateCallback = object : ActivityView.StateCallback() { override fun onActivityViewReady(view: ActivityView) { - val launchIntent = Intent(intent) - launchIntent.putExtra(EXTRA_USE_PANEL, true) - - // Apply flags to make behaviour match documentLaunchMode=always. - launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT) - launchIntent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK) - - view.startActivity(launchIntent) + view.startActivity(pendingIntent, fillInIntent, ActivityOptions.makeBasic()) } override fun onActivityViewDestroyed(view: ActivityView) {} @@ -68,6 +71,12 @@ class DetailDialog( override fun onTaskRemovalStarted(taskId: Int) { dismiss() } + + override fun onTaskCreated(taskId: Int, name: ComponentName?) { + requireViewById(R.id.controls_activity_view).apply { + setAlpha(1f) + } + } } init { @@ -76,6 +85,7 @@ class DetailDialog( requireViewById(R.id.controls_activity_view).apply { addView(activityView) + setAlpha(0f) } requireViewById(R.id.control_detail_close).apply { @@ -86,7 +96,7 @@ class DetailDialog( setOnClickListener { v: View -> dismiss() context.sendBroadcast(Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)) - v.context.startActivity(intent) + pendingIntent.send() } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/DetailDialogTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/DetailDialogTest.kt new file mode 100644 index 000000000000..0ad03d2b41b3 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/DetailDialogTest.kt @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.controls.ui + +import android.app.ActivityView +import android.app.PendingIntent +import android.testing.AndroidTestingRunner +import android.testing.TestableLooper +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.util.mockito.capture +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.ArgumentCaptor +import org.mockito.ArgumentMatchers.eq +import org.mockito.Captor +import org.mockito.Mock +import org.mockito.Mockito.any +import org.mockito.Mockito.verify +import org.mockito.MockitoAnnotations + +@SmallTest +@RunWith(AndroidTestingRunner::class) +@TestableLooper.RunWithLooper +class DetailDialogTest : SysuiTestCase() { + + @Mock + private lateinit var activityView: ActivityView + @Mock + private lateinit var controlViewHolder: ControlViewHolder + @Mock + private lateinit var pendingIntent: PendingIntent + @Captor + private lateinit var viewCaptor: ArgumentCaptor + + @Before + fun setUp() { + MockitoAnnotations.initMocks(this) + } + + @Test + fun testPendingIntentIsUnModified() { + // GIVEN the dialog is created with a PendingIntent + val dialog = createDialog(pendingIntent) + + // WHEN the ActivityView is initialized + dialog.stateCallback.onActivityViewReady(capture(viewCaptor)) + + // THEN the PendingIntent used to call startActivity is unmodified by systemui + verify(viewCaptor.value).startActivity(eq(pendingIntent), any(), any()) + } + + private fun createDialog(pendingIntent: PendingIntent): DetailDialog { + return DetailDialog( + controlViewHolder, + pendingIntent + ) + } +} -- cgit v1.2.3 From b41445ccfead9a9d6e5f036127db5aedf479217f Mon Sep 17 00:00:00 2001 From: Hai Zhang Date: Wed, 30 Dec 2020 18:30:25 -0800 Subject: DO NOT MERGE Re-implement reading/writing Throwables from/to Parcel, without Parcel private APIs. Bug:197228210 Test: atest CtsSecurityTestCases:android.security.cts.AndroidFutureTest (cherry picked from I577da5a3bc4ed537123b7eceaa5addf8f7bb0d92 and Icc5ce702f0cd84e9136dee3c65f63619df697358) Change-Id: I1d488c475f2f7af835a67496535cecdd6987c0cf (cherry picked from commit 562f1bd91f2845788ab907d687de6800ee49c6f8) Merged-In:I1d488c475f2f7af835a67496535cecdd6987c0cf --- .../com/android/internal/infra/AndroidFuture.java | 116 ++++++++++++++------- .../android/internal/infra/ServiceConnector.java | 28 ++--- 2 files changed, 86 insertions(+), 58 deletions(-) diff --git a/core/java/com/android/internal/infra/AndroidFuture.java b/core/java/com/android/internal/infra/AndroidFuture.java index 9f15d8991fa7..84391c169941 100644 --- a/core/java/com/android/internal/infra/AndroidFuture.java +++ b/core/java/com/android/internal/infra/AndroidFuture.java @@ -16,23 +16,21 @@ package com.android.internal.infra; -import static com.android.internal.util.ConcurrentUtils.DIRECT_EXECUTOR; - import android.annotation.CallSuper; import android.annotation.NonNull; import android.annotation.Nullable; import android.os.Handler; -import android.os.Message; +import android.os.Looper; import android.os.Parcel; import android.os.Parcelable; import android.os.RemoteException; -import android.util.ExceptionUtils; +import android.util.EventLog; import android.util.Log; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.Preconditions; -import com.android.internal.util.function.pooled.PooledLambda; +import java.lang.reflect.Constructor; import java.util.concurrent.CancellationException; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; @@ -75,14 +73,16 @@ public class AndroidFuture extends CompletableFuture implements Parcelable private static final boolean DEBUG = false; private static final String LOG_TAG = AndroidFuture.class.getSimpleName(); + private static final Executor DIRECT_EXECUTOR = Runnable::run; private static final StackTraceElement[] EMPTY_STACK_TRACE = new StackTraceElement[0]; + private static @Nullable Handler sMainHandler; private final @NonNull Object mLock = new Object(); @GuardedBy("mLock") private @Nullable BiConsumer mListener; @GuardedBy("mLock") private @Nullable Executor mListenerExecutor = DIRECT_EXECUTOR; - private @NonNull Handler mTimeoutHandler = Handler.getMain(); + private @NonNull Handler mTimeoutHandler = getMainHandler(); private final @Nullable IAndroidFuture mRemoteOrigin; public AndroidFuture() { @@ -96,7 +96,7 @@ public class AndroidFuture extends CompletableFuture implements Parcelable // Done if (in.readBoolean()) { // Failed - completeExceptionally(unparcelException(in)); + completeExceptionally(readThrowable(in)); } else { // Success complete((T) in.readValue(null)); @@ -108,6 +108,15 @@ public class AndroidFuture extends CompletableFuture implements Parcelable } } + @NonNull + private static Handler getMainHandler() { + // This isn't thread-safe but we are okay with it. + if (sMainHandler == null) { + sMainHandler = new Handler(Looper.getMainLooper()); + } + return sMainHandler; + } + /** * Create a completed future with the given value. * @@ -236,9 +245,7 @@ public class AndroidFuture extends CompletableFuture implements Parcelable if (mListenerExecutor == DIRECT_EXECUTOR) { callListener(listener, res, err); } else { - mListenerExecutor.execute(PooledLambda - .obtainRunnable(AndroidFuture::callListener, listener, res, err) - .recycleOnUse()); + mListenerExecutor.execute(() -> callListener(listener, res, err)); } } @@ -260,7 +267,8 @@ public class AndroidFuture extends CompletableFuture implements Parcelable } else { // listener exception-case threw // give up on listener but preserve the original exception when throwing up - throw ExceptionUtils.appendCause(t, err); + t.addSuppressed(err); + throw t; } } } catch (Throwable t2) { @@ -272,9 +280,7 @@ public class AndroidFuture extends CompletableFuture implements Parcelable /** @inheritDoc */ //@Override //TODO uncomment once java 9 APIs are exposed to frameworks public AndroidFuture orTimeout(long timeout, @NonNull TimeUnit unit) { - Message msg = PooledLambda.obtainMessage(AndroidFuture::triggerTimeout, this); - msg.obj = this; - mTimeoutHandler.sendMessageDelayed(msg, unit.toMillis(timeout)); + mTimeoutHandler.postDelayed(this::triggerTimeout, this, unit.toMillis(timeout)); return this; } @@ -507,7 +513,7 @@ public class AndroidFuture extends CompletableFuture implements Parcelable result = get(); } catch (Throwable t) { dest.writeBoolean(true); - parcelException(dest, unwrapExecutionException(t)); + writeThrowable(dest, unwrapExecutionException(t)); return; } dest.writeBoolean(false); @@ -545,45 +551,75 @@ public class AndroidFuture extends CompletableFuture implements Parcelable * Alternative to {@link Parcel#writeException} that stores the stack trace, in a * way consistent with the binder IPC exception propagation behavior. */ - private static void parcelException(Parcel p, @Nullable Throwable t) { - p.writeBoolean(t == null); - if (t == null) { + private static void writeThrowable(@NonNull Parcel parcel, @Nullable Throwable throwable) { + boolean hasThrowable = throwable != null; + parcel.writeBoolean(hasThrowable); + if (!hasThrowable) { + return; + } + + boolean isFrameworkParcelable = throwable instanceof Parcelable + && throwable.getClass().getClassLoader() == Parcelable.class.getClassLoader(); + parcel.writeBoolean(isFrameworkParcelable); + if (isFrameworkParcelable) { + parcel.writeParcelable((Parcelable) throwable, + Parcelable.PARCELABLE_WRITE_RETURN_VALUE); return; } - p.writeInt(Parcel.getExceptionCode(t)); - p.writeString(t.getClass().getName()); - p.writeString(t.getMessage()); - p.writeStackTrace(t); - parcelException(p, t.getCause()); + parcel.writeString(throwable.getClass().getName()); + parcel.writeString(throwable.getMessage()); + StackTraceElement[] stackTrace = throwable.getStackTrace(); + StringBuilder stackTraceBuilder = new StringBuilder(); + int truncatedStackTraceLength = Math.min(stackTrace != null ? stackTrace.length : 0, 5); + for (int i = 0; i < truncatedStackTraceLength; i++) { + if (i > 0) { + stackTraceBuilder.append('\n'); + } + stackTraceBuilder.append("\tat ").append(stackTrace[i]); + } + parcel.writeString(stackTraceBuilder.toString()); + writeThrowable(parcel, throwable.getCause()); } /** - * @see #parcelException + * @see #writeThrowable */ - private static @Nullable Throwable unparcelException(Parcel p) { - if (p.readBoolean()) { + private static @Nullable Throwable readThrowable(@NonNull Parcel parcel) { + final boolean hasThrowable = parcel.readBoolean(); + if (!hasThrowable) { return null; } - int exCode = p.readInt(); - String cls = p.readString(); - String msg = p.readString(); - String stackTrace = p.readInt() > 0 ? p.readString() : "\t"; - msg += "\n" + stackTrace; - - Exception ex = p.createExceptionOrNull(exCode, msg); - if (ex == null) { - ex = new RuntimeException(cls + ": " + msg); + boolean isFrameworkParcelable = parcel.readBoolean(); + if (isFrameworkParcelable) { + return parcel.readParcelable(Parcelable.class.getClassLoader()); } - ex.setStackTrace(EMPTY_STACK_TRACE); - Throwable cause = unparcelException(p); + String className = parcel.readString(); + String message = parcel.readString(); + String stackTrace = parcel.readString(); + String messageWithStackTrace = message + '\n' + stackTrace; + Throwable throwable; + try { + Class clazz = Class.forName(className, true, Parcelable.class.getClassLoader()); + if (Throwable.class.isAssignableFrom(clazz)) { + Constructor constructor = clazz.getConstructor(String.class); + throwable = (Throwable) constructor.newInstance(messageWithStackTrace); + } else { + android.util.EventLog.writeEvent(0x534e4554, "186530450", -1, ""); + throwable = new RuntimeException(className + ": " + messageWithStackTrace); + } + } catch (Throwable t) { + throwable = new RuntimeException(className + ": " + messageWithStackTrace); + throwable.addSuppressed(t); + } + throwable.setStackTrace(EMPTY_STACK_TRACE); + Throwable cause = readThrowable(parcel); if (cause != null) { - ex.initCause(ex); + throwable.initCause(cause); } - - return ex; + return throwable; } @Override diff --git a/core/java/com/android/internal/infra/ServiceConnector.java b/core/java/com/android/internal/infra/ServiceConnector.java index 167d128a76f8..89869389cb59 100644 --- a/core/java/com/android/internal/infra/ServiceConnector.java +++ b/core/java/com/android/internal/infra/ServiceConnector.java @@ -26,14 +26,11 @@ import android.content.ServiceConnection; import android.os.Handler; import android.os.IBinder; import android.os.IInterface; +import android.os.Looper; import android.os.RemoteException; import android.os.UserHandle; -import android.text.TextUtils; -import android.util.DebugUtils; import android.util.Log; -import com.android.internal.util.function.pooled.PooledLambda; - import java.io.PrintWriter; import java.util.ArrayDeque; import java.util.ArrayList; @@ -47,7 +44,6 @@ import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; import java.util.function.Function; - /** * Takes care of managing a {@link ServiceConnection} and auto-disconnecting from the service upon * a certain timeout. @@ -220,6 +216,7 @@ public interface ServiceConnector { private final @NonNull Queue> mQueue = this; private final @NonNull List> mUnfinishedJobs = new ArrayList<>(); + private final @NonNull Handler mMainHandler = new Handler(Looper.getMainLooper()); private final @NonNull ServiceConnection mServiceConnection = this; private final @NonNull Runnable mTimeoutDisconnect = this; @@ -250,9 +247,8 @@ public interface ServiceConnector { * {@link IInterface}. * Typically this is {@code IMyInterface.Stub::asInterface} */ - public Impl(@NonNull Context context, @NonNull Intent intent, - @Context.BindServiceFlags int bindingFlags, @UserIdInt int userId, - @Nullable Function binderAsInterface) { + public Impl(@NonNull Context context, @NonNull Intent intent, int bindingFlags, + @UserIdInt int userId, @Nullable Function binderAsInterface) { mContext = context; mIntent = intent; mBindingFlags = bindingFlags; @@ -264,7 +260,7 @@ public interface ServiceConnector { * {@link Handler} on which {@link Job}s will be called */ protected Handler getJobHandler() { - return Handler.getMain(); + return mMainHandler; } /** @@ -391,8 +387,7 @@ public interface ServiceConnector { private boolean enqueue(@NonNull Job job) { cancelTimeout(); - return getJobHandler().sendMessage(PooledLambda.obtainMessage( - ServiceConnector.Impl::enqueueJobThread, this, job)); + return getJobHandler().post(() -> enqueueJobThread(job)); } void enqueueJobThread(@NonNull Job job) { @@ -422,7 +417,7 @@ public interface ServiceConnector { if (DEBUG) { logTrace(); } - Handler.getMain().removeCallbacks(mTimeoutDisconnect); + mMainHandler.removeCallbacks(mTimeoutDisconnect); } void completeExceptionally(@NonNull Job job, @NonNull Throwable ex) { @@ -486,7 +481,7 @@ public interface ServiceConnector { } long timeout = getAutoDisconnectTimeoutMs(); if (timeout > 0) { - Handler.getMain().postDelayed(mTimeoutDisconnect, timeout); + mMainHandler.postDelayed(mTimeoutDisconnect, timeout); } else if (DEBUG) { Log.i(LOG_TAG, "Not scheduling unbind for permanently bound " + this); } @@ -502,7 +497,7 @@ public interface ServiceConnector { logTrace(); } mUnbinding = true; - getJobHandler().sendMessage(PooledLambda.obtainMessage(Impl::unbindJobThread, this)); + getJobHandler().post(this::unbindJobThread); } void unbindJobThread() { @@ -659,10 +654,7 @@ public interface ServiceConnector { } private void logTrace() { - Log.i(LOG_TAG, - TextUtils.join(" -> ", - DebugUtils.callersWithin(ServiceConnector.class, /* offset= */ 1)) - + "(" + this + ")"); + Log.i(LOG_TAG, "See stacktrace", new Throwable()); } /** -- cgit v1.2.3 From 1093b03044fd8dd3a1f5a631b557bd9fe816b7d0 Mon Sep 17 00:00:00 2001 From: Tomasz Wasilczyk Date: Tue, 26 Jan 2021 08:46:31 -0800 Subject: Don't crash if default supervision profile owner is not set Bug: 175430552 Bug: 197399948 Test: build, flash, watch logcat Change-Id: If441946fa278c04ae88122f6243f5a7dedd96ebc Merged-In: If441946fa278c04ae88122f6243f5a7dedd96ebc (cherry picked from commit bd27c365915f824824d865668c63a2119c4700fb) (cherry picked from commit bcb5ee6f43ea24fb74649f164ca3c3032a7be3b5) (cherry picked from commit b5fa0a6c5e96c420c1f6d808be603c4579f9a1ba) Merged-In:If441946fa278c04ae88122f6243f5a7dedd96ebc --- .../com/android/server/devicepolicy/DevicePolicyManagerService.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 2550f0282c4f..27d07abfc255 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -9396,6 +9396,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { final ComponentName doComponent = mOwners.getDeviceOwnerComponent(); final ComponentName poComponent = mOwners.getProfileOwnerComponent(userHandle.getIdentifier()); + if (supervisorComponent == null) { + return null; + } if (supervisorComponent.equals(doComponent) || supervisorComponent.equals( poComponent)) { return supervisorComponent; -- cgit v1.2.3 From 398b752a440f7d60198f9267334445aba4f9d4eb Mon Sep 17 00:00:00 2001 From: Joshua Duong Date: Wed, 22 Dec 2021 14:49:21 -0800 Subject: Restrict AdbManager broadcasts to apps with MANAGE_DEBUGGING permission. Bug: 205836329 Test: atest AdbDebuggingManagerTest Change-Id: If18a874c6d6232d9131f2cc3de3614ef67a58bbd (cherry picked from commit b139e9966102ba6fa1a4801214ea92e8afe376a6) --- core/java/android/debug/AdbManager.java | 3 + .../android/server/adb/AdbDebuggingManager.java | 21 ++-- .../java/com/android/server/adb/AdbService.java | 2 +- .../server/adb/AdbDebuggingManagerTest.java | 110 +++++++++++++++++++++ 4 files changed, 129 insertions(+), 7 deletions(-) diff --git a/core/java/android/debug/AdbManager.java b/core/java/android/debug/AdbManager.java index 7714dd80f910..243f80187185 100644 --- a/core/java/android/debug/AdbManager.java +++ b/core/java/android/debug/AdbManager.java @@ -38,6 +38,7 @@ public class AdbManager { * * @hide */ + @RequiresPermission(android.Manifest.permission.MANAGE_DEBUGGING) public static final String WIRELESS_DEBUG_STATE_CHANGED_ACTION = "com.android.server.adb.WIRELESS_DEBUG_STATUS"; @@ -46,6 +47,7 @@ public class AdbManager { * * @hide */ + @RequiresPermission(android.Manifest.permission.MANAGE_DEBUGGING) public static final String WIRELESS_DEBUG_PAIRED_DEVICES_ACTION = "com.android.server.adb.WIRELESS_DEBUG_PAIRED_DEVICES"; @@ -59,6 +61,7 @@ public class AdbManager { * * @hide */ + @RequiresPermission(android.Manifest.permission.MANAGE_DEBUGGING) public static final String WIRELESS_DEBUG_PAIRING_RESULT_ACTION = "com.android.server.adb.WIRELESS_DEBUG_PAIRING_RESULT"; diff --git a/services/core/java/com/android/server/adb/AdbDebuggingManager.java b/services/core/java/com/android/server/adb/AdbDebuggingManager.java index ed83a644cbfb..95da946496e8 100644 --- a/services/core/java/com/android/server/adb/AdbDebuggingManager.java +++ b/services/core/java/com/android/server/adb/AdbDebuggingManager.java @@ -18,6 +18,7 @@ package com.android.server.adb; import static com.android.internal.util.dump.DumpUtils.writeStringIfNotNull; +import android.annotation.NonNull; import android.annotation.TestApi; import android.app.ActivityManager; import android.app.Notification; @@ -171,6 +172,12 @@ public class AdbDebuggingManager { mAdbConnectionInfo = new AdbConnectionInfo(); } + static void sendBroadcastWithDebugPermission(@NonNull Context context, @NonNull Intent intent, + @NonNull UserHandle userHandle) { + context.sendBroadcastAsUser(intent, userHandle, + android.Manifest.permission.MANAGE_DEBUGGING); + } + class PairingThread extends Thread implements NsdManager.RegistrationListener { private NsdManager mNsdManager; private String mPublicKey; @@ -1279,7 +1286,7 @@ public class AdbDebuggingManager { ? AdbManager.WIRELESS_STATUS_CONNECTED : AdbManager.WIRELESS_STATUS_DISCONNECTED); intent.putExtra(AdbManager.WIRELESS_DEBUG_PORT_EXTRA, port); - mContext.sendBroadcastAsUser(intent, UserHandle.ALL); + AdbDebuggingManager.sendBroadcastWithDebugPermission(mContext, intent, UserHandle.ALL); } private void onAdbdWifiServerConnected(int port) { @@ -1351,7 +1358,8 @@ public class AdbDebuggingManager { if (publicKey == null) { Intent intent = new Intent(AdbManager.WIRELESS_DEBUG_PAIRING_RESULT_ACTION); intent.putExtra(AdbManager.WIRELESS_STATUS_EXTRA, AdbManager.WIRELESS_STATUS_FAIL); - mContext.sendBroadcastAsUser(intent, UserHandle.ALL); + AdbDebuggingManager.sendBroadcastWithDebugPermission(mContext, intent, + UserHandle.ALL); } else { Intent intent = new Intent(AdbManager.WIRELESS_DEBUG_PAIRING_RESULT_ACTION); intent.putExtra(AdbManager.WIRELESS_STATUS_EXTRA, @@ -1364,7 +1372,8 @@ public class AdbDebuggingManager { } PairDevice device = new PairDevice(fingerprints, hostname, false); intent.putExtra(AdbManager.WIRELESS_PAIR_DEVICE_EXTRA, device); - mContext.sendBroadcastAsUser(intent, UserHandle.ALL); + AdbDebuggingManager.sendBroadcastWithDebugPermission(mContext, intent, + UserHandle.ALL); // Add the key into the keystore mAdbKeyStore.setLastConnectionTime(publicKey, System.currentTimeMillis()); @@ -1378,14 +1387,14 @@ public class AdbDebuggingManager { intent.putExtra(AdbManager.WIRELESS_STATUS_EXTRA, AdbManager.WIRELESS_STATUS_CONNECTED); intent.putExtra(AdbManager.WIRELESS_DEBUG_PORT_EXTRA, port); - mContext.sendBroadcastAsUser(intent, UserHandle.ALL); + AdbDebuggingManager.sendBroadcastWithDebugPermission(mContext, intent, UserHandle.ALL); } private void sendPairedDevicesToUI(Map devices) { Intent intent = new Intent(AdbManager.WIRELESS_DEBUG_PAIRED_DEVICES_ACTION); // Map is not serializable, so need to downcast intent.putExtra(AdbManager.WIRELESS_DEVICES_EXTRA, (HashMap) devices); - mContext.sendBroadcastAsUser(intent, UserHandle.ALL); + AdbDebuggingManager.sendBroadcastWithDebugPermission(mContext, intent, UserHandle.ALL); } private void updateUIPairCode(String code) { @@ -1395,7 +1404,7 @@ public class AdbDebuggingManager { intent.putExtra(AdbManager.WIRELESS_PAIRING_CODE_EXTRA, code); intent.putExtra(AdbManager.WIRELESS_STATUS_EXTRA, AdbManager.WIRELESS_STATUS_PAIRING_CODE); - mContext.sendBroadcastAsUser(intent, UserHandle.ALL); + AdbDebuggingManager.sendBroadcastWithDebugPermission(mContext, intent, UserHandle.ALL); } } diff --git a/services/core/java/com/android/server/adb/AdbService.java b/services/core/java/com/android/server/adb/AdbService.java index 29bb5428dd84..5b16daa5e835 100644 --- a/services/core/java/com/android/server/adb/AdbService.java +++ b/services/core/java/com/android/server/adb/AdbService.java @@ -431,7 +431,7 @@ public class AdbService extends IAdbManager.Stub { ? AdbManager.WIRELESS_STATUS_CONNECTED : AdbManager.WIRELESS_STATUS_DISCONNECTED); intent.putExtra(AdbManager.WIRELESS_DEBUG_PORT_EXTRA, port); - mContext.sendBroadcastAsUser(intent, UserHandle.ALL); + AdbDebuggingManager.sendBroadcastWithDebugPermission(mContext, intent, UserHandle.ALL); Slog.i(TAG, "sent port broadcast port=" + port); } diff --git a/services/tests/servicestests/src/com/android/server/adb/AdbDebuggingManagerTest.java b/services/tests/servicestests/src/com/android/server/adb/AdbDebuggingManagerTest.java index cffff66b64f1..02cf971a8076 100644 --- a/services/tests/servicestests/src/com/android/server/adb/AdbDebuggingManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/adb/AdbDebuggingManagerTest.java @@ -23,7 +23,14 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import android.content.BroadcastReceiver; import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.pm.PackageManager; +import android.debug.AdbManager; +import android.debug.IAdbManager; +import android.os.ServiceManager; import android.provider.Settings; import android.util.Log; @@ -105,6 +112,7 @@ public final class AdbDebuggingManagerTest { public void tearDown() throws Exception { mKeyStore.deleteKeyStore(); setAllowedConnectionTime(mOriginalAllowedConnectionTime); + dropShellPermissionIdentity(); } /** @@ -813,6 +821,108 @@ public final class AdbDebuggingManagerTest { return hasAtLeastOneLetter; } + CountDownLatch mAdbActionLatch = new CountDownLatch(1); + private final BroadcastReceiver mReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + Log.i(TAG, "Received intent action=" + action); + if (AdbManager.WIRELESS_DEBUG_PAIRED_DEVICES_ACTION.equals(action)) { + assertEquals("Received broadcast without MANAGE_DEBUGGING permission.", + context.checkSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING), + PackageManager.PERMISSION_GRANTED); + Log.i(TAG, "action=" + action + " paired_device=" + intent.getSerializableExtra( + AdbManager.WIRELESS_DEVICES_EXTRA).toString()); + mAdbActionLatch.countDown(); + } else if (AdbManager.WIRELESS_DEBUG_STATE_CHANGED_ACTION.equals(action)) { + assertEquals("Received broadcast without MANAGE_DEBUGGING permission.", + context.checkSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING), + PackageManager.PERMISSION_GRANTED); + int status = intent.getIntExtra(AdbManager.WIRELESS_STATUS_EXTRA, + AdbManager.WIRELESS_STATUS_DISCONNECTED); + Log.i(TAG, "action=" + action + " status=" + status); + mAdbActionLatch.countDown(); + } else if (AdbManager.WIRELESS_DEBUG_PAIRING_RESULT_ACTION.equals(action)) { + assertEquals("Received broadcast without MANAGE_DEBUGGING permission.", + context.checkSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING), + PackageManager.PERMISSION_GRANTED); + Integer res = intent.getIntExtra( + AdbManager.WIRELESS_STATUS_EXTRA, + AdbManager.WIRELESS_STATUS_FAIL); + Log.i(TAG, "action=" + action + " result=" + res); + + if (res.equals(AdbManager.WIRELESS_STATUS_PAIRING_CODE)) { + String pairingCode = intent.getStringExtra( + AdbManager.WIRELESS_PAIRING_CODE_EXTRA); + Log.i(TAG, "pairingCode=" + pairingCode); + } else if (res.equals(AdbManager.WIRELESS_STATUS_CONNECTED)) { + int port = intent.getIntExtra(AdbManager.WIRELESS_DEBUG_PORT_EXTRA, 0); + Log.i(TAG, "port=" + port); + } + mAdbActionLatch.countDown(); + } + } + }; + + private void adoptShellPermissionIdentity() { + InstrumentationRegistry.getInstrumentation().getUiAutomation() + .adoptShellPermissionIdentity(android.Manifest.permission.MANAGE_DEBUGGING); + } + + private void dropShellPermissionIdentity() { + InstrumentationRegistry.getInstrumentation().getUiAutomation() + .dropShellPermissionIdentity(); + } + + @Test + public void testBroadcastReceiverWithPermissions() throws Exception { + adoptShellPermissionIdentity(); + final IAdbManager mAdbManager = IAdbManager.Stub.asInterface( + ServiceManager.getService(Context.ADB_SERVICE)); + IntentFilter intentFilter = + new IntentFilter(AdbManager.WIRELESS_DEBUG_PAIRED_DEVICES_ACTION); + intentFilter.addAction(AdbManager.WIRELESS_DEBUG_STATE_CHANGED_ACTION); + intentFilter.addAction(AdbManager.WIRELESS_DEBUG_PAIRING_RESULT_ACTION); + assertEquals("Context does not have MANAGE_DEBUGGING permission.", + mContext.checkSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING), + PackageManager.PERMISSION_GRANTED); + try { + mContext.registerReceiver(mReceiver, intentFilter); + mAdbManager.enablePairingByPairingCode(); + if (!mAdbActionLatch.await(TIMEOUT, TIMEOUT_TIME_UNIT)) { + fail("Receiver did not receive adb intent action within the timeout duration"); + } + } finally { + mContext.unregisterReceiver(mReceiver); + } + } + + @Test + public void testBroadcastReceiverWithoutPermissions() throws Exception { + adoptShellPermissionIdentity(); + final IAdbManager mAdbManager = IAdbManager.Stub.asInterface( + ServiceManager.getService(Context.ADB_SERVICE)); + IntentFilter intentFilter = + new IntentFilter(AdbManager.WIRELESS_DEBUG_PAIRED_DEVICES_ACTION); + intentFilter.addAction(AdbManager.WIRELESS_DEBUG_STATE_CHANGED_ACTION); + intentFilter.addAction(AdbManager.WIRELESS_DEBUG_PAIRING_RESULT_ACTION); + mAdbManager.enablePairingByPairingCode(); + + dropShellPermissionIdentity(); + assertEquals("Context has MANAGE_DEBUGGING permission.", + mContext.checkSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING), + PackageManager.PERMISSION_DENIED); + try { + mContext.registerReceiver(mReceiver, intentFilter); + + if (mAdbActionLatch.await(TIMEOUT, TIMEOUT_TIME_UNIT)) { + fail("Broadcast receiver received adb action intent without debug permissions"); + } + } finally { + mContext.unregisterReceiver(mReceiver); + } + } + /** * Runs an adb test with the provided configuration. * -- cgit v1.2.3 From dc7d96c9e50fb2cc38c1c53eb03b975f6de9d0e7 Mon Sep 17 00:00:00 2001 From: Joshua Duong Date: Wed, 22 Dec 2021 14:49:21 -0800 Subject: Restrict AdbManager broadcasts to apps with MANAGE_DEBUGGING permission. Bug: 205836329 Test: atest AdbDebuggingManagerTest Change-Id: If18a874c6d6232d9131f2cc3de3614ef67a58bbd (cherry picked from commit b139e9966102ba6fa1a4801214ea92e8afe376a6) --- core/java/android/debug/AdbManager.java | 3 + .../android/server/adb/AdbDebuggingManager.java | 21 ++-- .../java/com/android/server/adb/AdbService.java | 2 +- .../server/adb/AdbDebuggingManagerTest.java | 110 +++++++++++++++++++++ 4 files changed, 129 insertions(+), 7 deletions(-) diff --git a/core/java/android/debug/AdbManager.java b/core/java/android/debug/AdbManager.java index 7714dd80f910..243f80187185 100644 --- a/core/java/android/debug/AdbManager.java +++ b/core/java/android/debug/AdbManager.java @@ -38,6 +38,7 @@ public class AdbManager { * * @hide */ + @RequiresPermission(android.Manifest.permission.MANAGE_DEBUGGING) public static final String WIRELESS_DEBUG_STATE_CHANGED_ACTION = "com.android.server.adb.WIRELESS_DEBUG_STATUS"; @@ -46,6 +47,7 @@ public class AdbManager { * * @hide */ + @RequiresPermission(android.Manifest.permission.MANAGE_DEBUGGING) public static final String WIRELESS_DEBUG_PAIRED_DEVICES_ACTION = "com.android.server.adb.WIRELESS_DEBUG_PAIRED_DEVICES"; @@ -59,6 +61,7 @@ public class AdbManager { * * @hide */ + @RequiresPermission(android.Manifest.permission.MANAGE_DEBUGGING) public static final String WIRELESS_DEBUG_PAIRING_RESULT_ACTION = "com.android.server.adb.WIRELESS_DEBUG_PAIRING_RESULT"; diff --git a/services/core/java/com/android/server/adb/AdbDebuggingManager.java b/services/core/java/com/android/server/adb/AdbDebuggingManager.java index 1f35b88c8cbd..d91537c8afc6 100644 --- a/services/core/java/com/android/server/adb/AdbDebuggingManager.java +++ b/services/core/java/com/android/server/adb/AdbDebuggingManager.java @@ -18,6 +18,7 @@ package com.android.server.adb; import static com.android.internal.util.dump.DumpUtils.writeStringIfNotNull; +import android.annotation.NonNull; import android.annotation.TestApi; import android.app.ActivityManager; import android.app.Notification; @@ -170,6 +171,12 @@ public class AdbDebuggingManager { mAdbConnectionInfo = new AdbConnectionInfo(); } + static void sendBroadcastWithDebugPermission(@NonNull Context context, @NonNull Intent intent, + @NonNull UserHandle userHandle) { + context.sendBroadcastAsUser(intent, userHandle, + android.Manifest.permission.MANAGE_DEBUGGING); + } + class PairingThread extends Thread implements NsdManager.RegistrationListener { private NsdManager mNsdManager; private String mPublicKey; @@ -1278,7 +1285,7 @@ public class AdbDebuggingManager { ? AdbManager.WIRELESS_STATUS_CONNECTED : AdbManager.WIRELESS_STATUS_DISCONNECTED); intent.putExtra(AdbManager.WIRELESS_DEBUG_PORT_EXTRA, port); - mContext.sendBroadcastAsUser(intent, UserHandle.ALL); + AdbDebuggingManager.sendBroadcastWithDebugPermission(mContext, intent, UserHandle.ALL); } private void onAdbdWifiServerConnected(int port) { @@ -1350,7 +1357,8 @@ public class AdbDebuggingManager { if (publicKey == null) { Intent intent = new Intent(AdbManager.WIRELESS_DEBUG_PAIRING_RESULT_ACTION); intent.putExtra(AdbManager.WIRELESS_STATUS_EXTRA, AdbManager.WIRELESS_STATUS_FAIL); - mContext.sendBroadcastAsUser(intent, UserHandle.ALL); + AdbDebuggingManager.sendBroadcastWithDebugPermission(mContext, intent, + UserHandle.ALL); } else { Intent intent = new Intent(AdbManager.WIRELESS_DEBUG_PAIRING_RESULT_ACTION); intent.putExtra(AdbManager.WIRELESS_STATUS_EXTRA, @@ -1363,7 +1371,8 @@ public class AdbDebuggingManager { } PairDevice device = new PairDevice(fingerprints, hostname, false); intent.putExtra(AdbManager.WIRELESS_PAIR_DEVICE_EXTRA, device); - mContext.sendBroadcastAsUser(intent, UserHandle.ALL); + AdbDebuggingManager.sendBroadcastWithDebugPermission(mContext, intent, + UserHandle.ALL); // Add the key into the keystore mAdbKeyStore.setLastConnectionTime(publicKey, System.currentTimeMillis()); @@ -1377,14 +1386,14 @@ public class AdbDebuggingManager { intent.putExtra(AdbManager.WIRELESS_STATUS_EXTRA, AdbManager.WIRELESS_STATUS_CONNECTED); intent.putExtra(AdbManager.WIRELESS_DEBUG_PORT_EXTRA, port); - mContext.sendBroadcastAsUser(intent, UserHandle.ALL); + AdbDebuggingManager.sendBroadcastWithDebugPermission(mContext, intent, UserHandle.ALL); } private void sendPairedDevicesToUI(Map devices) { Intent intent = new Intent(AdbManager.WIRELESS_DEBUG_PAIRED_DEVICES_ACTION); // Map is not serializable, so need to downcast intent.putExtra(AdbManager.WIRELESS_DEVICES_EXTRA, (HashMap) devices); - mContext.sendBroadcastAsUser(intent, UserHandle.ALL); + AdbDebuggingManager.sendBroadcastWithDebugPermission(mContext, intent, UserHandle.ALL); } private void updateUIPairCode(String code) { @@ -1394,7 +1403,7 @@ public class AdbDebuggingManager { intent.putExtra(AdbManager.WIRELESS_PAIRING_CODE_EXTRA, code); intent.putExtra(AdbManager.WIRELESS_STATUS_EXTRA, AdbManager.WIRELESS_STATUS_PAIRING_CODE); - mContext.sendBroadcastAsUser(intent, UserHandle.ALL); + AdbDebuggingManager.sendBroadcastWithDebugPermission(mContext, intent, UserHandle.ALL); } } diff --git a/services/core/java/com/android/server/adb/AdbService.java b/services/core/java/com/android/server/adb/AdbService.java index 29bb5428dd84..5b16daa5e835 100644 --- a/services/core/java/com/android/server/adb/AdbService.java +++ b/services/core/java/com/android/server/adb/AdbService.java @@ -431,7 +431,7 @@ public class AdbService extends IAdbManager.Stub { ? AdbManager.WIRELESS_STATUS_CONNECTED : AdbManager.WIRELESS_STATUS_DISCONNECTED); intent.putExtra(AdbManager.WIRELESS_DEBUG_PORT_EXTRA, port); - mContext.sendBroadcastAsUser(intent, UserHandle.ALL); + AdbDebuggingManager.sendBroadcastWithDebugPermission(mContext, intent, UserHandle.ALL); Slog.i(TAG, "sent port broadcast port=" + port); } diff --git a/services/tests/servicestests/src/com/android/server/adb/AdbDebuggingManagerTest.java b/services/tests/servicestests/src/com/android/server/adb/AdbDebuggingManagerTest.java index cffff66b64f1..02cf971a8076 100644 --- a/services/tests/servicestests/src/com/android/server/adb/AdbDebuggingManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/adb/AdbDebuggingManagerTest.java @@ -23,7 +23,14 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import android.content.BroadcastReceiver; import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.pm.PackageManager; +import android.debug.AdbManager; +import android.debug.IAdbManager; +import android.os.ServiceManager; import android.provider.Settings; import android.util.Log; @@ -105,6 +112,7 @@ public final class AdbDebuggingManagerTest { public void tearDown() throws Exception { mKeyStore.deleteKeyStore(); setAllowedConnectionTime(mOriginalAllowedConnectionTime); + dropShellPermissionIdentity(); } /** @@ -813,6 +821,108 @@ public final class AdbDebuggingManagerTest { return hasAtLeastOneLetter; } + CountDownLatch mAdbActionLatch = new CountDownLatch(1); + private final BroadcastReceiver mReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + Log.i(TAG, "Received intent action=" + action); + if (AdbManager.WIRELESS_DEBUG_PAIRED_DEVICES_ACTION.equals(action)) { + assertEquals("Received broadcast without MANAGE_DEBUGGING permission.", + context.checkSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING), + PackageManager.PERMISSION_GRANTED); + Log.i(TAG, "action=" + action + " paired_device=" + intent.getSerializableExtra( + AdbManager.WIRELESS_DEVICES_EXTRA).toString()); + mAdbActionLatch.countDown(); + } else if (AdbManager.WIRELESS_DEBUG_STATE_CHANGED_ACTION.equals(action)) { + assertEquals("Received broadcast without MANAGE_DEBUGGING permission.", + context.checkSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING), + PackageManager.PERMISSION_GRANTED); + int status = intent.getIntExtra(AdbManager.WIRELESS_STATUS_EXTRA, + AdbManager.WIRELESS_STATUS_DISCONNECTED); + Log.i(TAG, "action=" + action + " status=" + status); + mAdbActionLatch.countDown(); + } else if (AdbManager.WIRELESS_DEBUG_PAIRING_RESULT_ACTION.equals(action)) { + assertEquals("Received broadcast without MANAGE_DEBUGGING permission.", + context.checkSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING), + PackageManager.PERMISSION_GRANTED); + Integer res = intent.getIntExtra( + AdbManager.WIRELESS_STATUS_EXTRA, + AdbManager.WIRELESS_STATUS_FAIL); + Log.i(TAG, "action=" + action + " result=" + res); + + if (res.equals(AdbManager.WIRELESS_STATUS_PAIRING_CODE)) { + String pairingCode = intent.getStringExtra( + AdbManager.WIRELESS_PAIRING_CODE_EXTRA); + Log.i(TAG, "pairingCode=" + pairingCode); + } else if (res.equals(AdbManager.WIRELESS_STATUS_CONNECTED)) { + int port = intent.getIntExtra(AdbManager.WIRELESS_DEBUG_PORT_EXTRA, 0); + Log.i(TAG, "port=" + port); + } + mAdbActionLatch.countDown(); + } + } + }; + + private void adoptShellPermissionIdentity() { + InstrumentationRegistry.getInstrumentation().getUiAutomation() + .adoptShellPermissionIdentity(android.Manifest.permission.MANAGE_DEBUGGING); + } + + private void dropShellPermissionIdentity() { + InstrumentationRegistry.getInstrumentation().getUiAutomation() + .dropShellPermissionIdentity(); + } + + @Test + public void testBroadcastReceiverWithPermissions() throws Exception { + adoptShellPermissionIdentity(); + final IAdbManager mAdbManager = IAdbManager.Stub.asInterface( + ServiceManager.getService(Context.ADB_SERVICE)); + IntentFilter intentFilter = + new IntentFilter(AdbManager.WIRELESS_DEBUG_PAIRED_DEVICES_ACTION); + intentFilter.addAction(AdbManager.WIRELESS_DEBUG_STATE_CHANGED_ACTION); + intentFilter.addAction(AdbManager.WIRELESS_DEBUG_PAIRING_RESULT_ACTION); + assertEquals("Context does not have MANAGE_DEBUGGING permission.", + mContext.checkSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING), + PackageManager.PERMISSION_GRANTED); + try { + mContext.registerReceiver(mReceiver, intentFilter); + mAdbManager.enablePairingByPairingCode(); + if (!mAdbActionLatch.await(TIMEOUT, TIMEOUT_TIME_UNIT)) { + fail("Receiver did not receive adb intent action within the timeout duration"); + } + } finally { + mContext.unregisterReceiver(mReceiver); + } + } + + @Test + public void testBroadcastReceiverWithoutPermissions() throws Exception { + adoptShellPermissionIdentity(); + final IAdbManager mAdbManager = IAdbManager.Stub.asInterface( + ServiceManager.getService(Context.ADB_SERVICE)); + IntentFilter intentFilter = + new IntentFilter(AdbManager.WIRELESS_DEBUG_PAIRED_DEVICES_ACTION); + intentFilter.addAction(AdbManager.WIRELESS_DEBUG_STATE_CHANGED_ACTION); + intentFilter.addAction(AdbManager.WIRELESS_DEBUG_PAIRING_RESULT_ACTION); + mAdbManager.enablePairingByPairingCode(); + + dropShellPermissionIdentity(); + assertEquals("Context has MANAGE_DEBUGGING permission.", + mContext.checkSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING), + PackageManager.PERMISSION_DENIED); + try { + mContext.registerReceiver(mReceiver, intentFilter); + + if (mAdbActionLatch.await(TIMEOUT, TIMEOUT_TIME_UNIT)) { + fail("Broadcast receiver received adb action intent without debug permissions"); + } + } finally { + mContext.unregisterReceiver(mReceiver); + } + } + /** * Runs an adb test with the provided configuration. * -- cgit v1.2.3 From f29223746d9009a592b0ee7ee5a92398589c5b53 Mon Sep 17 00:00:00 2001 From: Ganesh Olekar Date: Mon, 13 Dec 2021 23:05:08 +0000 Subject: Validate pid can be trusted Bug: 200288596 Test: Manual Test: atest android.security.cts.AttributionSourceTest#testPidCheck Change-Id: I07f86ba220bedb1393f4d7ed23175e92d4576601 --- core/api/test-current.txt | 1 + core/java/android/content/AttributionSource.java | 46 +++++++++++++++++++++--- 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/core/api/test-current.txt b/core/api/test-current.txt index ea6d0cecfd73..3c95afa9acd3 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -683,6 +683,7 @@ package android.content { ctor public AttributionSource(int, @Nullable String, @Nullable String); ctor public AttributionSource(int, @Nullable String, @Nullable String, @NonNull android.os.IBinder); ctor public AttributionSource(int, @Nullable String, @Nullable String, @Nullable java.util.Set, @Nullable android.content.AttributionSource); + method public void enforceCallingPid(); } public final class AutofillOptions implements android.os.Parcelable { diff --git a/core/java/android/content/AttributionSource.java b/core/java/android/content/AttributionSource.java index bdb7900b5bb9..2f61fee88e9f 100644 --- a/core/java/android/content/AttributionSource.java +++ b/core/java/android/content/AttributionSource.java @@ -154,8 +154,8 @@ public final class AttributionSource implements Parcelable { this(AttributionSourceState.CREATOR.createFromParcel(in)); // Since we just unpacked this object as part of it transiting a Binder - // call, this is the perfect time to enforce that its UID can be trusted - enforceCallingUid(); + // call, this is the perfect time to enforce that its UID and PID can be trusted + enforceCallingUidAndPid(); } /** @hide */ @@ -225,14 +225,25 @@ public final class AttributionSource implements Parcelable { } } + /** + * If you are handling an IPC and you don't trust the caller you need to validate whether the + * attribution source is one for the calling app to prevent the caller to pass you a source from + * another app without including themselves in the attribution chain. + * + * @throws SecurityException if the attribution source cannot be trusted to be from the caller. + */ + private void enforceCallingUidAndPid() { + enforceCallingUid(); + enforceCallingPid(); + } + /** * If you are handling an IPC and you don't trust the caller you need to validate * whether the attribution source is one for the calling app to prevent the caller * to pass you a source from another app without including themselves in the * attribution chain. * - * @throws SecurityException if the attribution source cannot be trusted to be - * from the caller. + * @throws SecurityException if the attribution source cannot be trusted to be from the caller. */ public void enforceCallingUid() { if (!checkCallingUid()) { @@ -261,6 +272,33 @@ public final class AttributionSource implements Parcelable { return true; } + /** + * Validate that the pid being claimed for the calling app is not spoofed + * + * @throws SecurityException if the attribution source cannot be trusted to be from the caller. + * @hide + */ + @TestApi + public void enforceCallingPid() { + if (!checkCallingPid()) { + throw new SecurityException("Calling pid: " + Binder.getCallingPid() + + " doesn't match source pid: " + mAttributionSourceState.pid); + } + } + + /** + * Validate that the pid being claimed for the calling app is not spoofed + * + * @return if the attribution source cannot be trusted to be from the caller. + */ + private boolean checkCallingPid() { + final int callingPid = Binder.getCallingPid(); + if (mAttributionSourceState.pid != -1 && callingPid != mAttributionSourceState.pid) { + return false; + } + return true; + } + @Override public String toString() { if (Build.IS_DEBUGGABLE) { -- cgit v1.2.3 From c5b545329fad3da10a6640995f6110013ad8ff5a Mon Sep 17 00:00:00 2001 From: Julia Reynolds Date: Wed, 12 Jan 2022 15:08:29 -0500 Subject: Prevent apps from creating blocked channel groups setBlocked is a hidden API, so apps should not be calling the method, but fix up the data in case they do Test: PreferencesHelperTest; manual with ApiDemos FGS Bug: 209966086 Change-Id: Icc709a6b0d0a8c5f2d9243959992f1b6764354db Merged-In: I8a27853c7ed05d9dfd38a3142fbbe185946c3992 --- .../android/server/notification/PreferencesHelper.java | 3 +++ .../server/notification/PreferencesHelperTest.java | 15 ++++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java index bc78d66037fe..fba4f1a34121 100644 --- a/services/core/java/com/android/server/notification/PreferencesHelper.java +++ b/services/core/java/com/android/server/notification/PreferencesHelper.java @@ -759,6 +759,9 @@ public class PreferencesHelper implements RankingConfig { if (r == null) { throw new IllegalArgumentException("Invalid package"); } + if (fromTargetApp) { + group.setBlocked(false); + } final NotificationChannelGroup oldGroup = r.groups.get(group.getId()); if (oldGroup != null) { group.setChannels(oldGroup.getChannels()); diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java index 2e49929ec032..439f059e97b5 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java @@ -2131,6 +2131,19 @@ public class PreferencesHelperTest extends UiServiceTestCase { assertTrue(mHelper.isGroupBlocked(PKG_N_MR1, UID_N_MR1, group.getId())); } + @Test + public void testIsGroupBlocked_appCannotCreateAsBlocked() throws Exception { + NotificationChannelGroup group = new NotificationChannelGroup("id", "name"); + group.setBlocked(true); + mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, group, true); + assertFalse(mHelper.isGroupBlocked(PKG_N_MR1, UID_N_MR1, group.getId())); + + NotificationChannelGroup group3 = group.clone(); + group3.setBlocked(false); + mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, group3, true); + assertFalse(mHelper.isGroupBlocked(PKG_N_MR1, UID_N_MR1, group.getId())); + } + @Test public void testIsGroup_appCannotResetBlock() throws Exception { NotificationChannelGroup group = new NotificationChannelGroup("id", "name"); @@ -3270,7 +3283,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { public void testGetConversations_noDisabledGroups() { NotificationChannelGroup group = new NotificationChannelGroup("a", "a"); group.setBlocked(true); - mHelper.createNotificationChannelGroup(PKG_O, UID_O, group, true); + mHelper.createNotificationChannelGroup(PKG_O, UID_O, group, false); NotificationChannel parent = new NotificationChannel("parent", "p", 1); mHelper.createNotificationChannel(PKG_O, UID_O, parent, true, false); -- cgit v1.2.3 From 37d4053d47ee64712eac28e410ab2ec973c5684c Mon Sep 17 00:00:00 2001 From: Julia Reynolds Date: Wed, 12 Jan 2022 15:08:29 -0500 Subject: Prevent apps from creating blocked channel groups setBlocked is a hidden API, so apps should not be calling the method, but fix up the data in case they do Test: PreferencesHelperTest; manual with ApiDemos FGS Bug: 209966086 Change-Id: Icc709a6b0d0a8c5f2d9243959992f1b6764354db Merged-In: I8a27853c7ed05d9dfd38a3142fbbe185946c3992 --- .../android/server/notification/PreferencesHelper.java | 3 +++ .../server/notification/PreferencesHelperTest.java | 15 ++++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java index fd4a3024179c..98d9e9a7468f 100644 --- a/services/core/java/com/android/server/notification/PreferencesHelper.java +++ b/services/core/java/com/android/server/notification/PreferencesHelper.java @@ -777,6 +777,9 @@ public class PreferencesHelper implements RankingConfig { if (r == null) { throw new IllegalArgumentException("Invalid package"); } + if (fromTargetApp) { + group.setBlocked(false); + } final NotificationChannelGroup oldGroup = r.groups.get(group.getId()); if (oldGroup != null) { group.setChannels(oldGroup.getChannels()); diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java index 6aeb40dae20b..06cfbea72a82 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java @@ -2132,6 +2132,19 @@ public class PreferencesHelperTest extends UiServiceTestCase { assertTrue(mHelper.isGroupBlocked(PKG_N_MR1, UID_N_MR1, group.getId())); } + @Test + public void testIsGroupBlocked_appCannotCreateAsBlocked() throws Exception { + NotificationChannelGroup group = new NotificationChannelGroup("id", "name"); + group.setBlocked(true); + mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, group, true); + assertFalse(mHelper.isGroupBlocked(PKG_N_MR1, UID_N_MR1, group.getId())); + + NotificationChannelGroup group3 = group.clone(); + group3.setBlocked(false); + mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, group3, true); + assertFalse(mHelper.isGroupBlocked(PKG_N_MR1, UID_N_MR1, group.getId())); + } + @Test public void testIsGroup_appCannotResetBlock() throws Exception { NotificationChannelGroup group = new NotificationChannelGroup("id", "name"); @@ -3402,7 +3415,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { public void testGetConversations_noDisabledGroups() { NotificationChannelGroup group = new NotificationChannelGroup("a", "a"); group.setBlocked(true); - mHelper.createNotificationChannelGroup(PKG_O, UID_O, group, true); + mHelper.createNotificationChannelGroup(PKG_O, UID_O, group, false); NotificationChannel parent = new NotificationChannel("parent", "p", 1); mHelper.createNotificationChannel(PKG_O, UID_O, parent, true, false); -- cgit v1.2.3 From 119d8e1b284964e9934c073dcf4d750daed78b1a Mon Sep 17 00:00:00 2001 From: Julia Reynolds Date: Wed, 12 Jan 2022 15:08:29 -0500 Subject: Prevent apps from creating blocked channel groups setBlocked is a hidden API, so apps should not be calling the method, but fix up the data in case they do Test: PreferencesHelperTest; manual with ApiDemos FGS Bug: 209966086 Change-Id: Icc709a6b0d0a8c5f2d9243959992f1b6764354db Merged-In: I8a27853c7ed05d9dfd38a3142fbbe185946c3992 --- .../android/server/notification/PreferencesHelper.java | 3 +++ .../server/notification/PreferencesHelperTest.java | 15 ++++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java index 96bde3df1e68..d5d5308015c7 100644 --- a/services/core/java/com/android/server/notification/PreferencesHelper.java +++ b/services/core/java/com/android/server/notification/PreferencesHelper.java @@ -797,6 +797,9 @@ public class PreferencesHelper implements RankingConfig { if (r == null) { throw new IllegalArgumentException("Invalid package"); } + if (fromTargetApp) { + group.setBlocked(false); + } final NotificationChannelGroup oldGroup = r.groups.get(group.getId()); if (oldGroup != null) { group.setChannels(oldGroup.getChannels()); diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java index bf0ed713e4c3..cc1483594a41 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java @@ -2231,6 +2231,19 @@ public class PreferencesHelperTest extends UiServiceTestCase { assertTrue(mHelper.isGroupBlocked(PKG_N_MR1, UID_N_MR1, group.getId())); } + @Test + public void testIsGroupBlocked_appCannotCreateAsBlocked() throws Exception { + NotificationChannelGroup group = new NotificationChannelGroup("id", "name"); + group.setBlocked(true); + mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, group, true); + assertFalse(mHelper.isGroupBlocked(PKG_N_MR1, UID_N_MR1, group.getId())); + + NotificationChannelGroup group3 = group.clone(); + group3.setBlocked(false); + mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, group3, true); + assertFalse(mHelper.isGroupBlocked(PKG_N_MR1, UID_N_MR1, group.getId())); + } + @Test public void testIsGroup_appCannotResetBlock() throws Exception { NotificationChannelGroup group = new NotificationChannelGroup("id", "name"); @@ -3623,7 +3636,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { public void testGetConversations_noDisabledGroups() { NotificationChannelGroup group = new NotificationChannelGroup("a", "a"); group.setBlocked(true); - mHelper.createNotificationChannelGroup(PKG_O, UID_O, group, true); + mHelper.createNotificationChannelGroup(PKG_O, UID_O, group, false); NotificationChannel parent = new NotificationChannel("parent", "p", 1); mHelper.createNotificationChannel(PKG_O, UID_O, parent, true, false); -- cgit v1.2.3 From 450617d4fbaac20e0137cf141f683f0b42438263 Mon Sep 17 00:00:00 2001 From: Julia Reynolds Date: Wed, 12 Jan 2022 15:08:29 -0500 Subject: Prevent apps from creating blocked channel groups setBlocked is a hidden API, so apps should not be calling the method, but fix up the data in case they do Test: PreferencesHelperTest; manual with ApiDemos FGS Bug: 209966086 Change-Id: Icc709a6b0d0a8c5f2d9243959992f1b6764354db Merged-In: I8a27853c7ed05d9dfd38a3142fbbe185946c3992 --- .../com/android/server/notification/PreferencesHelper.java | 3 +++ .../android/server/notification/PreferencesHelperTest.java | 13 +++++++++++++ 2 files changed, 16 insertions(+) diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java index 4835c97f0bb7..4795d3d6ead1 100644 --- a/services/core/java/com/android/server/notification/PreferencesHelper.java +++ b/services/core/java/com/android/server/notification/PreferencesHelper.java @@ -601,6 +601,9 @@ public class PreferencesHelper implements RankingConfig { if (r == null) { throw new IllegalArgumentException("Invalid package"); } + if (fromTargetApp) { + group.setBlocked(false); + } final NotificationChannelGroup oldGroup = r.groups.get(group.getId()); if (!group.equals(oldGroup)) { // will log for new entries as well as name/description changes diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java index 80439cf66387..2cede07de257 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java @@ -2009,6 +2009,19 @@ public class PreferencesHelperTest extends UiServiceTestCase { assertTrue(mHelper.isGroupBlocked(PKG_N_MR1, UID_N_MR1, group.getId())); } + @Test + public void testIsGroupBlocked_appCannotCreateAsBlocked() throws Exception { + NotificationChannelGroup group = new NotificationChannelGroup("id", "name"); + group.setBlocked(true); + mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, group, true); + assertFalse(mHelper.isGroupBlocked(PKG_N_MR1, UID_N_MR1, group.getId())); + + NotificationChannelGroup group3 = group.clone(); + group3.setBlocked(false); + mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, group3, true); + assertFalse(mHelper.isGroupBlocked(PKG_N_MR1, UID_N_MR1, group.getId())); + } + @Test public void testIsGroup_appCannotResetBlock() throws Exception { NotificationChannelGroup group = new NotificationChannelGroup("id", "name"); -- cgit v1.2.3 From f4dc39454572a3ceb59b423559a39bdc412b1495 Mon Sep 17 00:00:00 2001 From: Julia Reynolds Date: Wed, 12 Jan 2022 15:08:29 -0500 Subject: Prevent apps from creating blocked channel groups setBlocked is a hidden API, so apps should not be calling the method, but fix up the data in case they do Test: PreferencesHelperTest; manual with ApiDemos FGS Bug: 209966086 Change-Id: Icc709a6b0d0a8c5f2d9243959992f1b6764354db Merged-In: I8a27853c7ed05d9dfd38a3142fbbe185946c3992 --- .../android/server/notification/PreferencesHelper.java | 3 +++ .../server/notification/PreferencesHelperTest.java | 15 ++++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java index e8a3a8150377..185c0231b534 100644 --- a/services/core/java/com/android/server/notification/PreferencesHelper.java +++ b/services/core/java/com/android/server/notification/PreferencesHelper.java @@ -796,6 +796,9 @@ public class PreferencesHelper implements RankingConfig { if (r == null) { throw new IllegalArgumentException("Invalid package"); } + if (fromTargetApp) { + group.setBlocked(false); + } final NotificationChannelGroup oldGroup = r.groups.get(group.getId()); if (oldGroup != null) { group.setChannels(oldGroup.getChannels()); diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java index 66d157708332..77612b9d8cef 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java @@ -2223,6 +2223,19 @@ public class PreferencesHelperTest extends UiServiceTestCase { assertTrue(mHelper.isGroupBlocked(PKG_N_MR1, UID_N_MR1, group.getId())); } + @Test + public void testIsGroupBlocked_appCannotCreateAsBlocked() throws Exception { + NotificationChannelGroup group = new NotificationChannelGroup("id", "name"); + group.setBlocked(true); + mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, group, true); + assertFalse(mHelper.isGroupBlocked(PKG_N_MR1, UID_N_MR1, group.getId())); + + NotificationChannelGroup group3 = group.clone(); + group3.setBlocked(false); + mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, group3, true); + assertFalse(mHelper.isGroupBlocked(PKG_N_MR1, UID_N_MR1, group.getId())); + } + @Test public void testIsGroup_appCannotResetBlock() throws Exception { NotificationChannelGroup group = new NotificationChannelGroup("id", "name"); @@ -3615,7 +3628,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { public void testGetConversations_noDisabledGroups() { NotificationChannelGroup group = new NotificationChannelGroup("a", "a"); group.setBlocked(true); - mHelper.createNotificationChannelGroup(PKG_O, UID_O, group, true); + mHelper.createNotificationChannelGroup(PKG_O, UID_O, group, false); NotificationChannel parent = new NotificationChannel("parent", "p", 1); mHelper.createNotificationChannel(PKG_O, UID_O, parent, true, false); -- cgit v1.2.3 From aba1d77ff786bb54a578bdc3c86637501e24dfdb Mon Sep 17 00:00:00 2001 From: Wu Ahan Date: Thu, 13 Jan 2022 14:30:26 +0000 Subject: Revert "Decode the input of both setStream and setResource calls first" This reverts commit f6a946bbcd024ebcddaf213bd74bd7e57e9d1b49. Reason for revert: will deliver a better fix for that, ag/16580245. Change-Id: I9c401b4cbded8753fc89df25a2c4f88a2fe72087 --- core/java/android/app/WallpaperManager.java | 40 ++++++++--------------------- 1 file changed, 11 insertions(+), 29 deletions(-) diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java index 3712caeddaf5..fca4c698c49c 100644 --- a/core/java/android/app/WallpaperManager.java +++ b/core/java/android/app/WallpaperManager.java @@ -1488,27 +1488,18 @@ public class WallpaperManager { mContext.getUserId()); if (fd != null) { FileOutputStream fos = null; - final Bitmap tmp = BitmapFactory.decodeStream(resources.openRawResource(resid)); + boolean ok = false; try { - // If the stream can't be decoded, treat it as an invalid input. - if (tmp != null) { - fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd); - tmp.compress(Bitmap.CompressFormat.PNG, 100, fos); - // The 'close()' is the trigger for any server-side image manipulation, - // so we must do that before waiting for completion. - fos.close(); - completion.waitForCompletion(); - } else { - throw new IllegalArgumentException( - "Resource 0x" + Integer.toHexString(resid) + " is invalid"); - } + fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd); + copyStreamToWallpaperFile(resources.openRawResource(resid), fos); + // The 'close()' is the trigger for any server-side image manipulation, + // so we must do that before waiting for completion. + fos.close(); + completion.waitForCompletion(); } finally { // Might be redundant but completion shouldn't wait unless the write // succeeded; this is a fallback if it threw past the close+wait. IoUtils.closeQuietly(fos); - if (tmp != null) { - tmp.recycle(); - } } } } catch (RemoteException e) { @@ -1750,22 +1741,13 @@ public class WallpaperManager { result, which, completion, mContext.getUserId()); if (fd != null) { FileOutputStream fos = null; - final Bitmap tmp = BitmapFactory.decodeStream(bitmapData); try { - // If the stream can't be decoded, treat it as an invalid input. - if (tmp != null) { - fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd); - tmp.compress(Bitmap.CompressFormat.PNG, 100, fos); - fos.close(); - completion.waitForCompletion(); - } else { - throw new IllegalArgumentException("InputStream is invalid"); - } + fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd); + copyStreamToWallpaperFile(bitmapData, fos); + fos.close(); + completion.waitForCompletion(); } finally { IoUtils.closeQuietly(fos); - if (tmp != null) { - tmp.recycle(); - } } } } catch (RemoteException e) { -- cgit v1.2.3 From 4c5f09cab3c5ef0c49452efd1c68213df65e16bd Mon Sep 17 00:00:00 2001 From: Wu Ahan Date: Thu, 13 Jan 2022 14:39:56 +0000 Subject: Revert "DO NOT MERGE: Decode the input of both setStream and setResource calls first" This reverts commit 51b874f628dc45d99d10ce84694277e33a736894. Reason for revert: will deliver a better fix for that, ag/16580245. Change-Id: Icf2d0a656512e6b6bb46dd7ffef3e3cd71ac1a37 --- core/java/android/app/WallpaperManager.java | 40 ++++++++--------------------- 1 file changed, 11 insertions(+), 29 deletions(-) diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java index 3ffaad254cee..8d332ab1d58b 100644 --- a/core/java/android/app/WallpaperManager.java +++ b/core/java/android/app/WallpaperManager.java @@ -1394,27 +1394,18 @@ public class WallpaperManager { mContext.getUserId()); if (fd != null) { FileOutputStream fos = null; - final Bitmap tmp = BitmapFactory.decodeStream(resources.openRawResource(resid)); + boolean ok = false; try { - // If the stream can't be decoded, treat it as an invalid input. - if (tmp != null) { - fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd); - tmp.compress(Bitmap.CompressFormat.PNG, 100, fos); - // The 'close()' is the trigger for any server-side image manipulation, - // so we must do that before waiting for completion. - fos.close(); - completion.waitForCompletion(); - } else { - throw new IllegalArgumentException( - "Resource 0x" + Integer.toHexString(resid) + " is invalid"); - } + fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd); + copyStreamToWallpaperFile(resources.openRawResource(resid), fos); + // The 'close()' is the trigger for any server-side image manipulation, + // so we must do that before waiting for completion. + fos.close(); + completion.waitForCompletion(); } finally { // Might be redundant but completion shouldn't wait unless the write // succeeded; this is a fallback if it threw past the close+wait. IoUtils.closeQuietly(fos); - if (tmp != null) { - tmp.recycle(); - } } } } catch (RemoteException e) { @@ -1656,22 +1647,13 @@ public class WallpaperManager { result, which, completion, mContext.getUserId()); if (fd != null) { FileOutputStream fos = null; - final Bitmap tmp = BitmapFactory.decodeStream(bitmapData); try { - // If the stream can't be decoded, treat it as an invalid input. - if (tmp != null) { - fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd); - tmp.compress(Bitmap.CompressFormat.PNG, 100, fos); - fos.close(); - completion.waitForCompletion(); - } else { - throw new IllegalArgumentException("InputStream is invalid"); - } + fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd); + copyStreamToWallpaperFile(bitmapData, fos); + fos.close(); + completion.waitForCompletion(); } finally { IoUtils.closeQuietly(fos); - if (tmp != null) { - tmp.recycle(); - } } } } catch (RemoteException e) { -- cgit v1.2.3 From b6509bdc18b369742e09274904dee78ffb055de7 Mon Sep 17 00:00:00 2001 From: Wu Ahan Date: Thu, 13 Jan 2022 14:41:40 +0000 Subject: Revert "DO NOT MERGE: Decode the input of both setStream and setResource calls first" This reverts commit 4d91b5aa0b564551af2be26fb7ace1c83dff3884. Reason for revert: will deliver a better fix for that, ag/16580245. Change-Id: I8691f47251157aae83d326eb808dd1c06b13a420 --- core/java/android/app/WallpaperManager.java | 40 ++++++++--------------------- 1 file changed, 11 insertions(+), 29 deletions(-) diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java index a67475b301ee..325a54bffbfb 100644 --- a/core/java/android/app/WallpaperManager.java +++ b/core/java/android/app/WallpaperManager.java @@ -1180,27 +1180,18 @@ public class WallpaperManager { mContext.getUserId()); if (fd != null) { FileOutputStream fos = null; - final Bitmap tmp = BitmapFactory.decodeStream(resources.openRawResource(resid)); + boolean ok = false; try { - // If the stream can't be decoded, treat it as an invalid input. - if (tmp != null) { - fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd); - tmp.compress(Bitmap.CompressFormat.PNG, 100, fos); - // The 'close()' is the trigger for any server-side image manipulation, - // so we must do that before waiting for completion. - fos.close(); - completion.waitForCompletion(); - } else { - throw new IllegalArgumentException( - "Resource 0x" + Integer.toHexString(resid) + " is invalid"); - } + fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd); + copyStreamToWallpaperFile(resources.openRawResource(resid), fos); + // The 'close()' is the trigger for any server-side image manipulation, + // so we must do that before waiting for completion. + fos.close(); + completion.waitForCompletion(); } finally { // Might be redundant but completion shouldn't wait unless the write // succeeded; this is a fallback if it threw past the close+wait. IoUtils.closeQuietly(fos); - if (tmp != null) { - tmp.recycle(); - } } } } catch (RemoteException e) { @@ -1442,22 +1433,13 @@ public class WallpaperManager { result, which, completion, mContext.getUserId()); if (fd != null) { FileOutputStream fos = null; - final Bitmap tmp = BitmapFactory.decodeStream(bitmapData); try { - // If the stream can't be decoded, treat it as an invalid input. - if (tmp != null) { - fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd); - tmp.compress(Bitmap.CompressFormat.PNG, 100, fos); - fos.close(); - completion.waitForCompletion(); - } else { - throw new IllegalArgumentException("InputStream is invalid"); - } + fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd); + copyStreamToWallpaperFile(bitmapData, fos); + fos.close(); + completion.waitForCompletion(); } finally { IoUtils.closeQuietly(fos); - if (tmp != null) { - tmp.recycle(); - } } } } catch (RemoteException e) { -- cgit v1.2.3 From cc4fe8984ad59ee0e40634f48934545bedd6fb00 Mon Sep 17 00:00:00 2001 From: Wu Ahan Date: Thu, 13 Jan 2022 14:43:00 +0000 Subject: Revert "DO NOT MERGE: Decode the input of both setStream and setResource calls first" This reverts commit fa9c73975e1d2b5bf6335e1e387130890d787b15. Reason for revert: will deliver a better fix for that, ag/16580245. Change-Id: I567f20b4f545bed906938731c27eac6eb7aeddff --- core/java/android/app/WallpaperManager.java | 40 ++++++++--------------------- 1 file changed, 11 insertions(+), 29 deletions(-) diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java index 6d4489e99e6f..c5d343d168ca 100644 --- a/core/java/android/app/WallpaperManager.java +++ b/core/java/android/app/WallpaperManager.java @@ -1275,27 +1275,18 @@ public class WallpaperManager { mContext.getUserId()); if (fd != null) { FileOutputStream fos = null; - final Bitmap tmp = BitmapFactory.decodeStream(resources.openRawResource(resid)); + boolean ok = false; try { - // If the stream can't be decoded, treat it as an invalid input. - if (tmp != null) { - fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd); - tmp.compress(Bitmap.CompressFormat.PNG, 100, fos); - // The 'close()' is the trigger for any server-side image manipulation, - // so we must do that before waiting for completion. - fos.close(); - completion.waitForCompletion(); - } else { - throw new IllegalArgumentException( - "Resource 0x" + Integer.toHexString(resid) + " is invalid"); - } + fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd); + copyStreamToWallpaperFile(resources.openRawResource(resid), fos); + // The 'close()' is the trigger for any server-side image manipulation, + // so we must do that before waiting for completion. + fos.close(); + completion.waitForCompletion(); } finally { // Might be redundant but completion shouldn't wait unless the write // succeeded; this is a fallback if it threw past the close+wait. IoUtils.closeQuietly(fos); - if (tmp != null) { - tmp.recycle(); - } } } } catch (RemoteException e) { @@ -1537,22 +1528,13 @@ public class WallpaperManager { result, which, completion, mContext.getUserId()); if (fd != null) { FileOutputStream fos = null; - final Bitmap tmp = BitmapFactory.decodeStream(bitmapData); try { - // If the stream can't be decoded, treat it as an invalid input. - if (tmp != null) { - fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd); - tmp.compress(Bitmap.CompressFormat.PNG, 100, fos); - fos.close(); - completion.waitForCompletion(); - } else { - throw new IllegalArgumentException("InputStream is invalid"); - } + fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd); + copyStreamToWallpaperFile(bitmapData, fos); + fos.close(); + completion.waitForCompletion(); } finally { IoUtils.closeQuietly(fos); - if (tmp != null) { - tmp.recycle(); - } } } } catch (RemoteException e) { -- cgit v1.2.3 From fa861a6b5d87bae55319f5d92897d26ef490929f Mon Sep 17 00:00:00 2001 From: Mill Chen Date: Fri, 14 Jan 2022 15:51:31 +0800 Subject: Enable nested scrolling for locale picker This change is to make the locale picker list enable the nested scrolling feature. It is necessay to enable this feature to be able to work with CollapsingToolbarLayout. Fixes: 207318265 Fixes: 213036789 Test: manual test 1. Verify the locale picker works with Activity 2. Verify the locale picker works with SettingsBaseActivity Change-Id: Iaf90211da640cd265fc2b23dd34b3149c4406891 --- core/java/com/android/internal/app/LocalePickerWithRegion.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/core/java/com/android/internal/app/LocalePickerWithRegion.java b/core/java/com/android/internal/app/LocalePickerWithRegion.java index d0719eeca04e..b4ae56f23443 100644 --- a/core/java/com/android/internal/app/LocalePickerWithRegion.java +++ b/core/java/com/android/internal/app/LocalePickerWithRegion.java @@ -158,6 +158,14 @@ public class LocalePickerWithRegion extends ListFragment implements SearchView.O setListAdapter(mAdapter); } + @Override + public void onViewCreated(View view, Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + // In order to make the list view work with CollapsingToolbarLayout, + // we have to enable the nested scrolling feature of the list view. + getListView().setNestedScrollingEnabled(true); + } + @Override public boolean onOptionsItemSelected(MenuItem menuItem) { int id = menuItem.getItemId(); -- cgit v1.2.3 From fdc43c053164ecae2dccf3b4be2fb3df375496b1 Mon Sep 17 00:00:00 2001 From: Bill Yi Date: Fri, 14 Jan 2022 20:15:57 +0000 Subject: Import translations. DO NOT MERGE ANYWHERE Auto-generated-cl: translation import Change-Id: I44644a4ca1204a07e71ea7e1fa2cc3139396463c --- core/res/res/values-b+sr+Latn/strings.xml | 2 +- core/res/res/values-es-rUS/strings.xml | 4 ++-- core/res/res/values-eu/strings.xml | 6 +++--- core/res/res/values-fi/strings.xml | 2 +- core/res/res/values-pa/strings.xml | 10 +++++----- core/res/res/values-sr/strings.xml | 2 +- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml index 4179ab03dac3..1e1a359a1328 100644 --- a/core/res/res/values-b+sr+Latn/strings.xml +++ b/core/res/res/values-b+sr+Latn/strings.xml @@ -1523,7 +1523,7 @@ "Veza sa uvek uključenim VPN-om je prekinuta" "Povezivanje na stalno uključeni VPN nije uspelo" "Promenite podešavanja VPN-a" - "Odaberi datoteku" + "Odaberi fajl" "Nije izabrana nijedna datoteka" "Resetuj" "Pošalji" diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml index 19847ca9179c..5ad3faff90f6 100644 --- a/core/res/res/values-es-rUS/strings.xml +++ b/core/res/res/values-es-rUS/strings.xml @@ -755,7 +755,7 @@ "Evita el uso de algunas funciones de bloqueo de pantalla." "Casa" - "Móvil" + "Celular" "Trabajo" "Fax laboral" "Fax residencial" @@ -798,7 +798,7 @@ "Personalizado" "Casa" - "Móvil" + "Celular" "Trabajo" "Fax laboral" "Fax personal" diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml index 5f068e6eaace..7d1fb338c6ac 100644 --- a/core/res/res/values-eu/strings.xml +++ b/core/res/res/values-eu/strings.xml @@ -552,7 +552,7 @@ "erabili hardware biometrikoa" "Autentifikatzeko hardware biometrikoa erabiltzeko baimena ematen die aplikazioei." "kudeatu hatz-marken hardwarea" - "Erreferentzia-gako digitalen txantiloiak gehitzeko eta ezabatzeko metodoei dei egitea baimentzen die aplikazioei." + "Aztarna digitalaren txantiloiak gehitzeko eta ezabatzeko metodoei dei egitea baimentzen die aplikazioei." "erabili hatz-marken hardwarea" "Autentifikatzeko hatz-marken hardwarea erabiltzeko baimena ematen die aplikazioei." "musika-bilduma aldatu" @@ -1606,8 +1606,8 @@ "Iraungitze-data:" "Serie-zenbakia:" "Erreferentzia-fitxategiak:" - "SHA-256 erreferentzia-gako digitala:" - "SHA-1 erreferentzia-gako digitala:" + "SHA-256 aztarna digitala:" + "SHA-1 aztarna digitala:" "Ikusi guztiak" "Aukeratu jarduera" "Partekatu hauekin:" diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml index 5998269aae48..b401839c9538 100644 --- a/core/res/res/values-fi/strings.xml +++ b/core/res/res/values-fi/strings.xml @@ -1618,7 +1618,7 @@ "Vain kerran" "%1$s ei tue työprofiilia" "Tabletti" - "Televisio" + "TV" "Puhelin" "Telineen kaiuttimet" "HDMI" diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml index 9f945fe0cb15..cfaa321f1e18 100644 --- a/core/res/res/values-pa/strings.xml +++ b/core/res/res/values-pa/strings.xml @@ -174,7 +174,7 @@ "ਬਹੁਤ ਜ਼ਿਆਦਾ ਬੇਨਤੀਆਂ ਦੀ ਪ੍ਰਕਿਰਿਆ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ। ਬਾਅਦ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।" "%1$s ਲਈ ਸਾਈਨਇਨ ਅਸ਼ੁੱਧੀ" "ਸਿੰਕ ਕਰੋ" - "ਸਮਕਾਲੀਕਿਰਤ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ" + "ਸਿੰਕ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ" "ਬਹੁਤ ਸਾਰੀਆਂ %s ਨੂੰ ਮਿਟਾਉਣ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਗਈ।" "ਟੈਬਲੈੱਟ ਸਟੋਰੇਜ ਪੂਰੀ ਭਰੀ ਹੈ। ਜਗ੍ਹਾ ਖਾਲੀ ਕਰਨ ਲਈ ਕੁਝ ਫ਼ਾਈਲਾਂ ਮਿਟਾਓ।" "ਘੜੀ ਸਟੋਰੇਜ ਪੂਰੀ ਭਰੀ ਹੈ। ਜਗ੍ਹਾ ਖਾਲੀ ਕਰਨ ਲਈ ਕੁਝ ਫ਼ਾਈਲਾਂ ਮਿਟਾਓ।" @@ -663,11 +663,11 @@ "ਚਿਹਰਾ ਪ੍ਰਤੀਕ" "ਸਿੰਕ ਸੈਟਿੰਗਾਂ ਪੜ੍ਹੋ" - "ਐਪ ਨੂੰ ਕਿਸੇ ਖਾਤੇ ਲਈ ਸਮਕਾਲੀਕਰਨ ਸੈਟਿੰਗਾਂ ਪੜ੍ਹਨ ਦੇ ਯੋਗ ਬਣਾਉਂਦਾ ਹੈ। ਉਦਾਹਰਨ ਲਈ, ਇਹ ਪਤਾ ਕਰ ਸਕਦਾ ਹੈ ਕਿ People ਐਪ ਦਾ ਕਿਸੇ ਖਾਤੇ ਨਾਲ ਸਮਕਾਲੀਕਿਰਤ ਕੀਤਾ ਗਿਆ ਹੈ ਜਾਂ ਨਹੀਂ।" - "ਸਮਕਾਲੀਕਰਨ ਚਾਲੂ ਅਤੇ ਬੰਦ ਨੂੰ ਟੌਗਲ ਕਰੋ" - "ਐਪ ਨੂੰ ਇੱਕ ਖਾਤੇ ਲਈ ਸਮਕਾਲੀਕਰਨ ਸੈਟਿੰਗਾਂ ਸੋਧਣ ਦੇ ਯੋਗ ਬਣਾਉਂਦਾ ਹੈ। ਉਦਾਹਰਨ ਲਈ, ਇਸਦੀ ਵਰਤੋਂ ਕਿਸੇ ਖਾਤੇ ਨਾਲ People ਐਪ ਦਾ ਸਮਕਾਲੀਕਰਨ ਚਾਲੂ ਕਰਨ ਲਈ ਕੀਤੀ ਜਾ ਸਕਦੀ ਹੈ।" + "ਐਪ ਨੂੰ ਕਿਸੇ ਖਾਤੇ ਲਈ ਸਿੰਕ ਸੈਟਿੰਗਾਂ ਪੜ੍ਹਨ ਦੇ ਯੋਗ ਬਣਾਉਂਦਾ ਹੈ। ਉਦਾਹਰਨ ਲਈ, ਇਹ ਪਤਾ ਕਰ ਸਕਦਾ ਹੈ ਕਿ People ਐਪ ਨੂੰ ਕਿਸੇ ਖਾਤੇ ਨਾਲ ਸਿੰਕ ਕੀਤਾ ਗਿਆ ਹੈ ਜਾਂ ਨਹੀਂ।" + "ਸਿੰਕ ਚਾਲੂ ਅਤੇ ਬੰਦ ਨੂੰ ਟੌਗਲ ਕਰੋ" + "ਐਪ ਨੂੰ ਇੱਕ ਖਾਤੇ ਲਈ ਸਿੰਕ ਸੈਟਿੰਗਾਂ ਸੋਧਣ ਦੇ ਯੋਗ ਬਣਾਉਂਦਾ ਹੈ। ਉਦਾਹਰਨ ਲਈ, ਇਸਦੀ ਵਰਤੋਂ ਕਿਸੇ ਖਾਤੇ ਨਾਲ People ਐਪ ਦਾ ਸਿੰਕ ਚਾਲੂ ਕਰਨ ਲਈ ਕੀਤੀ ਜਾ ਸਕਦੀ ਹੈ।" "ਸਿੰਕ ਅੰਕੜੇ ਪੜ੍ਹੋ" - "ਐਪ ਨੂੰ ਇੱਕ ਖਾਤੇ ਲਈ ਸਮਕਾਲੀਕਰਨ ਸਥਿਤੀ ਪੜ੍ਹਨ ਦੇ ਯੋਗ ਬਣਾਉਂਦਾ ਹੈ, ਇਸ ਵਿੱਚ ਸਮਕਾਲੀਕਰਨ ਵਰਤਾਰਿਆਂ ਦਾ ਇਤਿਹਾਸ ਅਤੇ ਕਿੰਨੇ ਡਾਟਾ ਦਾ ਸਮਕਾਲੀਕਿਰਤ ਕੀਤਾ ਜਾਂਦਾ ਹੈ, ਵੀ ਸ਼ਾਮਲ ਹੈ।" + "ਐਪ ਨੂੰ ਇੱਕ ਖਾਤੇ ਲਈ ਸਿੰਕ ਸਥਿਤੀ ਪੜ੍ਹਨ ਦੇ ਯੋਗ ਬਣਾਉਂਦਾ ਹੈ, ਇਸ ਵਿੱਚ ਸਿੰਕ ਇਵੈਂਟਾਂ ਦਾ ਇਤਿਹਾਸ ਅਤੇ ਕਿੰਨਾ ਡਾਟਾ ਸਿੰਕ ਕੀਤਾ ਜਾਂਦਾ ਹੈ, ਇਹ ਵੀ ਸ਼ਾਮਲ ਹੈ।" "ਸਮੱਗਰੀਆਂ ਪੜ੍ਹੋ" "ਐਪ ਨੂੰ ਸਮੱਗਰੀਆਂ ਪੜ੍ਹਨ ਦਿੰਦੀ ਹੈ।" "ਸਮੱਗਰੀਆਂ ਦਾ ਸੰਸ਼ੋਧਨ ਕਰੋ ਜਾਂ ਮਿਟਾਓ" diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml index cd03394c58d4..353257c93104 100644 --- a/core/res/res/values-sr/strings.xml +++ b/core/res/res/values-sr/strings.xml @@ -1523,7 +1523,7 @@ "Веза са увек укљученим VPN-ом је прекинута" "Повезивање на стално укључени VPN није успело" "Промените подешавања VPN-а" - "Одабери датотеку" + "Одабери фајл" "Није изабрана ниједна датотека" "Ресетуј" "Пошаљи" -- cgit v1.2.3 From 5631f245d40c419f3bee637d0ee67fd4e6031f17 Mon Sep 17 00:00:00 2001 From: Bill Yi Date: Fri, 14 Jan 2022 20:18:49 +0000 Subject: Import translations. DO NOT MERGE ANYWHERE Auto-generated-cl: translation import Change-Id: Id6c0756724fbe70f94e3afb497410eb694291fc7 --- core/res/res/values-b+sr+Latn/strings.xml | 2 +- core/res/res/values-es-rUS/strings.xml | 4 ++-- core/res/res/values-eu/strings.xml | 6 +++--- core/res/res/values-fi/strings.xml | 2 +- core/res/res/values-pa/strings.xml | 10 +++++----- core/res/res/values-sr/strings.xml | 2 +- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml index 7f7d62e8ce7d..361d5f7c7b55 100644 --- a/core/res/res/values-b+sr+Latn/strings.xml +++ b/core/res/res/values-b+sr+Latn/strings.xml @@ -1525,7 +1525,7 @@ "Veza sa uvek uključenim VPN-om je prekinuta" "Povezivanje na stalno uključeni VPN nije uspelo" "Promenite podešavanja VPN-a" - "Odaberi datoteku" + "Odaberi fajl" "Nije izabrana nijedna datoteka" "Resetuj" "Pošalji" diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml index 2e1b59ad5f87..a4242241a4b3 100644 --- a/core/res/res/values-es-rUS/strings.xml +++ b/core/res/res/values-es-rUS/strings.xml @@ -757,7 +757,7 @@ "Evita el uso de algunas funciones de bloqueo de pantalla." "Casa" - "Móvil" + "Celular" "Trabajo" "Fax laboral" "Fax residencial" @@ -800,7 +800,7 @@ "Personalizado" "Casa" - "Móvil" + "Celular" "Trabajo" "Fax laboral" "Fax personal" diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml index aa3d0b386f7d..ccaaf335d30e 100644 --- a/core/res/res/values-eu/strings.xml +++ b/core/res/res/values-eu/strings.xml @@ -552,7 +552,7 @@ "erabili hardware biometrikoa" "Autentifikatzeko hardware biometrikoa erabiltzeko baimena ematen die aplikazioei." "kudeatu hatz-marken hardwarea" - "Erreferentzia-gako digitalen txantiloiak gehitzeko eta ezabatzeko metodoei dei egitea baimentzen die aplikazioei." + "Aztarna digitalaren txantiloiak gehitzeko eta ezabatzeko metodoei dei egitea baimentzen die aplikazioei." "erabili hatz-marken hardwarea" "Autentifikatzeko hatz-marken hardwarea erabiltzeko baimena ematen die aplikazioei." "musika-bilduma aldatu" @@ -1608,8 +1608,8 @@ "Iraungitze-data:" "Serie-zenbakia:" "Erreferentzia-fitxategiak:" - "SHA-256 erreferentzia-gako digitala:" - "SHA-1 erreferentzia-gako digitala:" + "SHA-256 aztarna digitala:" + "SHA-1 aztarna digitala:" "Ikusi guztiak" "Aukeratu jarduera" "Partekatu hauekin:" diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml index 1e491e5b7482..9eed5b18f19f 100644 --- a/core/res/res/values-fi/strings.xml +++ b/core/res/res/values-fi/strings.xml @@ -1620,7 +1620,7 @@ "Vain kerran" "%1$s ei tue työprofiilia" "Tabletti" - "Televisio" + "TV" "Puhelin" "Telineen kaiuttimet" "HDMI" diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml index 8a2ee3f74f96..09442eec8a2c 100644 --- a/core/res/res/values-pa/strings.xml +++ b/core/res/res/values-pa/strings.xml @@ -174,7 +174,7 @@ "ਬਹੁਤ ਜ਼ਿਆਦਾ ਬੇਨਤੀਆਂ ਦੀ ਪ੍ਰਕਿਰਿਆ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ। ਬਾਅਦ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।" "%1$s ਲਈ ਸਾਈਨਇਨ ਅਸ਼ੁੱਧੀ" "ਸਿੰਕ ਕਰੋ" - "ਸਮਕਾਲੀਕਿਰਤ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ" + "ਸਿੰਕ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ" "ਬਹੁਤ ਸਾਰੀਆਂ %s ਨੂੰ ਮਿਟਾਉਣ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਗਈ।" "ਟੈਬਲੈੱਟ ਸਟੋਰੇਜ ਪੂਰੀ ਭਰੀ ਹੈ। ਜਗ੍ਹਾ ਖਾਲੀ ਕਰਨ ਲਈ ਕੁਝ ਫ਼ਾਈਲਾਂ ਮਿਟਾਓ।" "ਘੜੀ ਸਟੋਰੇਜ ਪੂਰੀ ਭਰੀ ਹੈ। ਜਗ੍ਹਾ ਖਾਲੀ ਕਰਨ ਲਈ ਕੁਝ ਫ਼ਾਈਲਾਂ ਮਿਟਾਓ।" @@ -665,11 +665,11 @@ "ਕੋਈ ਗੜਬੜ ਹੋ ਗਈ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।" "ਚਿਹਰਾ ਪ੍ਰਤੀਕ" "ਸਿੰਕ ਸੈਟਿੰਗਾਂ ਪੜ੍ਹੋ" - "ਐਪ ਨੂੰ ਕਿਸੇ ਖਾਤੇ ਲਈ ਸਮਕਾਲੀਕਰਨ ਸੈਟਿੰਗਾਂ ਪੜ੍ਹਨ ਦੇ ਯੋਗ ਬਣਾਉਂਦਾ ਹੈ। ਉਦਾਹਰਨ ਲਈ, ਇਹ ਪਤਾ ਕਰ ਸਕਦਾ ਹੈ ਕਿ People ਐਪ ਦਾ ਕਿਸੇ ਖਾਤੇ ਨਾਲ ਸਮਕਾਲੀਕਿਰਤ ਕੀਤਾ ਗਿਆ ਹੈ ਜਾਂ ਨਹੀਂ।" - "ਸਮਕਾਲੀਕਰਨ ਚਾਲੂ ਅਤੇ ਬੰਦ ਨੂੰ ਟੌਗਲ ਕਰੋ" - "ਐਪ ਨੂੰ ਇੱਕ ਖਾਤੇ ਲਈ ਸਮਕਾਲੀਕਰਨ ਸੈਟਿੰਗਾਂ ਸੋਧਣ ਦੇ ਯੋਗ ਬਣਾਉਂਦਾ ਹੈ। ਉਦਾਹਰਨ ਲਈ, ਇਸਦੀ ਵਰਤੋਂ ਕਿਸੇ ਖਾਤੇ ਨਾਲ People ਐਪ ਦਾ ਸਮਕਾਲੀਕਰਨ ਚਾਲੂ ਕਰਨ ਲਈ ਕੀਤੀ ਜਾ ਸਕਦੀ ਹੈ।" + "ਐਪ ਨੂੰ ਕਿਸੇ ਖਾਤੇ ਲਈ ਸਿੰਕ ਸੈਟਿੰਗਾਂ ਪੜ੍ਹਨ ਦੇ ਯੋਗ ਬਣਾਉਂਦਾ ਹੈ। ਉਦਾਹਰਨ ਲਈ, ਇਹ ਪਤਾ ਕਰ ਸਕਦਾ ਹੈ ਕਿ People ਐਪ ਨੂੰ ਕਿਸੇ ਖਾਤੇ ਨਾਲ ਸਿੰਕ ਕੀਤਾ ਗਿਆ ਹੈ ਜਾਂ ਨਹੀਂ।" + "ਸਿੰਕ ਚਾਲੂ ਅਤੇ ਬੰਦ ਨੂੰ ਟੌਗਲ ਕਰੋ" + "ਐਪ ਨੂੰ ਇੱਕ ਖਾਤੇ ਲਈ ਸਿੰਕ ਸੈਟਿੰਗਾਂ ਸੋਧਣ ਦੇ ਯੋਗ ਬਣਾਉਂਦਾ ਹੈ। ਉਦਾਹਰਨ ਲਈ, ਇਸਦੀ ਵਰਤੋਂ ਕਿਸੇ ਖਾਤੇ ਨਾਲ People ਐਪ ਦਾ ਸਿੰਕ ਚਾਲੂ ਕਰਨ ਲਈ ਕੀਤੀ ਜਾ ਸਕਦੀ ਹੈ।" "ਸਿੰਕ ਅੰਕੜੇ ਪੜ੍ਹੋ" - "ਐਪ ਨੂੰ ਇੱਕ ਖਾਤੇ ਲਈ ਸਮਕਾਲੀਕਰਨ ਸਥਿਤੀ ਪੜ੍ਹਨ ਦੇ ਯੋਗ ਬਣਾਉਂਦਾ ਹੈ, ਇਸ ਵਿੱਚ ਸਮਕਾਲੀਕਰਨ ਵਰਤਾਰਿਆਂ ਦਾ ਇਤਿਹਾਸ ਅਤੇ ਕਿੰਨੇ ਡਾਟਾ ਦਾ ਸਮਕਾਲੀਕਿਰਤ ਕੀਤਾ ਜਾਂਦਾ ਹੈ, ਵੀ ਸ਼ਾਮਲ ਹੈ।" + "ਐਪ ਨੂੰ ਇੱਕ ਖਾਤੇ ਲਈ ਸਿੰਕ ਸਥਿਤੀ ਪੜ੍ਹਨ ਦੇ ਯੋਗ ਬਣਾਉਂਦਾ ਹੈ, ਇਸ ਵਿੱਚ ਸਿੰਕ ਇਵੈਂਟਾਂ ਦਾ ਇਤਿਹਾਸ ਅਤੇ ਕਿੰਨਾ ਡਾਟਾ ਸਿੰਕ ਕੀਤਾ ਜਾਂਦਾ ਹੈ, ਇਹ ਵੀ ਸ਼ਾਮਲ ਹੈ।" "ਸਮੱਗਰੀਆਂ ਪੜ੍ਹੋ" "ਐਪ ਨੂੰ ਸਮੱਗਰੀਆਂ ਪੜ੍ਹਨ ਦਿੰਦੀ ਹੈ।" "ਸਮੱਗਰੀਆਂ ਦਾ ਸੰਸ਼ੋਧਨ ਕਰੋ ਜਾਂ ਮਿਟਾਓ" diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml index 911ba91d058e..5487e9e93f7f 100644 --- a/core/res/res/values-sr/strings.xml +++ b/core/res/res/values-sr/strings.xml @@ -1525,7 +1525,7 @@ "Веза са увек укљученим VPN-ом је прекинута" "Повезивање на стално укључени VPN није успело" "Промените подешавања VPN-а" - "Одабери датотеку" + "Одабери фајл" "Није изабрана ниједна датотека" "Ресетуј" "Пошаљи" -- cgit v1.2.3 From 2711c92eb6f7d87f2ee3f3a8648c5013cfca021e Mon Sep 17 00:00:00 2001 From: Bill Yi Date: Fri, 14 Jan 2022 23:30:21 +0000 Subject: Import translations. DO NOT MERGE ANYWHERE Auto-generated-cl: translation import Change-Id: Iec0e13284f07275b5f720070dfd5458c1b0d26d4 --- packages/SystemUI/res/values-be/strings.xml | 4 ++-- packages/SystemUI/res/values-fi/strings.xml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml index 168aa3bbef38..71e08df02f33 100644 --- a/packages/SystemUI/res/values-be/strings.xml +++ b/packages/SystemUI/res/values-be/strings.xml @@ -531,7 +531,7 @@ "За профілем могуць назіраць" "За сеткай могуць назіраць" "За сеткай могуць назіраць" - "Гэта прылада знаходзіцца пад кантролем вашых бацькоў" + "Гэта прылада знаходзіцца пад кантролем бацькоў" "Ваша арганізацыя валодае гэтай прыладай і можа кантраляваць сеткавы трафік" "%1$s валодае гэтай прыладай і можа кантраляваць сеткавы трафік" "Гэта прылада належыць арганізацыі \"%s\"" @@ -585,7 +585,7 @@ "Ваш адміністратар уключыў вядзенне журнала сеткі, з дапамогай якога адсочваецца трафік на вашай прыладзе.\n\nДля атрымання дадатковай інфармацыі звярніцеся да адміністратара." "Вы далі праграме дазвол на наладжванне злучэння VPN.\n\nГэта праграма можа сачыць за актыўнасцю вашай прылады і вашай сеткавай актыўнасцю, уключаючы электронную пошту, праграмы і вэб-сайты." "Ваш працоўны профіль знаходзіцца пад кіраваннем %1$s.\n\nВаш адміністратар можа сачыць за вашай сеткавай дзейнасцю, уключаючы электронную пошту, праграмы і вэб-сайты.\n\nДля атрымання дадатковай інфармацыі звярніцеся да адміністратара.\n\nВы таксама падключаны да сеткі VPN, якая можа сачыць за вашай сеткавай дзейнасцю." - "Гэта прылада знаходзіцца пад кантролем вашых бацькоў. Бацькі могуць праглядаць і кантраляваць вашу інфармацыю, напрыклад пра праграмы, якія вы выкарыстоўваеце, даныя пра ваша месцазнаходжанне і час карыстання прыладай." + "Гэта прылада знаходзіцца пад кантролем бацькоў. Бацькі могуць праглядаць і кантраляваць тваю інфармацыю, напрыклад пра праграмы, якія ты выкарыстоўваеш, даныя пра тваё месцазнаходжанне і час карыстання прыладай." "VPN" "Вы падключаны да праграмы %1$s, якая можа сачыць за вашай сеткавай актыўнасцю, уключаючы электронную пошту, праграмы і вэб-сайты." "Вы падлучаны да праграмы %1$s, якая сачыць за вашай асабістай сеткавай актыўнасцю, уключаючы электронную пошту, праграмы і вэб-сайты." diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml index 88de800efc40..c75d0186a8b7 100644 --- a/packages/SystemUI/res/values-fi/strings.xml +++ b/packages/SystemUI/res/values-fi/strings.xml @@ -129,7 +129,7 @@ "Takaisin" "Aloitus" "Valikko" - "Esteettömyys" + "Saavutettavuus" "Näytön kääntäminen" "Viimeisimmät" "Haku" -- cgit v1.2.3 From 8dfdfa5310565f015c5a3972f451cfc1fd102d70 Mon Sep 17 00:00:00 2001 From: Bill Yi Date: Fri, 14 Jan 2022 23:33:53 +0000 Subject: Import translations. DO NOT MERGE ANYWHERE Auto-generated-cl: translation import Change-Id: I65e9a99182df565c87259817deefb1793ffcdf3d --- packages/SystemUI/res/values-be/strings.xml | 4 ++-- packages/SystemUI/res/values-fi/strings.xml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml index 0bea4e4cda59..b9c70c123439 100644 --- a/packages/SystemUI/res/values-be/strings.xml +++ b/packages/SystemUI/res/values-be/strings.xml @@ -532,7 +532,7 @@ "За профілем могуць назіраць" "За сеткай могуць назіраць" "За сеткай могуць назіраць" - "Гэта прылада знаходзіцца пад кантролем вашых бацькоў" + "Гэта прылада знаходзіцца пад кантролем бацькоў" "Ваша арганізацыя валодае гэтай прыладай і можа кантраляваць сеткавы трафік" "%1$s валодае гэтай прыладай і можа кантраляваць сеткавы трафік" "Гэта прылада належыць арганізацыі \"%s\"" @@ -586,7 +586,7 @@ "Ваш адміністратар уключыў вядзенне журнала сеткі, з дапамогай якога адсочваецца трафік на вашай прыладзе.\n\nДля атрымання дадатковай інфармацыі звярніцеся да адміністратара." "Вы далі праграме дазвол на наладжванне злучэння VPN.\n\nГэта праграма можа сачыць за актыўнасцю вашай прылады і вашай сеткавай актыўнасцю, уключаючы электронную пошту, праграмы і вэб-сайты." "Ваш працоўны профіль знаходзіцца пад кіраваннем %1$s.\n\nВаш адміністратар можа сачыць за вашай сеткавай дзейнасцю, уключаючы электронную пошту, праграмы і вэб-сайты.\n\nДля атрымання дадатковай інфармацыі звярніцеся да адміністратара.\n\nВы таксама падключаны да сеткі VPN, якая можа сачыць за вашай сеткавай дзейнасцю." - "Гэта прылада знаходзіцца пад кантролем вашых бацькоў. Бацькі могуць праглядаць і кантраляваць вашу інфармацыю, напрыклад пра праграмы, якія вы выкарыстоўваеце, даныя пра ваша месцазнаходжанне і час карыстання прыладай." + "Гэта прылада знаходзіцца пад кантролем бацькоў. Бацькі могуць праглядаць і кантраляваць тваю інфармацыю, напрыклад пра праграмы, якія ты выкарыстоўваеш, даныя пра тваё месцазнаходжанне і час карыстання прыладай." "VPN" "Вы падключаны да праграмы %1$s, якая можа сачыць за вашай сеткавай актыўнасцю, уключаючы электронную пошту, праграмы і вэб-сайты." "Вы падлучаны да праграмы %1$s, якая сачыць за вашай асабістай сеткавай актыўнасцю, уключаючы электронную пошту, праграмы і вэб-сайты." diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml index bb5396d24ce4..440a030f018f 100644 --- a/packages/SystemUI/res/values-fi/strings.xml +++ b/packages/SystemUI/res/values-fi/strings.xml @@ -130,7 +130,7 @@ "Takaisin" "Aloitus" "Valikko" - "Esteettömyys" + "Saavutettavuus" "Näytön kääntäminen" "Viimeisimmät" "Haku" -- cgit v1.2.3 From 4b28a9a63cc807226de48cc4e33f79f438e3d367 Mon Sep 17 00:00:00 2001 From: Zoey Chen Date: Fri, 14 Jan 2022 15:27:40 +0800 Subject: [Provider Model] Fix the overlap when changing the font/display size Bug: 211540142 Test: manual Change-Id: I10032a866ee05030070b40076fa946c3e73e0d56 --- .../res/layout/internet_connectivity_dialog.xml | 18 ++++++++++++------ packages/SystemUI/res/values/styles.xml | 3 ++- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/packages/SystemUI/res/layout/internet_connectivity_dialog.xml b/packages/SystemUI/res/layout/internet_connectivity_dialog.xml index e69582f52ebf..f72a8dc08c9c 100644 --- a/packages/SystemUI/res/layout/internet_connectivity_dialog.xml +++ b/packages/SystemUI/res/layout/internet_connectivity_dialog.xml @@ -378,7 +378,8 @@ android:clickable="true"/> - -