diff options
379 files changed, 6333 insertions, 3841 deletions
diff --git a/core/api/test-current.txt b/core/api/test-current.txt index a8e06fc4c8a0..5c9da0bc97e6 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -3289,7 +3289,7 @@ package android.window { method @NonNull public android.window.WindowContainerTransaction reparentTasks(@Nullable android.window.WindowContainerToken, @Nullable android.window.WindowContainerToken, @Nullable int[], @Nullable int[], boolean); method @NonNull public android.window.WindowContainerTransaction scheduleFinishEnterPip(@NonNull android.window.WindowContainerToken, @NonNull android.graphics.Rect); method @NonNull public android.window.WindowContainerTransaction setActivityWindowingMode(@NonNull android.window.WindowContainerToken, int); - method @NonNull public android.window.WindowContainerTransaction setAdjacentRoots(@NonNull android.window.WindowContainerToken, @NonNull android.window.WindowContainerToken); + method @NonNull public android.window.WindowContainerTransaction setAdjacentRoots(@NonNull android.window.WindowContainerToken, @NonNull android.window.WindowContainerToken, boolean); method @NonNull public android.window.WindowContainerTransaction setAdjacentTaskFragments(@NonNull android.os.IBinder, @Nullable android.os.IBinder, @Nullable android.window.WindowContainerTransaction.TaskFragmentAdjacentParams); method @NonNull public android.window.WindowContainerTransaction setAppBounds(@NonNull android.window.WindowContainerToken, @NonNull android.graphics.Rect); method @NonNull public android.window.WindowContainerTransaction setBounds(@NonNull android.window.WindowContainerToken, @NonNull android.graphics.Rect); diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 19a1d7af5382..45df0d9a8a9f 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -1294,8 +1294,11 @@ public final class ActivityThread extends ClientTransactionHandler } @Override - public void scheduleCrash(String msg, int typeId) { - sendMessage(H.SCHEDULE_CRASH, msg, typeId); + public void scheduleCrash(String msg, int typeId, @Nullable Bundle extras) { + SomeArgs args = SomeArgs.obtain(); + args.arg1 = msg; + args.arg2 = extras; + sendMessage(H.SCHEDULE_CRASH, args, typeId); } public void dumpActivity(ParcelFileDescriptor pfd, IBinder activitytoken, @@ -1925,11 +1928,11 @@ public final class ActivityThread extends ClientTransactionHandler } } - private void throwRemoteServiceException(String message, int typeId) { + private void throwRemoteServiceException(String message, int typeId, @Nullable Bundle extras) { // Use a switch to ensure all the type IDs are unique. switch (typeId) { case ForegroundServiceDidNotStartInTimeException.TYPE_ID: - throw new ForegroundServiceDidNotStartInTimeException(message); + throw generateForegroundServiceDidNotStartInTimeException(message, extras); case CannotDeliverBroadcastException.TYPE_ID: throw new CannotDeliverBroadcastException(message); @@ -1952,6 +1955,15 @@ public final class ActivityThread extends ClientTransactionHandler } } + private ForegroundServiceDidNotStartInTimeException + generateForegroundServiceDidNotStartInTimeException(String message, Bundle extras) { + final String serviceClassName = + ForegroundServiceDidNotStartInTimeException.getServiceClassNameFromExtras(extras); + final Exception inner = (serviceClassName == null) ? null + : Service.getStartForegroundServiceStackTrace(serviceClassName); + throw new ForegroundServiceDidNotStartInTimeException(message, inner); + } + class H extends Handler { public static final int BIND_APPLICATION = 110; @UnsupportedAppUsage @@ -2169,9 +2181,14 @@ public final class ActivityThread extends ClientTransactionHandler handleDispatchPackageBroadcast(msg.arg1, (String[])msg.obj); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); break; - case SCHEDULE_CRASH: - throwRemoteServiceException((String) msg.obj, msg.arg1); + case SCHEDULE_CRASH: { + SomeArgs args = (SomeArgs) msg.obj; + String message = (String) args.arg1; + Bundle extras = (Bundle) args.arg2; + args.recycle(); + throwRemoteServiceException(message, msg.arg1, extras); break; + } case DUMP_HEAP: handleDumpHeap((DumpHeapData) msg.obj); break; diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index e76c1398b04a..db3c7d9bcb02 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -1862,6 +1862,14 @@ class ContextImpl extends Context { "Not allowed to start service " + service + ": " + cn.getClassName()); } } + // If we started a foreground service in the same package, remember the stack trace. + if (cn != null && requireForeground) { + if (cn.getPackageName().equals(getOpPackageName())) { + Service.setStartForegroundServiceStackTrace(cn.getClassName(), + new StackTrace("Last startServiceCommon() call for this service was " + + "made here")); + } + } return cn; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java index 9833ed60fe46..306035341ea3 100644 --- a/core/java/android/app/Dialog.java +++ b/core/java/android/app/Dialog.java @@ -151,6 +151,9 @@ public class Dialog implements DialogInterface, Window.Callback, private final Runnable mDismissAction = this::dismissDialog; + /** A {@link Runnable} to run instead of dismissing when {@link #dismiss()} is called. */ + private Runnable mDismissOverride; + /** * Creates a dialog window that uses the default dialog theme. * <p> @@ -370,6 +373,11 @@ public class Dialog implements DialogInterface, Window.Callback, */ @Override public void dismiss() { + if (mDismissOverride != null) { + mDismissOverride.run(); + return; + } + if (Looper.myLooper() == mHandler.getLooper()) { dismissDialog(); } else { @@ -1354,6 +1362,21 @@ public class Dialog implements DialogInterface, Window.Callback, mDismissMessage = msg; } + /** + * Set a {@link Runnable} to run when this dialog is dismissed instead of directly dismissing + * it. This allows to animate the dialog in its window before dismissing it. + * + * Note that {@code override} should always end up calling this method with {@code null} + * followed by a call to {@link #dismiss() dismiss} to actually dismiss the dialog. + * + * @see #dismiss() + * + * @hide + */ + public void setDismissOverride(@Nullable Runnable override) { + mDismissOverride = override; + } + /** @hide */ public boolean takeCancelAndDismissListeners(@Nullable String msg, @Nullable OnCancelListener cancel, @Nullable OnDismissListener dismiss) { diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl index 4912703bc2ce..64a9c441c57f 100644 --- a/core/java/android/app/IActivityManager.aidl +++ b/core/java/android/app/IActivityManager.aidl @@ -321,6 +321,8 @@ interface IActivityManager { boolean isTopActivityImmersive(); void crashApplicationWithType(int uid, int initialPid, in String packageName, int userId, in String message, boolean force, int exceptionTypeId); + void crashApplicationWithTypeWithExtras(int uid, int initialPid, in String packageName, + int userId, in String message, boolean force, int exceptionTypeId, in Bundle extras); /** @deprecated -- use getProviderMimeTypeAsync */ @UnsupportedAppUsage(maxTargetSdk = 29, publicAlternatives = "Use {@link android.content.ContentResolver#getType} public API instead.") diff --git a/core/java/android/app/IApplicationThread.aidl b/core/java/android/app/IApplicationThread.aidl index d6ff6d3dfc3a..448c3cf48e10 100644 --- a/core/java/android/app/IApplicationThread.aidl +++ b/core/java/android/app/IApplicationThread.aidl @@ -107,7 +107,7 @@ oneway interface IApplicationThread { void scheduleOnNewActivityOptions(IBinder token, in Bundle options); void scheduleSuicide(); void dispatchPackageBroadcast(int cmd, in String[] packages); - void scheduleCrash(in String msg, int typeId); + void scheduleCrash(in String msg, int typeId, in Bundle extras); void dumpHeap(boolean managed, boolean mallocInfo, boolean runGc, in String path, in ParcelFileDescriptor fd, in RemoteCallback finishCallback); void dumpActivity(in ParcelFileDescriptor fd, IBinder servicetoken, in String prefix, diff --git a/core/java/android/app/RemoteServiceException.java b/core/java/android/app/RemoteServiceException.java index 1038530d92d3..e220627706f9 100644 --- a/core/java/android/app/RemoteServiceException.java +++ b/core/java/android/app/RemoteServiceException.java @@ -16,6 +16,10 @@ package android.app; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.content.ComponentName; +import android.os.Bundle; import android.util.AndroidRuntimeException; /** @@ -33,6 +37,10 @@ public class RemoteServiceException extends AndroidRuntimeException { super(msg); } + public RemoteServiceException(String msg, Throwable cause) { + super(msg, cause); + } + /** * Exception used to crash an app process when it didn't call {@link Service#startForeground} * in time after the service was started with @@ -44,8 +52,21 @@ public class RemoteServiceException extends AndroidRuntimeException { /** The type ID passed to {@link IApplicationThread#scheduleCrash}. */ public static final int TYPE_ID = 1; - public ForegroundServiceDidNotStartInTimeException(String msg) { - super(msg); + private static final String KEY_SERVICE_CLASS_NAME = "serviceclassname"; + + public ForegroundServiceDidNotStartInTimeException(String msg, Throwable cause) { + super(msg, cause); + } + + public static Bundle createExtrasForService(@NonNull ComponentName service) { + Bundle b = new Bundle(); + b.putString(KEY_SERVICE_CLASS_NAME, service.getClassName()); + return b; + } + + @Nullable + public static String getServiceClassNameFromExtras(@Nullable Bundle extras) { + return (extras == null) ? null : extras.getString(KEY_SERVICE_CLASS_NAME); } } diff --git a/core/java/android/app/Service.java b/core/java/android/app/Service.java index 336387204410..5a5ccb5d8987 100644 --- a/core/java/android/app/Service.java +++ b/core/java/android/app/Service.java @@ -33,9 +33,12 @@ import android.content.res.Configuration; import android.os.Build; import android.os.IBinder; import android.os.RemoteException; +import android.util.ArrayMap; import android.util.Log; import android.view.contentcapture.ContentCaptureManager; +import com.android.internal.annotations.GuardedBy; + import java.io.FileDescriptor; import java.io.PrintWriter; import java.lang.annotation.Retention; @@ -733,6 +736,7 @@ public abstract class Service extends ContextWrapper implements ComponentCallbac mActivityManager.setServiceForeground( new ComponentName(this, mClassName), mToken, id, notification, 0, FOREGROUND_SERVICE_TYPE_MANIFEST); + clearStartForegroundServiceStackTrace(); } catch (RemoteException ex) { } } @@ -786,6 +790,7 @@ public abstract class Service extends ContextWrapper implements ComponentCallbac mActivityManager.setServiceForeground( new ComponentName(this, mClassName), mToken, id, notification, 0, foregroundServiceType); + clearStartForegroundServiceStackTrace(); } catch (RemoteException ex) { } } @@ -941,4 +946,34 @@ public abstract class Service extends ContextWrapper implements ComponentCallbac private IActivityManager mActivityManager = null; @UnsupportedAppUsage private boolean mStartCompatibility = false; + + /** + * This keeps track of the stacktrace where Context.startForegroundService() was called + * for each service class. We use that when we crash the app for not calling + * {@link #startForeground} in time, in {@link ActivityThread#throwRemoteServiceException}. + */ + @GuardedBy("sStartForegroundServiceStackTraces") + private static final ArrayMap<String, StackTrace> sStartForegroundServiceStackTraces = + new ArrayMap<>(); + + /** @hide */ + public static void setStartForegroundServiceStackTrace( + @NonNull String className, @NonNull StackTrace stacktrace) { + synchronized (sStartForegroundServiceStackTraces) { + sStartForegroundServiceStackTraces.put(className, stacktrace); + } + } + + private void clearStartForegroundServiceStackTrace() { + synchronized (sStartForegroundServiceStackTraces) { + sStartForegroundServiceStackTraces.remove(this.getClassName()); + } + } + + /** @hide */ + public static StackTrace getStartForegroundServiceStackTrace(@NonNull String className) { + synchronized (sStartForegroundServiceStackTraces) { + return sStartForegroundServiceStackTraces.get(className); + } + } } diff --git a/core/java/android/hardware/devicestate/DeviceStateManagerInternal.java b/core/java/android/app/StackTrace.java index 4c91c160f891..ec058f88118b 100644 --- a/core/java/android/hardware/devicestate/DeviceStateManagerInternal.java +++ b/core/java/android/app/StackTrace.java @@ -14,15 +14,14 @@ * limitations under the License. */ -package android.hardware.devicestate; +package android.app; /** - * Device state manager local system service interface. - * - * @hide Only for use within the system server. + * An Exception subclass that's used only for logging stacktraces. + * @hide */ -public abstract class DeviceStateManagerInternal { - - /** Returns the list of currently supported device state identifiers. */ - public abstract int[] getSupportedStateIdentifiers(); +public class StackTrace extends Exception { + public StackTrace(String message) { + super(message); + } } diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java index 22b1c03fba50..fca4c698c49c 100644 --- a/core/java/android/app/WallpaperManager.java +++ b/core/java/android/app/WallpaperManager.java @@ -365,17 +365,18 @@ public class WallpaperManager { private int mCachedWallpaperUserId; private Bitmap mDefaultWallpaper; private Handler mMainLooperHandler; - private ArrayMap<RectF, ArraySet<LocalWallpaperColorConsumer>> mLocalColorAreas = - new ArrayMap<>(); + private ArrayMap<LocalWallpaperColorConsumer, ArraySet<RectF>> mLocalColorCallbackAreas = + new ArrayMap<>(); private ILocalWallpaperColorConsumer mLocalColorCallback = new ILocalWallpaperColorConsumer.Stub() { @Override public void onColorsChanged(RectF area, WallpaperColors colors) { - ArraySet<LocalWallpaperColorConsumer> callbacks = - mLocalColorAreas.get(area); - if (callbacks == null) return; - for (LocalWallpaperColorConsumer callback: callbacks) { - callback.onColorsChanged(area, colors); + for (LocalWallpaperColorConsumer callback : + mLocalColorCallbackAreas.keySet()) { + ArraySet<RectF> areas = mLocalColorCallbackAreas.get(callback); + if (areas != null && areas.contains(area)) { + callback.onColorsChanged(area, colors); + } } } }; @@ -420,46 +421,52 @@ public class WallpaperManager { } } - public void addOnColorsChangedListener(@NonNull LocalWallpaperColorConsumer callback, + public void addOnColorsChangedListener( + @NonNull LocalWallpaperColorConsumer callback, @NonNull List<RectF> regions, int which, int userId, int displayId) { - for (RectF area: regions) { - ArraySet<LocalWallpaperColorConsumer> callbacks = mLocalColorAreas.get(area); - if (callbacks == null) { - callbacks = new ArraySet<>(); - mLocalColorAreas.put(area, callbacks); + synchronized (this) { + for (RectF area : regions) { + ArraySet<RectF> areas = mLocalColorCallbackAreas.get(callback); + if (areas == null) { + areas = new ArraySet<>(); + mLocalColorCallbackAreas.put(callback, areas); + } + areas.add(area); + } + try { + // one way returns immediately + mService.addOnLocalColorsChangedListener(mLocalColorCallback, regions, which, + userId, displayId); + } catch (RemoteException e) { + // Can't get colors, connection lost. + Log.e(TAG, "Can't register for local color updates", e); } - callbacks.add(callback); - } - try { - mService.addOnLocalColorsChangedListener(mLocalColorCallback , regions, which, - userId, displayId); - } catch (RemoteException e) { - // Can't get colors, connection lost. - Log.e(TAG, "Can't register for local color updates", e); } } public void removeOnColorsChangedListener( @NonNull LocalWallpaperColorConsumer callback, int which, int userId, int displayId) { - final ArrayList<RectF> removeAreas = new ArrayList<>(); - for (RectF area : mLocalColorAreas.keySet()) { - ArraySet<LocalWallpaperColorConsumer> callbacks = mLocalColorAreas.get(area); - if (callbacks == null) continue; - callbacks.remove(callback); - if (callbacks.size() == 0) { - mLocalColorAreas.remove(area); - removeAreas.add(area); + synchronized (this) { + final ArraySet<RectF> removeAreas = mLocalColorCallbackAreas.remove(callback); + if (removeAreas == null || removeAreas.size() == 0) { + return; } - } - try { - if (removeAreas.size() > 0) { - mService.removeOnLocalColorsChangedListener( - mLocalColorCallback, removeAreas, which, userId, displayId); + for (LocalWallpaperColorConsumer cb : mLocalColorCallbackAreas.keySet()) { + ArraySet<RectF> areas = mLocalColorCallbackAreas.get(cb); + if (areas != null && cb != callback) removeAreas.removeAll(areas); + } + try { + if (removeAreas.size() > 0) { + // one way returns immediately + mService.removeOnLocalColorsChangedListener( + mLocalColorCallback, new ArrayList(removeAreas), which, userId, + displayId); + } + } catch (RemoteException e) { + // Can't get colors, connection lost. + Log.e(TAG, "Can't unregister for local color updates", e); } - } catch (RemoteException e) { - // Can't get colors, connection lost. - Log.e(TAG, "Can't unregister for local color updates", e); } } diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java index 88649392c23c..9b19fc4d3ef2 100644 --- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java +++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java @@ -110,6 +110,11 @@ public class CameraDeviceImpl extends CameraDevice private int mRepeatingRequestId = REQUEST_ID_NONE; // Latest repeating request list's types private int[] mRepeatingRequestTypes; + + // Cache failed requests to process later in case of a repeating error callback + private int mFailedRepeatingRequestId = REQUEST_ID_NONE; + private int[] mFailedRepeatingRequestTypes; + // Map stream IDs to input/output configurations private SimpleEntry<Integer, InputConfiguration> mConfiguredInput = new SimpleEntry<>(REQUEST_ID_NONE, null); @@ -1326,16 +1331,25 @@ public class CameraDeviceImpl extends CameraDevice int requestId = mRepeatingRequestId; mRepeatingRequestId = REQUEST_ID_NONE; + mFailedRepeatingRequestId = REQUEST_ID_NONE; int[] requestTypes = mRepeatingRequestTypes; mRepeatingRequestTypes = null; + mFailedRepeatingRequestTypes = null; long lastFrameNumber; try { lastFrameNumber = mRemoteDevice.cancelRequest(requestId); } catch (IllegalArgumentException e) { if (DEBUG) { - Log.v(TAG, "Repeating request was already stopped for request " + requestId); + Log.v(TAG, "Repeating request was already stopped for request " + + requestId); } + // Cache request id and request types in case of a race with + // "onRepeatingRequestError" which may no yet be scheduled on another thread + // or blocked by us. + mFailedRepeatingRequestId = requestId; + mFailedRepeatingRequestTypes = requestTypes; + // Repeating request was already stopped. Nothing more to do. return; } @@ -1965,7 +1979,17 @@ public class CameraDeviceImpl extends CameraDevice synchronized(mInterfaceLock) { // Camera is already closed or no repeating request is present. if (mRemoteDevice == null || mRepeatingRequestId == REQUEST_ID_NONE) { - return; // Camera already closed + if ((mFailedRepeatingRequestId == repeatingRequestId) && + (mFailedRepeatingRequestTypes != null) && (mRemoteDevice != null)) { + Log.v(TAG, "Resuming stop of failed repeating request with id: " + + mFailedRepeatingRequestId); + + checkEarlyTriggerSequenceCompleteLocked(mFailedRepeatingRequestId, + lastFrameNumber, mFailedRepeatingRequestTypes); + mFailedRepeatingRequestId = REQUEST_ID_NONE; + mFailedRepeatingRequestTypes = null; + } + return; } // Redirect device callback to the offline session in case we are in the middle diff --git a/core/java/android/hardware/display/AmbientDisplayConfiguration.java b/core/java/android/hardware/display/AmbientDisplayConfiguration.java index 7d719846f343..0b1ed65ef937 100644 --- a/core/java/android/hardware/display/AmbientDisplayConfiguration.java +++ b/core/java/android/hardware/display/AmbientDisplayConfiguration.java @@ -109,7 +109,8 @@ public class AmbientDisplayConfiguration { /** {@hide} */ public boolean quickPickupSensorEnabled(int user) { - return !TextUtils.isEmpty(quickPickupSensorType()) + return boolSettingDefaultOn(Settings.Secure.DOZE_QUICK_PICKUP_GESTURE, user) + && !TextUtils.isEmpty(quickPickupSensorType()) && pickupGestureEnabled(user) && !alwaysOnEnabled(user); } diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java index 5bb51c19342d..4f205530ef0d 100644 --- a/core/java/android/hardware/display/DisplayManagerInternal.java +++ b/core/java/android/hardware/display/DisplayManagerInternal.java @@ -35,7 +35,6 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.List; import java.util.Objects; -import java.util.Set; /** * Display manager local system service interface. @@ -130,14 +129,6 @@ public abstract class DisplayManagerInternal { public abstract DisplayInfo getDisplayInfo(int displayId); /** - * Returns a set of DisplayInfo, for the states that may be assumed by either the given display, - * or any other display within that display's group. - * - * @param displayId The logical display id to fetch DisplayInfo for. - */ - public abstract Set<DisplayInfo> getPossibleDisplayInfo(int displayId); - - /** * Returns the position of the display's projection. * * @param displayId The logical display id. diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index 9721279bcd24..e0324c0ded26 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -395,7 +395,7 @@ public class InputMethodService extends AbstractInputMethodService { /** * @hide - * The IME is visible. + * The IME is perceptibly visible to the user. */ public static final int IME_VISIBLE = 0x2; @@ -406,6 +406,15 @@ public class InputMethodService extends AbstractInputMethodService { */ public static final int IME_INVISIBLE = 0x4; + /** + * @hide + * The IME is visible, but not yet perceptible to the user (e.g. fading in) + * by {@link android.view.WindowInsetsController}. + * + * @see InputMethodManager#reportPerceptible + */ + public static final int IME_VISIBLE_IMPERCEPTIBLE = 0x8; + // Min and max values for back disposition. private static final int BACK_DISPOSITION_MIN = BACK_DISPOSITION_DEFAULT; private static final int BACK_DISPOSITION_MAX = BACK_DISPOSITION_ADJUST_NOTHING; diff --git a/core/java/android/os/SharedMemory.java b/core/java/android/os/SharedMemory.java index 136e3de731a9..da478594dc1c 100644 --- a/core/java/android/os/SharedMemory.java +++ b/core/java/android/os/SharedMemory.java @@ -63,7 +63,7 @@ public final class SharedMemory implements Parcelable, Closeable { mMemoryRegistration = new MemoryRegistration(mSize); mCleaner = Cleaner.create(mFileDescriptor, - new Closer(mFileDescriptor, mMemoryRegistration)); + new Closer(mFileDescriptor.getInt$(), mMemoryRegistration)); } /** @@ -256,6 +256,7 @@ public final class SharedMemory implements Parcelable, Closeable { */ @Override public void close() { + mFileDescriptor.setInt$(-1); if (mCleaner != null) { mCleaner.clean(); mCleaner = null; @@ -305,10 +306,10 @@ public final class SharedMemory implements Parcelable, Closeable { * Cleaner that closes the FD */ private static final class Closer implements Runnable { - private FileDescriptor mFd; + private int mFd; private MemoryRegistration mMemoryReference; - private Closer(FileDescriptor fd, MemoryRegistration memoryReference) { + private Closer(int fd, MemoryRegistration memoryReference) { mFd = fd; mMemoryReference = memoryReference; } @@ -316,7 +317,9 @@ public final class SharedMemory implements Parcelable, Closeable { @Override public void run() { try { - Os.close(mFd); + FileDescriptor fd = new FileDescriptor(); + fd.setInt$(mFd); + Os.close(fd); } catch (ErrnoException e) { /* swallow error */ } mMemoryReference.release(); mMemoryReference = null; diff --git a/core/java/android/os/TEST_MAPPING b/core/java/android/os/TEST_MAPPING index 55b1f940c764..07f40828eb56 100644 --- a/core/java/android/os/TEST_MAPPING +++ b/core/java/android/os/TEST_MAPPING @@ -73,6 +73,15 @@ "[^/]*BatteryConsumer[^/]*\\.java" ], "name": "BatteryUsageStatsProtoTests" + }, + { + "file_patterns": ["SharedMemory[^/]*\\.java"], + "name": "CtsOsTestCases", + "options": [ + { + "include-filter": "android.os.cts.SharedMemoryTest" + } + ] } ], "postsubmit": [ diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java index 7b8410bba6ec..b68717a9b457 100644 --- a/core/java/android/service/wallpaper/WallpaperService.java +++ b/core/java/android/service/wallpaper/WallpaperService.java @@ -196,7 +196,7 @@ public abstract class WallpaperService extends Service { EngineWindowPage[] mWindowPages = new EngineWindowPage[1]; Bitmap mLastScreenshot; int mLastWindowPage = -1; - float mLastPageOffset = 0; + private boolean mResetWindowPages; // Copies from mIWallpaperEngine. HandlerCaller mCaller; @@ -787,7 +787,7 @@ public abstract class WallpaperService extends Service { Log.w(TAG, "Can't notify system because wallpaper connection " + "was not established."); } - resetWindowPages(); + mResetWindowPages = true; processLocalColors(mPendingXOffset, mPendingXOffsetStep); } catch (RemoteException e) { Log.w(TAG, "Can't notify system because wallpaper connection was lost.", e); @@ -1515,6 +1515,7 @@ public abstract class WallpaperService extends Service { float finalXOffsetStep = xOffsetStep; float finalXOffset = xOffset; mHandler.post(() -> { + resetWindowPages(); int xPage = xCurrentPage; EngineWindowPage current; if (mWindowPages.length == 0 || (mWindowPages.length != xPages)) { @@ -1699,15 +1700,15 @@ public abstract class WallpaperService extends Service { private void resetWindowPages() { if (supportsLocalColorExtraction()) return; + if (!mResetWindowPages) return; + mResetWindowPages = false; mLastWindowPage = -1; - mHandler.post(() -> { - for (int i = 0; i < mWindowPages.length; i++) { - EngineWindowPage page = mWindowPages[i]; - if (page != null) { - page.setLastUpdateTime(0L); - } + for (int i = 0; i < mWindowPages.length; i++) { + EngineWindowPage page = mWindowPages[i]; + if (page != null) { + page.setLastUpdateTime(0L); } - }); + } } private int getRectFPage(RectF area, float step) { @@ -1730,40 +1731,8 @@ public abstract class WallpaperService extends Service { if (DEBUG) { Log.d(TAG, "addLocalColorsAreas adding local color areas " + regions); } - - List<WallpaperColors> colors = getLocalWallpaperColors(regions); mHandler.post(() -> { - float step = mPendingXOffsetStep; - if (!validStep(step)) { - step = 0; - } - for (int i = 0; i < regions.size(); i++) { - RectF area = regions.get(i); - if (!isValid(area)) continue; - int pageInx = getRectFPage(area, step); - // no page should be null - EngineWindowPage page = mWindowPages[pageInx]; - - if (page != null) { - mLocalColorAreas.add(area); - page.addArea(area); - WallpaperColors color = colors.get(i); - if (color != null && !color.equals(page.getColors(area))) { - page.addWallpaperColors(area, color); - } - } else { - mLocalColorsToAdd.add(area); - } - } - for (int i = 0; i < colors.size() && colors.get(i) != null; i++) { - try { - mConnection.onLocalWallpaperColorsChanged(regions.get(i), colors.get(i), - mDisplayContext.getDisplayId()); - } catch (RemoteException e) { - Log.e(TAG, "Error calling Connection.onLocalWallpaperColorsChanged", e); - return; - } - } + mLocalColorsToAdd.addAll(regions); processLocalColors(mPendingXOffset, mPendingYOffset); }); @@ -1784,88 +1753,15 @@ public abstract class WallpaperService extends Service { if (!validStep(step)) { return; } - for (int i = 0; i < regions.size(); i++) { - RectF area = regions.get(i); - if (!isValid(area)) continue; - int pageInx = getRectFPage(area, step); - // no page should be null - EngineWindowPage page = mWindowPages[pageInx]; - if (page != null) { - page.removeArea(area); + for (int i = 0; i < mWindowPages.length; i++) { + for (int j = 0; j < regions.size(); j++) { + EngineWindowPage page = mWindowPages[i]; + if (page != null) page.removeArea(regions.get(j)); } } }); } - private @NonNull List<WallpaperColors> getLocalWallpaperColors(@NonNull List<RectF> areas) { - ArrayList<WallpaperColors> colors = new ArrayList<>(areas.size()); - float step = mPendingXOffsetStep; - if (!validStep(step)) { - if (DEBUG) Log.d(TAG, "invalid step size " + step); - step = 1.0f; - } - for (int i = 0; i < areas.size(); i++) { - RectF currentArea = areas.get(i); - if (currentArea == null || !isValid(currentArea)) { - Log.wtf(TAG, "invalid local area " + currentArea); - continue; - } - EngineWindowPage page; - RectF area; - int pageIndx; - synchronized (mLock) { - pageIndx = getRectFPage(currentArea, step); - if (mWindowPages.length == 0 || pageIndx < 0 - || pageIndx > mWindowPages.length || !isValid(currentArea)) { - colors.add(null); - continue; - } - area = generateSubRect(currentArea, pageIndx, mWindowPages.length); - page = mWindowPages[pageIndx]; - } - if (page == null) { - colors.add(null); - continue; - } - float finalStep = step; - int finalPageIndx = pageIndx; - Bitmap screenShot = page.getBitmap(); - if (screenShot == null) screenShot = mLastScreenshot; - if (screenShot == null || screenShot.isRecycled()) { - if (DEBUG) { - Log.d(TAG, "invalid bitmap " + screenShot - + " for page " + finalPageIndx); - } - page.setLastUpdateTime(0); - colors.add(null); - continue; - } - Bitmap b = screenShot; - Rect subImage = new Rect( - Math.round(area.left * b.getWidth() / finalStep), - Math.round(area.top * b.getHeight()), - Math.round(area.right * b.getWidth() / finalStep), - Math.round(area.bottom * b.getHeight()) - ); - subImage = fixRect(b, subImage); - if (DEBUG) { - Log.d(TAG, "getting subbitmap of " + subImage.toString() - + " for RectF " + area.toString() - + " screenshot width " + screenShot.getWidth() + " height " - + screenShot.getHeight()); - } - Bitmap colorImg = Bitmap.createBitmap(screenShot, - subImage.left, subImage.top, subImage.width(), subImage.height()); - if (DEBUG) { - Log.d(TAG, "created bitmap " + colorImg.getWidth() + ", " - + colorImg.getHeight()); - } - WallpaperColors color = WallpaperColors.fromBitmap(colorImg); - colors.add(color); - } - return colors; - } - // fix the rect to be included within the bounds of the bitmap private Rect fixRect(Bitmap b, Rect r) { r.left = r.left >= r.right || r.left >= b.getWidth() || r.left > 0 diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java index e7ff978266a2..9cb0d1ff2c3f 100644 --- a/core/java/android/view/Display.java +++ b/core/java/android/view/Display.java @@ -1463,10 +1463,10 @@ public final class Display { return false; } final Configuration config = mResources.getConfiguration(); - // TODO(b/179308296) Temporarily - never report max bounds to only Launcher if the feature - // is disabled. + // TODO(b/179308296) Temporarily exclude Launcher from being given max bounds, by checking + // if the caller is the recents component. return config != null && !config.windowConfiguration.getMaxBounds().isEmpty() - && (mDisplayInfo.shouldConstrainMetricsForLauncher || !isRecentsComponent()); + && !isRecentsComponent(); } /** diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java index 657251046551..8e5f905e9c74 100644 --- a/core/java/android/view/DisplayInfo.java +++ b/core/java/android/view/DisplayInfo.java @@ -306,13 +306,6 @@ public final class DisplayInfo implements Parcelable { public float brightnessDefault; /** - * @hide - * True if Display#getRealSize and getRealMetrics should be constrained for Launcher, false - * otherwise. - */ - public boolean shouldConstrainMetricsForLauncher = false; - - /** * The {@link RoundedCorners} if present, otherwise {@code null}. */ @Nullable @@ -388,8 +381,7 @@ public final class DisplayInfo implements Parcelable { && brightnessMinimum == other.brightnessMinimum && brightnessMaximum == other.brightnessMaximum && brightnessDefault == other.brightnessDefault - && Objects.equals(roundedCorners, other.roundedCorners) - && shouldConstrainMetricsForLauncher == other.shouldConstrainMetricsForLauncher; + && Objects.equals(roundedCorners, other.roundedCorners); } @Override @@ -440,7 +432,6 @@ public final class DisplayInfo implements Parcelable { brightnessMaximum = other.brightnessMaximum; brightnessDefault = other.brightnessDefault; roundedCorners = other.roundedCorners; - shouldConstrainMetricsForLauncher = other.shouldConstrainMetricsForLauncher; } public void readFromParcel(Parcel source) { @@ -497,7 +488,6 @@ public final class DisplayInfo implements Parcelable { for (int i = 0; i < numUserDisabledFormats; i++) { userDisabledHdrTypes[i] = source.readInt(); } - shouldConstrainMetricsForLauncher = source.readBoolean(); } @Override @@ -552,7 +542,6 @@ public final class DisplayInfo implements Parcelable { for (int i = 0; i < userDisabledHdrTypes.length; i++) { dest.writeInt(userDisabledHdrTypes[i]); } - dest.writeBoolean(shouldConstrainMetricsForLauncher); } @Override @@ -807,8 +796,6 @@ public final class DisplayInfo implements Parcelable { sb.append(brightnessMaximum); sb.append(", brightnessDefault "); sb.append(brightnessDefault); - sb.append(", shouldConstrainMetricsForLauncher "); - sb.append(shouldConstrainMetricsForLauncher); sb.append("}"); return sb.toString(); } diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index ae32a481691a..b64d25a5b72c 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -33,7 +33,6 @@ import android.os.Bundle; import android.os.IRemoteCallback; import android.os.ParcelFileDescriptor; import android.view.DisplayCutout; -import android.view.DisplayInfo; import android.view.IApplicationToken; import android.view.IAppTransitionAnimationSpecsFuture; import android.view.ICrossWindowBlurEnabledListener; @@ -746,17 +745,6 @@ interface IWindowManager out InsetsState outInsetsState); /** - * Returns a list of {@link android.view.DisplayInfo} for the logical display. This is not - * guaranteed to include all possible device states. The list items are unique. - * - * If invoked through a package other than a launcher app, returns an empty list. - * - * @param displayId the id of the logical display - * @param packageName the name of the calling package - */ - List<DisplayInfo> getPossibleDisplayInfo(int displayId, String packageName); - - /** * Called to show global actions. */ void showGlobalActions(); diff --git a/core/java/android/view/ImeInsetsSourceConsumer.java b/core/java/android/view/ImeInsetsSourceConsumer.java index 02b2c5d5db84..d609fb8eb234 100644 --- a/core/java/android/view/ImeInsetsSourceConsumer.java +++ b/core/java/android/view/ImeInsetsSourceConsumer.java @@ -124,7 +124,12 @@ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer { public void setControl(@Nullable InsetsSourceControl control, int[] showTypes, int[] hideTypes) { super.setControl(control, showTypes, hideTypes); - if (control == null && !isRequestedVisibleAwaitingControl()) { + // TODO(b/204524304): clean-up how to deal with the timing issues of hiding IME: + // 1) Already requested show IME, in the meantime of WM callback the control but got null + // control when relayout comes first + // 2) Make sure no regression on some implicit request IME visibility calls (e.g. + // toggleSoftInput) + if (control == null && !mIsRequestedVisibleAwaitingControl) { hide(); removeSurface(); } diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java index adda721e00a4..9bf71ec80998 100644 --- a/core/java/android/view/InsetsController.java +++ b/core/java/android/view/InsetsController.java @@ -1266,6 +1266,11 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation public void notifyFinished(InsetsAnimationControlRunner runner, boolean shown) { cancelAnimation(runner, false /* invokeCallback */); if (DEBUG) Log.d(TAG, "notifyFinished. shown: " + shown); + if (runner.getAnimationType() == ANIMATION_TYPE_RESIZE) { + // The resize animation doesn't show or hide the insets. We shouldn't change the + // requested visibility. + return; + } if (shown) { showDirectly(runner.getTypes(), true /* fromIme */); } else { diff --git a/core/java/android/view/InsetsResizeAnimationRunner.java b/core/java/android/view/InsetsResizeAnimationRunner.java index e1352dd8dd4f..edcfc95fe4e4 100644 --- a/core/java/android/view/InsetsResizeAnimationRunner.java +++ b/core/java/android/view/InsetsResizeAnimationRunner.java @@ -131,6 +131,9 @@ public class InsetsResizeAnimationRunner implements InsetsAnimationControlRunner @Override public boolean applyChangeInsets(InsetsState outState) { + if (mCancelled) { + return false; + } final float fraction = mAnimation.getInterpolatedFraction(); for (@InternalInsetsType int type = 0; type < InsetsState.SIZE; type++) { final InsetsSource fromSource = mFromState.peekSource(type); diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java index 39172794f602..75b69cb12d32 100644 --- a/core/java/android/view/InsetsState.java +++ b/core/java/android/view/InsetsState.java @@ -202,7 +202,7 @@ public class InsetsState implements Parcelable { @Nullable @InternalInsetsSide SparseIntArray typeSideMap) { Insets[] typeInsetsMap = new Insets[Type.SIZE]; Insets[] typeMaxInsetsMap = new Insets[Type.SIZE]; - boolean[] typeVisibilityMap = new boolean[Type.SIZE]; + boolean[] typeVisibilityMap = new boolean[SIZE]; final Rect relativeFrame = new Rect(frame); final Rect relativeFrameMax = new Rect(frame); for (int type = FIRST_TYPE; type <= LAST_TYPE; type++) { diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index cdfd7bea1a82..f1eb783726db 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -768,6 +768,12 @@ public final class ViewRootImpl implements ViewParent, private boolean mWaitForBlastSyncComplete = false; /** + * Keeps track of the last frame number that was attempted to draw. Should only be accessed on + * the RenderThread. + */ + private long mRtLastAttemptedDrawFrameNum = 0; + + /** * Keeps track of whether a traverse was triggered while the UI thread was paused. This can * occur when the client is waiting on another process to submit the transaction that * contains the buffer. The UI thread needs to wait on the callback before it can submit @@ -4051,73 +4057,112 @@ public final class ViewRootImpl implements ViewParent, } /** - * The callback will run on the render thread. + * Only call this on the UI Thread. */ - private HardwareRenderer.FrameCompleteCallback createFrameCompleteCallback(Handler handler, - boolean reportNextDraw, ArrayList<Runnable> commitCallbacks) { - final Consumer<SurfaceControl.Transaction> blastSyncConsumer = mBLASTDrawConsumer; - mBLASTDrawConsumer = null; - return frameNr -> { + void clearBlastSync() { + mNextDrawUseBlastSync = false; + mWaitForBlastSyncComplete = false; + if (DEBUG_BLAST) { + Log.d(mTag, "Scheduling a traversal=" + mRequestedTraverseWhilePaused + + " due to a previous skipped traversal."); + } + if (mRequestedTraverseWhilePaused) { + mRequestedTraverseWhilePaused = false; + scheduleTraversals(); + } + } + + /** + * @hide + */ + public boolean isHardwareEnabled() { + return mAttachInfo.mThreadedRenderer != null && mAttachInfo.mThreadedRenderer.isEnabled(); + } + + private boolean addFrameCompleteCallbackIfNeeded(boolean reportNextDraw) { + if (!isHardwareEnabled()) { + return false; + } + + if (!mNextDrawUseBlastSync && !reportNextDraw) { + return false; + } + + if (DEBUG_BLAST) { + Log.d(mTag, "Creating frameCompleteCallback"); + } + + mAttachInfo.mThreadedRenderer.setFrameCompleteCallback(() -> { + long frameNr = mBlastBufferQueue.getLastAcquiredFrameNum(); if (DEBUG_BLAST) { - Log.d(mTag, "Received frameCompleteCallback frameNum=" + frameNr); + Log.d(mTag, "Received frameCompleteCallback " + + " lastAcquiredFrameNum=" + frameNr + + " lastAttemptedDrawFrameNum=" + mRtLastAttemptedDrawFrameNum); } - handler.postAtFrontOfQueue(() -> { + boolean frameWasNotDrawn = frameNr != mRtLastAttemptedDrawFrameNum; + // If frame wasn't drawn, clear out the next transaction so it doesn't affect the next + // draw attempt. The next transaction and transaction complete callback were only set + // for the current draw attempt. + if (frameWasNotDrawn) { + mBlastBufferQueue.setNextTransaction(null); + mBlastBufferQueue.setTransactionCompleteCallback(mRtLastAttemptedDrawFrameNum, + null); + } + + mHandler.postAtFrontOfQueue(() -> { if (mNextDrawUseBlastSync) { // We don't need to synchronize mRtBLASTSyncTransaction here since we're // guaranteed that this is called after onFrameDraw and mNextDrawUseBlastSync // is only true when the UI thread is paused. Therefore, no one should be // modifying this object until the next vsync. mSurfaceChangedTransaction.merge(mRtBLASTSyncTransaction); - if (blastSyncConsumer != null) { - blastSyncConsumer.accept(mSurfaceChangedTransaction); + if (mBLASTDrawConsumer != null) { + mBLASTDrawConsumer.accept(mSurfaceChangedTransaction); } + mBLASTDrawConsumer = null; } if (reportNextDraw) { - // TODO: Use the frame number pendingDrawFinished(); } - if (commitCallbacks != null) { - for (int i = 0; i < commitCallbacks.size(); i++) { - commitCallbacks.get(i).run(); - } + + if (frameWasNotDrawn) { + clearBlastSync(); } }); - }; - } - - /** - * @hide - */ - public boolean isHardwareEnabled() { - return mAttachInfo.mThreadedRenderer != null && mAttachInfo.mThreadedRenderer.isEnabled(); + }); + return true; } - private boolean addFrameCompleteCallbackIfNeeded() { + private void addFrameCommitCallbackIfNeeded() { if (!isHardwareEnabled()) { - return false; + return; } ArrayList<Runnable> commitCallbacks = mAttachInfo.mTreeObserver .captureFrameCommitCallbacks(); - final boolean needFrameCompleteCallback = - mNextDrawUseBlastSync || mReportNextDraw - || (commitCallbacks != null && commitCallbacks.size() > 0); - if (needFrameCompleteCallback) { - if (DEBUG_BLAST) { - Log.d(mTag, "Creating frameCompleteCallback" - + " mNextDrawUseBlastSync=" + mNextDrawUseBlastSync - + " mReportNextDraw=" + mReportNextDraw - + " commitCallbacks size=" - + (commitCallbacks == null ? 0 : commitCallbacks.size())); - } - mAttachInfo.mThreadedRenderer.setFrameCompleteCallback( - createFrameCompleteCallback(mAttachInfo.mHandler, mReportNextDraw, - commitCallbacks)); - return true; + final boolean needFrameCommitCallback = + (commitCallbacks != null && commitCallbacks.size() > 0); + if (!needFrameCommitCallback) { + return; } - return false; + + if (DEBUG_DRAW) { + Log.d(mTag, "Creating frameCommitCallback" + + " commitCallbacks size=" + commitCallbacks.size()); + } + mAttachInfo.mThreadedRenderer.setFrameCommitCallback(didProduceBuffer -> { + if (DEBUG_DRAW) { + Log.d(mTag, "Received frameCommitCallback didProduceBuffer=" + didProduceBuffer); + } + + mHandler.postAtFrontOfQueue(() -> { + for (int i = 0; i < commitCallbacks.size(); i++) { + commitCallbacks.get(i).run(); + } + }); + }); } private void addFrameCallbackIfNeeded() { @@ -4147,6 +4192,8 @@ public final class ViewRootImpl implements ViewParent, + " Creating transactionCompleteCallback=" + nextDrawUseBlastSync); } + mRtLastAttemptedDrawFrameNum = frame; + if (needsCallbackForBlur) { mBlurRegionAggregator .dispatchBlurTransactionIfNeeded(frame, blurRegionsForFrame, hasBlurUpdates); @@ -4169,18 +4216,7 @@ public final class ViewRootImpl implements ViewParent, if (DEBUG_BLAST) { Log.d(mTag, "Received transactionCompleteCallback frameNum=" + frame); } - mHandler.postAtFrontOfQueue(() -> { - mNextDrawUseBlastSync = false; - mWaitForBlastSyncComplete = false; - if (DEBUG_BLAST) { - Log.d(mTag, "Scheduling a traversal=" + mRequestedTraverseWhilePaused - + " due to a previous skipped traversal."); - } - if (mRequestedTraverseWhilePaused) { - mRequestedTraverseWhilePaused = false; - scheduleTraversals(); - } - }); + mHandler.postAtFrontOfQueue(this::clearBlastSync); }); } }; @@ -4201,8 +4237,9 @@ public final class ViewRootImpl implements ViewParent, mIsDrawing = true; Trace.traceBegin(Trace.TRACE_TAG_VIEW, "draw"); - boolean usingAsyncReport = addFrameCompleteCallbackIfNeeded(); addFrameCallbackIfNeeded(); + addFrameCommitCallbackIfNeeded(); + boolean usingAsyncReport = addFrameCompleteCallbackIfNeeded(mReportNextDraw); try { boolean canUseAsync = draw(fullRedrawNeeded); @@ -8374,7 +8411,7 @@ public final class ViewRootImpl implements ViewParent, if (mTranslator != null) { mTranslator.translateInsetsStateInScreenToAppWindow(insetsState); } - if (insetsState != null && insetsState.getSource(ITYPE_IME).isVisible()) { + if (insetsState != null && insetsState.getSourceOrDefaultVisibility(ITYPE_IME)) { ImeTracing.getInstance().triggerClientDump("ViewRootImpl#dispatchInsetsChanged", getInsetsController().getHost().getInputMethodManager(), null /* icProto */); } @@ -8399,7 +8436,7 @@ public final class ViewRootImpl implements ViewParent, mTranslator.translateInsetsStateInScreenToAppWindow(insetsState); mTranslator.translateSourceControlsInScreenToAppWindow(activeControls); } - if (insetsState != null && insetsState.getSource(ITYPE_IME).isVisible()) { + if (insetsState != null && insetsState.getSourceOrDefaultVisibility(ITYPE_IME)) { ImeTracing.getInstance().triggerClientDump("ViewRootImpl#dispatchInsetsControlChanged", getInsetsController().getHost().getInputMethodManager(), null /* icProto */); } diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java index cde1cc704f92..0f1a9d9c0a98 100644 --- a/core/java/android/view/WindowInsets.java +++ b/core/java/android/view/WindowInsets.java @@ -903,16 +903,6 @@ public final class WindowInsets { result.append(mPrivacyIndicatorBounds != null ? "privacyIndicatorBounds=" + mPrivacyIndicatorBounds : ""); result.append("\n "); - result.append("compatInsetsTypes=" + mCompatInsetsTypes); - result.append("\n "); - result.append("compatIgnoreVisibility=" + mCompatIgnoreVisibility); - result.append("\n "); - result.append("systemWindowInsetsConsumed=" + mSystemWindowInsetsConsumed); - result.append("\n "); - result.append("stableInsetsConsumed=" + mStableInsetsConsumed); - result.append("\n "); - result.append("displayCutoutConsumed=" + mDisplayCutoutConsumed); - result.append("\n "); result.append(isRound() ? "round" : ""); result.append("}"); return result.toString(); diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index 8764ccc9d5f8..27c5ac2887c1 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -123,7 +123,6 @@ import java.lang.annotation.RetentionPolicy; import java.util.Arrays; import java.util.List; import java.util.Objects; -import java.util.Set; import java.util.concurrent.Executor; import java.util.function.Consumer; @@ -715,20 +714,6 @@ public interface WindowManager extends ViewManager { } /** - * Returns a set of {@link WindowMetrics} for the given display. Each WindowMetrics instance - * is the maximum WindowMetrics for a device state, including rotations. This is not guaranteed - * to include all possible device states. - * - * This API can only be used by Launcher. - * - * @param displayId the id of the logical display - * @hide - */ - default @NonNull Set<WindowMetrics> getPossibleMaximumWindowMetrics(int displayId) { - throw new UnsupportedOperationException(); - } - - /** * Used to asynchronously request Keyboard Shortcuts from the focused window. * * @hide @@ -4769,6 +4754,16 @@ public interface WindowManager extends ViewManager { return Integer.toString(inputFeature); } } + + /** + * True if the window should consume all pointer events itself, regardless of whether they + * are inside of the window. If the window is modal, its touchable region will expand to the + * size of its task. + * @hide + */ + public boolean isModal() { + return (flags & (FLAG_NOT_TOUCH_MODAL | FLAG_NOT_FOCUSABLE)) == 0; + } } /** diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java index 1c915cb016d4..a2d3e3447354 100644 --- a/core/java/android/view/WindowManagerImpl.java +++ b/core/java/android/view/WindowManagerImpl.java @@ -16,9 +16,12 @@ package android.view; -import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; +import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; +import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION; import static android.view.View.SYSTEM_UI_FLAG_VISIBLE; import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW; +import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR; +import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW; import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING; import static android.window.WindowProviderService.isWindowProviderService; @@ -43,9 +46,7 @@ import android.window.WindowProvider; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.os.IResultReceiver; -import java.util.HashSet; import java.util.List; -import java.util.Set; import java.util.concurrent.Executor; import java.util.function.Consumer; @@ -303,83 +304,31 @@ public final class WindowManagerImpl implements WindowManager { private WindowInsets computeWindowInsets(Rect bounds) { // Initialize params which used for obtaining all system insets. final WindowManager.LayoutParams params = new WindowManager.LayoutParams(); + params.flags = FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR; final Context context = (mParentWindow != null) ? mParentWindow.getContext() : mContext; params.token = Context.getToken(context); - return getWindowInsetsFromServerForCurrentDisplay(params, bounds); - } + params.systemUiVisibility = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + | SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION; + params.setFitInsetsTypes(0); + params.setFitInsetsSides(0); - private WindowInsets getWindowInsetsFromServerForCurrentDisplay( - WindowManager.LayoutParams attrs, Rect bounds) { - final Configuration config = mContext.getResources().getConfiguration(); - return getWindowInsetsFromServerForDisplay(mContext.getDisplayId(), attrs, bounds, - config.isScreenRound(), config.windowConfiguration.getWindowingMode()); + return getWindowInsetsFromServer(params, bounds); } - /** - * Retrieves WindowInsets for the given context and display, given the window bounds. - * - * @param displayId the ID of the logical display to calculate insets for - * @param attrs the LayoutParams for the calling app - * @param bounds the window bounds to calculate insets for - * @param isScreenRound if the display identified by displayId is round - * @param windowingMode the windowing mode of the window to calculate insets for - * @return WindowInsets calculated for the given window bounds, on the given display - */ - private static WindowInsets getWindowInsetsFromServerForDisplay(int displayId, - WindowManager.LayoutParams attrs, Rect bounds, boolean isScreenRound, - int windowingMode) { + private WindowInsets getWindowInsetsFromServer(WindowManager.LayoutParams attrs, Rect bounds) { try { final InsetsState insetsState = new InsetsState(); final boolean alwaysConsumeSystemBars = WindowManagerGlobal.getWindowManagerService() - .getWindowInsets(attrs, displayId, insetsState); + .getWindowInsets(attrs, mContext.getDisplayId(), insetsState); + final Configuration config = mContext.getResources().getConfiguration(); + final boolean isScreenRound = config.isScreenRound(); + final int windowingMode = config.windowConfiguration.getWindowingMode(); return insetsState.calculateInsets(bounds, null /* ignoringVisibilityState*/, isScreenRound, alwaysConsumeSystemBars, SOFT_INPUT_ADJUST_NOTHING, attrs.flags, - SYSTEM_UI_FLAG_VISIBLE, attrs.type, windowingMode, - null /* typeSideMap */); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - @Override - @NonNull - public Set<WindowMetrics> getPossibleMaximumWindowMetrics(int displayId) { - List<DisplayInfo> possibleDisplayInfos; - try { - possibleDisplayInfos = WindowManagerGlobal.getWindowManagerService() - .getPossibleDisplayInfo(displayId, mContext.getPackageName()); + SYSTEM_UI_FLAG_VISIBLE, attrs.type, windowingMode, null /* typeSideMap */); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } - - Set<WindowMetrics> maxMetrics = new HashSet<>(); - WindowInsets windowInsets; - DisplayInfo currentDisplayInfo; - final WindowManager.LayoutParams params = new WindowManager.LayoutParams(); - for (int i = 0; i < possibleDisplayInfos.size(); i++) { - currentDisplayInfo = possibleDisplayInfos.get(i); - - // Calculate max bounds for this rotation and state. - Rect maxBounds = new Rect(0, 0, currentDisplayInfo.logicalWidth, - currentDisplayInfo.logicalHeight); - - // Calculate insets for the rotated max bounds. - final boolean isScreenRound = (currentDisplayInfo.flags & Display.FLAG_ROUND) != 0; - // Initialize insets based upon display rotation. Note any window-provided insets - // will not be set. - windowInsets = getWindowInsetsFromServerForDisplay( - currentDisplayInfo.displayId, params, - new Rect(0, 0, currentDisplayInfo.getNaturalWidth(), - currentDisplayInfo.getNaturalHeight()), isScreenRound, - WINDOWING_MODE_FULLSCREEN); - // Set the hardware-provided insets. - windowInsets = new WindowInsets.Builder(windowInsets).setRoundedCorners( - currentDisplayInfo.roundedCorners) - .setDisplayCutout(currentDisplayInfo.displayCutout).build(); - - maxMetrics.add(new WindowMetrics(maxBounds, windowInsets)); - } - return maxMetrics; } @Override diff --git a/core/java/android/view/WindowManagerPolicyConstants.java b/core/java/android/view/WindowManagerPolicyConstants.java index e634d601c1f1..94f633314b4e 100644 --- a/core/java/android/view/WindowManagerPolicyConstants.java +++ b/core/java/android/view/WindowManagerPolicyConstants.java @@ -236,6 +236,9 @@ public interface WindowManagerPolicyConstants { */ int LAYER_OFFSET_THUMBNAIL = WINDOW_LAYER_MULTIPLIER - 1; + // TODO(b/207185041): Remove this divider workaround after we full remove leagacy split and + // make app pair split only have single root then we can just attach the + // divider to the single root task in shell. int SPLIT_DIVIDER_LAYER = TYPE_LAYER_MULTIPLIER * 3; int WATERMARK_LAYER = TYPE_LAYER_MULTIPLIER * 100; int STRICT_MODE_LAYER = TYPE_LAYER_MULTIPLIER * 101; diff --git a/core/java/android/view/contentcapture/ContentCaptureManager.java b/core/java/android/view/contentcapture/ContentCaptureManager.java index 9241c3074ddd..cd3c8c9c48f2 100644 --- a/core/java/android/view/contentcapture/ContentCaptureManager.java +++ b/core/java/android/view/contentcapture/ContentCaptureManager.java @@ -483,6 +483,8 @@ public final class ContentCaptureManager { /** * Returns the component name of the system service that is consuming the captured events for * the current user. + * + * @throws RuntimeException if getting the component name is timed out. */ @Nullable public ComponentName getServiceComponentName() { diff --git a/core/java/android/window/WindowContainerTransaction.java b/core/java/android/window/WindowContainerTransaction.java index bbf813891387..6864ccaa7c8a 100644 --- a/core/java/android/window/WindowContainerTransaction.java +++ b/core/java/android/window/WindowContainerTransaction.java @@ -368,10 +368,12 @@ public final class WindowContainerTransaction implements Parcelable { */ @NonNull public WindowContainerTransaction setAdjacentRoots( - @NonNull WindowContainerToken root1, @NonNull WindowContainerToken root2) { + @NonNull WindowContainerToken root1, @NonNull WindowContainerToken root2, + boolean moveTogether) { mHierarchyOps.add(HierarchyOp.createForAdjacentRoots( root1.asBinder(), - root2.asBinder())); + root2.asBinder(), + moveTogether)); return this; } @@ -975,6 +977,9 @@ public final class WindowContainerTransaction implements Parcelable { private boolean mReparentTopOnly; + // TODO(b/207185041): Remove this once having a single-top root for split screen. + private boolean mMoveAdjacentTogether; + @Nullable private int[] mWindowingModes; @@ -1033,10 +1038,13 @@ public final class WindowContainerTransaction implements Parcelable { .build(); } - public static HierarchyOp createForAdjacentRoots(IBinder root1, IBinder root2) { + /** Create a hierarchy op for setting adjacent root tasks. */ + public static HierarchyOp createForAdjacentRoots(IBinder root1, IBinder root2, + boolean moveTogether) { return new HierarchyOp.Builder(HIERARCHY_OP_TYPE_SET_ADJACENT_ROOTS) .setContainer(root1) .setReparentContainer(root2) + .setMoveAdjacentTogether(moveTogether) .build(); } @@ -1070,6 +1078,7 @@ public final class WindowContainerTransaction implements Parcelable { mReparent = copy.mReparent; mToTop = copy.mToTop; mReparentTopOnly = copy.mReparentTopOnly; + mMoveAdjacentTogether = copy.mMoveAdjacentTogether; mWindowingModes = copy.mWindowingModes; mActivityTypes = copy.mActivityTypes; mLaunchOptions = copy.mLaunchOptions; @@ -1084,6 +1093,7 @@ public final class WindowContainerTransaction implements Parcelable { mReparent = in.readStrongBinder(); mToTop = in.readBoolean(); mReparentTopOnly = in.readBoolean(); + mMoveAdjacentTogether = in.readBoolean(); mWindowingModes = in.createIntArray(); mActivityTypes = in.createIntArray(); mLaunchOptions = in.readBundle(); @@ -1128,6 +1138,10 @@ public final class WindowContainerTransaction implements Parcelable { return mReparentTopOnly; } + public boolean getMoveAdjacentTogether() { + return mMoveAdjacentTogether; + } + public int[] getWindowingModes() { return mWindowingModes; } @@ -1175,7 +1189,8 @@ public final class WindowContainerTransaction implements Parcelable { return "{reorder: " + mContainer + " to " + (mToTop ? "top" : "bottom") + "}"; case HIERARCHY_OP_TYPE_SET_ADJACENT_ROOTS: return "{SetAdjacentRoot: container=" + mContainer - + " adjacentRoot=" + mReparent + "}"; + + " adjacentRoot=" + mReparent + " mMoveAdjacentTogether=" + + mMoveAdjacentTogether + "}"; case HIERARCHY_OP_TYPE_LAUNCH_TASK: return "{LaunchTask: " + mLaunchOptions + "}"; case HIERARCHY_OP_TYPE_SET_LAUNCH_ADJACENT_FLAG_ROOT: @@ -1212,6 +1227,7 @@ public final class WindowContainerTransaction implements Parcelable { dest.writeStrongBinder(mReparent); dest.writeBoolean(mToTop); dest.writeBoolean(mReparentTopOnly); + dest.writeBoolean(mMoveAdjacentTogether); dest.writeIntArray(mWindowingModes); dest.writeIntArray(mActivityTypes); dest.writeBundle(mLaunchOptions); @@ -1251,6 +1267,8 @@ public final class WindowContainerTransaction implements Parcelable { private boolean mReparentTopOnly; + private boolean mMoveAdjacentTogether; + @Nullable private int[] mWindowingModes; @@ -1293,6 +1311,11 @@ public final class WindowContainerTransaction implements Parcelable { return this; } + Builder setMoveAdjacentTogether(boolean moveAdjacentTogether) { + mMoveAdjacentTogether = moveAdjacentTogether; + return this; + } + Builder setWindowingModes(@Nullable int[] windowingModes) { mWindowingModes = windowingModes; return this; @@ -1336,6 +1359,7 @@ public final class WindowContainerTransaction implements Parcelable { : null; hierarchyOp.mToTop = mToTop; hierarchyOp.mReparentTopOnly = mReparentTopOnly; + hierarchyOp.mMoveAdjacentTogether = mMoveAdjacentTogether; hierarchyOp.mLaunchOptions = mLaunchOptions; hierarchyOp.mActivityIntent = mActivityIntent; hierarchyOp.mPendingIntent = mPendingIntent; diff --git a/core/jni/android_graphics_BLASTBufferQueue.cpp b/core/jni/android_graphics_BLASTBufferQueue.cpp index c1587eb2c4f4..3b7328e72913 100644 --- a/core/jni/android_graphics_BLASTBufferQueue.cpp +++ b/core/jni/android_graphics_BLASTBufferQueue.cpp @@ -134,6 +134,11 @@ static void nativeSetTransactionCompleteCallback(JNIEnv* env, jclass clazz, jlon } } +static jlong nativeGetLastAcquiredFrameNum(JNIEnv* env, jclass clazz, jlong ptr) { + sp<BLASTBufferQueue> queue = reinterpret_cast<BLASTBufferQueue*>(ptr); + return queue->getLastAcquiredFrameNum(); +} + static const JNINativeMethod gMethods[] = { /* name, signature, funcPtr */ // clang-format off @@ -145,7 +150,8 @@ static const JNINativeMethod gMethods[] = { {"nativeMergeWithNextTransaction", "(JJJ)V", (void*)nativeMergeWithNextTransaction}, {"nativeSetTransactionCompleteCallback", "(JJLandroid/graphics/BLASTBufferQueue$TransactionCompleteCallback;)V", - (void*)nativeSetTransactionCompleteCallback} + (void*)nativeSetTransactionCompleteCallback}, + {"nativeGetLastAcquiredFrameNum", "(J)J", (void*)nativeGetLastAcquiredFrameNum}, // clang-format on }; diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp index 4c2b114c724a..5e0d9b32380c 100644 --- a/core/jni/android_os_Debug.cpp +++ b/core/jni/android_os_Debug.cpp @@ -34,6 +34,7 @@ #include <vector> #include <android-base/logging.h> +#include <android-base/properties.h> #include <bionic/malloc.h> #include <debuggerd/client.h> #include <log/log.h> @@ -859,7 +860,22 @@ static jlong android_os_Debug_getDmabufHeapPoolsSizeKb(JNIEnv* env, jobject claz return poolsSizeKb; } +static bool halSupportsGpuPrivateMemory() { + int productApiLevel = + android::base::GetIntProperty("ro.product.first_api_level", + android::base::GetIntProperty("ro.build.version.sdk", + __ANDROID_API_FUTURE__)); + int boardApiLevel = + android::base::GetIntProperty("ro.board.api_level", + android::base::GetIntProperty("ro.board.first_api_level", + __ANDROID_API_FUTURE__)); + + return std::min(productApiLevel, boardApiLevel) >= __ANDROID_API_S__; +} + static jlong android_os_Debug_getGpuPrivateMemoryKb(JNIEnv* env, jobject clazz) { + static bool gpuPrivateMemorySupported = halSupportsGpuPrivateMemory(); + struct memtrack_proc* p = memtrack_proc_new(); if (p == nullptr) { LOG(ERROR) << "getGpuPrivateMemoryKb: Failed to create memtrack_proc"; @@ -876,6 +892,12 @@ static jlong android_os_Debug_getGpuPrivateMemoryKb(JNIEnv* env, jobject clazz) ssize_t gpuPrivateMem = memtrack_proc_gl_pss(p); memtrack_proc_destroy(p); + + // Old HAL implementations may return 0 for GPU private memory if not supported + if (gpuPrivateMem == 0 && !gpuPrivateMemorySupported) { + return -1; + } + return gpuPrivateMem / 1024; } diff --git a/core/res/res/layout/splash_screen_view.xml b/core/res/res/layout/splash_screen_view.xml index 2b9f95227f08..304affe068a4 100644 --- a/core/res/res/layout/splash_screen_view.xml +++ b/core/res/res/layout/splash_screen_view.xml @@ -36,6 +36,7 @@ android:layout_marginBottom="60dp" android:padding="0dp" android:background="@null" + android:forceHasOverlappingRendering="false" android:contentDescription="@string/splash_screen_view_branding_description"/> </android.window.SplashScreenView>
\ No newline at end of file diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml index 7763416976c1..ec1300b8b7a3 100644 --- a/core/res/res/values-af/strings.xml +++ b/core/res/res/values-af/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"Monitor pogings om skerm te ontsluit"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Monitor die aantal keer wat \'n verkeerde wagwoorde ingevoer is wanneer die skerm ontsluit word. Sluit die tablet of vee al die data uit as die wagwoord te veel keer verkeerd ingevoer word."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Monitor die aantal verkeerde wagwoorde wat ingetik word wanneer die skerm ontsluit word, en sluit jou Android TV-toestel of vee al jou Android TV-toestel se data uit as te veel verkeerde wagwoorde ingetik word."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Monitor die aantal verkeerde wagwoorde wat ingevoer word wanneer die skerm ontsluit word, en sluit die inligtingvermaakstelsel of vee al die inligtingvermaakstelsel se data uit as te veel verkeerde wagwoorde ingevoer word."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Monitor die aantal keer wat \'n verkeerde wagwoorde ingevoer is wanneer die skerm ontsluit word. Sluit die foon of vee al die data uit as die wagwoord te veel keer verkeerd ingevoer word."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Monitor die aantal verkeerde wagwoorde wat ingevoer word wanneer die skerm ontsluit word, en sluit die tablet of vee al hierdie gebruiker se data uit as te veel verkeerde wagwoorde ingevoer word."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Monitor die aantal verkeerde wagwoorde wat ingetik word wanneer die skerm ontsluit word, en sluit jou Android TV-toestel of vee al hierdie gebruiker se data uit as hulle te veel verkeerde wagwoorde intik."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Monitor die aantal verkeerde wagwoorde wat ingevoer word wanneer die skerm ontsluit word, en sluit die inligtingvermaakstelsel of vee al hierdie profiel se data uit as te veel verkeerde wagwoorde ingevoer word."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Monitor die aantal verkeerde wagwoorde wat ingevoer word wanneer die skerm ontsluit word, en sluit die foon of vee al hierdie gebruiker se data uit as te veel verkeerde wagwoorde ingevoer word."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"Om die skermslot te verander"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"Verander die skermslot."</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"Om alle data uit te vee"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Vee die tablet se data uit sonder waarskuwing, deur \'n fabrieksterugstelling uit te voer."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Vee jou Android TV-toestel se data sonder waarskuwing uit deur \'n fabrieksterugstelling uit te voer."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Vee die inligtingvermaakstelsel se data sonder waarskuwing uit deur \'n fabriekterugstelling te doen."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Vee die foon se data uit sonder waarskuwing, deur \'n fabrieksterugstelling uit te voer."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"Vee gebruikerdata uit"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Vee profieldata uit"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Vee gebruikerdata uit"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Vee hierdie gebruiker se data in hierdie tablet sonder waarskuwing uit."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Vee hierdie gebruiker se data op hierdie Android TV-toestel sonder waarskuwing uit."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"Vee hierdie profiel se data op hierdie inligtingvermaakstelsel sonder waarskuwing uit."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"Vee hierdie gebruiker se data in hierdie foon sonder waarskuwing uit."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Stel die toestel se globale instaan"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Stel die toestel se globale instaanbediener wat gebruik moet word terwyl die beleid geaktiveer is. Net die toesteladministrateur kan die globale instaanbediener stel."</string> diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml index 1c306403aaec..bc931112d865 100644 --- a/core/res/res/values-am/strings.xml +++ b/core/res/res/values-am/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"የማሳያ-ክፈት ሙከራዎችን ክትትል ያድርጉባቸው"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"ማሳያውን በምትከፍትበት ጊዜ በስህተት የተተየቡ የይለፍ ቃሎችን ቁጥር ተቆጣጠር፤ እና ጡባዊ ተኮውን ቆልፍ ወይም በጣም ብዙ የተሳሳቱ የይለፍ ቃሎች ከተተየቡ የጡባዊ ተኮን ውሂብ አጥፋ፡፡"</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"ማያ ገጹን ሲከፍቱ በትክክል ያልተተየቡ የይለፍ ቃላት ብዛት ተከታተል፣ እና በጣም ብዙ ትክክል ያልሆኑ የይለፍ ቃላት ከተተየቡ የእርስዎን Android TV ን ቆልፍ ወይም ሁሉንም የእርስዎን Android TV ደምስስ።"</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"ማያ ገጹን ሲያስከፍቱ በትክክል ያልተተየቡ የይለፍ ቃላት ብዛት ተከታተል፣ እና በጣም ብዙ ትክክል ያልሆኑ የይለፍ ቃላት ከተተየቡ የኢንፎቴይንመንት ስርዓቱን ቆልፍ ወይም ሁሉንም የኢንፎቴይንመንት ስርዓት ውሂብ ደምስስ።"</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"የተተየቡ ልክ ያልሆኑ የይለፍ ቃሎችን ቁጥር ተቆጣጠር፡፡ማሳያውን በምትከፍትበት ጊዜ፤ እና በጣም ብዙ ልክ ያልሆኑ የይለፍ ቃሎች ከተተየቡ ስልኩን ቆልፈው ወይም ሁሉንም የስልኩን ውሂብ ደምስሰው፡፡"</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"ማያ ገጹን ሲያስከፍቱ በትክክል ያልተተየቡ የይለፍ ቃላት ብዛት ተከታተል፣ እና በጣም ብዙ ትክክል ያልሆኑ የይለፍ ቃላት ከተተየቡ ጡባዊውን ቆልፍ ወይም ሁሉንም የዚህን ተጠቃሚ ውሂብ ደምስስ።."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"ማያ ገጹን ሲያስከፍቱ በትክክል ያልተተየቡ የይለፍ ቃላት ብዛት ተከታተል፣ እና በጣም ብዙ ትክክል ያልሆኑ የይለፍ ቃላት ከተተየቡ የእርስዎ Android TV መሣሪያን ቆልፍ ወይም ሁሉንም የዚህን ተጠቃሚ ውሂብ ደምስስ።"</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"ማያ ገጹን ሲያስከፍቱ በትክክል ያልተተየቡ የይለፍ ቃላት ብዛት ተከታተል፣ እና በጣም ብዙ ትክክል ያልሆኑ የይለፍ ቃላት ከተተየቡ የኢንፎቴይንመንት ስርዓቱን ቆልፍ ወይም ሁሉንም የዚህን ተጠቃሚ ውሂብ ደምስስ።"</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"ማያ ገጹን ሲያስከፍቱ በትክክል ያልተተየቡ የይለፍ ቃላት ብዛት ተከታተል፣ እና በጣም ብዙ ትክክል ያልሆኑ የይለፍ ቃላት ከተተየቡ ስልኩን ቆልፍ ወይም ሁሉንም የዚህን ተጠቃሚ ውሂብ ደምስስ።"</string> <string name="policylab_resetPassword" msgid="214556238645096520">"የማያ ገጹን መቆለፊያ መለወጥ"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"የማያ ገጽ መቆለፊያውን ለውጥ።"</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"ሁሉንም ውሂብ መሰረዝ"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"የፋብሪካው ውሂብ ዳግም አስጀምርን በማከናወን፣ያለ ማስጠንቀቂያ የጡባዊውን ውሂብ አጥፋ።"</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"የፋብሪካ ውሂብ ዳግም ቅንብርን ያለ ማስጠንቀቂያ በማከናወን የእርስዎን Android TV መሣሪያ ውሂብን ደምስስ።"</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"የፋብሪካ ውሂብ ዳግም ማስጀመር በማከናወን ያለማስጠንቀቂያ የኢንፎቴይንመንት ስርዓትን ውሂብ ደምስስ።"</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"የፋብሪካ ውሂብ ድጋሚ አስጀምር በማከናወን ያለ ማሰጠንቀቂያ የስልኩን ውሂብ ደምስስ።"</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"የተጠቃሚ ውሂብ ደምስስ"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"የመገለጫ ውሂብ ደምስስ"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"የተጠቃሚ ውሂብ ደምስስ"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"ያለምንም ማስጠንቀቂያ የዚህን ጡባዊ የተጠቃሚ ውሂብ ደምስስ።"</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"በዚህ Android TV መሣሪያ ላይ ያለ ማስጠንቀቂያ የዚህን ተጠቃሚ ውሂብ ደምስስ።"</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"በዚህ የኢንፎቴይንመንት ሥርዓት ላይ ያለ ማስጠንቀቂያ የዚህን መገለጫ ውሂብ ደምስስ።"</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"ያለምንም ማስጠንቀቂያ የዚህን ስልክ የተጠቃሚ ውሂብ ደምስስ።"</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"የመሣሪያውን ሁሉንም ፕሮክሲ አዘጋጅ"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"መመሪያ ነቅቶ እያለ ጥቅም ላይ ሊውል የሚችለውን የመሣሪያውን ሁሉንተናዊ ተኪ አዘጋጅ። የመሣሪያ ባለቤት ብቻ የሁሉንተናዊ ተኪውን ማዘጋጀት ይችላል።"</string> diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml index 284c0e313750..ddbf6afe548c 100644 --- a/core/res/res/values-ar/strings.xml +++ b/core/res/res/values-ar/strings.xml @@ -741,9 +741,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"مراقبة محاولات فتح قفل الشاشة"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"لمراقبة عدد مرات كتابة كلمات المرور غير الصحيحة عند فتح قفل الشاشة وتأمين الجهاز اللوحي أو مسح جميع بياناته في حالة كتابة الكثير من كلمات المرور غير الصحيحة."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"يمكنك مراقبة عدد كلمات المرور غير الصحيحة التي تمت كتابتها عند فتح قفل الشاشة، وقفل جهاز Android TV أو محو جميع بيانات جهاز Android TV إذا تمت كتابة عدد أكبر من اللازم من كلمات المرور غير الصحيحة."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"يمكنك مراقبة عدد كلمات المرور غير الصحيحة التي تمت كتابتها عند فتح قفل الشاشة، وقفل \"نظام الترفيه والمعلومات\" أو محو جميع بياناته إذا تمت كتابة عدد كبير جدًا من كلمات المرور غير الصحيحة."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"مراقبة عدد كلمات المرور غير الصحيحة التي تمت كتابتها عند فتح قفل الشاشة، وتأمين الهاتف ومحو جميع بياناته إذا تمت كتابة عدد أكبر من اللازم من كلمات المرور غير الصحيحة."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"يمكنك مراقبة عدد كلمات المرور غير الصحيحة التي تمت كتابتها عند فتح قفل الشاشة، وتأمين الجهاز اللوحي ومحو جميع بيانات هذا المستخدم إذا تمت كتابة عدد أكبر من اللازم من كلمات المرور غير الصحيحة."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"يمكنك مراقبة عدد كلمات المرور غير الصحيحة التي تمت كتابتها عند فتح قفل الشاشة، وقفل جهاز Android TV أو محو جميع بيانات هذا المستخدم إذا تمت كتابة عدد أكبر من اللازم من كلمات المرور غير الصحيحة."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"يمكنك مراقبة عدد كلمات المرور غير الصحيحة التي تمت كتابتها عند فتح قفل الشاشة، وتأمين \"نظام الترفيه والمعلومات\" ومحو جميع بيانات هذا الملف الشخصي إذا تمت كتابة عدد كبير جدًا من كلمات المرور غير الصحيحة."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"يمكنك مراقبة عدد كلمات المرور غير الصحيحة التي تمت كتابتها عند فتح قفل الشاشة، وتأمين الهاتف ومحو جميع بيانات هذا المستخدم إذا تمت كتابة عدد أكبر من اللازم من كلمات المرور غير الصحيحة."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"تغيير قفل الشاشة"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"إمكانية تغيير قفل الشاشة"</string> @@ -752,10 +754,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"محو جميع البيانات"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"يمكنك محو بيانات الجهاز اللوحي بدون تحذير، وذلك عبر إجراء إعادة الضبط على الإعدادات الأصلية."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"يمكنك محو بيانات جهاز Android TV بدون تحذير عن طريق تنفيذ إعادة الضبط على الإعدادات الأصلية."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"يمكنك محو بيانات \"نظام الترفيه والمعلومات\" بدون تحذير، وذلك من خلال إعادة الضبط على الإعدادات الأصلية."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"محو بيانات الهاتف بدون تحذير، وذلك من خلال إعادة ضبط البيانات على الإعدادات الأصلية"</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"محو بيانات المستخدم"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"محو بيانات الملف الشخصي"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"محو بيانات المستخدم"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"لمحو بيانات هذا المستخدم على هذا الجهاز اللوحي بدون تحذير."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"لمحو بيانات هذا المستخدم على جهاز Android TV هذا بدون تحذير."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"يمكنك محو بيانات هذا الملف الشخصي على \"نظام الترفيه والمعلومات\" هذا بدون تحذير."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"لمحو بيانات هذا المستخدم على هذا الهاتف بدون تحذير."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"تعيين الخادم الوكيل العمومي للجهاز"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"لضبط الخادم الوكيل العام في الجهاز على الاستخدام أثناء تفعيل السياسة. ولن يمكن لأحد سوى مالك الجهاز ضبط الخادم الوكيل العام."</string> diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml index 683b093039cd..4ae2eed9af58 100644 --- a/core/res/res/values-as/strings.xml +++ b/core/res/res/values-as/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"স্ক্ৰীন আনলক কৰা প্ৰয়াসবোৰ নিৰীক্ষণ কৰক"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"স্ক্ৰীন আনলক কৰোঁতে টাইপ কৰা অশুদ্ধ পাছৱৰ্ডৰ সংখ্যা নিৰীক্ষণ কৰক আৰু যদিহে অত্যাধিকবাৰ অশুদ্ধ পাছৱৰ্ড টাইপ কৰা হয়, তেন্তে টেবলেটটো লক কৰক বা টেবলেটটোৰ আটাইখিনি ডেটা মচক।"</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"স্ক্ৰীন আনলক কৰোঁতে টাইপ কৰা ভুল পাছৱৰ্ডবোৰৰ সংখ্যা নিৰীক্ষণ কৰক আৰু যদিহে অত্যাধিকবাৰ ভুল পাছৱৰ্ড টাইপ কৰা হয়, তেন্তে Android TV ডিভাইচটো লক কৰক অথবা আপোনাৰ Android TV ডিভাইচৰ আটাইখিনি ডেটা মচক।"</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"স্ক্ৰীন আনলক কৰোঁতে দিয়া অশুদ্ধ পাছৱৰ্ডৰ সংখ্যা নিৰীক্ষণ কৰক আৰু যদিহে অত্যধিকবাৰ অশুদ্ধ পাছৱৰ্ড দিয়া হয় তেন্তে ইনফ’টেইনমেণ্ট ছিষ্টেমটো লক কৰক অথবা এই ইনফ’টেইনমেণ্ট ছিষ্টেমটোৰ আটাইবোৰ ডেটা মোহাৰক।"</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"স্ক্ৰীন আনলক কৰোঁতে টাইপ কৰা অশুদ্ধ পাছৱৰ্ডৰ সংখ্যা নিৰীক্ষণ কৰক আৰু যদিহে অত্যাধিকবাৰ অশুদ্ধ পাছৱৰ্ড টাইপ কৰা হয়, তেন্তে ফ\'নটো লক কৰক বা ফ\'নটোৰ আটাইখিনি ডেটা মচক।"</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"স্ক্ৰীন আনলক কৰোঁতে টাইপ কৰা অশুদ্ধ পাছৱৰ্ডৰ সংখ্যা নিৰীক্ষণ কৰক আৰু যদিহে অত্যধিকবাৰ অশুদ্ধ পাছৱৰ্ড টাইপ কৰা হয়, তেন্তে টেবলেটটো লক কৰক বা এই ব্যৱহাৰকাৰীৰ আটাইখিনি ডেটা মচক।"</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"স্ক্ৰীনখন আনলক কৰোঁতে টাইপ কৰা ভুল পাছৱৰ্ডবোৰৰ সংখ্যা নিৰীক্ষণ কৰক আৰু যদিহে অত্যধিকবাৰ ভুল পাছৱৰ্ড টাইপ কৰা হয়, তেন্তে Android TV ডিভাইচটো লক কৰক অথবা এই ব্যৱহাৰকাৰীৰ আটাইখিনি ডেটা মচক।"</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"স্ক্ৰীন আনলক কৰোঁতে দিয়া অশুদ্ধ পাছৱৰ্ডৰ সংখ্যা নিৰীক্ষণ কৰক আৰু যদিহে অত্যধিকবাৰ অশুদ্ধ পাছৱৰ্ড দিয়া হয় তেন্তে ইনফ’টেইনমেণ্ট ছিষ্টেমটো লক কৰক অথবা এই প্ৰ’ফাইলটোৰ আটাইবোৰ ডেটা মোহাৰক।"</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"স্ক্ৰীনখন আনলক কৰোঁতে টাইপ কৰা ভুল পাছৱৰ্ডবোৰৰ সংখ্যা নিৰীক্ষণ কৰক আৰু যদিহে অত্যধিকবাৰ ভুল পাছৱৰ্ড টাইপ কৰা হয়, তেন্তে ফ\'নটো লক কৰক অথবা এই ব্যৱহাৰকাৰীৰ আটাইখিনি ডেটা মচক।"</string> <string name="policylab_resetPassword" msgid="214556238645096520">"স্ক্ৰীন লক সলনি কৰক"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"স্ক্ৰীন লক সলনি কৰক।"</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"আটাইবোৰ ডেটা মচক"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"সতৰ্কবাণী প্ৰেৰণ নকৰাকৈয়ে ফেক্টৰী ডেটা ৰিছেট কৰি টেবলেটৰ ডেটা মচক।"</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"কোনো সতর্কবার্তা নপঠিওৱাকৈ ফেক্টৰী ডেটা ৰিছেট কৰি আপোনাৰ Android TV ডিভাইচৰ ডেটা মচক।"</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"সর্তকবাণী নিদিয়াকৈয়ে ফেক্টৰী ডেটা ৰিছেট কৰি ইনফ’টেইনমেণ্ট ছিষ্টেমৰ ডেটা মোহাৰক।"</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"সতৰ্কবাণী প্ৰেৰণ নকৰাকৈয়ে ফেক্টৰী ডেটা ৰিছেট কৰি ফ\'নৰ ডেটা মচক।"</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"ব্য়ৱহাৰকাৰীৰ তথ্য় মচক"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"প্ৰ’ফাইলৰ ডেটা মোহাৰক"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"ব্য়ৱহাৰকাৰীৰ তথ্য় মচক"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"এই টেবলেটটোত থকা এই ব্যৱহাৰকাৰীৰ তথ্য কোনো সর্তকবাণী নিদিয়াকৈ মচি পেলাওক।"</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"কোনো সতর্কবার্তা নপঠিওৱাকৈ এই Android TV ডিভাইচটোত এই ব্যৱহাৰকাৰীৰ ডেটা মচক।"</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"সর্তকবাণী নিদিয়াকৈয়ে এই ইনফ’টেইনমেণ্ট ছিষ্টেমত এই প্ৰ’ফাইলটোৰ ডেটা মোহাৰক।"</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"এই ফ\'নটোত থকা এই ব্যৱহাৰকাৰীৰ তথ্য কোনো সর্তকবাণী নিদিয়াকৈ মচি পেলাওক।"</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"ডিভাইচৰ বাবে গ্ল\'বেল প্ৰক্সী ছেট কৰক"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"নীতি সক্ষম কৰি থোৱা অৱস্থাত ব্য়ৱহাৰ কৰিবৰ বাবে ডিভাইচৰ বাবে গ্ল\'বেল প্ৰক্সী ছেট কৰক। কেৱল ডিভাইচৰ গৰাকীয়েহে গ্ল\'বেল প্ৰক্সী ছেট কৰিব পাৰে।"</string> diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml index 4825382f72f5..dd911d65f5f9 100644 --- a/core/res/res/values-az/strings.xml +++ b/core/res/res/values-az/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"Ekranı kiliddən çıxarmaq üçün edilən cəhdlərə nəzarət edin"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Ekan kilidini açarkən daxil edilmiş yanlış parollara baxın və əgər həddindən çox yanlış parollar daxil edilibsə, planşeti kilidləyin və ya bütün planşet datasını silin."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Ekranı kiliddən çıxararkən yazılan yanlış parolların sayına nəzarət edin, Android TV cihazını kilidləyin və ya həddən çox yanlış parol yazılıbsa, Android TV cihazının bütün datasını silin."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Ekranı kiliddən çıxararkən yazılan yanlış parolların sayına nəzarət edin və həddindən çox yanlış parol daxil edilibsə, əyləncə-məlumat sistemini kilidləyin və ya bütün əyləncə-məlumat sistemi datasını silin."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Ekan kilidini açarkən daxil edilmiş yanlış parollara baxın və əgər həddindən çox yanlış parollar daxil edilibsə, telefonu kilidləyin və ya bütün telefon datasını silin."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Ekranı kiliddən çıxararkən yazılan yanlış parolların sayına nəzarət edin və planşeti kilidləyin və ya əgər həddən çox yanlış parol yazılıbsa, həmin istifadəçinin bütün verilənlərini silin."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Ekranı kiliddən çıxararkən yazılan yanlış parolların sayına nəzarət edin, Android TV cihazını kilidləyin və ya həddən çox yanlış parol yazılıbsa, həmin istifadəçinin bütün datasını silin."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Ekranı kiliddən çıxararkən yazılan yanlış parolların sayına nəzarət edin və həddindən çox yanlış parol daxil edilibsə, əyləncə-məlumat sistemini kilidləyin və ya bu profilin bütün datasını silin."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Ekranı kiliddən çıxararkən yazılan yanlış parolların sayına nəzarət edin və telefonu kilidləyin və ya əgər həddən çox yanlış parol yazılıbsa, həmin istifadəçinin bütün verilənlərini silin."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"Ekran kilidini dəyişmək"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"Ekran kilidini dəyişmək"</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"Bütün məlumatları silmək"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Planşetin datasını xəbərdarlıq olmadan, zavod data sıfırlaması ilə silin."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Android TV cihazının datasını fabrik sıfırlaması haqqında xəbərdarlıq olmadan silin."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Xəbərdarlıq etmədən istehsalçı nizamlarına qaytarmaqla əyləncə-məlumat sistemi datasını silin."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Telefondakı bütün məlumatları xəbərdarlıqsız sıfırlayaraq məhv etmək"</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"İstifadəçi verilənlərini sil"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Profil datasını silin"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"İstifadəçi verilənlərini sil"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Xəbərdarlıq etmədən bu istifadəçinin verilənlərini bu planşetdə silin."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Bu istifadəçinin datasını xəbərdarlıq olmadan Android TV cihazında silin."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"Xəbərdarlıq etmədən bu əyləncə-məlumat sistemində bu profilin datasını silin."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"Xəbərdarlıq etmədən bu istifadəçinin bu telefondakı verilənlərini silin."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Cihazın qlobal proksisini ayarlayın"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Siyasət aktivləşdirilən zaman istifadə edilmək üçün cihazın qlobal proksisini təyin edin. Yalnız cihazın sahibi qlobal proksini təyin edə bilər."</string> diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml index 014215a364c1..5fc3f817724b 100644 --- a/core/res/res/values-b+sr+Latn/strings.xml +++ b/core/res/res/values-b+sr+Latn/strings.xml @@ -732,9 +732,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"Nadgledajte pokušaje otključavanja ekrana"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Prati broj netačno unetih lozinki prilikom otključavanja ekrana i zaključava tablet ili briše podatke sa tableta ako je netačna lozinka uneta previše puta."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Nadgleda broj netačnih lozinki unetih pri otključavanju ekrana i zaključava Android TV uređaj ili briše sve podatke sa Android TV uređaja ako se unese previše netačnih lozinki."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Prati broj netačno unetih lozinki pri otključavanju ekrana i zaključava sistem za info-zabavu ili briše sve podatke sa sistema za info-zabavu ako je netačna lozinka uneta previše puta."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Prati broj netačno unetih lozinki pri otključavanju ekrana i zaključava telefon ili briše sve podatke sa telefona ako je netačna lozinka uneta previše puta."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Nadgleda broj netačnih lozinki unetih pri otključavanju ekrana i zaključava tablet ili briše sve podatke ovog korisnika ako se unese previše netačnih lozinki."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Nadgleda broj netačnih lozinki unetih pri otključavanju ekrana i zaključava Android TV uređaj ili briše sve podatke ovog korisnika ako se unese previše netačnih lozinki."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Nadgleda broj netačnih lozinki unetih pri otključavanju ekrana i zaključava sistem za info-zabavu ili briše sve podatke ovog profila ako se unese previše netačnih lozinki."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Nadgleda broj netačnih lozinki unetih pri otključavanju ekrana i zaključava telefon ili briše sve podatke ovog korisnika ako se unese previše netačnih lozinki."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"Promena zaključavanja ekrana"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"Menja zaključavanje ekrana."</string> @@ -743,10 +745,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"Brisanje svih podataka"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Brisanje podataka na tabletu bez upozorenja resetovanjem na fabrička podešavanja."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Briše podatke Android TV uređaja bez upozorenja pomoću resetovanja na fabrička podešavanja."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Briše podatke na sistemu za info-zabavu bez upozorenja resetovanjem na fabrička podešavanja."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Brisanje podataka na telefonu bez upozorenja resetovanjem na fabrička podešavanja."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"Obriši podatke korisnika"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Brisanje podataka profila"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Obriši podatke korisnika"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Briše podatke ovog korisnika na ovom tabletu bez upozorenja."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Briše podatke ovog korisnika na ovom Android TV uređaju bez upozorenja."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"Briše podatke ovog profila na ovom sistemu za info-zabavu bez upozorenja."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"Briše podatke ovog korisnika na ovom telefonu bez upozorenja."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Podesite globalni proksi server uređaja"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Podešava globalni proksi uređaja koji će se koristiti dok su smernice omogućene. Samo vlasnik uređaja može da podesi globalni proksi."</string> diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml index d0491ce8124f..2209b15dcaeb 100644 --- a/core/res/res/values-be/strings.xml +++ b/core/res/res/values-be/strings.xml @@ -735,9 +735,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"Сачыць за спробамі разблакіроўкі экрана"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Сачыць за колькасцю няправільных набраных пароляў падчас разблакоўкі экрана і блакаваць планшэт або сціраць усе дадзеныя на ім, калі няправільны пароль набраны занадта шмат разоў."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Сачыць за колькасцю няправільна набраных пароляў падчас разблакіроўкі экрана і заблакіраваць прыладу Android TV або сцерці ўсе даныя на прыладзе, калі няправільны пароль набраны занадта шмат разоў."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Падчас разблакіроўкі экрана сачыць за колькасцю няправільна набраных пароляў і, калі няправільны пароль набраны занадта шмат разоў, заблакіраваць інфармацыйна-забаўляльную сістэму ці сцерці ў ёй усе даныя."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Сачыць за колькасцю няправільных набраных пароляў падчас разблакоўкі экрана і блакаваць тяэлефон або сціраць усе дадзеныя на ім, калі набрана занадта шмат няправільных пароляў."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Сачыць за колькасцю няправільна набраных пароляў падчас разблакіроўкі экрана і блакіраваць планшэт або сцерці ўсе даныя гэтага карыстальніка, калі няправільны пароль набраны занадта шмат разоў."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Сачыць за колькасцю няправільна набраных пароляў падчас разблакіроўкі экрана і заблакіраваць прыладу Android TV або сцерці ўсе даныя карыстальніка, калі няправільны пароль набраны занадта шмат разоў."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Падчас разблакіроўкі экрана сачыць за колькасцю няправільна набраных пароляў і, калі няправільны пароль набраны занадта шмат разоў, заблакіраваць інфармацыйна-забаўляльную сістэму ці сцерці ўсе даныя гэтага профілю."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Сачыць за колькасцю няправільна набраных пароляў падчас разблакіроўкі экрана і блакіраваць тэлефон або сцерці ўсе даныя гэтага карыстальніка, калі няправільны пароль набраны занадта шмат разоў."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"Змяніць блакіроўку экрана"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"Змяніць блакіроўку экрана."</string> @@ -746,10 +748,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"Сцерці ўсе даныя"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Cцерці даныя з планшэта без папярэджання, выканаўшы скід да заводскіх даных."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Сцерці даныя з прылады Android TV без папярэджання, выканаўшы скід да заводскіх налад."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Падчас скіду да заводскіх налад сцерці даныя ў інфармацыйна-забаўляльнай сістэме без папярэджання."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Сцерці даныя з тэлефона без папярэджання, выканаўшы скід да заводскіх налад."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"Сцерці карыстальніцкія даныя"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Сцерці даныя профілю"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Сцерці карыстальніцкія даныя"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Сцерці даныя гэтага карыстальніка на дадзеным планшэце без папярэджання."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Сцерці даныя карыстальніка з гэтай прылады Android TV без папярэджання."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"Сцерці даныя гэтага профілю ў гэтай інфармацыйна-забаўляльнай сістэме без папярэджання."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"Сцерці даныя гэтага карыстальніка на дадзеным тэлефоне без папярэджання."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Усталяваць глабальны проксі прылады"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Задаць агульны проксі-cервер прылады, які будзе выкарыстоўвацца, калі прылада актыўная. Толькі ўладальнік прылады можа задаць агульны проксі-сервер."</string> diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml index cdd27d4ac514..3a819a335115 100644 --- a/core/res/res/values-bg/strings.xml +++ b/core/res/res/values-bg/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"Наблюдаване на опитите за отключване на екрана"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Наблюдава броя въведени неправилни пароли при отключването на екрана и заключва таблета или изтрива всички данни от него, ако неправилните пароли са твърде много."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Следене на броя на неправилно въведените пароли при отключване на екрана и заключване на устройството ви с Android TV или изтриване на всички данни от него, ако неуспешните опити са твърде много."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Наблюдава броя на неправилно въведените пароли при отключването на екрана и заключва основното устройство или изтрива всички данни от него, ако неуспешните опити са твърде много."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Наблюдава броя въведени неправилни пароли при отключването на екрана и заключва телефона или изтрива всички данни от него, ако неправилните пароли са твърде много."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Наблюдава броя на неправилно въведените пароли при отключване на екрана и заключва таблета или изтрива всички данни на този потребител, ако неуспешните опити са твърде много."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Следене на броя на неправилно въведените пароли при отключване на екрана и заключване на устройството ви с Android TV или изтриване на всички данни на този потребител, ако неуспешните опити са твърде много."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Наблюдава броя на неправилно въведените пароли при отключване на екрана и заключва основното устройство или изтрива всички данни в този потребителски профил, ако неуспешните опити са твърде много."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Наблюдава броя на неправилно въведените пароли при отключване на екрана и заключва телефона или изтрива всички данни на този потребител, ако неуспешните опити са твърде много."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"Промяна на заключването на екрана"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"Променя заключването на екрана."</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"Изтриване на всички данни"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Изтриване на данните в таблета без предупреждение чрез възстановяване на фабричните настройки."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Изтриване на данните от устройството ви с Android TV без предупреждение чрез възстановяване на фабричните настройки."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Изтрива данните на основното устройство без предупреждение чрез възстановяване на фабричните настройки."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Изтрива данните в телефона без предупреждение чрез възстановяване на фабричните настройки."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"Изтриване на потребителските данни"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Изтриване на данните в потребителския профил"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Изтриване на потребителските данни"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Изтрива данните на този потребител от таблета без предупреждение."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Изтриване на данните на този потребител от устройството с Android TV без предупреждение."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"Изтрива данните в този потребителски профил на основното устройство без предупреждение."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"Изтрива данните на този потребител от телефона без предупреждение."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Задаване на глобален прокси сървър за устройството"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Задава глобалния прокси сървър за устройството, който да се използва, когато правилото е активирано. Само собственикът на устройството може да задава такъв сървър."</string> diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml index 057a409c15c0..e788069e4332 100644 --- a/core/res/res/values-bn/strings.xml +++ b/core/res/res/values-bn/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"স্ক্রিন আনলক করার প্রচেষ্টাগুলির উপরে নজর রাখুন"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"স্ক্রীণ আনলক করার সময় ভুলভাবে লেখা পাসওয়ার্ড প্রবেশের সংখ্যা মনিটার করে, এবং ট্যাবলেট লক করে এবং অনেক বার পাসওয়ার্ড ভুল ভাবে লেখা হলে ট্যাবলেটের ডেটা মুছে ফেলে৷"</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"স্ক্রিন আনলক করার সময় কতবার ভুল পাসওয়ার্ড লেখা হচ্ছে তা মনিটর করুন এবং Android TV ডিভাইস লক করুন অথবা অনেকবার ভুল পাসওয়ার্ড লেখা হলে ডিভাইসের সব ডেটা মুছে ফেলুন।"</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"ফোনের স্ক্রিন আনলক করার সময় কতবার ভুল পাসওয়ার্ড টাইপ করা হয়েছে তা মনিটর করুন। একাধিকবার ভুল পাসওয়ার্ড টাইপ করা হলে ইনফোটেইনমেন্ট সিস্টেম লক করুন অথবা এর সব ডেটা মুছে ফেলুন।"</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"স্ক্রীণ আনলক করার সময় ভুলভাবে লেখা পাসওয়ার্ড প্রবেশের সংখ্যা মনিটার করে, এবং ফোন লক করে এবং অনেক বার পাসওয়ার্ড ভুল ভাবে লেখা হলে ফোনের ডেটা মুছে ফেলে৷"</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"স্ক্রিন আনলক করার সময় ভুলভাবে লেখা পাসওয়ার্ড প্রবেশের সংখ্যা মনিটার করে, এবং ট্যাবলেট লক করে এবং অনেক বার পাসওয়ার্ড ভুল ভাবে লেখা হলে ব্যবহারকারীর ডেটা মুছে ফেলে৷"</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"স্ক্রিন আনলক করার সময় কতবার ভুল পাসওয়ার্ড লেখা হচ্ছে তা মনিটর করুন এবং Android TV ডিভাইস লক করুন অথবা অনেকবার ভুল পাসওয়ার্ড লেখা হলে সব ব্যবহারকারীর ডেটা মুছে ফেলুন।"</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"ফোনের স্ক্রিন আনলক করার সময় কতবার ভুল পাসওয়ার্ড টাইপ করা হয়েছে তা মনিটর করুন। একাধিকবার ভুল পাসওয়ার্ড টাইপ করা হলে ইনফোটেইনমেন্ট সিস্টেম লক করুন অথবা এই প্রোফাইলের সব ডেটা মুছে ফেলুন।"</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"স্ক্রিন আনলক করার সময় ভুলভাবে লেখা পাসওয়ার্ড প্রবেশের সংখ্যা মনিটার করে, এবং ফোন লক করে এবং অনেক বার পাসওয়ার্ড ভুল ভাবে লেখা হলে ব্যবহারকারীর ডেটা মুছে ফেলে৷"</string> <string name="policylab_resetPassword" msgid="214556238645096520">"স্ক্রিন লক পরিবর্তন করে"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"স্ক্রিন লক পরিবর্তন করুন৷"</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"সমস্ত ডেটা মুছে দেয়"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"ফ্যাক্টরি ডেটা আবার সেট কার্য সম্পাদনার দ্বারা কোনো রকম সতর্কতা ছাড়াই ট্যাবলেটের ডেটা মোছে৷"</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"ফ্যাক্টরি ডেটা রিসেট করে কোনও সতর্কতা ছাড়াই আপনার Android TV ডিভাইসের ডেটা মুছে ফেলুন।"</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"ফ্যাক্টরি ডেটা রিসেট করে কোনও সতর্কতা মূলক বিজ্ঞপ্তি ছাড়াই আপনার ইনফোটেইনমেন্ট সিস্টেমের ডেটা মুছে ফেলুন।"</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"ফ্যাক্টরি ডেটা রিসেট করে কোনও সতর্কতা ছাড়াই ফোনের ডেটা মোছে৷"</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"ব্যবহারকারীর ডেটা মুছুন"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"প্রোফাইল ডেটা মুছে ফেলুন"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"ব্যবহারকারীর ডেটা মুছুন"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"সতর্কীকরণ ছাড়াই এই ট্যাবলেটে থাকা ব্যাবহারকার্রী ডেটা মুছে ফেলে৷"</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"কোনও সতর্কতা ছাড়াই এই ব্যবহারকারীর ডেটা Android TV ডিভাইসটি থেকে মুছুন।"</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"কোনও সতর্কতা মূলক বিজ্ঞপ্তি ছাড়াই ইনফোটেইনমেন্ট সিস্টেমে থাকা এই প্রোফাইলের ডেটা মুছে ফেলুন।"</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"সতর্কীকরণ ছাড়াই এই ফোনে থাকা ব্যাবহারকার্রী ডেটা মুছে ফেলে৷"</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"ডিভাইসের বৈশ্বিক প্রক্সী সেট করে"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"নীতিযখন নীতি সক্ষম করা হয় তখন ডিভাইসের বৈশ্বিক প্রক্সী ব্যবহার করা হবে সেই হিসেবে সেট করে৷ শুধুমাত্র ডিভাইসের মালিক বৈশ্বিক প্রক্সী সেট করতে পারেন৷"</string> diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml index 3fef88bd15bc..f5415e8c45a4 100644 --- a/core/res/res/values-bs/strings.xml +++ b/core/res/res/values-bs/strings.xml @@ -732,9 +732,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"Prati pokušaje otključavanja ekrana"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Prati broj pogrešno unijetih lozinki prilikom otključavanja ekrana i zaključava tablet ili briše sve podatke s njega ukoliko se previše puta unese pogrešna lozinka."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Praćenje broja unosa netačnih lozinki pri otključavanju ekrana i zaključavanje Android TV uređaja ili brisanje svih podataka Android TV uređaja u slučaju prevelikog broja unosa netačnih lozinki."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Prati koliko puta je lozinka neispravno unijeta prilikom otključavanja ekrana i zaključava informativno-zabavni sistem ili briše sve podatke informativno-zabavnog sistema ako se lozinka neispravno unese previše puta."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Prati broj pogrešno unesenih lozinki prilikom otključavanja ekrana i zaključava telefon ili briše sve podatke s telefona ukoliko se previše puta unese pogrešna lozinka."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Prati broj neispravnih lozinki koje su unijete za otključavanje ekrana te zaključava tablet ili briše sve podatke ovog korisnika ukoliko je unijeto previše neispravnih lozinki."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Praćenje broja unosa netačnih lozinki za otključavanje ekrana te zaključavanje Android TV uređaja ili brisanje svih podataka ovog korisnika u slučaju prekomjernog unosa netačnih lozinki."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Prati koliko puta je lozinka neispravno unijeta prilikom otključavanja ekrana i zaključava informativno-zabavni sistem ili briše sve podatke ovog profila ako se lozinka neispravno unese previše puta."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Prati broj neispravnih lozinki koje su unijete za otključavanje ekrana te zaključava telefon ili briše sve podatke ovog korisnika ukoliko je unijeto previše neispravnih lozinki."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"Promjena zaključavanja ekrana"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"Mijenja zaključavanje ekrana."</string> @@ -743,10 +745,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"Brisanje svih podataka"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Briše podatke s tableta bez upozorenja tako što ga vraća na fabričke postavke."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Brisanje podataka Android TV uređaja bez upozorenja vraćanjem uređaja na fabričke postavke."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Bez upozorenja briše podatke informativno-zabavnog sistema vraćanjem na fabričke postavke."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Briše podatke s telefona bez upozorenja vraćanjem telefona na fabričke postavke."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"Izbriši podatke korisnika"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Briše podatke profila"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Izbriši podatke korisnika"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Bez upozorenja briše podatke ovog korisnika sa ovog tableta."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Brisanje podataka ovog korisnika na Android TV uređaju bez upozorenja."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"Bez upozorenja briše podatke ovog profila na ovom informativno-zabavnom sistemu."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"Bez upozorenja briše podatke ovog korisnika sa ovog telefona."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Postavlja globalni proksi uređaja"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Postavlja globalni proksi uređaja koji će se koristiti dok su smjernice omogućene. Samo vlasnik uređaja može postaviti globalni proksi."</string> diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml index 7bc5905f5136..05fb36e45dcf 100644 --- a/core/res/res/values-ca/strings.xml +++ b/core/res/res/values-ca/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"Supervisar els intents de desbloqueig de la pantalla"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Supervisa el nombre de contrasenyes incorrectes introduïdes per desbloquejar la pantalla i bloqueja la tauleta o n\'esborra totes les dades si s\'introdueixen massa contrasenyes incorrectes."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Fa un seguiment del nombre de contrasenyes incorrectes que s\'han introduït en intentar desbloquejar la pantalla i bloqueja el dispositiu Android TV o esborra totes les dades del dispositiu si s\'introdueixen massa contrasenyes incorrectes."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Supervisa el nombre de contrasenyes incorrectes introduïdes en desbloquejar la pantalla, i bloqueja el sistema d\'informació i entreteniment o n\'esborra totes les dades si s\'introdueixen massa contrasenyes incorrectes."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Supervisa el nombre de contrasenyes incorrectes introduïdes en desbloquejar la pantalla, i bloqueja el telèfon o esborra totes les dades del telèfon si s\'introdueixen massa contrasenyes incorrectes."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Fa un seguiment del nombre de contrasenyes incorrectes que s\'han escrit en intentar desbloquejar la pantalla i bloqueja la tauleta o n\'esborra totes les dades de l\'usuari si s\'escriuen massa contrasenyes incorrectes."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Fa un seguiment del nombre de contrasenyes incorrectes que s\'han introduït en intentar desbloquejar la pantalla i bloqueja el dispositiu Android TV o n\'esborra totes les dades de l\'usuari si s\'introdueixen massa contrasenyes incorrectes."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Supervisa el nombre de contrasenyes incorrectes introduïdes en desbloquejar la pantalla, i bloqueja el sistema d\'informació i entreteniment o esborra totes les dades d\'aquest perfil si s\'introdueixen massa contrasenyes incorrectes."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Fa un seguiment del nombre de contrasenyes incorrectes que s\'han escrit en intentar desbloquejar la pantalla i bloqueja el telèfon o n\'esborra totes les dades de l\'usuari si s\'escriuen massa contrasenyes incorrectes."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"Canviar el bloqueig de pantalla"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"Canvia el bloqueig de pantalla."</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"Esborrar totes les dades"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Esborra les dades de la tauleta sense avisar, i restableix les dades de fàbrica."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Suprimeix les dades del dispositiu Android TV sense previ avís mitjançant el restabliment de les dades de fàbrica."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Esborra les dades del sistema d\'informació i entreteniment sense avisar mitjançant el restabliment de les dades de fàbrica."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Esborra les dades del telèfon sense avisar, i restableix les dades de fàbrica."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"Esborrar les dades de l\'usuari"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Esborra les dades del perfil"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Esborrar les dades de l\'usuari"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Esborra les dades de l\'usuari desades a la tauleta sense avisar-ne."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Esborra les dades de l\'usuari desades al dispositiu Android TV sense previ avís."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"Esborra les dades del perfil d\'aquest sistema d\'informació i entreteniment sense avisar."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"Esborra les dades de l\'usuari desades al telèfon sense avisar-ne."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Definir el servidor intermediari global del dispositiu"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Si la política s\'activa, s\'utilitza el servidor intermediari global del dispositiu. Només el propietari del dispositiu el pot establir."</string> diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml index 2c8477c0b515..151b5cee0b1f 100644 --- a/core/res/res/values-cs/strings.xml +++ b/core/res/res/values-cs/strings.xml @@ -735,9 +735,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"Sledovat pokusy o odemknutí obrazovky"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Sledovat počet nesprávných hesel zadaných při odemykání obrazovky a uzamknout tablet nebo vymazat z tabletu všechna data, pokud bylo zadáno příliš mnoho nesprávných hesel."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Sledovat počet nesprávných hesel zadaných při odemykání obrazovky, a pokud jich bude zadáno příliš mnoho, uzamknout zařízení Android TV nebo z něj vymazat všechna data."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Monitorovat počet nesprávných hesel zadaných při odemykání obrazovky a uzamknout informační a zábavní systém nebo vymazat veškerá data v informačním a zábavním systému, pokud je zadáno příliš mnoho nesprávných hesel."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Sledovat počet nesprávných hesel zadaných při odemykání obrazovky a uzamknout telefon nebo vymazat z telefonu všechna data, pokud bylo zadáno příliš mnoho nesprávných hesel."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Monitorovat počet nesprávných hesel zadaných při odemykání obrazovky, a pokud je zadáno příliš mnoho nesprávných hesel, uzamknout tablet nebo vymazat veškerá data uživatele."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Sledovat počet nesprávných hesel zadaných při odemykání obrazovky, a pokud jich bude zadáno příliš mnoho, uzamknout zařízení Android TV nebo z něj vymazat všechna data tohoto uživatele."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Monitorovat počet nesprávných hesel zadaných při odemykání obrazovky, a pokud je zadáno příliš mnoho nesprávných hesel, uzamknout informační a zábavní systém nebo vymazat veškerá data profilu."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Monitorovat počet nesprávných hesel zadaných při odemykání obrazovky, a pokud je zadáno příliš mnoho nesprávných hesel, uzamknout telefon nebo vymazat veškerá data uživatele."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"Změnit zámek obrazovky"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"Změní se zámek obrazovky."</string> @@ -746,10 +748,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"Vymazat všechna data"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Bez upozornění smazat všechna data tabletu obnovením továrních dat."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Provést obnovení továrních dat a bez upozornění tím vymazat data v zařízení Android TV."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Bez upozornění se smažou všechna data informačního a zábavního systému obnovením továrních dat."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Bez upozornění se smažou všechna data telefonu obnovením továrních dat."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"Vymazat data uživatele"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Vymazání profilových dat"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Vymazat data uživatele"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Vymazat data tohoto uživatele v tomto tabletu bez upozornění."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Bez upozornění vymazat data tohoto uživatele v tomto zařízení Android TV."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"Bez upozornění se smažou data tohoto profilu v informačním a zábavním systému."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"Vymazat data tohoto uživatele v tomto telefonu bez upozornění."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Nastavit globální proxy server zařízení"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Nastaví globální proxy server, který bude používán, když je zásada zapnuta. Globální proxy server může nastavit pouze vlastník zařízení."</string> @@ -992,7 +997,7 @@ <string name="js_dialog_before_unload" msgid="7213364985774778744">"<xliff:g id="MESSAGE">%s</xliff:g>\n\nOpravdu tuto stránku chcete opustit?"</string> <string name="save_password_label" msgid="9161712335355510035">"Potvrdit"</string> <string name="double_tap_toast" msgid="7065519579174882778">"Tip: Dvojitým klepnutím můžete zobrazení přiblížit nebo oddálit."</string> - <string name="autofill_this_form" msgid="3187132440451621492">"Aut.vyp."</string> + <string name="autofill_this_form" msgid="3187132440451621492">"Autofill"</string> <string name="setup_autofill" msgid="5431369130866618567">"Nastav aut. vyp."</string> <string name="autofill_window_title" msgid="4379134104008111961">"Automatické vyplňování pomocí služby <xliff:g id="SERVICENAME">%1$s</xliff:g>"</string> <string name="autofill_address_name_separator" msgid="8190155636149596125">" "</string> diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml index 353358d7658f..fd9a48e24f39 100644 --- a/core/res/res/values-da/strings.xml +++ b/core/res/res/values-da/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"Overvåg forsøg på oplåsning af skærm"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Overvåg antallet af forkert indtastede adgangskoder, når du låser skærmen op, og lås din tablet, eller slet alle data i den, hvis der er indtastet for mange forkerte adgangskoder."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Registrer antallet af forkerte adgangskoder, der angives ved oplåsning af skærmen, og lås din Android TV-enhed, eller ryd alle dataene på din Android TV-enhed, hvis adgangskoden angives forkert for mange gange."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Registrer antallet af forkert indtastede adgangskoder, når du låser skærmen op, og lås infotainmentsystemet, eller slet alle data i infotainmentsystemet, hvis der er indtastet for mange forkerte adgangskoder."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Overvåg antallet af forkerte adgangskoder ved oplåsning af skærmen, og lås telefonen eller slet alle data på telefonen, hvis der er indtastet for mange forkerte adgangskoder."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Registrer antallet af forkerte adgangskoder, der angives ved oplåsning af skærmen, og lås din tablet, eller slet alle brugerens data, hvis adgangskoden tastes forkert for mange gange."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Registrer antallet af forkerte adgangskoder, der angives ved oplåsning af skærmen, og lås din Android TV-enhed, eller ryd alle brugerens data, hvis adgangskoden angives forkert for mange gange."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Registrer antallet af forkert indtastede adgangskoder, når du låser skærmen op, og lås infotainmentsystemet, eller slet alle data på denne profil, hvis der er indtastet for mange forkerte adgangskoder."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Registrer antallet af forkerte adgangskoder, der angives ved oplåsning af skærmen, og lås telefonen, eller slet alle brugerens data, hvis adgangskoden tastes forkert for mange gange."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"Skifte skærmlås"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"Skifter skærmlåsen."</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"Slette alle data"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Slet din tablets data uden varsel ved at gendanne fabriksindstillingerne."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Ryd dataene på din Android TV-enhed uden at gendanne fabriksdataene."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Ryd infotainmentsystemets data uden varsel ved at gendanne fabriksindstillingerne."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Sletter telefonens data uden varsel ved at gendanne fabriksindstillingerne."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"Slet brugerdata"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Ryd profildata"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Slet brugerdata"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Slet denne brugers data på denne tablet uden varsel."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Ryd denne brugers data på denne Android TV-enhed uden varsel."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"Ryd denne profils data i dette infotainmentsystem uden varsel."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"Slet denne brugers data på denne telefon uden varsel."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Angiv enhedens globale proxy"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Indstil den globale proxy for enheden, der skal bruges, mens politikken er aktiveret. Det er kun enhedens ejer, der kan indstille den globale proxy."</string> diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml index a974e90736dd..7a598e182389 100644 --- a/core/res/res/values-de/strings.xml +++ b/core/res/res/values-de/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"Versuche zum Entsperren des Displays überwachen"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Anzahl der falsch eingegebenen Passwörter beim Entsperren des Displays überwachen und Tablet sperren oder alle Daten auf dem Tablet löschen, wenn zu häufig ein falsches Passwort eingegeben wird."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Es wird überwacht, wie oft beim Versuch, den Bildschirm zu entsperren, ein falsches Passwort eingegeben wird. Wenn es zu viele Fehlversuche gibt, wird das Android TV-Gerät gesperrt oder alle Daten darauf werden gelöscht."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Anzahl der falsch eingegebenen Passwörter beim Entsperren des Displays erfassen und Infotainmentsystem sperren oder alle Daten des Infotainmentsystems löschen, wenn zu häufig ein falsches Passwort eingegeben wird."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Anzahl der falsch eingegebenen Passwörter beim Entsperren des Bildschirms überwachen und Telefon sperren oder alle Daten auf dem Telefon löschen, wenn zu häufig ein falsches Passwort eingegeben wird."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Anzahl der falsch eingegebenen Passwörter beim Entsperren des Displays überwachen und Tablet sperren oder alle Daten dieses Nutzers löschen, wenn zu häufig ein falsches Passwort eingegeben wird"</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Es wird überwacht, wie oft beim Versuch, den Bildschirm zu entsperren, ein falsches Passwort eingegeben wird. Wenn es zu viele Fehlversuche gibt, wird das Android TV-Gerät gesperrt oder alle Daten dieses Nutzers werden gelöscht."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Anzahl der falsch eingegebenen Passwörter beim Entsperren des Displays erfassen und Infotainmentsystem sperren oder alle Daten dieses Profils löschen, wenn zu häufig ein falsches Passwort eingegeben wird."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Anzahl der falsch eingegebenen Passwörter beim Entsperren des Displays überwachen und Smartphone sperren oder alle Daten dieses Nutzers löschen, wenn zu häufig ein falsches Passwort eingegeben wird"</string> <string name="policylab_resetPassword" msgid="214556238645096520">"Displaysperre ändern"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"Ändern der Displaysperre"</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"Alle Daten löschen"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Auf Werkseinstellungen zurücksetzen und Daten auf dem Tablet ohne Warnung löschen"</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Du kannst die Daten auf deinem Android TV-Gerät ohne vorherige Warnung löschen, indem du es auf die Werkseinstellungen zurücksetzt."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Gerät auf Werkseinstellungen zurücksetzen und damit Daten des Infotainmentsystems ohne Warnung löschen."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Gerät auf Werkseinstellungen zurücksetzen und damit Daten auf dem Telefon ohne Warnung löschen"</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"Nutzerdaten löschen"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Profildaten löschen"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Nutzerdaten löschen"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Daten dieses Nutzers auf diesem Tablet ohne vorherige Warnung löschen"</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Daten dieses Nutzers auf diesem Android TV-Gerät werden ohne vorherige Warnung gelöscht."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"Daten dieses Profils in diesem Infotainmentsystem ohne Warnung löschen."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"Daten dieses Nutzers auf diesem Smartphone ohne vorherige Warnung löschen"</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Den globalen Proxy des Geräts festlegen"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Bei aktivierter Richtlinie zu verwendenden globalen Geräteproxy festlegen. Nur der Eigentümer des Geräts kann den globalen Proxy festlegen."</string> diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml index 03d978e6268b..03307f643850 100644 --- a/core/res/res/values-el/strings.xml +++ b/core/res/res/values-el/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"Παρακολούθηση προσπαθειών ξεκλειδώματος οθόνης"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Παρακολούθηση του αριθμού λανθασμένων κωδικών πρόσβασης που πληκτρολογούνται κατά το ξεκλείδωμα της οθόνης και κλείδωμα του tablet ή διαγραφή όλων των δεδομένων του σε περίπτωση πληκτρολόγησης πάρα πολλών εσφαλμένων κωδικών πρόσβασης."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Παρακολουθήστε τον αριθμό των εσφαλμένων κωδικών πρόσβασης που πληκτρολογούνται κατά το ξεκλείδωμα της οθόνης και κλειδώστε τη συσκευή Android TV ή διαγράψτε όλα τα δεδομένα της σε περίπτωση εισαγωγής εσφαλμένων κωδικών πρόσβασης πάρα πολλές φορές."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Παρακολούθηση του αριθμού των εσφαλμένων κωδικών πρόσβασης που πληκτρολογούνται κατά το ξεκλείδωμα της οθόνης και κλείδωμα του συστήματος ενημέρωσης και ψυχαγωγίας ή διαγραφή όλων των δεδομένων του εάν πληκτρολογηθούν πολλοί εσφαλμένοι κωδικοί πρόσβασης."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Παρακολούθηση του αριθμού λανθασμένων κωδικών πρόσβασης που πληκτρολογούνται κατά το ξεκλείδωμα της οθόνης και κλείδωμα του τηλεφώνου ή διαγραφή όλων των δεδομένων του σε περίπτωση πληκτρολόγησης πάρα πολλών εσφαλμένων κωδικών πρόσβασης."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Παρακολουθήστε τον αριθμό των εσφαλμένων κωδικών πρόσβασης που πληκτρολογούνται κατά το ξεκλείδωμα της οθόνης και κλειδώστε το tablet ή διαγράψτε όλα τα δεδομένα του χρήστη, σε περίπτωση εισαγωγής πάρα πολλών εσφαλμένων κωδικών πρόσβασης."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Παρακολουθήστε τον αριθμό των εσφαλμένων κωδικών πρόσβασης που πληκτρολογούνται κατά το ξεκλείδωμα της οθόνης και κλειδώστε τη συσκευή Android TV ή διαγράψτε όλα τα δεδομένα χρήστη σε περίπτωση εισαγωγής εσφαλμένων κωδικών πρόσβασης πάρα πολλές φορές."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Παρακολούθηση του αριθμού των εσφαλμένων κωδικών πρόσβασης που πληκτρολογούνται κατά το ξεκλείδωμα της οθόνης και κλείδωμα του συστήματος ενημέρωσης και ψυχαγωγίας ή διαγραφή όλων των δεδομένων αυτού του προφίλ εάν πληκτρολογηθούν πολλοί εσφαλμένοι κωδικοί πρόσβασης."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Παρακολουθήστε τον αριθμό των εσφαλμένων κωδικών πρόσβασης που πληκτρολογούνται κατά το ξεκλείδωμα της οθόνης και κλειδώστε το τηλέφωνο ή διαγράψτε όλα τα δεδομένα του χρήστη, σε περίπτωση εισαγωγής πάρα πολλών εσφαλμένων κωδικών πρόσβασης."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"Αλλαγή του κλειδώματος οθόνης"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"Αλλαγή του κλειδώματος οθόνης."</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"Διαγραφή όλων των δεδομένων"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Διαγραφή των δεδομένων του tablet χωρίς προειδοποίηση με επαναφορά των εργοστασιακών ρυθμίσεων."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Διαγράψτε τα δεδομένα της συσκευής σας Android TV χωρίς προειδοποίηση εκτελώντας επαναφορά των εργοστασιακών δεδομένων."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Διαγραφή των δεδομένων του συστήματος ενημέρωσης και ψυχαγωγίας χωρίς προειδοποίηση με εκτέλεση επαναφοράς εργοστασιακών ρυθμίσεων."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Διαγραφή των δεδομένων του τηλεφώνου χωρίς προειδοποίηση με επαναφορά των εργοστασιακών ρυθμίσεων."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"Διαγραφή δεδομένων χρήστη"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Διαγραφή δεδομένων προφίλ"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Διαγραφή δεδομένων χρήστη"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Διαγραφή των δεδομένων αυτού του χρήστη σε αυτό το tablet χωρίς προειδοποίηση."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Διαγράψτε τα δεδομένα χρήστη σε αυτή τη συσκευή Android TV χωρίς προειδοποίηση."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"Διαγραφή των δεδομένων αυτού του προφίλ σε αυτό το σύστημα ενημέρωσης και ψυχαγωγίας χωρίς προειδοποίηση."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"Διαγραφή των δεδομένων αυτού του χρήστη σε αυτό το τηλέφωνο χωρίς προειδοποίηση."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Ρύθμιση του γενικού διακομιστή μεσολάβησης της συσκευής"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Ρυθμίστε τη χρήση του γενικού διακομιστή μεσολάβησης της συσκευής, ενώ η πολιτική είναι ενεργοποιημένη. Μόνο ο κάτοχος της συσκευής μπορεί να ρυθμίσει τον γενικό διακομιστής μεσολάβησης."</string> diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml index 04158b40e79e..1c477a0ca9d6 100644 --- a/core/res/res/values-en-rAU/strings.xml +++ b/core/res/res/values-en-rAU/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"Monitor screen unlock attempts"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Monitor the number of incorrect passwords typed when unlocking the screen and lock the tablet or erase all the tablet\'s data if too many incorrect passwords are typed."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Monitor the number of incorrect passwords typed when unlocking the screen, and lock your Android TV device or delete all of your Android TV device\'s data if too many incorrect passwords are typed."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Monitor the number of incorrect passwords typed when unlocking the screen, and lock the infotainment system or erase all the infotainment system\'s data if too many incorrect passwords are typed."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Monitor the number of incorrect passwords typed when unlocking the screen and lock the phone or erase all the phone\'s data if too many incorrect passwords are typed."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Monitor the number of incorrect passwords typed when unlocking the screen, and lock the tablet or erase all this user\'s data if too many incorrect passwords are typed."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Monitor the number of incorrect passwords typed when unlocking the screen, and lock your Android TV device or delete all of this user\'s data if too many incorrect passwords are typed."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Monitor the number of incorrect passwords typed when unlocking the screen, and lock the infotainment system or erase all this profile\'s data if too many incorrect passwords are typed."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Monitor the number of incorrect passwords typed when unlocking the screen, and lock the phone or erase all this user\'s data if too many incorrect passwords are typed."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"Change the screen lock"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"Change the screen lock."</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"Delete all data"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Erase the tablet\'s data without warning by performing a factory data reset."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Delete your Android TV device\'s data without warning by performing a factory data reset."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Erase the infotainment system\'s data without warning by performing a factory data reset."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Erase the phone\'s data without warning by performing a factory data reset."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"Erase user data"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Erase profile data"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Erase user data"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Erase this user\'s data on this tablet without warning."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Delete this user\'s data on this Android TV device without warning."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"Erase this profile\'s data on this infotainment system without warning."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"Erase this user\'s data on this phone without warning."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Set the device global proxy"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Set the device global proxy to be used while policy is enabled. Only the device owner can set the global proxy."</string> diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml index 3b019f47045e..3291368a61bd 100644 --- a/core/res/res/values-en-rCA/strings.xml +++ b/core/res/res/values-en-rCA/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"Monitor screen unlock attempts"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Monitor the number of incorrect passwords typed when unlocking the screen and lock the tablet or erase all the tablet\'s data if too many incorrect passwords are typed."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Monitor the number of incorrect passwords typed when unlocking the screen, and lock your Android TV device or delete all of your Android TV device\'s data if too many incorrect passwords are typed."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Monitor the number of incorrect passwords typed when unlocking the screen, and lock the infotainment system or erase all the infotainment system\'s data if too many incorrect passwords are typed."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Monitor the number of incorrect passwords typed when unlocking the screen and lock the phone or erase all the phone\'s data if too many incorrect passwords are typed."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Monitor the number of incorrect passwords typed when unlocking the screen, and lock the tablet or erase all this user\'s data if too many incorrect passwords are typed."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Monitor the number of incorrect passwords typed when unlocking the screen, and lock your Android TV device or delete all of this user\'s data if too many incorrect passwords are typed."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Monitor the number of incorrect passwords typed when unlocking the screen, and lock the infotainment system or erase all this profile\'s data if too many incorrect passwords are typed."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Monitor the number of incorrect passwords typed when unlocking the screen, and lock the phone or erase all this user\'s data if too many incorrect passwords are typed."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"Change the screen lock"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"Change the screen lock."</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"Erase all data"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Erase the tablet\'s data without warning by performing a factory data reset."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Delete your Android TV device\'s data without warning by performing a factory data reset."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Erase the infotainment system\'s data without warning by performing a factory data reset."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Erase the phone\'s data without warning by performing a factory data reset."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"Erase user data"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Erase profile data"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Erase user data"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Erase this user\'s data on this tablet without warning."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Delete this user\'s data on this Android TV device without warning."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"Erase this profile\'s data on this infotainment system without warning."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"Erase this user\'s data on this phone without warning."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Set the device global proxy"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Set the device global proxy to be used while policy is enabled. Only the device owner can set the global proxy."</string> diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml index 91d39a97e3f8..ce4bf212c116 100644 --- a/core/res/res/values-en-rGB/strings.xml +++ b/core/res/res/values-en-rGB/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"Monitor screen unlock attempts"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Monitor the number of incorrect passwords typed when unlocking the screen and lock the tablet or erase all the tablet\'s data if too many incorrect passwords are typed."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Monitor the number of incorrect passwords typed when unlocking the screen, and lock your Android TV device or delete all of your Android TV device\'s data if too many incorrect passwords are typed."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Monitor the number of incorrect passwords typed when unlocking the screen, and lock the infotainment system or erase all the infotainment system\'s data if too many incorrect passwords are typed."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Monitor the number of incorrect passwords typed when unlocking the screen and lock the phone or erase all the phone\'s data if too many incorrect passwords are typed."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Monitor the number of incorrect passwords typed when unlocking the screen, and lock the tablet or erase all this user\'s data if too many incorrect passwords are typed."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Monitor the number of incorrect passwords typed when unlocking the screen, and lock your Android TV device or delete all of this user\'s data if too many incorrect passwords are typed."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Monitor the number of incorrect passwords typed when unlocking the screen, and lock the infotainment system or erase all this profile\'s data if too many incorrect passwords are typed."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Monitor the number of incorrect passwords typed when unlocking the screen, and lock the phone or erase all this user\'s data if too many incorrect passwords are typed."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"Change the screen lock"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"Change the screen lock."</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"Delete all data"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Erase the tablet\'s data without warning by performing a factory data reset."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Delete your Android TV device\'s data without warning by performing a factory data reset."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Erase the infotainment system\'s data without warning by performing a factory data reset."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Erase the phone\'s data without warning by performing a factory data reset."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"Erase user data"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Erase profile data"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Erase user data"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Erase this user\'s data on this tablet without warning."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Delete this user\'s data on this Android TV device without warning."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"Erase this profile\'s data on this infotainment system without warning."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"Erase this user\'s data on this phone without warning."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Set the device global proxy"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Set the device global proxy to be used while policy is enabled. Only the device owner can set the global proxy."</string> diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml index fe23e6367f98..c52ffa202422 100644 --- a/core/res/res/values-en-rIN/strings.xml +++ b/core/res/res/values-en-rIN/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"Monitor screen unlock attempts"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Monitor the number of incorrect passwords typed when unlocking the screen and lock the tablet or erase all the tablet\'s data if too many incorrect passwords are typed."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Monitor the number of incorrect passwords typed when unlocking the screen, and lock your Android TV device or delete all of your Android TV device\'s data if too many incorrect passwords are typed."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Monitor the number of incorrect passwords typed when unlocking the screen, and lock the infotainment system or erase all the infotainment system\'s data if too many incorrect passwords are typed."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Monitor the number of incorrect passwords typed when unlocking the screen and lock the phone or erase all the phone\'s data if too many incorrect passwords are typed."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Monitor the number of incorrect passwords typed when unlocking the screen, and lock the tablet or erase all this user\'s data if too many incorrect passwords are typed."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Monitor the number of incorrect passwords typed when unlocking the screen, and lock your Android TV device or delete all of this user\'s data if too many incorrect passwords are typed."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Monitor the number of incorrect passwords typed when unlocking the screen, and lock the infotainment system or erase all this profile\'s data if too many incorrect passwords are typed."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Monitor the number of incorrect passwords typed when unlocking the screen, and lock the phone or erase all this user\'s data if too many incorrect passwords are typed."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"Change the screen lock"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"Change the screen lock."</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"Delete all data"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Erase the tablet\'s data without warning by performing a factory data reset."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Delete your Android TV device\'s data without warning by performing a factory data reset."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Erase the infotainment system\'s data without warning by performing a factory data reset."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Erase the phone\'s data without warning by performing a factory data reset."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"Erase user data"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Erase profile data"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Erase user data"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Erase this user\'s data on this tablet without warning."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Delete this user\'s data on this Android TV device without warning."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"Erase this profile\'s data on this infotainment system without warning."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"Erase this user\'s data on this phone without warning."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Set the device global proxy"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Set the device global proxy to be used while policy is enabled. Only the device owner can set the global proxy."</string> diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml index 787de9b81d62..aba009dc447f 100644 --- a/core/res/res/values-en-rXC/strings.xml +++ b/core/res/res/values-en-rXC/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"Monitor screen unlock attempts"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Monitor the number of incorrect passwords typed when unlocking the screen, and lock the tablet or erase all the tablet\'s data if too many incorrect passwords are typed."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Monitor the number of incorrect passwords typed when unlocking the screen, and lock your Android TV device or erase all your Android TV device\'s data if too many incorrect passwords are typed."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Monitor the number of incorrect passwords typed. when unlocking the screen, and lock the infotainment system or erase all the infotainment system\'s data if too many incorrect passwords are typed."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Monitor the number of incorrect passwords typed. when unlocking the screen, and lock the phone or erase all the phone\'s data if too many incorrect passwords are typed."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Monitor the number of incorrect passwords typed when unlocking the screen, and lock the tablet or erase all this user\'s data if too many incorrect passwords are typed."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Monitor the number of incorrect passwords typed when unlocking the screen, and lock your Android TV device or erase all this user\'s data if too many incorrect passwords are typed."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Monitor the number of incorrect passwords typed when unlocking the screen, and lock the infotainment system or erase all this profile\'s data if too many incorrect passwords are typed."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Monitor the number of incorrect passwords typed when unlocking the screen, and lock the phone or erase all this user\'s data if too many incorrect passwords are typed."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"Change the screen lock"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"Change the screen lock."</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"Erase all data"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Erase the tablet\'s data without warning by performing a factory data reset."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Erase your Android TV device\'s data without warning by performing a factory data reset."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Erase the infotainment system\'s data without warning by performing a factory data reset."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Erase the phone\'s data without warning by performing a factory data reset."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"Erase user data"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Erase profile data"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Erase user data"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Erase this user\'s data on this tablet without warning."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Erase this user\'s data on this Android TV device without warning."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"Erase this profile\'s data on this infotainment system without warning."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"Erase this user\'s data on this phone without warning."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Set the device global proxy"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Set the device global proxy to be used while policy is enabled. Only the device owner can set the global proxy."</string> diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml index 2ec544d69ef3..d00ee6895da8 100644 --- a/core/res/res/values-es-rUS/strings.xml +++ b/core/res/res/values-es-rUS/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"Supervisa los intentos para desbloquear la pantalla"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Controla la cantidad de contraseñas incorrectas ingresadas al desbloquear la pantalla y bloquea la tablet o borra todos los datos de la tablet si se ingresaron demasiadas contraseñas incorrectas."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Supervisa la cantidad de contraseñas incorrectas que se escriben al desbloquear la pantalla y bloquea el dispositivo Android TV o borra todos sus datos si se ingresan demasiadas contraseñas incorrectas."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Permite controlar la cantidad de contraseñas incorrectas que se escriben al desbloquear la pantalla y bloquear el sistema de infoentretenimiento, o borrar todos los datos del sistema, si se ingresaron demasiadas contraseñas incorrectas."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Supervisar la cantidad de contraseñas ingresadas incorrectamente al desbloquear la pantalla, y bloquear el dispositivo o borrar todos sus datos si se ingresan demasiadas contraseñas incorrectas."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Permite controlar la cantidad de contraseñas incorrectas que se escriben al desbloquear la pantalla y bloquear la tablet, o borrar todos los datos del usuario, si se ingresan demasiadas contraseñas incorrectas."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Supervisa la cantidad de contraseñas incorrectas que se escriben al desbloquear la pantalla y bloquea el dispositivo Android TV o borra todos los datos del usuario si se ingresan demasiadas contraseñas incorrectas."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Permite controlar la cantidad de contraseñas incorrectas que se escriben al desbloquear la pantalla y bloquear el sistema de infoentretenimiento, o borrar todos los datos de perfil, si se ingresaron demasiadas contraseñas incorrectas."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Permite controlar la cantidad de contraseñas incorrectas que se escriben al desbloquear la pantalla y bloquear el teléfono, o borrar todos los datos del usuario, si se ingresan demasiadas contraseñas incorrectas."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"Cambiar el bloqueo de pantalla"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"Cambia el bloqueo de pantalla."</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"Borrar todos los datos"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Eliminar los datos de la tablet sin avisar y restablecer la configuración de fábrica"</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Restablece la configuración de fábrica para borrar los datos del dispositivo Android TV sin previo aviso."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Permite borrar los datos del sistema de infoentretenimiento sin previo aviso mediante el restablecimiento de la configuración de fábrica."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Borra los datos del dispositivo sin avisar y restablece la configuración de fábrica."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"Borrar los datos del usuario"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Borrar los datos de perfil"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Borrar los datos del usuario"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Permite borrar los datos del usuario en esta tablet sin previo aviso."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Borra los datos del usuario en este dispositivo Android TV sin previo aviso."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"Permite borrar los datos de perfil en este sistema de infoentretenimiento sin previo aviso."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"Permite borrar los datos del usuario en este teléfono sin previo aviso."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Configura el proxy global de dispositivo"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Configura el proxy global de dispositivo que se usará mientras se habilita la política. Solo el propietario del dispositivo puede configurar el proxy global."</string> diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml index afc064461f9e..ec0d321aad49 100644 --- a/core/res/res/values-es/strings.xml +++ b/core/res/res/values-es/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"Supervisar los intentos de desbloqueo de pantalla"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Controla el número de contraseñas incorrectas introducidas al desbloquear la pantalla y bloquea el tablet o elimina todos sus datos si se introducen demasiadas contraseñas incorrectas."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Comprueba cuántas veces se han introducido contraseñas incorrectas para desbloquear la pantalla y, si te parece que han sido demasiadas, bloquea tu dispositivo Android TV o borra todos sus datos."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Controla el número de contraseñas incorrectas introducidas al desbloquear la pantalla y bloquea el sistema de infoentretenimiento o borra todos sus datos si se introducen demasiadas contraseñas incorrectas."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Controla el número de contraseñas incorrectas introducidas al desbloquear la pantalla y bloquea el teléfono o elimina todos sus datos si se introducen demasiadas contraseñas incorrectas."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Controla el número de contraseñas incorrectas introducidas para desbloquear la pantalla y bloquea el tablet o borra todos los datos del usuario si se introducen demasiadas contraseñas incorrectas."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Comprueba cuántas veces se han introducido contraseñas incorrectas para desbloquear la pantalla y, si te parece que han sido demasiadas, bloquea tu dispositivo Android TV o borra todos los datos de este usuario."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Controla el número de contraseñas incorrectas introducidas al desbloquear la pantalla y bloquea el sistema de infoentretenimiento o borra todos los datos del perfil si se introducen demasiadas contraseñas incorrectas."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Controla el número de contraseñas incorrectas introducidas para desbloquear la pantalla y bloquea el teléfono o borra todos los datos del usuario si se introducen demasiadas contraseñas incorrectas."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"Cambiar el bloqueo de pantalla"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"Cambia el bloqueo de pantalla"</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"Borrar todos los datos"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Borrar los datos del tablet sin avisar restableciendo el estado de fábrica"</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Restablece los datos de fábrica de tu dispositivo Android TV, eliminando sin previo aviso los datos que tuviera."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Borra los datos del sistema de infoentretenimiento sin avisar restableciendo el estado de fábrica."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Borra los datos del teléfono sin avisar restableciendo el estado de fábrica"</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"Borrar datos del usuario"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Borrar datos del perfil"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Borrar datos del usuario"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Borra los datos del usuario en este tablet sin avisar."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Eliminar los datos de este usuario del dispositivo Android TV sin previo aviso."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"Borra los datos del perfil de este sistema de infoentretenimiento sin avisar."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"Borra los datos del usuario en este teléfono sin avisar."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Definir el servidor proxy global"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Define el servidor proxy global que se debe utilizar mientras la política esté habilitada. Solo el propietario del dispositivo puede definir el proxy global."</string> diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml index 70de8d910116..b1ce6f43c6d5 100644 --- a/core/res/res/values-et/strings.xml +++ b/core/res/res/values-et/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"Ekraani avamiskatsete jälgimine"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Jälgib ekraani avamisel valesti sisestatud paroolide arvu ja lukustab tahvelarvuti või kustutab kõik selle andmed, kui vale parool sisestatakse liiga palju kordi."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Jälgitakse ekraanikuva avamisel sisestatud valede paroolide arvu ja lukustatakse Android TV seade või kustutatakse kõik Android TV seadme andmed, kui vale parool sisestatakse liiga palju kordi."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Jälgib ekraani avamisel valesti sisestatud paroolide arvu ning lukustab teabe ja meelelahutuse süsteemi või kustutab kõik selle andmed, kui vale parool sisestatakse liiga palju kordi."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Jälgib ekraani avamisel valesti sisestatud paroolide arvu ja lukustab telefoni või kustutab kõik selle andmed, kui vale parool sisestatakse liiga palju kordi."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Jälgitakse ekraani avamisel sisestatud valede paroolide arvu ja lukustatakse tahvelarvuti või kustutatakse kõik selle kasutaja andmed, kui vale parool sisestatakse liiga palju kordi."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Jälgitakse ekraanikuva avamisel sisestatud valede paroolide arvu ja lukustatakse Android TV seade või kustutatakse kõik selle kasutaja andmed, kui vale parool sisestatakse liiga palju kordi."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Jälgitakse ekraani avamisel sisestatud valede paroolide arvu ning lukustatakse teabe ja meelelahutuse süsteem või kustutatakse kõik selle profiili andmed, kui vale parool sisestatakse liiga palju kordi."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Jälgitakse ekraani avamisel sisestatud valede paroolide arvu ja lukustatakse telefon või kustutatakse kõik selle kasutaja andmed, kui vale parool sisestatakse liiga palju kordi."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"Ekraaniluku muutmine"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"Muutke ekraanilukku."</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"Kõikide andmete kustutamine"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Kustutage tahvelarvuti andmed hoiatamata, lähtestades arvuti tehaseandmetele."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Kustutatakse teie Android TV seadme andmed ilma hoiatamata, lähtestades seadme tehase andmetele."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Teabe ja meelelahutuse süsteemi andmete hoiatamata kustutamine tehase andmetele lähtestamise abil."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Telefoniandmete hoiatuseta kustutamine, lähtestades telefoni tehaseseadetele."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"Kasutaja andmete kustutamine"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Profiili andmete kustutamine"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Kasutaja andmete kustutamine"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Kustutatakse selle kasutaja andmed sellest tahvelarvutist ilma hoiatamata."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Kustutatakse selle kasutaja andmed sellest Android TV seadmest ilma hoiatamata."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"Selle profiili andmete hoiatamata kustutamine teabe ja meelelahutuse süsteemist."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"Kustutatakse selle kasutaja andmed sellest telefonist ilma hoiatamata."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Määra seadme globaalne puhverserver"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Määratakse kasutatava seadme üldine puhverserver, kui reegel on lubatud. Üldise puhverserveri saab määrata ainult seadme omanik."</string> diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml index 72f98c6da479..d953d71ad9f8 100644 --- a/core/res/res/values-eu/strings.xml +++ b/core/res/res/values-eu/strings.xml @@ -670,10 +670,10 @@ <string name="permdesc_writeSyncSettings" msgid="6029151549667182687">"Kontu baten sinkronizazio-ezarpenak aldatzeko baimena ematen die aplikazioei. Adibidez, Jendea aplikazioa kontu batekin sinkronizatzeko erabil daiteke."</string> <string name="permlab_readSyncStats" msgid="3747407238320105332">"irakurri sinkronizazio-estatistikak"</string> <string name="permdesc_readSyncStats" msgid="3867809926567379434">"Kontu baten sinkronizazio-estatistikak irakurtzeko baimena ematen dio; besteak beste, sinkronizazio-gertaeren historia eta sinkronizatutako datu kopurua."</string> - <string name="permlab_sdcardRead" msgid="5791467020950064920">"Irakurri biltegiratze partekatuko edukia"</string> - <string name="permdesc_sdcardRead" msgid="6872973242228240382">"Biltegiratze partekatuko edukia irakurtzeko baimena ematen die aplikazioei."</string> - <string name="permlab_sdcardWrite" msgid="4863021819671416668">"aldatu edo ezabatu biltegiratze partekatuko edukia"</string> - <string name="permdesc_sdcardWrite" msgid="8376047679331387102">"Biltegiratze partekatuko edukian idazteko baimena ematen die aplikazioei."</string> + <string name="permlab_sdcardRead" msgid="5791467020950064920">"Irakurri biltegi partekatuko edukia"</string> + <string name="permdesc_sdcardRead" msgid="6872973242228240382">"Biltegi partekatuko edukia irakurtzeko baimena ematen die aplikazioei."</string> + <string name="permlab_sdcardWrite" msgid="4863021819671416668">"aldatu edo ezabatu biltegi partekatuko edukia"</string> + <string name="permdesc_sdcardWrite" msgid="8376047679331387102">"Biltegi partekatuko edukian idazteko baimena ematen die aplikazioei."</string> <string name="permlab_use_sip" msgid="8250774565189337477">"egin/jaso SIP deiak"</string> <string name="permdesc_use_sip" msgid="3590270893253204451">"SIP deiak egitea eta jasotzeko baimena ematen die aplikazioei."</string> <string name="permlab_register_sim_subscription" msgid="1653054249287576161">"erregistratu telekomunikabideekiko SIM konexio berriak"</string> @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"Gainbegiratu pantaila desblokeatzeko saiakerak"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Kontrolatu pantaila desblokeatzen saiatzean idatzitako pasahitz oker kopurua, eta blokeatu tableta edo ezabatu bere datuak pasahitza gehiegitan oker idazten bada."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Kontrolatu zenbat aldiz idatzi duzun oker pasahitza pantaila desblokeatzen saiatzean, eta blokeatu Android TV gailua edo ezabatu bertako datu guztiak pasahitza gehiegitan idazten baduzu oker."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Kontrolatu zenbatetan idazten duzun pasahitza oker pantaila desblokeatzen saiatzean eta, gehiegitan idazten bada oker, blokeatu informazio- eta aisia-sistema edo ezabatu hango eduki guztia."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Kontrolatu pantaila desblokeatzen saiatzean idatzitako pasahitz oker kopurua, eta blokeatu telefonoa edo ezabatu bere datuak pasahitza gehiegitan oker idazten bada."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Kontrolatu pantaila desblokeatzen saiatzean idatzitako pasahitz oker kopurua, eta blokeatu tableta edo ezabatu erabiltzailearen datuak pasahitza gehiegitan oker idazten bada."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Kontrolatu zenbat aldiz idatzi duzun oker pasahitza pantaila desblokeatzen saiatzean, eta blokeatu Android TV gailua edo ezabatu erabiltzailearen datuak pasahitza gehiegitan idazten baduzu oker."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Kontrolatu zenbatetan idazten duzun pasahitza oker pantaila desblokeatzen saiatzean eta, gehiegitan idazten bada oker, blokeatu informazio- eta aisia-sistema edo ezabatu profil honetako eduki guztia."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Kontrolatu pantaila desblokeatzen saiatzean idatzitako pasahitz oker kopurua, eta blokeatu telefonoa edo ezabatu erabiltzailearen datuak pasahitza gehiegitan oker idazten bada."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"Aldatu pantailaren blokeoa"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"Aldatu pantailaren blokeoa."</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"Ezabatu datu guztiak"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Ezabatu tabletaren datuak abisatu gabe, jatorrizko datuak berrezarrita."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Ezabatu Android TV gailuaren datuak abisatu gabe eta berrezarri jatorrizko datuak."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Berrezarri informazio- eta aisia-sistemako jatorrizko datuak abisatu gabe, bertan zegoen eduki guztia ezabatzeko."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Ezabatu telefonoaren datuak abisatu gabe, jatorrizko datuak berrezarrita."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"Ezabatu erabiltzailearen datuak"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Ezabatu profileko eduki guztia"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Ezabatu erabiltzailearen datuak"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Ezabatu erabiltzaileak tabletan dituen datuak abisatu gabe."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Ezabatu erabiltzaileak Android TV gailuan dituen datuak abisatu gabe."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"Ezabatu informazio- eta aisia-sisteman dagoen profil honetako eduki guztia abisatu gabe."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"Ezabatu erabiltzaileak telefonoan dituen datuak abisatu gabe."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Ezarri gailuaren proxy orokorra"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Ezarri gailuaren proxy orokorra gidalerroak gaituta dauden bitartean erabiltzeko. Gailuaren jabeak soilik ezar dezake proxy orokorra."</string> @@ -1521,7 +1526,7 @@ <item quantity="one">Emaitza bat</item> </plurals> <string name="action_mode_done" msgid="2536182504764803222">"Eginda"</string> - <string name="progress_erasing" msgid="6891435992721028004">"Biltegiratze partekatuko eduki guztia ezabatzen…"</string> + <string name="progress_erasing" msgid="6891435992721028004">"Biltegi partekatuko eduki guztia ezabatzen…"</string> <string name="share" msgid="4157615043345227321">"Partekatu"</string> <string name="find" msgid="5015737188624767706">"Aurkitu"</string> <string name="websearch" msgid="5624340204512793290">"Web-bilaketa"</string> @@ -1576,7 +1581,7 @@ <string name="action_menu_overflow_description" msgid="4579536843510088170">"Aukera gehiago"</string> <string name="action_bar_home_description_format" msgid="5087107531331621803">"%1$s, %2$s"</string> <string name="action_bar_home_subtitle_description_format" msgid="4346835454749569826">"%1$s, %2$s, %3$s"</string> - <string name="storage_internal" msgid="8490227947584914460">"Barneko memoria partekatua"</string> + <string name="storage_internal" msgid="8490227947584914460">"Barneko biltegi partekatua"</string> <string name="storage_sd_card" msgid="3404740277075331881">"SD txartela"</string> <string name="storage_sd_card_label" msgid="7526153141147470509">"<xliff:g id="MANUFACTURER">%s</xliff:g> SD txartela"</string> <string name="storage_usb_drive" msgid="448030813201444573">"USB bidezko unitatea"</string> diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml index 9f7204496f1d..946039e220c0 100644 --- a/core/res/res/values-fa/strings.xml +++ b/core/res/res/values-fa/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"پایش تلاشهای باز کردن قفل صفحه"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"تعداد گذرواژههای نادرست تایپ شده را هنگام بازکردن قفل صفحه کنترل میکند، و اگر دفعات زیادی گذرواژه نادرست وارد شود رایانهٔ لوحی را قفل میکند و همه دادههای رایانهٔ لوحی را پاک میکند."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"بر تعداد گذرواژههای نادرستی که هنگام بازکردن قفل صفحه تایپ میشود، نظارت میکند، و اگر گذرواژههای نادرست دفعات زیادی تایپ شوند، Android TV را قفل میکند یا همه دادههای آن را پاک میکند."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"بر تعداد گذرواژههای نادرست تایپشده در زمان باز کردن قفل صفحه نظارت میشود و اگر گذرواژههای نادرست دفعات خیلی زیادی تایپ شود، سیستم اطلاعات-سرگرمی قفل میشود یا همه دادههای سیستم اطلاعات-سرگرمی پاک میشود."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"تعداد گذرواژههای نادرست تایپشده را هنگام بازکردن قفل صفحه کنترل میکند و اگر چندین بار گذرواژههای نادرست وارد شود، تلفن را قفل میکند یا همه دادههای تلفن را پاک میکند."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"بر تعداد گذرواژههای نادرستی که هنگام باز کردن قفل صفحه تایپ شده، نظارت میکند، و اگر تعداد گذرواژههای تایپ شده نادرست بیش از حد بود، رایانه لوحی را قفل میکند یا کلیه دادههای کاربر را پاک میکند."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"بر تعداد گذرواژههای نادرستی که هنگام باز کردن قفل صفحه تایپ میشود، نظارت میکند، و اگر گذرواژههای نادرست دفعات زیادی تایپ شوند، دستگاه Android TV را قفل یا همه دادههای کاربر را پاک میکند."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"بر تعداد گذرواژههای نادرستی که هنگام باز کردن قفل صفحه تایپ شده نظارت میشود و اگر گذرواژههای نادرست دفعات خیلی زیادی تایپ شود، تلفن قفل میشود یا همه دادههای کاربر پاک میشود."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"بر تعداد گذرواژههای نادرستی که هنگام باز کردن قفل صفحه تایپ شده، نظارت میکند، و اگر تعداد گذرواژههای تایپ شده نادرست بیش از حد بود، تلفن را قفل میکند یا کلیه دادههای کاربر را پاک میکند."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"تغییر قفل صفحه"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"قفل صفحه را تغییر میدهد."</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"پاک کردن تمام دادهها"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"با انجام بازنشانی دادههای کارخانه، دادههای رایانهٔ لوحی بدون هشدار پاک میشود."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"دادههای دستگاه Android TV شما، بدون نشان داده شدن هشدار و با انجام بازنشانی دادههای کارخانه، پاک میشود."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"دادههای سیستم اطلاعات-سرگرمی بدون هشدار و با انجام بازنشانی دادههای کارخانه پاک میشود."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"با انجام بازنشانی دادههای کارخانه، دادههای تلفن بدون هشدار پاک میشود."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"پاک کردن دادههای کاربر"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"پاک کردن دادههای نمایه"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"پاک کردن دادههای کاربر"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"دادههای این کاربر را در این رایانه لوحی بدون هشدار پاک میکند."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"بدون نشان داده شدن هشدار، دادههای این کاربر در این دستگاه Android TV پاک میشود."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"دادههای این نمایه در این سیستم اطلاعات-سرگرمی بدوم هشدار پاک میشود."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"دادههای این کاربر را در این تلفن بدون هشدار پاک میکند."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"تنظیم پروکسی جهانی دستگاه"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"پروکسی کلی دستگاه را برای استفاده هنگام فعال بودن این خطمشی تنظیم میکند. تنها مالک دستگاه میتواند پروکسی کلی را تنظیم کند."</string> @@ -909,7 +914,7 @@ <string name="emergency_calls_only" msgid="3057351206678279851">"فقط تماسهای اضطراری"</string> <string name="lockscreen_network_locked_message" msgid="2814046965899249635">"شبکه قفل شد"</string> <string name="lockscreen_sim_puk_locked_message" msgid="6618356415831082174">"سیم کارت با PUK قفل شده است."</string> - <string name="lockscreen_sim_puk_locked_instructions" msgid="5307979043730860995">"لطفاً به راهنمای کاربر مراجعه کرده یا با مرکز پشتیبانی از مشتریان تماس بگیرید."</string> + <string name="lockscreen_sim_puk_locked_instructions" msgid="5307979043730860995">"لطفاً به «راهنمای کاربر» مراجعه کنید یا با مرکز «مراقبت از مشتریان» تماس بگیرید."</string> <string name="lockscreen_sim_locked_message" msgid="3160196135801185938">"سیم کارت قفل شد."</string> <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="2286497117428409709">"بازگشایی قفل سیم کارت…"</string> <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6458790975898594240">"الگوی بازگشایی قفل را <xliff:g id="NUMBER_0">%1$d</xliff:g> بار اشتباه کشیدهاید. \n\nپساز <xliff:g id="NUMBER_1">%2$d</xliff:g> ثانیه دوباره امتحان کنید."</string> diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml index 388a586ba2ff..714167fed25f 100644 --- a/core/res/res/values-fi/strings.xml +++ b/core/res/res/values-fi/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"Tarkkailla näytön avaamisyrityksiä"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Valvoo väärien salasanojen lukumäärää näytön lukituksen poistossa sekä lukitsee tablet-laitteen tai poistaa sen tiedot, jos salasana syötetään väärin liian monta kertaa."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Valvo väärien salasanojen määrää ruudun lukitusta avattaessa ja lukitse Android TV ‑laite tai poista kaikki Android TV ‑laitteen tiedot, jos salasana kirjoitetaan väärin liian monta kertaa."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Valvoo väärien salasanojen lukumäärää näytön lukituksen poistossa ja lukitsee infotainment-järjestelmän tai poistaa sen kaiken datan, jos väärä salasana syötetään liian monta kertaa."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Valvoo väärien salasanojen lukumäärää näytön lukituksen poistossa ja lukitsee puhelimen tai poistaa sen kaikki tiedot, jos väärä salasana syötetään liian monta kertaa."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Valvo väärien salasanojen määrää ruudun lukitusta avattaessa ja lukitse tabletti tai poista kaikki tämän käyttäjän tiedot, jos salasana kirjoitetaan väärin liian monta kertaa."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Valvo väärien salasanojen määrää ruudun lukitusta avattaessa ja lukitse Android TV ‑laite tai poista kaikki tämän käyttäjän tiedot, jos salasana kirjoitetaan väärin liian monta kertaa."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Valvoo väärien salasanojen määrää näytön lukituksen poistossa ja lukitsee infotainment-järjestelmän tai poistaa kaiken tämän profiilin datan, jos väärä salasana syötetään liian monta kertaa."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Valvo väärien salasanojen määrää ruudun lukitusta avattaessa ja lukitse puhelin tai poista kaikki tämän käyttäjän tiedot, jos salasana kirjoitetaan väärin liian monta kertaa."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"Muuttaa näytön lukituksen"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"Muuttaa näytön lukituksen."</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"Pyyhkiä kaikki tiedot"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Tyhjennä tablet-laitteen tiedot varoituksetta palauttamalla tehdasasetukset."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Tyhjentää Android TV ‑laitteen tiedot ilman varoitusta palauttamalla tehdasasetukset."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Poistaa infotainment-järjestelmän datan ilman varoitusta palauttamalla tehdasasetukset."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Tyhjentää puhelimen tiedot varoituksetta palauttamalla tehdasasetukset."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"Pyyhi käyttäjän tiedot"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Profiilidatan poistaminen"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Pyyhi käyttäjän tiedot"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Pyyhi tämän käyttäjän tiedot tabletista ilman varoitusta."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Tyhjentää tämän käyttäjän tiedot Android TV ‑laitteesta ilman varoitusta."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"Poistaa tämän profiilin datan tästä infotainment-järjestelmästä ilman varoitusta."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"Pyyhi tämän käyttäjän tiedot puhelimesta ilman varoitusta."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Aseta laitteen yleinen välityspalvelin"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Aseta laitteen yleinen välityspalvelin käyttöön, kun käytäntö on käytössä. Vain laitteen omistaja voi asettaa yleisen välityspalvelimen."</string> diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml index 4b0f4bbe4ac7..586d745ae894 100644 --- a/core/res/res/values-fr-rCA/strings.xml +++ b/core/res/res/values-fr-rCA/strings.xml @@ -551,10 +551,10 @@ <string name="permdesc_requestPasswordComplexity" msgid="1130556896836258567">"Autorise l\'application à apprendre le niveau de complexité de l\'écran de verrouillage (élevé, moyen, faible ou aucun), qui indique la gamme possible de longueur et de type de verrouillage d\'écran. L\'application peut aussi suggérer aux utilisateurs de mettre à jour l\'écran de verrouillage afin d\'utiliser un certain niveau de complexité, mais ils peuvent ignorer la suggestion. Notez que le verrouillage d\'écran n\'est pas stocké en texte brut pour de manière à ce que l\'application n\'ait pas accès au mot de passe exact."</string> <string name="permlab_useBiometric" msgid="6314741124749633786">"utiliser le matériel biométrique"</string> <string name="permdesc_useBiometric" msgid="7502858732677143410">"Permet à l\'application d\'utiliser du matériel biométrique pour l\'authentification"</string> - <string name="permlab_manageFingerprint" msgid="7432667156322821178">"gérer le matériel d\'empreinte digitale"</string> + <string name="permlab_manageFingerprint" msgid="7432667156322821178">"gérer le lecteur d\'empreintes digitales"</string> <string name="permdesc_manageFingerprint" msgid="2025616816437339865">"Permet à l\'application de faire appel à des méthodes d\'ajout et de suppression de modèles d\'empreinte digitale que vous pouvez utiliser."</string> - <string name="permlab_useFingerprint" msgid="1001421069766751922">"utiliser le matériel d\'empreinte digitale"</string> - <string name="permdesc_useFingerprint" msgid="412463055059323742">"Permet à l\'application d\'utiliser du matériel d\'empreinte digitale pour l\'authentification"</string> + <string name="permlab_useFingerprint" msgid="1001421069766751922">"utiliser le lecteur d\'empreintes digitales"</string> + <string name="permdesc_useFingerprint" msgid="412463055059323742">"Permet à l\'application d\'utiliser le lecteur d\'empreintes digitales pour l\'authentification"</string> <string name="permlab_audioWrite" msgid="8501705294265669405">"modifier votre collection de musique"</string> <string name="permdesc_audioWrite" msgid="8057399517013412431">"Autorise l\'application à modifier votre collection de musique."</string> <string name="permlab_videoWrite" msgid="5940738769586451318">"modifier votre collection de vidéos"</string> @@ -590,7 +590,7 @@ <string name="fingerprint_authenticated" msgid="2024862866860283100">"Empreinte digitale authentifiée"</string> <string name="face_authenticated_no_confirmation_required" msgid="8867889115112348167">"Visage authentifié"</string> <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Visage authentifié, veuillez appuyer sur le bouton Confirmer"</string> - <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Matériel d\'empreinte digitale numérique indisponible."</string> + <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Lecteur d\'empreintes digitales indisponible."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Impossible de configurer l\'empreinte digitale"</string> <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Le temps attribué pour lire l\'empreinte digitale est écoulé. Veuillez réessayer."</string> <string name="fingerprint_error_canceled" msgid="540026881380070750">"Opération d\'empreinte digitale numérique annulée."</string> @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"Gérer les tentatives de déverrouillage de l\'écran"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Contrôler le nombre de mots de passe incorrects saisis pour le déverrouillage de l\'écran, puis verrouiller la tablette ou effacer toutes ses données si le nombre maximal de tentatives de saisie du mot de passe est atteint"</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Surveillez le nombre de mots de passe incorrects entrés lors du déverrouillage de l\'écran et verrouillez votre appareil Android TV ou effacez toutes les données qu\'il contient en cas d\'un nombre trop élevé de tentatives."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Surveillez le nombre de mots de passe incorrects entrés lors du déverrouillage de l\'écran et verrouillez le système d\'infodivertissement ou effacez toutes ses données en cas d\'un nombre trop élevé de tentatives."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Contrôler le nombre de mots de passe incorrects saisis pour le déverrouillage de l\'écran, puis verrouille le téléphone ou efface toutes ses données si le nombre maximal de tentatives de saisie du mot de passe est atteint."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Surveille le nombre de mots de passe incorrects entrés lors du déverrouillage de l\'écran et verrouille la tablette ou efface toutes les données de l\'utilisateur en cas d\'un nombre trop élevé de tentatives."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Surveillez le nombre de mots de passe incorrects entrés lors du déverrouillage de l\'écran et verrouillez votre appareil Android TV ou effacez toutes les données de l\'utilisateur en cas d\'un nombre trop élevé de tentatives."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Surveillez le nombre de mots de passe incorrects entrés lors du déverrouillage de l\'écran et verrouillez le système d\'infodivertissement ou effacez toutes les données de ce profil en cas d\'un nombre trop élevé de tentatives."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Surveille le nombre de mots de passe incorrects entrés lors du déverrouillage de l\'écran et verrouille le téléphone ou efface toutes les données de l\'utilisateur en cas d\'un nombre trop élevé de tentatives."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"Modifier le verrouillage de l\'écran"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"Modifier le verrouillage de l\'écran."</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"Effacer toutes les données"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Effacer les données de la tablette sans avertissement, en rétablissant les paramètres par défaut"</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Effacez les données de votre appareil Android TV sans avertissement en effectuant une réinitialisation des paramètres d\'usine."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Effacez les données du système d\'infodivertissement sans avertissement en rétablissant les paramètres par défaut."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Effacer les données du téléphone sans avertissement en rétablissant les paramètres par défaut."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"Effacer les données de l\'utilisateur"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Effacer les données de profil"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Effacer les données de l\'utilisateur"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Effacer les données de l\'utilisateur sur cette tablette sans avertissement."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Effacez les données de cet utilisateur sur cet appareil Android TV sans avertissement."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"Effacez les données de ce profil sur ce système d\'infodivertissement sans avertissement."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"Effacer les données de l\'utilisateur sur ce téléphone sans avertissement."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Définir le serveur mandataire global du mobile"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Indiquer le mandataire global à utiliser pour l\'appareil lorsque la politique est activée. Seul le propriétaire de l\'appareil peut définir le mandataire global."</string> diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml index 59046eea2272..81e78b431df1 100644 --- a/core/res/res/values-fr/strings.xml +++ b/core/res/res/values-fr/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"Gérer les tentatives de déverrouillage de l\'écran"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Contrôler le nombre de mots de passe incorrects saisis pour le déverrouillage de l\'écran, puis verrouiller la tablette ou effacer toutes ses données si le nombre maximal de tentatives de saisie du mot de passe est atteint"</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Contrôle le nombre de fois qu\'un mot de passe incorrect est saisi lors du déverrouillage de l\'écran, et verrouille votre appareil Android TV ou en efface toutes les données si le nombre maximal de mots de passe incorrects autorisé est dépassé."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Contrôler le nombre de mots de passe incorrects saisis pour le déverrouillage de l\'écran, puis verrouiller le système d\'infoloisirs ou effacer toutes ses données si le nombre maximal de tentatives de saisie du mot de passe est atteint."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Contrôler le nombre de mots de passe incorrects saisis pour le déverrouillage de l\'écran, puis verrouiller le téléphone ou effacer toutes ses données si le nombre maximal de tentatives de saisie du mot de passe est atteint"</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Contrôlez le nombre de fois qu\'un mot de passe incorrect est saisi lors du déverrouillage de l\'écran, et verrouillez la tablette ou effacez toutes les informations sur l\'utilisateur si le nombre maximal de mots de passe incorrects autorisés est dépassé."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Contrôle le nombre de fois qu\'un mot de passe incorrect est saisi lors du déverrouillage de l\'écran, et verrouille votre appareil Android TV ou efface toutes les données de cet utilisateur si le nombre maximal de mots de passe incorrects autorisé est dépassé."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Contrôler le nombre de mots de passe incorrects saisis pour le déverrouillage de l\'écran, puis verrouiller le système d\'infoloisirs ou effacer toutes les données de ce profil si le nombre maximal de tentatives de saisie du mot de passe est atteint."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Contrôlez le nombre de fois qu\'un mot de passe incorrect est saisi lors du déverrouillage de l\'écran, et verrouillez le téléphone ou effacez toutes les informations sur l\'utilisateur si le nombre maximal de mots de passe incorrects autorisés est dépassé."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"Modifier le verrouillage de l\'écran"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"Modifier le verrouillage de l\'écran"</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"Effacer toutes les données"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Effacer les données de la tablette sans avertissement, en rétablissant la configuration d\'usine"</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Efface les données de votre appareil Android TV sans avertissement en rétablissant la configuration d\'usine."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Effacer les données du système d\'infoloisirs sans avertissement en rétablissant la configuration d\'usine."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Effacer les données du téléphone sans avertissement, en rétablissant la configuration d\'usine"</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"Effacer les informations sur l\'utilisateur"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Effacer les données du profil"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Effacer les informations sur l\'utilisateur"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Effacer les informations sur cet utilisateur de cette tablette sans avertissement"</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Efface les données concernant cet utilisateur de cet appareil Android TV sans avertissement."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"Effacer les données de ce profil sur ce système d\'infoloisirs sans avertissement."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"Effacer les informations sur cet utilisateur de ce téléphone sans avertissement"</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Définir le proxy global du mobile"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Indiquer le proxy global à utiliser pour l\'appareil lorsque la règle est activée. Seul le propriétaire de l\'appareil peut définir le proxy global."</string> diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml index 34f027caa32d..c3622b251a08 100644 --- a/core/res/res/values-gl/strings.xml +++ b/core/res/res/values-gl/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"Controlar os intentos de desbloqueo da pantalla"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Supervisa o número de contrasinais incorrectos escritos ao desbloquear a pantalla e bloquea a tableta ou borra todos os datos da tableta se se escriben demasiados contrasinais incorrectos."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Controla o número de contrasinais incorrectos escritos ao desbloquear a pantalla e bloquea o dispositivo Android TV ou borra todos os datos do dispositivo se se escriben demasiados contrasinais incorrectos."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Supervisa o número de contrasinais incorrectos que se escriben ao desbloquear a pantalla e bloquea o sistema de información e entretemento ou borra todos os seus datos se se meten demasiados incorrectos."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Supervisa o número de contrasinais incorrectos escritos ao desbloquear a pantalla e bloquea o teléfono ou borra todos os datos do teléfono se se escriben demasiados contrasinais incorrectos."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Supervisar o número de contrasinais incorrectos escritos ao desbloquear a pantalla e bloquear a tableta ou borrar todos os datos do usuario se se escriben demasiados contrasinais incorrectos."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Controla o número de contrasinais incorrectos escritos ao desbloquear a pantalla e bloquea o dispositivo Android TV ou borra todos os datos deste usuario se se escriben demasiados contrasinais incorrectos."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Supervisa o número de contrasinais incorrectos que se escriben ao desbloquear a pantalla e bloquea o sistema de información e entretemento ou borra todos os datos deste perfil se se meten demasiados incorrectos."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Supervisar o número de contrasinais incorrectos escritos ao desbloquear a pantalla e bloquear o teléfono ou borrar todos os datos do usuario se se escriben demasiados contrasinais incorrectos."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"Cambiar o bloqueo da pantalla"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"Cambia o bloqueo da pantalla."</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"Borrar todos os datos"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Borra os datos da tableta sen previo aviso mediante a realización dun restablecemento dos datos de fábrica."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Borra a información do dispositivo Android TV sen avisar e realiza un restablecemento dos datos de fábrica."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Borra os datos do sistema de información e entretemento sen previo aviso a través do restablecemento dos datos de fábrica."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Borra os datos do teléfono sen previo aviso mediante a realización dun restablecemento dos datos de fábrica."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"Borrar os datos do usuario"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Borrar os datos do perfil"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Borrar os datos do usuario"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Borra os datos deste usuario nesta tableta sen previo aviso."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Borra os datos deste usuario neste dispositivo Android TV sen avisar."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"Borra os datos deste perfil do sistema de información e entretemento sen previo aviso."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"Borra os datos deste usuario neste teléfono sen previo aviso."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Establecer o proxy global do dispositivo"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Configura o proxy global do dispositivo que se debe usar cando a política está activada. Só o propietario do dispositivo pode configurar o proxy global."</string> diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml index 45934d2bd296..77e3aa0ea15a 100644 --- a/core/res/res/values-gu/strings.xml +++ b/core/res/res/values-gu/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"સ્ક્રીનને અનલૉક કરવાના પ્રયત્નોનું નિયમન કરો"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"સ્ક્રીનને અનલૉક કરતી વખતે લખેલા ખોટા પાસવર્ડ્સની સંખ્યાને મૉનિટર કરો અને જો ઘણા બધા ખોટા પાસવર્ડ્સ લખ્યાં છે તો ટેબ્લેટને લૉક કરો અથવા ટેબ્લેટનો તમામ ડેટા કાઢી નાખો."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"સ્ક્રીનને અનલૉક કરતી વખતે ટાઇપ કરેલા ખોટા પાસવર્ડની સંખ્યાને મૉનિટર કરો અને જો ઘણા બધા ખોટા પાસવર્ડ ટાઇપ કર્યા હોય, તો તમારા Android TV ડિવાઇસના ડેટાને લૉક કરો અથવા આ વપરાશકર્તાનો બધો ડેટા કાઢી નાખો."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"સ્ક્રીનને અનલૉક કરતી વખતે લખેલા ખોટા પાસવર્ડની સંખ્યાને મૉનિટર કરો અને જો ઘણા બધા ખોટા પાસવર્ડ લખ્યા હોય તો ઇન્ફોટેનમેન્ટ સિસ્ટમને લૉક કરો અથવા ઇન્ફોટેનમેન્ટ સિસ્ટમનો બધો ડેટા કાઢી નાખો."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"સ્ક્રીનને અનલૉક કરતી વખતે લખેલા ખોટા પાસવર્ડ્સની સંખ્યાને મૉનિટર કરો અને જો ઘણા બધા ખોટા પાસવર્ડ્સ લખ્યાં છે તો ફોનને લૉક કરો અથવા ફોનનો તમામ ડેટા કાઢી નાખો."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"સ્ક્રીનને અનલૉક કરતી વખતે લખેલા ખોટા પાસવર્ડ્સની સંખ્યાને મૉનિટર કરો અને જો ઘણા બધા ખોટા પાસવર્ડ્સ લખ્યાં છે તો ટેબ્લેટને લૉક કરો અથવા આ વપરાશકર્તાનો તમામ ડેટા કાઢી નાખો."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"સ્ક્રીનને અનલૉક કરતી વખતે ટાઇપ કરેલા ખોટા પાસવર્ડની સંખ્યાને મૉનિટર કરો અને જો ઘણા બધા ખોટા પાસવર્ડ ટાઇપ કર્યા હોય તો તમારા Android TV ડિવાઇસને લૉક કરો અથવા આ વપરાશકર્તાનો બધો ડેટા કાઢી નાખો."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"સ્ક્રીનને અનલૉક કરતી વખતે લખેલા ખોટા પાસવર્ડની સંખ્યાને મૉનિટર કરો અને જો ઘણા બધા ખોટા પાસવર્ડ લખ્યા હોય તો ઇન્ફોટેનમેન્ટ સિસ્ટમને લૉક કરો અથવા આ પ્રોફાઇલનો બધો ડેટા કાઢી નાખો."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"સ્ક્રીનને અનલૉક કરતી વખતે લખેલા ખોટા પાસવર્ડ્સની સંખ્યાને મૉનિટર કરો અને જો ઘણા બધા ખોટા પાસવર્ડ્સ લખ્યાં છે તો ફોનને લૉક કરો અથવા આ વપરાશકર્તાનો તમામ ડેટા કાઢી નાખો."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"સ્ક્રીન લૉક બદલો"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"સ્ક્રીન લૉક બદલો."</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"બધો ડેટા કાઢી નાખો"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"ફેક્ટરી ડેટા ફરીથી સેટ કરોને કરીને ચેતવણી વિના ટેબ્લેટનો ડેટા કાઢી નાખો."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"ફેક્ટરી ડેટા રીસેટ કરીને ચેતવણી વિના તમારા Android TV ડિવાઇસનો ડેટા કાઢી નાખો."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"ફેક્ટરી ડેટા રીસેટ કરીને કોઈ ચેતવણી વિના જ ઇન્ફોટેનમેન્ટ સિસ્ટમનો ડેટા કાઢી નાખો."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"ફેક્ટરી ડેટા ફરીથી સેટ કરોને કરીને ચેતવણી વિના ફોનનો ડેટા કાઢી નાખો."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"વપરાશકર્તા ડેટા કાઢી નાખો"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"પ્રોફાઇલનો ડેટા કાઢી નાખો"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"વપરાશકર્તા ડેટા કાઢી નાખો"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"ચેતવણી વિના આ ટેબ્લેટ પરનો આ વપરાશકર્તાનો ડેટા કાઢી નાખો."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"ચેતવણી વિના આ Android TV ડિવાઇસ પર રહેલો આ વપરાશકર્તાનો ડેટા કાઢી નાખો."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"કોઈ ચેતવણી વિના જ આ ઇન્ફોટેનમેન્ટ સિસ્ટમ પર રહેલો આ પ્રોફાઇલનો ડેટા કાઢી નાખો."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"ચેતવણી વિના આ ફોન પરનો આ વપરાશકર્તાનો ડેટા કાઢી નાખો."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"ઉપકરણ વૈશ્વિક પ્રોક્સી સેટ કરો"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"પૉલિસી ચાલુ હોય તે વખતે ઉપયોગ કરવા માટેના ડિવાઇસ વૈશ્વિક પ્રોક્સીને સેટ કરો. ફક્ત ડિવાઇસના માલિક વૈશ્વિક પ્રોક્સી સેટ કરી શકે છે."</string> diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml index 81251f16c0b4..90192d5fa747 100644 --- a/core/res/res/values-hi/strings.xml +++ b/core/res/res/values-hi/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"स्क्रीन अनलॉक करने के की कोशिशों पर नज़र रखना"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"स्क्रीन को अनलॉक करते समय गलत लिखे गए पासवर्ड की संख्या पर निगरानी करें, और बहुत ज़्यादा बार गलत पासवर्ड लिखे जाने पर टैबलेट लॉक करें या टैबलेट का संपूर्ण डेटा मिटाएं."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"स्क्रीन को अनलॉक करते समय ध्यान रखें कि कितनी बार गलत पासवर्ड डाला गया है. अगर बहुत ज़्यादा बार गलत पासवर्ड डाला गया है, तो अपने Android TV डिवाइस को तुरंत लॉक करें या इसका सभी डेटा मिटाएं."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"स्क्रीन को अनलॉक करते समय ध्यान रखें कि कितनी बार गलत पासवर्ड डाला गया है. अगर बहुत ज़्यादा बार गलत पासवर्ड डाला गया है, तो सूचना और मनोरंजन की सुविधा देने वाले डिवाइस को लॉक करें या इस डिवाइस का सारा डेटा मिटाएं."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"स्क्रीन को अनलॉक करते समय जितनी बार गलत पासवर्ड लिखा गया है, उसकी संख्या पर नज़र रखना और अगर बहुत बार गलत पासवर्ड डाले गए हैं, तो फ़ोन को लॉक कर देना या फ़ोन का सारा डेटा मिटा देना."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"स्क्रीन का लॉक खोलते समय गलत तरीके से लिखे गए पासवर्ड पर नज़र रखें, और अगर बार-बार ज़्यादा पासवर्ड लिखे जाते हैं तो टैबलेट को लॉक करें या इस उपयोगकर्ता का सभी डेटा मिटा दें."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"स्क्रीन को अनलॉक करते समय ध्यान रखें कि कितनी बार गलत पासवर्ड डाला गया है. अगर बहुत ज़्यादा बार गलत पासवर्ड डाला गया है, तो अपने Android TV डिवाइस को तुरंत लॉक करें या इस उपयोगकर्ता का सभी डेटा मिटाएं."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"स्क्रीन को अनलॉक करते समय ध्यान रखें कि कितनी बार गलत पासवर्ड डाला गया है. अगर बहुत ज़्यादा बार गलत पासवर्ड डाला गया है, तो सूचना और मनोरंजन की सुविधा देने वाले डिवाइस को लॉक करें या इस प्रोफ़ाइल का सारा डेटा मिटाएं."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"स्क्रीनका लॉक खोलते समय गलत तरीके से लिखे गए पासवर्ड पर नज़र रखें, और अगर बार-बार गलत पासवर्ड लिखा जाता है तो फ़ोन को लॉक करें या इस उपयोगकर्ता का सभी डेटा मिटा दें."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"स्क्रीन लॉक बदलना"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"इससे स्क्रीन लॉक बदला जाता है."</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"सारा डेटा मिटाना"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"फ़ैक्टरी डेटा रीसेट करके चेतावनी दिए बिना फ़ोन का डेटा मिटाना."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"फ़ैक्ट्री डेटा रीसेट करके अपने Android TV डिवाइस का डेटा बिना चेतावनी दिए मिटाएं."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"फ़ैक्ट्री डेटा रीसेट करके, बिना किसी चेतावनी के सूचना और मनोरंजन की सुविधा देने वाले डिवाइस में सेव डेटा को हमेशा के लिए मिटाएं."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"इससे फ़ैक्टरी डेटा रीसेट करके, चेतावनी दिए बिना फ़ोन का डेटा मिट जाता है."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"उपयोगकर्ता डेटा मिटाएं"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"प्रोफ़ाइल का डेटा मिटाना"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"उपयोगकर्ता डेटा मिटाएं"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"इस टैबलेट पर मौजूद इस उपयोगकर्ता का डेटा बिना चेतावनी के मिटा दें."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"बिना चेतावनी दिए, इस Android TV डिवाइस से उपयोगकर्ता का डेटा मिटाएं."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"बिना किसी चेतावनी के, सूचना और मनोरंजन की सुविधा देने वाले डिवाइस में मौजूद इस प्रोफ़ाइल का डेटा मिटाएं."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"इस फ़ोन पर मौजूद इस उपयोगकर्ता का डेटा बिना चेतावनी के मिटा दें."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"डिवाइस वैश्विक प्रॉक्सी सेट करें"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"नीति चालू होने के दौरान इस्तेमाल करने के लिए डिवाइस ग्लोबल प्रॉक्सी सेट करें. केवल डिवाइस का मालिक ही ग्लोबल प्रॉक्सी सेट कर सकता है."</string> diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml index e326f8f03fd0..cde958a44ada 100644 --- a/core/res/res/values-hr/strings.xml +++ b/core/res/res/values-hr/strings.xml @@ -732,9 +732,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"Nadziri pokušaje otključavanja zaslona"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Nadziri broj netočnih zaporki unesenih pri otključavanju zaslona i zaključaj tabletno računalo ili izbriši sve podatke na njemu ako je uneseno previše netočnih zaporki."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Prati broj netočnih zaporki unesenih prilikom otključavanja zaslona i zaključava Android TV uređaj ili s njega briše sve podatke ako se unese previše netočnih zaporki."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Prati broj netočnih zaporki unesenih prilikom otključavanja zaslona i zaključava sustav za informiranje i zabavu ili briše sve njegove podatke ako se unese previše netočnih zaporki."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Nadzire broj netočno unesenih zaporki pri otključavanju zaslona i zaključava telefon ili briše sve podatke na telefonu ako je uneseno previše netočnih zaporki."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Prati broj netočnih zaporki unesenih prilikom otključavanja zaslona i zaključava tablet ili briše sve podatke korisnika ako se unese previše netočnih zaporki."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Prati broj netočnih zaporki unesenih prilikom otključavanja zaslona i zaključava Android TV uređaj ili briše sve podatke korisnika ako se unese previše netočnih zaporki."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Prati broj netočnih zaporki unesenih prilikom otključavanja zaslona i zaključava sustav za informiranje i zabavu ili briše sve podatke profila ako se unese previše netočnih zaporki."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Prati broj netočnih zaporki unesenih prilikom otključavanja zaslona i zaključava telefon ili briše sve podatke korisnika ako se unese previše netočnih zaporki."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"Mijenjanje zaporke za zaključavanje"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"Mijenja se zaporka za zaključavanje zaslona."</string> @@ -743,10 +745,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"Brisanje svih podataka"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Vraćanjem u tvorničko stanje izbriši podatke tabletnog računala bez upozorenja."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Podatke Android TV uređaja izbrišite bez upozorenja vraćanjem uređaja na tvorničke postavke."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Briše podatke sustava za informiranje i zabavu bez upozorenja vraćanjem na tvorničko stanje."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Vraćanjem na tvorničke postavke brišu se podaci s telefona bez upozorenja."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"Izbriši podatke korisnika"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Izbriši podatke profila"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Izbriši podatke korisnika"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Briše podatke korisnika na ovom tabletu bez upozorenja."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Briše podatke korisnika na Android TV uređaju bez upozorenja."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"Briše podatke profila na ovom sustavu za informiranje i zabavu bez upozorenja."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"Briše podatke korisnika na ovom telefonu bez upozorenja."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"postavi globalni proxy uređaja"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Postavlja globalni proxy za uređaj koji će se upotrebljavati dok je pravilo omogućeno. Samo vlasnik uređaja može postaviti globalni proxy."</string> diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml index 567783d2be7c..4293394b9af0 100644 --- a/core/res/res/values-hu/strings.xml +++ b/core/res/res/values-hu/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"Képernyőzár-feloldási kísérletek figyelése"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Megfigyeli a képernyő feloldásakor helytelenül beírt jelszavak számát, és túl sok hibásan beírt jelszó esetén lezárja a táblagépet, vagy törli a táblagép összes adatát."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"A képernyő feloldásához megadott helytelen jelszavak számának figyelése, és az Android TV eszköz zárolása vagy az Android TV eszköz összes adatának törlése túl sok helytelen jelszó után."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Megfigyeli a képernyő feloldásakor helytelenül beírt jelszavak számát, és túl sok hibásan beírt jelszó esetén lezárja az infotainmentrendszert, vagy törli az infotainmentrendszer összes adatát."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Megfigyeli a képernyő feloldásakor helytelenül beírt jelszavak számát, és túl sok hibásan beírt jelszó esetén lezárja a telefont, vagy törli a telefon összes adatát."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"A képernyőzárolás során megadott helytelen jelszavak számának figyelése, és a táblagép zárolása vagy a felhasználó összes adatának törlése abban az esetben, ha túl sokszor adtak meg helytelen jelszót."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"A képernyő feloldásához megadott helytelen jelszavak számának figyelése, és az Android TV eszköz zárolása vagy ezen felhasználó összes adatának törlése túl sok helytelen jelszó után."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"A képernyőzárolás során megadott helytelen jelszavak számának figyelése, és az infotainmentrendszer zárolása vagy a profil összes adatának törlése abban az esetben, ha túl sokszor adtak meg helytelen jelszót."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"A képernyőzárolás során megadott helytelen jelszavak számának figyelése, és a telefon zárolása vagy a felhasználó összes adatának törlése abban az esetben, ha túl sokszor adtak meg helytelen jelszót."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"A képernyőzár módosítása"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"A képernyőzár módosítása."</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"Minden adat törlése"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Figyelmeztetés nélkül törli a táblagép adatait, visszaállítva a gyári adatokat."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Az Android TV eszköz adatainak figyelmeztetés nélküli törlése a gyári adatok visszaállításával."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Az infotainmentrendszer adatainak törlése a gyári alapbeállítások visszaállításával anélkül, hogy figyelmeztetés jelenne meg erről."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Figyelmeztetés nélkül törli a telefon összes adatát, visszaállítva a gyári adatokat."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"A felhasználói adatok törlése"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Profiladatok törlése"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"A felhasználói adatok törlése"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"A felhasználó összes adatának törlése erről a táblagépről figyelmeztetés nélkül."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"A felhasználó összes adatának figyelmeztetés nélküli törlése erről az Android TV eszközről."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"A profil adatainak törlése erről az infotainmentrendszerről figyelmeztetés nélkül."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"A felhasználó összes adatának törlése erről a telefonról figyelmeztetés nélkül."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Az eszköz globális proxyjának beállítása"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Az eszköz globális proxyja lesz használatban, amíg a házirend engedélyezve van. A globális proxyt csak az eszköz tulajdonosa állíthatja be."</string> diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml index 87523a4de717..a08c239f084d 100644 --- a/core/res/res/values-hy/strings.xml +++ b/core/res/res/values-hy/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"Վերահսկել էկրանի ապակողպման փորձերը"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Վերահսկել սխալ գաղտնաբառերի թիվը, որոնք մուտքագրվել են էկրանն ապակողպելիս, և կողպել պլանշետը կամ ջնջել պլանշետի բոլոր տվյալները, եթե մուտքագրվել են չափից շատ սխալ գաղտնաբառեր:"</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Գրանցել էկրանի ապակողպման համար մուտքագրվող սխալ գաղտնաբառերի թիվը և կողպել Android TV սարքը կամ ջնջել սարքի բոլոր տվյալները՝ չափից ավելի շատ սխալ գաղտնաբառեր մուտքագրելու դեպքում:"</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Վերահսկել սխալ գաղտնաբառերի թիվը, որոնք մուտքագրվել են էկրանը ապակողպելիս, և կողպել տեղեկատվաժամանցային համակարգը կամ ջնջել բոլոր տվյալները, եթե չափից ավելի սխալ գաղտնաբառեր են մուտքագրվել։"</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Վերահսկել սխալ գաղտնաբառերի թիվը, որոնք մուտքագրվել են էկրանն ապակողպելիս, և կողպել հեռախոսը կամ ջնջել հեռախոսի բոլոր տվյալները, եթե մուտքագրվել են չափից շատ սխալ գաղտնաբառեր:"</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Կառավարել էկրանն ապակողպելիս մուտքագրվող սխալ գաղտնաբառերի թիվը և կողպել պլանշետը կամ ջնջել այս օգտատիրոջ բոլոր տվյալները չափից ավելի սխալ գաղտնաբառեր մուտքագրելու դեպքում:"</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Գրանցել էկրանի ապակողպման համար մուտքագրվող սխալ գաղտնաբառերի թիվը և կողպել Android TV սարքը կամ ջնջել այս օգտատիրոջ բոլոր տվյալները՝ չափից ավելի շատ սխալ գաղտնաբառեր մուտքագրելու դեպքում:"</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Վերահսկել սխալ գաղտնաբառերի թիվը, որոնք մուտքագրվել են էկրանը ապակողպելիս, և կողպել տեղեկատվաժամանցային համակարգը կամ ջնջել այս պրոֆիլի բոլոր տվյալները, եթե չափից ավելի սխալ գաղտնաբառեր են մուտքագրվել։"</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Կառավարել էկրանն ապակողպելիս մուտքագրվող սխալ գաղտնաբառերի թիվը և կողպել հեռախոսը կամ ջնջել այս օգտատիրոջ բոլոր տվյալները չափից ավելի սխալ գաղտնաբառեր մուտքագրելու դեպքում:"</string> <string name="policylab_resetPassword" msgid="214556238645096520">"Փոխել էկրանի կողպման գաղտնաբառը"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"Փոխել էկրանի կողպման գաղտնաբառը:"</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"Ջնջել բոլոր տվյալները"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Ջնջել պլանշետի տվյալներն առանց նախազգուշացման` կատարելով գործարանային տվյալների վերակայում:"</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Ջնջել Android TV սարքի տվյալներն առանց զգուշացման՝ վերականգնելով գործարանային կարգավորումները:"</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Ջնջել տեղեկատվաժամանցային համակարգի տվյալները առանց զգուշացման՝ վերականգնելով գործարանային կարգավորումները։"</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Ջնջել հեռախոսի տվյալներն առանց նախազգուշացման` կատարելով գործարանային տվյալների վերակայում:"</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"Ջնջել օգտատիրոջ տվյալները"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Պրոֆիլի տվյալների ջնջում"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Ջնջել օգտատիրոջ տվյալները"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Ջնջել այս օգտատիրոջ տվյալներն այս պլանշետում առանց նախազգուշացման:"</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Ջնջել այս օգտատիրոջ տվյալներն Android TV սարքում առանց նախազգուշացման:"</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"Ջնջել տեղեկատվաժամանցային համակարգի այս պրոֆիլի տվյալները առանց զգուշացման։"</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"Ջնջել այս օգտատիրոջ տվյալներն այս հեռախոսում առանց նախազգուշացման:"</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Կարգավորել սարքի համաշխարհային պրոքսին"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Կարգավորել, որ սարքի համընդհանուր պրոքսի-սերվերն օգտագործվի, երբ քաղաքականությունը միացված է: Միայն սարքի սեփականատերը կարող է կարգավորել համընդհանուր պրոքսի-սերվերը:"</string> diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml index 2a2762a73cf4..e70d2954c0d6 100644 --- a/core/res/res/values-in/strings.xml +++ b/core/res/res/values-in/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"Pantau upaya pembukaan kunci layar"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Memantau berapa kali sandi yang dimasukkan salah saat ingin membuka kunci layar, dan mengunci tablet atau menghapus semua data tablet jika terjadi terlalu banyak kesalahan memasukkan sandi."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Memantau banyaknya sandi salah yang diketikkan saat membuka kunci layar, dan mengunci perangkat Android TV atau menghapus semua data perangkat Android TV jika terlalu banyak sandi salah diketikkan."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Memantau berapa kali sandi yang dimasukkan salah saat ingin membuka kunci layar, dan mengunci sistem infotainmen atau menghapus semua data sistem infotainmen jika terlalu banyak kesalahan memasukkan sandi."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Memantau berapa kali sandi yang dimasukkan salah saat ingin membuka kunci layar, dan mengunci ponsel atau menghapus semua data ponsel jika terjadi terlalu banyak kesalahan memasukkan sandi."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Memantau berapa kali sandi yang dimasukkan salah saat ingin membuka kunci layar, dan mengunci tablet atau menghapus semua data pengguna ini jika terjadi terlalu banyak kesalahan memasukkan sandi."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Memantau banyaknya sandi salah yang diketikkan saat membuka kunci layar, dan mengunci perangkat Android TV atau menghapus semua data pengguna ini jika terlalu banyak sandi salah diketikkan."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Memantau berapa kali sandi yang dimasukkan salah saat ingin membuka kunci layar, dan mengunci sistem infotainmen atau menghapus semua data profil ini jika terlalu banyak kesalahan memasukkan sandi."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Memantau berapa kali sandi yang dimasukkan salah saat ingin membuka kunci layar, dan mengunci ponsel atau menghapus semua data pengguna ini jika terjadi terlalu banyak kesalahan memasukkan sandi."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"Mengubah kunci layar"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"Mengubah kunci layar."</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"Menghapus semua data"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Menghapus data tablet tanpa peringatan dengan mereset ke setelan pabrik."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Menghapus data perangkat Android TV tanpa peringatan dengan melakukan reset ke setelan pabrik."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Menghapus data sistem infotainmen tanpa peringatan dengan melakukan reset ke setelan pabrik."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Menghapus data ponsel tanpa peringatan dengan melakukan reset ke setelan pabrik."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"Menghapus data pengguna"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Hapus data profil"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Menghapus data pengguna"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Menghapus data pengguna ini di tablet ini tanpa peringatan."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Menghapus data pengguna ini di perangkat Android TV ini tanpa peringatan."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"Menghapus data profil ini di sistem infotainmen ini tanpa peringatan."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"Menghapus data pengguna ini di ponsel ini tanpa peringatan."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Setel proxy global perangkat"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Menyetel proxy global perangkat yang akan digunakan jika kebijakan diaktifkan. Hanya pemilik perangkat yang dapat menyetel proxy global."</string> diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml index 8919bf76a998..028cff7383ea 100644 --- a/core/res/res/values-is/strings.xml +++ b/core/res/res/values-is/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"Fylgjast með tilraunum til að taka skjáinn úr lás"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Fylgjast með fjölda rangra innskráningartilrauna með aðgangsorði þegar skjárinn er tekinn úr lás og læsa spjaldtölvunni eða eyða öllum gögnum hennar ef rangt aðgangsorð er fært inn of oft."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Fylgjast með fjölda rangra innskráningartilrauna með aðgangsorði þegar skjárinn er tekinn úr lás og læsa Android TV tækinu eða eyða öllum gögnum tækisins ef rangt aðgangsorð er fært inn of oft."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Fylgjast með fjölda rangra innskráningartilrauna með aðgangsorði þegar skjárinn er tekinn úr lás og læsa upplýsinga- og afþreyingarkerfinu eða eyða öllum gögnum upplýsinga- og afþreyingarkerfisins ef rangt aðgangsorð er fært inn of oft."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Fylgjast með fjölda rangra innskráningartilrauna með aðgangsorði þegar skjárinn er tekinn úr lás og læsa símanum eða eyða öllum gögnum hans ef rangt aðgangsorð er fært inn of oft."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Fylgjast með fjölda rangra innskráningartilrauna með aðgangsorði þegar skjárinn er tekinn úr lás og læsa spjaldtölvunni eða eyða öllum gögnum viðkomandi notanda ef rangt aðgangsorð er fært inn of oft."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Fylgjast með fjölda rangra innskráningartilrauna með aðgangsorði þegar skjárinn er tekinn úr lás og læsa Android TV eða eyða öllum gögnum viðkomandi notanda ef rangt aðgangsorð er fært inn of oft."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Fylgjast með fjölda rangra innskráningartilrauna með aðgangsorði þegar skjárinn er tekinn úr lás og læsa upplýsinga- og afþreyingarkerfinu eða eyða öllum gögnum þessa prófíls ef rangt aðgangsorð er fært inn of oft."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Fylgjast með fjölda rangra innskráningartilrauna með aðgangsorði þegar skjárinn er tekinn úr lás og læsa símanum eða eyða öllum gögnum viðkomandi notanda ef rangt aðgangsorð er fært inn of oft."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"Breyta skjálásnum"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"Breyta skjálásnum."</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"Eyða öllum gögnum"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Eyða gögnum spjaldtölvunnar fyrirvaralaust með núllstillingu."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Eyða gögnum Android TV tækisins án viðvörunar með því að núllstilla það."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Eyða gögnum upplýsinga- og afþreyingarkerfisins án viðvörunar með núllstillingu."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Eyða gögnum símans fyrirvaralaust með núllstillingu."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"Eyða gögnum notanda"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Eyða prófílgögnum"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Eyða gögnum notanda"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Eyða gögnum viðkomandi notanda í þessari spjaldtölvu án viðvörunar."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Eyða gögnum þessa notanda úr þessu Android TV tæki án viðvörunar."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"Eyða gögnum þessa prófíls í þessu upplýsinga- og afþreyingarkerfi án viðvörunar."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"Eyða gögnum viðkomandi notanda í þessum síma án viðvörunar."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Stilla altækan proxy-þjón fyrir tækið"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Velja altækan proxy-þjón tækisins sem nota á þegar stefnan er virk. Aðeins eigandi tækisins getur valið altækan proxy-þjón."</string> diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml index 4f5de40a2bee..1a543a55a1f6 100644 --- a/core/res/res/values-it/strings.xml +++ b/core/res/res/values-it/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"Monitorare tentativi di sblocco dello schermo"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Monitora il numero di password errate digitate durante lo sblocco dello schermo e blocca il tablet o cancella tutti i dati del tablet se vengono digitate troppe password errate."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Consente di monitorare il numero di password errate digitate durante lo sblocco dello schermo e di bloccare il dispositivo Android TV o cancellare tutti i dati del dispositivo se vengono digitate troppe password errate."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Monitora il numero di password errate digitate durante lo sblocco dello schermo e blocca il sistema di infotainment o cancella tutti i dati del sistema se vengono digitate troppe password errate."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Monitora il numero di password errate digitate durante lo sblocco dello schermo e blocca il telefono o cancella tutti i dati del telefono se vengono digitate troppe password errate."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Monitora il numero di password errate digitate durante lo sblocco dello schermo e blocca il tablet o resetta tutti i dati dell\'utente se è stato raggiunto il limite massimo consentito."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Consente di monitorare il numero di password errate digitate durante lo sblocco dello schermo e di bloccare il dispositivo Android TV o cancellare tutti i dati dell\'utente se vengono digitate troppe password errate."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Monitora il numero di password errate digitate durante lo sblocco dello schermo e blocca il sistema di infotainment o cancella tutti i dati di questo profilo se vengono digitate troppe password errate."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Monitora il numero di password errate digitate durante lo sblocco dello schermo e blocca il telefono o resetta tutti i dati dell\'utente se è stato raggiunto il limite massimo consentito."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"Modificare il blocco schermo"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"Modifica il blocco schermo."</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"Cancellare tutti i dati"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Cancella i dati del tablet senza preavviso eseguendo un ripristino dati di fabbrica."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Consente di cancellare i dati del dispositivo Android TV senza preavviso eseguendo un ripristino dei dati di fabbrica."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Cancella i dati del sistema di infotainment senza preavviso eseguendo un ripristino dei dati di fabbrica."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Cancella i dati del telefono senza preavviso eseguendo un ripristino dei dati di fabbrica."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"Resettare i dati dell\'utente"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Cancella dati del profilo"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Resettare i dati dell\'utente"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Resetta i dati dell\'utente sul tablet senza preavviso."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Consente di cancellare i dati dell\'utente su questo dispositivo Android TV senza preavviso."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"Cancella i dati di questo profilo su questo sistema di infotainment senza preavviso."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"Resetta i dati dell\'utente sul telefono senza preavviso."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Impostare il proxy globale del dispositivo"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Imposta il proxy globale del dispositivo in modo da utilizzarlo mentre la norma è attiva. Il proxy globale può essere impostato solo dal proprietario del dispositivo."</string> diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml index 0aa6ad8afb6d..a318e86e4a54 100644 --- a/core/res/res/values-iw/strings.xml +++ b/core/res/res/values-iw/strings.xml @@ -735,9 +735,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"מעקב אחר ניסיונות לביטול של נעילת המסך"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"ניהול מעקב אחר מספר הסיסמאות השגויות שמוקלדות במהלך ביטול נעילת המסך, וביצוע נעילה של הטאבלט, או מחיקה של כל נתוני הטאבלט, אם מוקלדות יותר מדי סיסמאות שגויות."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"מעקב אחר מספר הסיסמאות השגויות שהוזנו בעת ביטול נעילת המסך, כמו גם נעילה של מכשיר ה-Android TV או מחיקה של כל נתוני מכשיר ה-Android TV אם הוזנו יותר מדי סיסמאות שגויות."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"מעקב אחר מספר הסיסמאות השגויות שהוזנו במהלך ביטול נעילת המסך, נעילת מערכת המידע והבידור או מחיקה של כל נתוני מערכת המידע והבידור, אם הוזנו יותר מדי סיסמאות שגויות."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"מעקב אחר מספר הסיסמאות השגויות שהוקלדו במהלך ביטול נעילת המסך, וביצוע נעילה של הטלפון או מחיקה של כל נתוני הטלפון אם הוקלדו יותר מדי סיסמאות שגויות."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"מעקב אחר מספר הסיסמאות השגויות שהוזנו בעת ביטול נעילת המסך, כמו גם נעילת הטאבלט או מחיקה של כל נתוני המשתמש הזה אם הוזנו יותר מדי סיסמאות שגויות."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"מעקב אחר מספר הסיסמאות השגויות שהוזנו במהלך ביטול נעילת המסך, כמו גם נעילה של מכשיר ה-Android TV או מחיקה של כל נתוני המשתמש הזה אם הוזנו יותר מדי סיסמאות שגויות."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"מעקב אחר מספר הסיסמאות השגויות שהוזנו במהלך ביטול נעילת המסך, נעילת מערכת המידע והבידור או מחיקה של כל נתוני הפרופיל הזה, אם הוזנו יותר מדי סיסמאות שגויות."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"מעקב אחר מספר הסיסמאות השגויות שהוזנו בעת ביטול נעילת המסך, כמו גם נעילת הטלפון או מחיקה של כל נתוני המשתמש הזה אם הוזנו יותר מדי סיסמאות שגויות."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"שינוי נעילת המסך"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"שינוי של נעילת המסך."</string> @@ -746,10 +748,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"מחיקת כל הנתונים"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"מחיקה של נתוני הטאבלט ללא אזהרה, באמצעות איפוס לנתוני היצרן."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"מחיקה ללא אזהרה של נתוני מכשיר ה-Android TV באמצעות איפוס לנתוני היצרן."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"מחיקה של נתוני מערכת המידע והבידור, ללא אזהרה, על ידי ביצוע איפוס לנתוני היצרן."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"מחיקה של נתוני הטלפון, ללא אזהרה, על ידי ביצוע איפוס לנתוני היצרן."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"מחיקת נתוני משתמש"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"מחיקת נתוני הפרופיל"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"מחיקת נתוני משתמש"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"מחיקה של נתוני המשתמש הזה בטאבלט, ללא אזהרה."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"מחיקה של נתוני המשתמש הזה במכשיר ה-Android TV, ללא אזהרה."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"מחיקה של נתוני הפרופיל במערכת המידע והבידור הזו, ללא אזהרה."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"מחיקה של נתוני המשתמש הזה בטלפון, ללא אזהרה."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"הגדרה של שרת ה-Proxy הכללי של המכשיר"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"הגדרה של שרת ה-proxy הגלובלי שבו ייעשה שימוש כשהמדיניות פועלת. רק לבעלים של המכשיר יש אפשרות להגדיר את שרת ה-proxy הגלובלי."</string> diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml index 739e19e3ef33..897a2e5ce3a5 100644 --- a/core/res/res/values-ja/strings.xml +++ b/core/res/res/values-ja/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"画面ロック解除試行の監視"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"画面のロック解除に正しくないパスワードを入力した回数を監視し、回数が多すぎる場合はタブレットをロックするかタブレットのデータをすべて消去します。"</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"画面のロック解除の際に入力したパスワードが間違っていた回数を監視し、回数が多すぎる場合は Android TV デバイスをロックするか Android TV デバイスのデータをすべて消去します。"</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"画面のロック解除に正しくないパスワードを入力した回数を監視し、回数が多すぎる場合はインフォテインメント システムをロックするかインフォテインメント システムのデータをすべて消去します。"</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"画面のロック解除に正しくないパスワードを入力した回数を監視し、回数が多すぎる場合はモバイルデバイスをロックするかモバイルデバイスのデータをすべて消去します。"</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"画面のロック解除の際に入力したパスワードが間違っていた回数を監視し、回数が多すぎる場合はタブレットをロックするかこのユーザーのデータをすべて消去します。"</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"画面のロック解除の際に入力したパスワードが間違っていた回数を監視し、回数が多すぎる場合は Android TV デバイスをロックするかこのユーザーのデータをすべて消去します。"</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"画面のロック解除に正しくないパスワードを入力した回数を監視し、回数が多すぎる場合はインフォテインメント システムをロックするかこのプロファイルのデータをすべて消去します。"</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"画面のロック解除の際に入力したパスワードが間違っていた回数を監視し、回数が多すぎる場合はスマートフォンをロックするかこのユーザーのデータをすべて消去します。"</string> <string name="policylab_resetPassword" msgid="214556238645096520">"画面ロックの変更"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"画面ロックを変更します。"</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"すべてのデータを消去"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"警告せずにタブレットを初期化して内部のデータを消去します。"</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"警告せずに出荷時設定へのリセットを実行して Android TV デバイスのデータを消去します。"</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"警告せずにインフォテインメント システムを初期化して内部のデータを消去します。"</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"警告せずにデバイスを初期化して内部のデータを消去します。"</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"ユーザーデータの消去"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"プロファイル データの消去"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"ユーザーデータの消去"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"このタブレットのこのユーザーのデータを警告なく消去します。"</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"この Android TV デバイスでこのユーザーのデータを警告なく消去します。"</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"警告せずにこのインフォテインメント システムにあるこのプロファイルのデータを消去します。"</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"このスマートフォンのこのユーザーのデータを警告なく消去します。"</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"デバイスのグローバルプロキシを設定"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"ポリシーが有効になっている場合はデバイスのグローバルプロキシが使用されるように設定します。グローバルプロキシを設定できるのはデバイスの所有者だけです。"</string> diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml index 3ecbdbbbb7ab..746ff49d840f 100644 --- a/core/res/res/values-ka/strings.xml +++ b/core/res/res/values-ka/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"ეკრანის განბლოკვის მცდელობების მონიტორინგი"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"ეკრანის განბლოკვისთვის არასწორად აკრეფილი პაროლების რაოდენობის მონიტორინგი. ტაბლეტის დაბლოკვა ან მასზე არსებული ყველა მონაცემის წაშლა ძალიან ბევრჯერ არასწორი პაროლის შეყვანის შემთხვევაში."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"ეკრანის განბლოკვისას არასწორი პაროლების შეყვანილი რაოდენობის მონიტორინგი და არასწორი პაროლის მეტისმეტად ბევრჯერ შეყვანის შემთხვევაში, Android TV მოწყობილობის დაბლოკვა ან Android TV მოწყობილობის მთელი ინფორმაციის ამოშლა."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"ეკრანის განბლოკვისას გააკონტროლეთ პაროლების არასწორად შეყვანის რაოდენობა და დაბლოკეთ გართობის/საინფორმაციო სისტემა ან წაშალეთ მისი ყველა მონაცემი იმ შემთხვევაში, თუ ძალიან ბევრჯერ მოხდა არასწორი პაროლის შეყვანა."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"ეკრანის განბლოკვისთვის არასწორად აკრეფილი პაროლების რაოდენობის მონიტორინგი. ტელეფონის დაბლოკვა ან მასზე არსებული ყველა მონაცემის წაშლა ძალიან ბევრჯერ არასწორი პაროლის შეყვანის შემთხვევაში."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"ეკრანის განბლოკვისას არასწორი პაროლების შეყვანილი რაოდენობის მონიტორინგი და ტაბლეტის დაბლოკვა ან მრავლალჯერ არასწორი პაროლის შეყვანის შემთხვევაში ამ მომხმარებლის მთელი ინფორმაციის წაშლა."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"ეკრანის განბლოკვისას არასწორი პაროლების შეყვანილი რაოდენობის მონიტორინგი და არასწორი პაროლის მეტისმეტად ბევრჯერ შეყვანის შემთხვევაში, Android TV მოწყობილობის დაბლოკვა ან ამ მომხმარებლის მთელი ინფორმაციის ამოშლა."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"ეკრანის განბლოკვისას გააკონტროლეთ პაროლების არასწორად შეყვანის რაოდენობა და დაბლოკეთ გართობის/საინფორმაციო სისტემა ან წაშალეთ ამ პროფილის ყველა მონაცემი იმ შემთხვევაში, თუ ძალიან ბევრჯერ მოხდა არასწორი პაროლის შეყვანა."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"ეკრანის განბლოკვისას არასწორი პაროლების შეყვანილი რაოდენობის მონიტორინგი და ტელეფონის დაბლოკვა ან მრავლალჯერ არასწორი პაროლის შეყვანის შემთხვევაში ამ მომხმარებლის მთელი ინფორმაციის წაშლა."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"ეკრანის დაბლოკვის შეცვლა"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"ეკრანის დაბლოკვის შეცვლა"</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"ყველა მონაცემის წაშლა"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"ტაბლეტის მონაცემების გაუფრთხილებლად წაშლა, ქარხნული მონაცემების აღდგენით"</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"თქვენი Android TV მოწყობილობის მონაცემების გაუფრთხილებლად ამოშლა ქარხნული მონაცემების აღდგენის გზით."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"ქარხნული მონაცემების აღდგენით წაშალეთ გართობის/საინფორმაციო სისტემის მონაცემები გაფრთხილების გარეშე."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"ტელეფონის მონაცემების გაუფრთხილებლად წაშლა, ქარხნული მონაცემების აღდგენით"</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"მომხმარებლის მონაცემების წაშლა"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"პროფილის მონაცემების წაშლა"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"მომხმარებლის მონაცემების წაშლა"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"ამ მომხმარებლის მონაცემების გაუფრთხილებელი წაშლა ამ ტაბლეტზე."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"მომხმარებლის მონაცემების გაუფრთხილებლად ამოშლა Android TV მოწყობილობიდან."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"ქარხნული მონაცემების აღდგენით წაშალეთ ამ პროფილის მონაცემები ამ გართობ/საინფორმაციო სისტემაში გაფრთხილების გარეშე."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"ამ მომხმარებლის მონაცემების გაუფრთხილებელი წაშლა ამ ტელეფონზე."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"მოწყობილობის გლობალური პროქსის დაყენება"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"ჩართული პოლიტიკის დროს მოწყობილობის გლობალური პროქსის დაყენება. მხოლოდ მოწყობილობის მფლობელს შეუძლია გლობალური პროქსის დაყენება."</string> diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml index 94989805353a..8fac1e714b12 100644 --- a/core/res/res/values-kk/strings.xml +++ b/core/res/res/values-kk/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"Экран құлпын ашу әркеттерін бақылау"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Экран бекітпесін ашқан кезде терілген қате құпия сөздердің санын бақылау және планшетті бекіту немесе тым көп қате құпия сөздер терілген болса, планшеттің бүкіл деректерін өшіру."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Экранның құлпын ашу кезінде қате енгізілген құпия сөздердің санын бақылау, құпия сөз тым көп қате енгізілген жағдайда, Android TV құрылғысын құлыптау және Android TV құрылғыңыздың барлық деректерінен тазарту."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Экран құлпын ашқан кезде, терілген қате құпия сөздердің саны бақыланады, сондай-ақ құпия сөздер бірнеше рет қате терілсе, ақпараттық-сауықтық жүйе құлыпталады немесе оның барлық дерегі жойылады."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Экран бекітпесін ашқан кезде терілген қате құпия сөздердің санын бақылау және телефонды бекіту немесе тым көп қате құпия сөздер терілген болса, телефонның бүкіл деректерін өшіру."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Экран бекітпесін ашқанда терілген қате құпия сөздердің санын бақылау және тым көп қате құпия сөздер терілсе, планшетті бекіту немесе осы пайдаланушының барлық деректерін өшіру."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Экранның құлпын ашу кезінде қате енгізілген құпия сөздердің санын бақылау, құпия сөз тым көп қате енгізілген жағдайда, Android TV құрылғысын құлыптау және барлық пайдаланушы деректерінен тазарту."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Экран құлпын ашқан кезде, терілген қате құпия сөздердің саны бақыланады, сондай-ақ құпия сөздер бірнеше рет қате терілсе, ақпараттық-сауықтық жүйе құлыпталады немесе осы профильдің барлық дерегі жойылады."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Экран бекітпесін ашқанда терілген қате құпия сөздердің санын бақылау және тым көп қате құпия сөздер терілсе, телефонды бекіту немесе осы пайдаланушының барлық деректерін өшіру."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"Экран құлпын өзгерту"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"Экран құлпын өзгерте алады."</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"Барлық деректерді өшіру"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Планшет дерекқорын ескертусіз, зауыттық дерекқорын қайта реттеу арқылы өшіру."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Зауыттық деректерді қалпына келтіру арқылы Android TV құрылғыңыздың деректерін ескертусіз тазартыңыз."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Зауыттық деректерді қалпына келтіру арқылы ақпараттық-сауықтық жүйе дерегі ескертусіз өшіріледі."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Зауыттық деректерге қайтару арқылы телефон деректерін ескертусіз өшіре алады."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"Пайдаланушы деректерін өшіру"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Профиль дерегін өшіру"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Пайдаланушы деректерін өшіру"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Осы пайдаланушының осы планшеттегі деректерін ескертусіз өшіре алады."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Android TV құрылғысын осы пайдаланушы деректерінен ескертусіз тазартыңыз."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"Осы ақпараттық-сауықтық жүйедегі профиль дерегі ескертусіз өшіріледі."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"Осы пайдаланушының осы телефондағы деректерін ескертусіз өшіре алады."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Құрылғы жаһандық прокси қызметін орнату"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Саясат қосулы болғанда пайдаланылатын құрылғының ғаламдық прокси-серверін орнатыңыз. Ғаламдық прокси-серверді тек құрылғы иесі орната алады."</string> diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml index 841f5bf325fe..350f22d0e1ff 100644 --- a/core/res/res/values-km/strings.xml +++ b/core/res/res/values-km/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"តាមដានការព្យាយាមដោះសោអេក្រង់"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"ពិនិត្យចំនួនបញ្ចូលពាក្យសម្ងាត់មិនត្រឹមត្រូវ។ ពេលដោះសោអេក្រង់ និងចាក់សោទូរស័ព្ទ ឬលុបទិន្នន័យទូរស័ព្ទទាំងអស់ ប្រសិនបើមានពាក្យសម្ងាត់បញ្ចូលមិនត្រឹមត្រូវច្រើនដងពេក។"</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"ពិនិត្យចំនួននៃការវាយបញ្ចូលពាក្យសម្ងាត់ដែលមិនត្រឹមត្រូវ នៅពេលដោះសោអេក្រង់ និងចាក់សោឧបករណ៍ Android TV របស់អ្នក ឬលុបទិន្នន័យឧបករណ៍ Android TV របស់អ្នកទាំងអស់ ប្រសិនបើវាយបញ្ចូលពាក្យសម្ងាត់ខុសច្រើនដងពេក។"</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"ពិនិត្យមើលចំនួនដងនៃការវាយបញ្ចូលពាក្យសម្ងាត់មិនត្រឹមត្រូវ នៅពេលដោះសោអេក្រង់ និងចាក់សោប្រព័ន្ធព័ត៌មាននិងកម្សាន្ត ឬលុបទិន្នន័យទាំងអស់របស់ប្រព័ន្ធព័ត៌មាននិងកម្សាន្ត ប្រសិនបើវាយបញ្ចូលពាក្យសម្ងាត់មិនត្រឹមត្រូវច្រើនដងពេក។"</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"ពិនិត្យចំនួនបញ្ចូលពាក្យសម្ងាត់មិនត្រឹមត្រូវ។ ពេលដោះសោអេក្រង់ និងចាក់សោទូរស័ព្ទ ឬលុបទិន្នន័យទូរស័ព្ទទាំងអស់ ប្រសិនបើមានពាក្យសម្ងាត់បញ្ចូលមិនត្រឹមត្រូវច្រើនដងពេក។"</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"ត្រួតពិនិត្យចំនួននៃការវាយបញ្ចូលពាក្យសម្ងាត់ដែលមិនត្រឹមត្រូវ នៅពេលដោះសោអេក្រង់ និងចាក់សោថេប្លេត ឬលុបទិន្នន័យអ្នកប្រើនេះទាំងអស់ ប្រសិនបើមានការវាយបញ្ចូលពាក្យសម្ងាត់ខុសច្រើនដងពេក។"</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"ពិនិត្យចំនួននៃការវាយបញ្ចូលពាក្យសម្ងាត់ដែលមិនត្រឹមត្រូវ នៅពេលដោះសោអេក្រង់ និងចាក់សោឧបករណ៍ Android TV របស់អ្នក ឬលុបទិន្នន័យរបស់អ្នកប្រើប្រាស់នេះទាំងអស់ ប្រសិនបើវាយបញ្ចូលពាក្យសម្ងាត់ខុសច្រើនដងពេក។"</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"ពិនិត្យមើលចំនួនដងនៃការវាយបញ្ចូលពាក្យសម្ងាត់មិនត្រឹមត្រូវ នៅពេលដោះសោអេក្រង់ និងចាក់សោប្រព័ន្ធព័ត៌មាននិងកម្សាន្ត ឬលុបទិន្នន័យទាំងអស់របស់កម្រងព័ត៌មាននេះ ប្រសិនបើវាយបញ្ចូលពាក្យសម្ងាត់មិនត្រឹមត្រូវច្រើនដងពេក។"</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"ត្រួតពិនិត្យចំនួននៃការវាយបញ្ចូលពាក្យសម្ងាត់ដែលមិនត្រឹមត្រូវ នៅពេលដោះសោអេក្រង់ និងចាក់សោទូរស័ព្ទ ឬលុបទិន្នន័យអ្នកប្រើនេះទាំងអស់ ប្រសិនបើមានការវាយបញ្ចូលពាក្យសម្ងាត់ខុសច្រើនដងពេក។"</string> <string name="policylab_resetPassword" msgid="214556238645096520">"ប្តូរការចាក់សោអេក្រង់"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"ប្តូរការចាក់សោអេក្រង់។"</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"លុបទិន្នន័យទាំងអស់"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"លុបទិន្នន័យកុំព្យូទ័របន្ទះដោយមិនព្រមានដោយអនុវត្តការកំណត់ទិន្នន័យដូចចេញពីរោងចក្រ។"</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"លុបទិន្នន័យឧបករណ៍ Android TV របស់អ្នកដោយមិនមានការព្រមាន ដោយធ្វើការកំណត់ទិន្នន័យដូចចេញពីរោងចក្រ។"</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"លុបទិន្នន័យរបស់ប្រព័ន្ធព័ត៌មាន និងកម្សាន្តដោយមិនមានការព្រមាន ដោយធ្វើការកំណត់ទិន្នន័យដូចចេញពីរោងចក្រ។"</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"លុបទិន្នន័យទូរសព្ទដោយមិនមានការព្រមានជាមុន ដោយអនុវត្តការកំណត់ទិន្នន័យដូចចេញពីរោងចក្រ ។"</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"លុបទិន្នន័យរបស់អ្នកប្រើ"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"លុបទិន្នន័យកម្រងព័ត៌មាន"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"លុបទិន្នន័យរបស់អ្នកប្រើ"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"លុបទិន្នន័យរបស់អ្នកប្រើនេះនៅលើថេប្លេតនេះដោយគ្មានការព្រមាន។"</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"លុបទិន្នន័យរបស់អ្នកប្រើប្រាស់នេះនៅលើឧបករណ៍ Android TV នេះដោយគ្មានការព្រមាន។"</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"លុបទិន្នន័យរបស់កម្រងព័ត៌មាននេះនៅលើប្រព័ន្ធព័ត៌មាន និងកម្សាន្តនេះដោយមិនមានការព្រមាន។"</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"លុបទិន្នន័យរបស់អ្នកប្រើនេះនៅលើទូរស័ព្ទនេះដោយគ្មានការព្រមាន។"</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"កំណត់ប្រូកស៊ីសកលរបស់ឧបករណ៍"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"កំណត់ប្រូកស៊ីសកលឧបករណ៍ដើម្បីប្រើប្រាស់ ខណៈពេលដែលគោលការណ៍បើកដំណើរការ។ មានតែឧបករណ៍ម្ចាស់ប៉ុណ្ណោះអាចកំណត់ប្រូកស៊ីសកលនេះបាន។"</string> diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml index 400b4218f129..9d9f818de2ed 100644 --- a/core/res/res/values-kn/strings.xml +++ b/core/res/res/values-kn/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"ಪರದೆಯ ಅನ್ಲಾಕ್ ಪ್ರಯತ್ನಗಳನ್ನು ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಿ"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"ಪರದೆಯನ್ನು ಅನ್ಲಾಕ್ ಮಾಡುವಾಗ ತಪ್ಪಾಗಿ ಟೈಪ್ ಮಾಡಿದ ಪಾಸ್ವರ್ಡ್ಗಳ ಸಂಖ್ಯೆಯನ್ನು ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಿ, ಮತ್ತು ಟ್ಯಾಬ್ಲೆಟ್ ಅನ್ನು ಲಾಕ್ ಮಾಡಿ ಅಥವಾ ಹಲವಾರು ತಪ್ಪಾದ ಪಾಸ್ವರ್ಡ್ಗಳನ್ನು ಟೈಪ್ ಮಾಡಿದ್ದರೆ ಟ್ಯಾಬ್ಲೆಟ್ನ ಎಲ್ಲಾ ಡೇಟಾವನ್ನು ಅಳಿಸಿಹಾಕಿ."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"ಪರದೆಯನ್ನು ಅನ್ಲಾಕ್ ಮಾಡುವಾಗ ತಪ್ಪಾಗಿ ಟೈಪ್ ಮಾಡಿದ ಪಾಸ್ವರ್ಡ್ಗಳ ಸಂಖ್ಯೆಯನ್ನು ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡುತ್ತದೆ ಮತ್ತು ನಿಮ್ಮ Android TV ಸಾಧನವನ್ನು ಲಾಕ್ ಮಾಡುತ್ತದೆ ಅಥವಾ ಹಲವಾರು ತಪ್ಪಾದ ಪಾಸ್ವರ್ಡ್ಗಳನ್ನು ಟೈಪ್ ಮಾಡಿದರೆ ನಿಮ್ಮ ಎಲ್ಲಾ Android TV ಸಾಧನದ ಡೇಟಾವನ್ನು ಅಳಿಸಿಹಾಕುತ್ತದೆ."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"ಸ್ಕ್ರೀನ್ ಅನ್ನು ಅನ್ಲಾಕ್ ಮಾಡುವಾಗ ತಪ್ಪಾಗಿ ಟೈಪ್ ಮಾಡಿದ ಪಾಸ್ವರ್ಡ್ಗಳ ಸಂಖ್ಯೆಯನ್ನು ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಿ ಮತ್ತು ಇನ್ಫೋಟೈನ್ಮೆಂಟ್ ಸಿಸ್ಟಂ ಅನ್ನು ಲಾಕ್ ಮಾಡಿ ಅಥವಾ ಹಲವಾರು ತಪ್ಪಾದ ಪಾಸ್ವರ್ಡ್ಗಳನ್ನು ಟೈಪ್ ಮಾಡಿದ್ದರೆ ಇನ್ಫೋಟೈನ್ಮೆಂಟ್ ಸಿಸ್ಟಂನ ಎಲ್ಲಾ ಡೇಟಾವನ್ನು ಅಳಿಸಿ."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"ಪರದೆಯನ್ನು ಅನ್ಲಾಕ್ ಮಾಡಿದಾಗ ತಪ್ಪಾಗಿ ಟೈಪ್ ಮಾಡಿದ ಪಾಸ್ವರ್ಡ್ಗಳ ಸಂಖ್ಯೆಯನ್ನು ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಿ, ಮತ್ತು ಫೋನ್ ಅನ್ನು ಲಾಕ್ ಮಾಡಿ ಅಥವಾ ಹಲವಾರು ತಪ್ಪಾದ ಪಾಸ್ವರ್ಡ್ಗಳನ್ನು ಟೈಪ್ ಮಾಡಿದ್ದರೆ ಫೋನ್ನ ಎಲ್ಲಾ ಡೇಟಾವನ್ನು ಅಳಿಸಿಹಾಕಿ."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"ಪರದೆಯನ್ನು ಅನ್ಲಾಕ್ ಮಾಡುವಾಗ ಟೈಪ್ ಮಾಡಲಾದ ತಪ್ಪಾಗಿರುವ ಪಾಸ್ವರ್ಡ್ಗಳ ಸಂಖ್ಯೆಯನ್ನು ವೀಕ್ಷಿಸಿ ಮತ್ತು ಟ್ಯಾಬ್ಲೆಟ್ ಲಾಕ್ ಮಾಡಿ ಅಥವಾ ಹಲವಾರು ತಪ್ಪಾದ ಪಾಸ್ವರ್ಡ್ಗಳನ್ನು ಟೈಪ್ ಮಾಡಲಾಗಿದ್ದರೆ ಈ ಬಳಕೆದಾರರ ಎಲ್ಲಾ ಡೇಟಾವನ್ನು ಅಳಿಸಿಹಾಕಿ."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"ಪರದೆಯನ್ನು ಅನ್ಲಾಕ್ ಮಾಡುವಾಗ ತಪ್ಪಾಗಿ ಟೈಪ್ ಮಾಡಲಾದ ಪಾಸ್ವರ್ಡ್ಗಳ ಸಂಖ್ಯೆಯನ್ನು ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಿ ಮತ್ತು ನಿಮ್ಮ Android TV ಸಾಧನವನ್ನು ಲಾಕ್ ಮಾಡಿ ಅಥವಾ ಹಲವಾರು ತಪ್ಪಾದ ಪಾಸ್ವರ್ಡ್ಗಳನ್ನು ಟೈಪ್ ಮಾಡಲಾಗಿದ್ದರೆ ಈ ಬಳಕೆದಾರರ ಎಲ್ಲಾ ಡೇಟಾವನ್ನು ಅಳಿಸಿಹಾಕಿ."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"ಸ್ಕ್ರೀನ್ ಅನ್ನು ಅನ್ಲಾಕ್ ಮಾಡುವಾಗ ತಪ್ಪಾಗಿ ಟೈಪ್ ಮಾಡಿದ ಪಾಸ್ವರ್ಡ್ಗಳ ಸಂಖ್ಯೆಯನ್ನು ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಿ ಮತ್ತು ಇನ್ಫೋಟೈನ್ಮೆಂಟ್ ಸಿಸ್ಟಂ ಅನ್ನು ಲಾಕ್ ಮಾಡಿ ಅಥವಾ ಹಲವಾರು ತಪ್ಪಾದ ಪಾಸ್ವರ್ಡ್ಗಳನ್ನು ಟೈಪ್ ಮಾಡಿದ್ದರೆ ಈ ಪ್ರೊಫೈಲ್ನ ಎಲ್ಲಾ ಡೇಟಾವನ್ನು ಅಳಿಸಿ."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"ಪರದೆಯನ್ನು ಅನ್ಲಾಕ್ ಮಾಡುವಾಗ ಟೈಪ್ ಮಾಡಲಾದ ತಪ್ಪಾಗಿರುವ ಪಾಸ್ವರ್ಡ್ಗಳ ಸಂಖ್ಯೆಯನ್ನು ವೀಕ್ಷಿಸಿ ಮತ್ತು ಫೋನ್ ಲಾಕ್ ಮಾಡಿ ಅಥವಾ ಹಲವಾರು ತಪ್ಪಾದ ಪಾಸ್ವರ್ಡ್ಗಳನ್ನು ಟೈಪ್ ಮಾಡಲಾಗಿದ್ದರೆ ಈ ಬಳಕೆದಾರರ ಎಲ್ಲಾ ಡೇಟಾವನ್ನು ಅಳಿಸಿಹಾಕಿ."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"ಸ್ಕ್ರೀನ್ ಲಾಕ್ ಬದಲಾಯಿಸಿ"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"ಸ್ಕ್ರೀನ್ ಲಾಕ್ ಬದಲಾಯಿಸಿ."</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"ಎಲ್ಲಾ ಡೇಟಾವನ್ನು ಅಳಿಸಿ"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"ಫ್ಯಾಕ್ಟರಿ ಡೇಟಾ ರೀಸೆಟ್ ಅನ್ನು ನಿರ್ವಹಿಸುವ ಮೂಲಕ ಎಚ್ಚರಿಕೆಯನ್ನು ನೀಡದೆಯೇ ಟ್ಯಾಬ್ಲೆಟ್ ಡೇಟಾವನ್ನು ಅಳಿಸಿಹಾಕಿ."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"ಫ್ಯಾಕ್ಟರಿ ಡೇಟಾ ರೀಸೆಟ್ ಮಾಡುವ ಮೂಲಕ ಎಚ್ಚರಿಕೆ ಇಲ್ಲದೆ ನಿಮ್ಮ Android TV ಸಾಧನದ ಡೇಟಾವನ್ನು ಅಳಿಸಿಹಾಕುತ್ತದೆ."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"ಫ್ಯಾಕ್ಟರಿ ಡೇಟಾ ರೀಸೆಟ್ ಮಾಡುವ ಮೂಲಕ ಎಚ್ಚರಿಕೆ ಇಲ್ಲದೆ ಇನ್ಫೋಟೈನ್ಮೆಂಟ್ ಸಿಸ್ಟಂನ ಡೇಟಾವನ್ನು ಅಳಿಸಿ."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"ಫ್ಯಾಕ್ಟರಿ ಡೇಟಾ ರೀಸೆಟ್ ಅನ್ನು ನಿರ್ವಹಿಸುವ ಮೂಲಕ ಎಚ್ಚರಿಕೆಯನ್ನು ನೀಡದೆಯೇ ಫೋನ್ ಡೇಟಾವನ್ನು ಅಳಿಸಿಹಾಕಿ."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"ಬಳಕೆದಾರ ಡೇಟಾ ಅಳಿಸಿ"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"ಪ್ರೊಫೈಲ್ನ ಡೇಟಾವನ್ನು ಅಳಿಸಿ"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"ಬಳಕೆದಾರ ಡೇಟಾ ಅಳಿಸಿ"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"ಯಾವುದೇ ಸೂಚನೆ ಇಲ್ಲದೆ ಈ ಟ್ಯಾಬ್ಲೆಟ್ನಲ್ಲಿ ಈ ಬಳಕೆದಾರರ ಡೇಟಾವನ್ನು ಅಳಿಸಿ."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"ಎಚ್ಚರಿಕೆ ಇಲ್ಲದೆ ಈ Android TV ಸಾಧನದಲ್ಲಿನ ಈ ಬಳಕೆದಾರರ ಡೇಟಾವನ್ನು ಅಳಿಸಿಹಾಕುತ್ತದೆ."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"ಎಚ್ಚರಿಕೆಯಿಲ್ಲದೆ ಈ ಇನ್ಫೋಟೈನ್ಮೆಂಟ್ ಸಿಸ್ಟಂನಲ್ಲಿ ಈ ಪ್ರೊಫೈಲ್ನ ಡೇಟಾವನ್ನು ಅಳಿಸಿ."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"ಯಾವುದೇ ಸೂಚನೆ ಇಲ್ಲದೆ ಈ ಫೋನ್ನಲ್ಲಿ ಈ ಬಳಕೆದಾರರ ಡೇಟಾವನ್ನು ಅಳಿಸಿ."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"ಸಾಧನವನ್ನು ಜಾಗತಿಕ ಪ್ರಾಕ್ಸಿಗೆ ಹೊಂದಿಸಿ"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"ನೀತಿಯನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿದಾಗ ಬಳಸಬೇಕಾದ ಸಾಧನದ ಜಾಗತಿಕ ಪ್ರಾಕ್ಸಿಯನ್ನು ಹೊಂದಿಸಿ. ಸಾಧನದ ಮಾಲೀಕರು ಮಾತ್ರ ಜಾಗತಿಕ ಪ್ರಾಕ್ಸಿಯನ್ನು ಹೊಂದಿಸಬಹುದಾಗಿರುತ್ತದೆ."</string> diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml index 78ec66185bcc..916585de16ff 100644 --- a/core/res/res/values-ko/strings.xml +++ b/core/res/res/values-ko/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"화면 잠금 해제 시도 모니터링"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"화면 잠금해제 시 비밀번호를 잘못 입력한 횟수를 모니터링하고, 잘못된 비밀번호 입력 횟수가 너무 많은 경우 태블릿을 잠그거나 태블릿에 있는 데이터를 모두 지웁니다."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"화면 잠금 해제 시 비밀번호를 잘못 입력한 횟수를 모니터링하고 잘못된 비밀번호 입력 횟수가 너무 많은 경우 Android TV 기기를 잠그거나 Android TV 기기의 데이터를 모두 삭제합니다."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"화면 잠금 해제 시 잘못된 비밀번호를 입력한 횟수를 모니터링하고 잘못된 비밀번호 입력 횟수가 너무 많은 경우 인포테인먼트 시스템을 잠그거나 인포테인먼트 시스템의 데이터를 모두 삭제합니다."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"화면 잠금해제 시 비밀번호를 잘못 입력한 횟수를 모니터링하고, 잘못된 비밀번호 입력 횟수가 너무 많은 경우 휴대전화를 잠그거나 휴대전화에 있는 데이터를 모두 지웁니다."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"화면 잠금 해제 시 비밀번호를 잘못 입력한 횟수를 모니터링하고 잘못된 비밀번호 입력 횟수가 너무 많은 경우 태블릿을 잠그거나 이 사용자의 데이터를 모두 삭제합니다."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"화면 잠금 해제 시 비밀번호를 잘못 입력한 횟수를 모니터링하고 잘못된 비밀번호 입력 횟수가 너무 많은 경우 Android TV 기기를 잠그거나 사용자 데이터를 모두 삭제합니다."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"화면 잠금 해제 시 잘못된 비밀번호를 입력한 횟수를 모니터링하고 잘못된 비밀번호 입력 횟수가 너무 많은 경우 인포테인먼트 시스템을 잠그거나 이 프로필의 데이터를 모두 삭제합니다."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"화면 잠금 해제 시 비밀번호를 잘못 입력한 횟수를 모니터링하고 잘못된 비밀번호 입력 횟수가 너무 많은 경우 휴대전화를 잠그거나 이 사용자의 데이터를 모두 삭제합니다."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"화면 잠금 변경"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"화면 잠금을 변경합니다."</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"모든 데이터 삭제"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"초기화를 수행하여 경고 없이 태블릿 데이터를 지웁니다."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"초기화를 실행하여 경고 없이 Android TV 기기의 데이터를 삭제합니다."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"초기화를 실행하여 인포테인먼트 시스템의 데이터를 경고 없이 삭제합니다."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"초기화를 수행하여 경고 없이 휴대전화 데이터를 지웁니다."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"사용자 데이터 삭제"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"프로필 데이터 삭제"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"사용자 데이터 삭제"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"이 태블릿에서 사용자의 데이터를 경고 없이 삭제합니다."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Android TV 기기에서 사용자 데이터를 경고 없이 삭제합니다."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"인포테인먼트 시스템에서 이 프로필의 데이터를 경고 없이 삭제합니다."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"이 휴대전화에서 사용자의 데이터를 경고 없이 삭제합니다."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"기기 전체 프록시 설정"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"정책이 사용 설정되어 있는 동안 사용될 기기 전체 프록시를 설정합니다. 기기 소유자만 전체 프록시를 설정할 수 있습니다."</string> diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml index ef922074d745..9a0913b550d5 100644 --- a/core/res/res/values-ky/strings.xml +++ b/core/res/res/values-ky/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"Экран кулпусун ачуу аракеттерин көзөмөлдөө"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Экрандын кулпусу ачылып жатканда туура эмес терилген сырсөздөрдүн санын текшерип, эгер алардын саны өтө эле көп болсо, планшетти кулпулаңыз же планшеттеги бардык маалыматтарды тазалап салыңыз."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Экрандын кулпусун ачуу учурунда сырсөздөр канча жолу туура эмес терилгенин тескөө жана сырсөз өтө көп жолу туура эмес терилген болсо, Android TV түзмөгүңүздү кулпулап же Android TV түзмөгүңүздөгү бардык дайын-даректериңизди тазалап салуу."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Экрандын кулпусу ачылып жатканда туура эмес терилген сырсөздөрдүн саны текшерилип, эгер алардын саны өтө эле көп болсо, инфозоок тутуму кулпуланып же инфозоок тутумундагы бардык маалыматтар өчүрүлөт."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Экрандын кулпусу ачылып жатканда туура эмес терилген сырсөздөрдүн санын текшерип, эгер алардын саны өтө эле көп болсо, телефонду кулпулаңыз же телефондогу бардык маалыматтарды тазалап салыңыз."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Экрандын кулпусун ачуу учурунда туура эмес терилген сырсөздөрдү тескөө жана сырсөз өтө көп жолу туура эмес терилген болсо, планшетти кулпулап же бул колдонуучунун бардык дайындарын тазалап салуу."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Экрандын кулпусун ачуу учурунда сырсөздөр канча жолу туура эмес терилгенин тескөө жана сырсөз өтө көп жолу туура эмес терилген болсо, Android TV түзмөгүңүздү кулпулап же колдонуучунун бардык дайындарын тазалап салуу."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Экрандын кулпусун ачуу учурунда туура эмес терилген сырсөздөрдү тескөө жана сырсөз өтө көп жолу туура эмес терилген болсо, инфозоок тутуму кулпуланып же бул профилдин бардык дайындары өчүрүлөт."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Экрандын кулпусун ачуу учурунда туура эмес терилген сырсөздөрдү тескөө жана сырсөз өтө көп жолу туура эмес терилген болсо, телефонду кулпулап же бул колдонуучунун бардык дайындарын тазалап салуу."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"Экран кулпусун өзгөртүү"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"Экран кулпусун өзгөртөт."</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"Бардык маалыматты өчүрүү"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Алдын-ала эскертпестен, баштапкы абалга келтирүү функциясы менен планшеттеги бардык маалыматтарды өчүрөт."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Android TV түзмөгүңүздүн дайындарын эскертүүсүз кайра башынан жөндөө аркылуу тазалоо."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Алдын ала эскертпестен, баштапкы абалга келтирүү функциясы менен инфозоок тутумундагы бардык маалыматтар өчүрүлөт."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Алдын-ала эскертпестен, баштапкы абалга келтирүү функциясы менен телефондогу бардык маалыматтарды өчүрөт."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"Колдонуучунун дайындарын тазалоо"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Профилдин маалыматын өчүрүү"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Колдонуучунун дайындарын тазалоо"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Бул колдонуучунун ушул планшеттеги дайындарын эскертүүсүз тазалоо."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Бул Android TV түзмөгүндөгү бул колдонуучу дайындарын эскертүүсүз тазалоо."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"Алдын ала эскертпестен, бул инфозоок тутумундагы профилдин бардык маалыматтары өчүрүлөт."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"Бул колдонуучунун ушул телефондогу дайындарын эскертүүсүз тазалоо."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Түзмөктүн глобалдык проксисин коюу"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Саясат иштетилгенде түзмөктүн глобалдык проксиси колдонулгудай кылып коюңуз. Түзмөк ээси гана глобалдык проксини коё алат."</string> @@ -1243,7 +1248,7 @@ <string name="screen_compat_mode_hint" msgid="4032272159093750908">"Муну тутум жөндөөлөрүнөн кайра иштетүү > Колдонмолор > Жүктөлүп алынган."</string> <string name="unsupported_display_size_message" msgid="7265211375269394699">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосу көрүнүштүн тандалган өлчөмүн экранда көрсөтө албайт жана туура эмес иштеши мүмкүн."</string> <string name="unsupported_display_size_show" msgid="980129850974919375">"Ар дайым көрүнсүн"</string> - <string name="unsupported_compile_sdk_message" msgid="7326293500707890537">"<xliff:g id="APP_NAME">%1$s</xliff:g> Android OS тутуму менен иштеген түзмөктүн шайкеш келбеген версиясы үчүн орнотулган колдонмо жана туура эмес иштеши мүмкүн. Колдонмонун жаңыртылган версиясы жеткиликтүү болушу мүмкүн."</string> + <string name="unsupported_compile_sdk_message" msgid="7326293500707890537">"<xliff:g id="APP_NAME">%1$s</xliff:g> Android OS тутуму менен иштеген түзмөктүн шайкеш келбеген версиясы үчүн орнотулган колдонмо жана туура эмес иштеши мүмкүн. Колдонмонун жаңырган версиясы жеткиликтүү болушу мүмкүн."</string> <string name="unsupported_compile_sdk_show" msgid="1601210057960312248">"Ар дайым көрүнсүн"</string> <string name="unsupported_compile_sdk_check_update" msgid="1103639989147664456">"Жаңыртууларды текшерүү"</string> <string name="smv_application" msgid="3775183542777792638">"<xliff:g id="APPLICATION">%1$s</xliff:g> колдонмосу (<xliff:g id="PROCESS">%2$s</xliff:g> процесси) өз алдынча иштеткен StrictMode саясатын бузду."</string> diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml index 564997b0e26b..579f871ebea8 100644 --- a/core/res/res/values-lo/strings.xml +++ b/core/res/res/values-lo/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"ຕິດຕາມການພະຍາຍາມປົດລັອກໜ້າຈໍ"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"ຕິດຕາມເບິ່ງຈຳນວນການພິມລະຫັດຜ່ານທີ່ບໍ່ຖືກຕ້ອງ ໃນເວລາປົດລັອກໜ້າຈໍ ແລະລັອກແທັບເລັດ ຫຼືລຶບຂໍ້ມູນທັງໝົດຂອງແທັບເລັດ ຖ້າມີການພິມລະຫັດຜ່ານບໍ່ຖືກຕ້ອງຫຼາຍເທື່ອເກີນໄປ."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"ຕິດຕາມຈຳນວນລະຫັດຜ່ານທີ່ບໍ່ຖືກຕ້ອງທີ່ພິມຕອນກຳລັງປົດລັອກໜ້າຈໍ ແລະ ລັອກອຸປະກອນ Android TV ຂອງທ່ານ ຫຼື ລຶບຂໍ້ມູນຂອງອຸປະກອນ Android TV ຂອງທ່ານຫາກພິມລະຫັດຜ່ານຜິດຫຼາຍເທື່ອເກີນໄປ."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"ຕິດຕາມຈຳນວນການພິມລະຫັດຜ່ານທີ່ບໍ່ຖືກຕ້ອງໃນເວລາປົດລັອກໜ້າຈໍ ແລະ ລັອກລະບົບສາລະບັນເທີງ ຫຼື ລຶບຂໍ້ມູນຂອງລະບົບສາລະບັນເທີງທັງໝົດຫາກມີການພິມລະຫັດຜ່ານທີ່ບໍ່ຖືກຕ້ອງຫຼາຍເກີນໄປ."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"ຕິດຕາມເບິ່ງຈຳນວນການພິມລະຫັດຜ່ານບໍ່ຖືກຕ້ອງ ໃນເວລາປົດລັອກໜ້າຈໍ ແລະລັອກໂທລະສັບ ຫຼືລຶບຂໍ້ມູນທັງໝົດຂອງໂປລະສັບ ຖ້າມີການພິມລະຫັດຜ່ານບໍ່ຖືກຕ້ອງຫຼາຍເທື່ອເກີນໄປ."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"ຕິດຕາມຈຳນວນຂອງລະຫັດຜ່ານບໍ່ຖືກຕ້ອງທີ່ພິມໄປແລ້ວ ເມື່ອປົດລັອກໜ້າຈໍ, ແລະລັອກແທັບເລັດ ຫຼືລຶບທຸກຂໍ້ມູນຜູ້ໃຊ້ນີ້ ຖ້າໄດ້ພິມລະຫັດຜ່ານບໍ່ຖືກຕ້ອງເຂົ້າໄປຫຼາຍອັນເກີນໄປ."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"ຕິດຕາມຈຳນວນຂອງລະຫັດຜ່ານບໍ່ຖືກຕ້ອງທີ່ພິມໄປແລ້ວຕອນກຳລັງປົດລັອກໜ້າຈໍ ແລະ ລັອກອຸປະກອນ Android TV ຂອງທ່ານ ຫຼື ລຶບທຸກຂໍ້ມູນຜູ້ໃຊ້ນີ້ຖ້າພິມລະຫັດຜ່ານບໍ່ຖືກຕ້ອງເຂົ້າໄປຫຼາຍເທື່ອເກີນໄປ."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"ຕິດຕາມຈຳນວນການພິມລະຫັດຜ່ານທີ່ບໍ່ຖືກຕ້ອງໃນເວລາປົດລັອກໜ້າຈໍ ແລະ ລັອກລະບົບສາລະບັນເທີງ ຫຼື ລຶບຂໍ້ມູນຂອງໂປຣໄຟລ໌ນີ້ທັງໝົດຫາກມີການພິມລະຫັດຜ່ານທີ່ບໍ່ຖືກຕ້ອງຫຼາຍເກີນໄປ."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"ຕິດຕາມຈຳນວນຂອງລະຫັດຜ່ານບໍ່ຖືກຕ້ອງທີ່ພິມໄປແລ້ວ ເມື່ອປົດລັອກໜ້າຈໍ, ແລະລັອກໂທລະສັບ ຫຼືລຶບທຸກຂໍ້ມູນຜູ້ໃຊ້ນີ້ ຖ້າໄດ້ພິມລະຫັດຜ່ານບໍ່ຖືກຕ້ອງເຂົ້າໄປຫຼາຍອັນເກີນໄປ."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"ປ່ຽນລັອກໜ້າຈໍ"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"ປ່ຽນລັອກໜ້າຈໍ."</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"ລຶບຂໍ້ມູນທັງໝົດ"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"ລຶບຂໍ້ມູນຂອງແທັບເລັດໂດຍບໍ່ມີການເຕືອນ ໂດຍການຣີເຊັດກັບຄືນໃຫ້ເປັນແບບທີ່ມາຈາກໂຮງງານ."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"ລຶບຂໍ້ມູນຂອງອຸປະກອນ Android TV ທ່ານໂດຍບໍ່ຕ້ອງແຈ້ງເຕືອນດ້ວຍການຣີເຊັດຂໍ້ມູນເປັນຄ່າເລີ່ມຕົ້ນຈາກໂຮງງານ."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"ລຶບຂໍ້ມູນຂອງລະບົບສາລະບັນເທີງໂດຍບໍ່ມີຄຳເຕືອນດ້ວຍການດຳເນີນການຕັ້ງຄ່າຈາກໂຮງງານ."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"ລຶບຂໍ້ມູນຂອງໂທລະສັບໂດຍບໍ່ມີການເຕືອນ ໂດຍການຣີເຊັດກັບຄືນໃຫ້ເປັນແບບທີ່ມາຈາກໂຮງງານ."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"ລຶບຂໍ້ມູນຜູ້ໃຊ້"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"ລຶບຂໍ້ມູນໂປຣໄຟລ໌"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"ລຶບຂໍ້ມູນຜູ້ໃຊ້"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"ລຶບຂໍ້ມູນຂອງຜູ້ໃຊ້ນີ້ຢູ່ໃນໂທລະທັດນີ້ໂດຍບໍ່ມີການເຕືອນ."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"ລຶບຂໍ້ມູນຂອງຜູ້ໃຊ້ນີ້ຢູ່ອຸປະກອນ Android TV ນີ້ໂດຍບໍ່ຕ້ອງມີການເຕືອນ."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"ລຶບຂໍ້ມູນຂອງໂປຣໄຟລ໌ນີ້ຢູ່ລະບົບສາລະບັນເທີງນີ້ໂດຍບໍ່ມີຄຳເຕືອນ."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"ລຶບຂໍ້ມູນຂອງຜູ້ໃຊ້ນີ້ຢູ່ໃນໂທລະສັບນີ້ໂດຍບໍ່ມີການເຕືອນ."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"ປ່ຽນ proxy ຮວມຂອງອຸປະກອນ"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"ຕັ້ງໃຫ້ພຣັອກຊີສ່ວນກາງຂອງອຸປະກອນ ທີ່ຈະໃຊ້ໃນຂະນະທີ່ເປີດນຳໃຊ້ນະໂຍບາຍ. ພຽງແຕ່ເຈົ້າຂອງອຸປະກອນເທົ່ານັ້ນສາມາດຕັ້ງພຣັອກຊີທົ່ວໄປໄດ້."</string> diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml index d09866ce76a1..5b1c08b27be8 100644 --- a/core/res/res/values-lt/strings.xml +++ b/core/res/res/values-lt/strings.xml @@ -735,9 +735,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"Stebėti bandymus atrakinti ekraną"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Stebimas neteisingai įvestų slaptažodžių skaičius atrakinant ekraną ir užrakinti planšetinį kompiuterį arba ištrinti visus jame esančius duomenis, jei įvedama per daug neteisingų slaptažodžių."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Stebėkite atrakinant ekraną įvestų netinkamų slaptažodžių skaičių ir užrakinkite „Android TV“ įrenginį arba ištrinkite visus „Android TV“ įrenginio duomenis, jei per daug kartų įvedamas netinkamas slaptažodis."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Stebėti atrakinant ekraną įvestų netinkamų slaptažodžių skaičių ir užrakinti informacinę pramoginę sistemą arba ištrinti visus informacinės pramoginės sistemos duomenis, jei per daug kartų įvedamas netinkamas slaptažodis."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Atrakindami ekraną stebėkite neteisingai įvestų slaptažodžių skaičių ir užrakinkite telefoną ar ištrinkite visus telefono duomenis, jei įvedama per daug neteisingų slaptažodžių."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Stebėkite atrakinant ekraną įvestų netinkamų slaptažodžių skaičių ir užrakinkite planšetinį kompiuterį arba ištrinkite visus šio naudotojo duomenis, jei per daug kartų įvedamas netinkamas slaptažodis."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Stebėkite atrakinant ekraną įvestų netinkamų slaptažodžių skaičių ir užrakinkite „Android TV“ įrenginį arba ištrinkite visus šio naudotojo duomenis, jei per daug kartų įvedamas netinkamas slaptažodis."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Stebėti atrakinant ekraną įvestų netinkamų slaptažodžių skaičių ir užrakinti informacinę pramoginę sistemą arba ištrinti visus šio profilio duomenis, jei per daug kartų įvedamas netinkamas slaptažodis."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Stebėkite atrakinant ekraną įvestų netinkamų slaptažodžių skaičių ir užrakinkite telefoną arba ištrinkite visus šio naudotojo duomenis, jei per daug kartų įvedamas netinkamas slaptažodis."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"Pakeisti ekrano užraktą"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"Pakeisti ekrano užraktą."</string> @@ -746,10 +748,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"Trinti visus duomenis"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Be įspėjimo ištrinti planšetinio kompiuterio duomenis atkuriant gamyklinius duomenis."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Neįspėjus ištrinami „Android TV“ įrenginio duomenys, atkūrus gamyklinius duomenis."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Ištrinti informacinės pramoginės sistemos be įspėjimo atliekant gamyklinių duomenų atkūrimą."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Be įspėjimo ištrinti telefono duomenis atkuriant gamyklinius duomenis."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"Naudotojo duomenų ištrynimas"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Profilio duomenų ištrynimas"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Naudotojo duomenų ištrynimas"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Ištrinkite šio naudotojo duomenis šiame planšetiniame kompiuteryje be įspėjimo."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Ištrinami šio naudotojo duomenys šiame „Android TV“ įrenginyje be įspėjimo."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"Ištrinti šio profilio duomenis šioje informacinėje pramoginėje sistemoje be įspėjimo."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"Ištrinkite šio naudotojo duomenis šiame telefone be įspėjimo."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Nustatyti įrenginio bendrąjį tarpinį serverį"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Nustatykite įrenginio visuotinį tarpinį serverį, kuris bus naudojamas, kai politika įgalinta. Tik įrenginio savininkas gali nustatyti visuotinį tarpinį serverį."</string> diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml index a2aa0ce5b42f..39708fe07abb 100644 --- a/core/res/res/values-lv/strings.xml +++ b/core/res/res/values-lv/strings.xml @@ -732,9 +732,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"Ekrāna atbloķēšanas mēģinājumu pārraudzīšana"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Pārrauga nepareizi ievadīto paroļu skaitu, atbloķējot ekrānu, un bloķē planšetdatoru vai dzēš visus planšetdatora datus, ja tiek ievadīts pārāk daudz nepareizu paroļu."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Pārraudzīt nepareizi ievadīto ekrāna atbloķēšanas paroļu skaitu un bloķēt Android TV vai dzēst visus Android TV ierīces datus, ja tiek ievadīts pārāk daudz nepareizu paroļu."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Ekrāna atbloķēšanas laikā pārraudzīt nepareizi ievadīto paroļu skaitu un bloķēt informatīvi izklaidējošo sistēmu vai dzēst visus informatīvi izklaidējošās sistēmas datus, ja tiek ievadīts pārāk daudz nepareizu paroļu."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Pārrauga nepareizi ievadīto paroļu skaitu, atbloķējot ekrānu, un bloķē tālruni vai dzēš visus tālruņa datus, ja tiek ievadīts pārāk daudz nepareizu paroļu."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Pārraudzīt nepareizi ievadīto ekrāna atbloķēšanas paroļu skaitu un bloķēt planšetdatoru vai dzēst visus šī lietotāja datus, ja tiek ievadīts pārāk daudz nepareizu paroļu."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Pārraudzīt nepareizi ievadīto ekrāna atbloķēšanas paroļu skaitu un bloķēt Android TV ierīci vai dzēst visus šī lietotāja datus, ja tiek ievadīts pārāk daudz nepareizu paroļu."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Pārraudzīt nepareizi ievadīto ekrāna atbloķēšanas paroļu skaitu un bloķēt informatīvi izklaidējošo sistēmu vai dzēst visus šī profila datus, ja tiek ievadīts pārāk daudz nepareizu paroļu."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Pārraudzīt nepareizi ievadīto ekrāna atbloķēšanas paroļu skaitu un bloķēt tālruni vai dzēst visus šī lietotāja datus, ja tiek ievadīts pārāk daudz nepareizu paroļu."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"Mainīt ekrāna bloķēšanas iestatījumus"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"Maina ekrāna bloķēšanas iestatījumu."</string> @@ -743,10 +745,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"Dzēst visus datus"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Dzēš planšetdatora datus bez brīdinājuma, veicot rūpnīcas datu atiestatīšanu."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Dzēst Android TV ierīces datus bez brīdinājuma, veicot rūpnīcas datu atiestatīšanu."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Bez brīdinājuma dzēst informatīvi izklaidējošās sistēmas datus, veicot rūpnīcas datu atiestatīšanu."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Dzēš tālruņa datus bez brīdinājuma, veicot rūpnīcas datu atiestatīšanu."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"Dzēst lietotāja datus"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Profila datu dzēšana"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Dzēst lietotāja datus"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Bez brīdinājuma dzēst šī lietotāja datus no planšetdatora."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Bez brīdinājuma dzēst šī lietotāja datus no Android TV ierīces."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"Bez brīdinājuma dzēst šī profila datus no šīs informatīvi izklaidējošās sistēmas."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"Bez brīdinājuma dzēst šī lietotāja datus no tālruņa."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Iestatīt ierīces globālo starpniekserveri"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Iestatīt ierīces globālo starpniekserveri, kas jāizmanto, kad politika ir iespējota. Globālo starpniekserveri var iestatīt tikai ierīces īpašnieks."</string> diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml index 9d46eccc2828..f5e2e04ffe1a 100644 --- a/core/res/res/values-mk/strings.xml +++ b/core/res/res/values-mk/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"Следи ги обидите за отклучување на екранот"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Посматрај го бројот на неточни лозинки што се напишани за да се отклучи екранот и заклучи го таблетот или избриши ги сите податоци од него ако бидат напишани премногу неточни лозинки."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Го следи бројот на погрешно внесени лозинки при отклучување на екранот и го заклучува уредот Android TV или ги брише сите податоци од уредот Android TV доколку се внесени премногу погрешни лозинки."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Набљудувај го бројот на погрешно внесени лозинки при отклучување на екранот и заклучи го системот за информации и забава или избриши ги сите негови податоци доколку се внесени премногу погрешни лозинки."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Посматрај го бројот на неточни лозинки што се напишани за да се отклучи екранот и заклучи го телефонот или избриши ги сите податоци од него ако бидат напишани премногу неточни лозинки."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Набљудувај го бројот на погрешно внесени лозинки при отклучување на екранот и заклучи го таблетот или избриши ги сите податоци од овој корисник доколку се внесени премногу погрешни лозинки."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Го следи бројот на погрешно внесени лозинки при отклучување на екранот и го заклучува уредот Android TV или ги брише сите податоци од овој корисник доколку се внесени премногу погрешни лозинки."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Набљудувај го бројот на погрешно внесени лозинки при отклучување на екранот и заклучи го системот за информации и забава или избриши ги сите податоци од овој профил доколку се внесени премногу погрешни лозинки."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Набљудувај го бројот на погрешно внесени лозинки при отклучување на екранот и заклучи го телефонот или избриши ги сите податоци од овој корисник доколку се внесени премногу погрешни лозинки."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"Промени го заклучувањето на екранот"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"Промени го заклучувањето на екранот."</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"Избриши ги сите податоци"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Избриши ги податоците во таблетот без предупредување со ресетирање на фабрички податоци."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Ги брише податоците на вашиот уред Android TV без предупредување, така што ќе изврши ресетирање на фабричките податоци."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Избриши ги податоците во системот за информации и забава без предупредување со ресетирање на фабрички податоци."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Избриши ги податоците во телефонот без предупредување со ресетирање на фабрички податоци."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"Избриши ги податоците на корисникот"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Избриши ги податоците на профилот"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Избриши ги податоците на корисникот"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Избриши ги податоците на овој корисник на таблетот без предупредување."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Ги брише податоците на овој корисник на уредов Android TV без предупредување."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"Избриши ги податоците на профилов во системот за информации и забава без предупредување."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"Избриши ги податоците на овој корисник на телефонот без предупредување."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Постави го глобалниот прокси на уредот"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Поставете го глобалниот прокси на уредот да се користи додека политиката е овозможена. Само сопственикот на уредот може да го поставува глобалниот прокси."</string> diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml index a5e2cbc0e4be..313166d6d42e 100644 --- a/core/res/res/values-ml/strings.xml +++ b/core/res/res/values-ml/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"സ്ക്രീൻ അൺലോക്ക് ശ്രമങ്ങൾ നിരീക്ഷിക്കുക"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"സ്ക്രീൻ അൺലോക്കുചെയ്യുമ്പോൾ തെറ്റായി ടൈപ്പുചെയ്ത പാസ്വേഡുകളുടെ എണ്ണം നിരീക്ഷിക്കുക, വളരെയധികം തെറ്റായ പാസ്വ്ഡുകൾ ടൈപ്പുചെയ്തിട്ടുണ്ടെങ്കിൽ ടാബ്ലെറ്റ് ലോക്കുചെയ്യുകയോ ടാബ്ലെറ്റിലെ എല്ലാ ഡാറ്റയും മായ്ക്കുകയോ ചെയ്യുക."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"സ്ക്രീൻ അൺലോക്ക് ചെയ്യുമ്പോൾ തെറ്റായി ടൈപ്പ് ചെയ്ത പാസ്വേഡുകളുടെ എണ്ണം നിരീക്ഷിക്കുകയും നിരവധി തവണ തെറ്റായ പാസ്വേഡുകൾ ടൈപ്പ് ചെയ്തിട്ടുണ്ടെങ്കിൽ നിങ്ങളുടെ Android TV ലോക്ക് ചെയ്യുകയോ Android TV-യിലെ എല്ലാ ഡാറ്റയും മായ്ക്കുകയോ ചെയ്യുക."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"സ്ക്രീൻ അൺലോക്ക് ചെയ്യുമ്പോൾ തെറ്റായി ടൈപ്പ് ചെയ്ത പാസ്വേഡുകളുടെ എണ്ണം നിരീക്ഷിക്കുക. നിരവധി തെറ്റായ പാസ്വേഡുകൾ ടൈപ്പ് ചെയ്താൽ, ഇൻഫോറ്റേയിൻമെന്റ് സിസ്റ്റം ലോക്ക് ചെയ്യുകയോ ഇൻഫോറ്റേയിൻമെന്റ് സിസ്റ്റത്തിന്റെ ഡാറ്റ മുഴുവനും മായ്ക്കുകയോ ചെയ്യുക."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"സ്ക്രീൻ അൺലോക്കുചെയ്യുമ്പോൾ തെറ്റായി ടൈപ്പുചെയ്ത പാസ്വേഡുകളുടെ എണ്ണം നിരീക്ഷിക്കുക, വളരെയധികം തെറ്റായ പാസ്വ്ഡുകൾ ടൈപ്പുചെയ്തിട്ടുണ്ടെങ്കിൽ ഫോൺ ലോക്കുചെയ്യുകയോ ഫോണിലെ എല്ലാ ഡാറ്റയും മായ്ക്കുകയോചെയ്യുക."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"സ്ക്രീൻ അൺലോക്കുചെയ്യുമ്പോൾ തെറ്റായി ടൈപ്പുചെയ്ത പാസ്വേഡുകളുടെ എണ്ണം നിരീക്ഷിക്കുകയും നിരവധി തവണ പാസ്വേഡ് ടൈപ്പുചെയ്തെങ്കിൽ ടാബ്ലെറ്റ് ലോക്കുചെയ്യുകയോ ഈ എല്ലാ ഉപയോക്തൃവിവരവും മായ്ക്കുകയോ ചെയ്യുക."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"സ്ക്രീൻ അൺലോക്ക് ചെയ്യുമ്പോൾ തെറ്റായി ടൈപ്പ് ചെയ്ത പാസ്വേഡുകളുടെ എണ്ണം നിരീക്ഷിക്കുകയും നിരവധി തവണ തെറ്റായ പാസ്വേഡുകൾ ടൈപ്പ് ചെയ്തിട്ടുണ്ടെങ്കിൽ നിങ്ങളുടെ Android TV ലോക്ക് ചെയ്യുകയോ ഈ ഉപയോക്തൃ ഡാറ്റയെല്ലാം മായ്ക്കുകയോ ചെയ്യുക."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"സ്ക്രീൻ അൺലോക്ക് ചെയ്യുമ്പോൾ തെറ്റായി ടൈപ്പ് ചെയ്ത പാസ്വേഡുകളുടെ എണ്ണം നിരീക്ഷിച്ച്, നിരവധി തെറ്റായ പാസ്വേഡുകൾ ടൈപ്പ് ചെയ്താൽ ഇൻഫോറ്റേയിൻമെന്റ് സിസ്റ്റം ലോക്ക് ചെയ്യുകയോ ഈ പ്രൊഫൈലിന്റെ ഡാറ്റ മുഴുവനും മായ്ക്കുകയോ ചെയ്യുക."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"സ്ക്രീൻ അൺലോക്കുചെയ്യുമ്പോൾ തെറ്റായി ടൈപ്പുചെയ്ത പാസ്വേഡുകളുടെ എണ്ണം നിരീക്ഷിക്കുകയും നിരവധി തവണ പാസ്വേഡ് ടൈപ്പുചെയ്തെങ്കിൽ ഫോൺ ലോക്കുചെയ്യുകയോ ഈ എല്ലാ ഉപയോക്തൃവിവരവും മായ്ക്കുകയോ ചെയ്യുക."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"സ്ക്രീൻ ലോക്ക് മാറ്റുക"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"സ്ക്രീൻ ലോക്ക് മാറ്റുക."</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"എല്ലാ ഡാറ്റയും മായ്ക്കുക"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"ഒരു ഫാക്ടറി ഡാറ്റ പുനഃസജ്ജീകരണം നടപ്പിലാക്കുന്നതിലൂടെ ടാബ്ലെറ്റിന്റെ ഡാറ്റ മുന്നറിയിപ്പില്ലാതെ മായ്ക്കുക."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"ഫാക്ടറി ഡാറ്റ റീസെറ്റ് ചെയ്ത് നിങ്ങളുടെ Android TV-യിലെ ഉപകരണ ഡാറ്റ മുന്നറിയിപ്പില്ലാതെ മായ്ക്കുക."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"ഒരു ഫാക്ടറി ഡാറ്റാ റീസെറ്റിലൂടെ ഇൻഫോറ്റേയിൻമെന്റ് സിസ്റ്റത്തിന്റെ ഡാറ്റ മുന്നറിയിപ്പില്ലാതെ മായ്ക്കുക."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"ഒരു ഫാക്ടറി ഡാറ്റാ റീസെറ്റിലൂടെ ഫോണിന്റെ ഡാറ്റ മുന്നറിയിപ്പില്ലാതെ മായ്ക്കുക."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"ഉപയോക്തൃ ഡാറ്റ മായ്ക്കുക"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"പ്രൊഫൈൽ ഡാറ്റ മായ്ക്കുക"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"ഉപയോക്തൃ ഡാറ്റ മായ്ക്കുക"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"മുന്നറിയിപ്പൊന്നും നൽകാതെ ഈ ടാബ്ലെറ്റിലെ ഈ ഉപയോക്താവിന്റെ ഡാറ്റ മായ്ക്കുക."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"ഈ Android TV-യിലെ ഈ ഉപയോക്തൃ ഡാറ്റ മുന്നറിയിപ്പില്ലാതെ മായ്ക്കുക."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"ഈ ഇൻഫോറ്റേയിൻമെന്റ് സിസ്റ്റത്തിലെ ഈ പ്രൊഫൈലിന്റെ ഡാറ്റ മുന്നറിയിപ്പില്ലാതെ മായ്ക്കുക."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"മുന്നറിയിപ്പൊന്നും നൽകാതെ ഈ ഫോണിലെ ഈ ഉപയോക്താവിന്റെ ഡാറ്റ മായ്ക്കുക."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"ഉപകരണ ഗ്ലോബൽ പ്രോക്സി സജ്ജീകരിക്കുക"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"നയം പ്രവർത്തനക്ഷമമാക്കിയിരിക്കുമ്പോൾ ഉപകരണ ഗ്ലോബൽ പ്രോക്സി ഉപയോഗിക്കുന്നത് സജ്ജമാക്കുക. ഉപകരണ ഉടമയ്ക്ക് മാത്രമേ ഗ്ലോബൽ പ്രോക്സി സജ്ജമാക്കാനാകൂ."</string> diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml index 47c856035c01..6e1685e36b9d 100644 --- a/core/res/res/values-mn/strings.xml +++ b/core/res/res/values-mn/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"Дэлгэцийн түгжээг тайлах оролдлогыг хянах"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Дэлгэц түгжигдсэн үед нууц үг буруу оруулалтын тоог хянах ба хэрэв хэт олон удаа нууц үгийг буруу оруулбал таблетыг түгжих болон таблетын бүх датаг арилгана"</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Дэлгэцийн түгжээг тайлахаар буруу оруулсан нууц үгийн тоог хянаж, нууц үгийг хэт олон удаа буруу оруулсан тохиолдолд таны Android TV төхөөрөмжийг түгжиж эсвэл үүний бүх өгөгдлийг устгана."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Дэлгэцийн түгжээг тайлахад буруу бичиж оруулсан нууц үгний тоог хянаж, инфотэйнмент системийг түгжих эсвэл хэт олон удаа нууц үгийг буруу бичиж оруулсан тохиолдолд инфотэйнмент системийн бүх өгөгдлийг устгана."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Дэлгэц түгжигдсэн үед нууц үг буруу оруулалтын тоог хянах, ба хэрэв хэт олон удаа нууц үгийг буруу оруулбал утсыг түгжих болон утасны бүх датаг арилгана"</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Дэлгэцийн түгжээг тайлахад оруулсан буруу нууц үгийн давтамжийг хянаж таблетыг түгжих эсвэл буруу нууц үгийг хэт олон удаа оруулсан тохиолдолд энэ хэрэглэгчийн мэдээллийг устгах."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Дэлгэцийн түгжээг тайлахаар буруу оруулсан нууц үгийн тоог хянаж, нууц үгийг хэт олон удаа буруу оруулсан тохиолдолд таны Android TV төхөөрөмжийг түгжиж эсвэл энэ хэрэглэгчийн бүх өгөгдлийг устгана."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Дэлгэцийн түгжээг тайлахад буруу бичиж оруулсан нууц үгний тоог хянаж, инфотэйнмент системийг түгжих эсвэл хэт олон удаа нууц үгийг буруу бичиж оруулсан тохиолдолд энэ профайлын бүх өгөгдлийг устгана."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Дэлгэцийн түгжээг тайлахад оруулсан буруу нууц үгийн давтамжийг хянаж гар утсыг түгжих эсвэл буруу нууц үгийг хэт олон удаа оруулсан тохиолдолд энэ хэрэглэгчийн мэдээллийг устгах."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"Дэлгэцийн түгжээг өөрчлөх"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"Дэлгэцийн түгжээг өөрчлөх."</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"Бүх датаг арилгах"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Үйлдвэрийн дата утгыг өгсөнөөр таблетын дата шууд арилгагдана."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Таны Android TV төхөөрөмжийн өгөгдлийг танд анхааруулалгүйгээр үйлдвэрээс гарсан төлөвт шилжүүлэн устгана."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Үйлдвэрийн өгөгдлийн төлөвт үйлдлийг гүйцэтгэснээр инфотэйнмент системийн өгөгдлийг сануулгагүйгээр устгана."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Сануулахгүйгээр утасны бүх мэдээллийг устгаж, үйлдвэрийн өгөгдмөл байдалд шилжүүлнэ"</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"Хэрэглэгчийн мэдээллийг арилгах"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Профайлын өгөгдлийг устгах"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Хэрэглэгчийн мэдээллийг арилгах"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Анхааруулга өгөхгүйгээр энэ хэрэглэгчийн энэ таблет дээрх мэдээллийг устгах."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Энэ Android TV төхөөрөмж дээрх хэрэглэгчийн өгөгдлийг хэрэглэгчид анхааруулалгүйгээр устгана."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"Энэ инфотэйнмент систем дээр энэ профайлын өгөгдлийг сануулгагүйгээр устгана."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"Анхааруулга өгөхгүйгээр энэ хэрэглэгчийн энэ гар утсан дээрх мэдээллийг устгах."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Төхөрөөмжийн глобал проксиг тохируулах"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Бодлогыг ашиглах боломжтой үед төхөөрөмжийн олон улсын эрхийг тохируулах. Зөвхөн төхөөрөмж эзэмшигч нь олон улсын эрхийг тохируулах боломжтой."</string> diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml index 8d4956d0cad0..8587c39be881 100644 --- a/core/res/res/values-mr/strings.xml +++ b/core/res/res/values-mr/strings.xml @@ -548,7 +548,7 @@ <string name="permlab_disableKeyguard" msgid="3605253559020928505">"तुमचे स्क्रीन लॉक अक्षम करा"</string> <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"कीलॉक आणि कोणतीही संबद्ध पासवर्ड सुरक्षितता अक्षम करण्यासाठी अॅप ला अनुमती देते. उदाहरणार्थ, येणारा फोन कॉल प्राप्त करताना फोन कीलॉक अक्षम करतो, नंतर जेव्हा कॉल समाप्त होतो तेव्हा तो कीलॉक पुन्हा-सक्षम करतो."</string> <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"स्क्रीन लॉक क्लिष्टतेची विनंती करा"</string> - <string name="permdesc_requestPasswordComplexity" msgid="1130556896836258567">"अॅपला स्क्रीन लॉक क्लिष्टता पातळी (उच्च, मध्यम, खालची किंवा काहीही नाही) जाणून घेऊ देते, जी लांबीची संभाव्य रेंज आणि स्क्रीन लॉकचा प्रकार सूचित करते. अॅप वापरकर्त्यांना असेदेखील सुचवू शकते की त्यांनी स्क्रीन लॉक ठराविक पातळीपर्यंत अपडेट करावे, परंतु वापरकर्ते त्याकडे मोकळेपणाने दुर्लक्ष करू शकतात आणि तेथून नेव्हिगेट करू शकतात. स्क्रीन लॉक प्लेनटेक्स्टमध्ये स्टोअर केले जात नसल्यामुळे अॅपला नेमका पासवर्ड माहीत नसतो याची नोंद घ्या."</string> + <string name="permdesc_requestPasswordComplexity" msgid="1130556896836258567">"अॅपला स्क्रीन लॉक क्लिष्टता पातळी (उच्च, मध्यम, खालची किंवा काहीही नाही) जाणून घेऊ देते, जी लांबीची संभाव्य रेंज आणि स्क्रीन लॉकचा प्रकार सूचित करते. अॅप वापरकर्त्यांना असेदेखील सुचवू शकते की त्यांनी स्क्रीन लॉक ठरावीक पातळीपर्यंत अपडेट करावे, परंतु वापरकर्ते त्याकडे मोकळेपणाने दुर्लक्ष करू शकतात आणि तेथून नेव्हिगेट करू शकतात. स्क्रीन लॉक प्लेनटेक्स्टमध्ये स्टोअर केले जात नसल्यामुळे अॅपला नेमका पासवर्ड माहीत नसतो याची नोंद घ्या."</string> <string name="permlab_useBiometric" msgid="6314741124749633786">"बायोमेट्रिक हार्डवेअर वापरा"</string> <string name="permdesc_useBiometric" msgid="7502858732677143410">"ऑथेंटिकेशनसाठी बायोमेट्रिक हार्डवेअरचा वापर करण्याची ॲपला अनुमती देते"</string> <string name="permlab_manageFingerprint" msgid="7432667156322821178">"फिंगरप्रिंट हार्डवेअर व्यवस्थापित करा"</string> @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"स्क्रीन अनलॉक प्रयत्नांचे परीक्षण करा"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"टाइप केलेल्या अयोग्य पासवर्डांच्या अंकांचे परीक्षण करा. स्क्रीन अनलॉक केली जाते, तेव्हा टॅबलेट लॉक करा किंवा बरेच पासवर्ड टाइप केले असल्यास टॅबलेटचा सर्व डेटा मिटवा."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"स्क्रीन अनलॉक करताना टाइप केलेल्या चुकीच्या पासवर्ड संख्येचे परीक्षण करते आणि Android TV डिव्हाइस लॉक करते किंवा अनेक चुकीचे पासवर्ड टाइप केले असल्यास Android TV डिव्हाइसचा सर्व डेटा मिटवते."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"टाइप केलेल्या चुकीच्या पासवर्डच्या संख्येचे निरीक्षण करा. स्क्रीन अनलॉक करताना, इंफोटेनमेंट सिस्टीम लॉक करा किंवा अनेक चुकीचे पासवर्ड टाइप केले असल्यास, इंफोटेनमेंट सिस्टीमचा सर्व डेटा मिटवा."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"टाइप केलेल्या अयोग्य पासवर्डांच्या अंकांचे परीक्षण करा. स्क्रीन अनलॉक केली जाते, तेव्हा फोन लॉक करा किंवा बरेच पासवर्ड टाइप केले असल्यास फोनचा सर्व डेटा मिटवा."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"स्क्रीन अनलॉक करताना टाइप केलेल्या चुकीच्या पासवर्डांच्या संख्येचे परीक्षण करा आणि टॅबलेट लॉक करा किंवा अनेक चुकीचे पासवर्ड टाइप केले असल्यास या वापरकर्त्याचा सर्व डेटा मिटवा."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"स्क्रीन अनलॉक करताना टाइप केलेल्या चुकीच्या पासवर्ड संख्येचे परीक्षण करते आणि Android TV डिव्हाइस लॉक करते किंवा अनेक चुकीचे पासवर्ड टाइप केले असल्यास वापरकर्त्याचा सर्व डेटा मिटवते."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"स्क्रीन अनलॉक करताना टाइप केलेल्या चुकीच्या पासवर्डच्या संख्येचे निरीक्षण करा आणि इंफोटेनमेंट सिस्टीम लॉक करा किंवा अनेक चुकीचे पासवर्ड टाइप केले असल्यास, या प्रोफाइलचा सर्व डेटा मिटवा."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"टाइप केलेल्या अयोग्य पासवर्डांच्या अंकांचे परीक्षण करा. स्क्रीन अनलॉक केली जाते, तेव्हा फोन लॉक करा किंवा बरेच पासवर्ड टाइप केले असल्यास या वापरकर्त्याचा सर्व डेटा मिटवा."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"स्क्रीन लॉक बदला"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"स्क्रीन लॉक बदला."</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"सर्व डेटा मिटवा"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"फॅक्टरी डेटा रीसेट करून चेतावणीशिवाय टॅब्लेटचा डेटा मिटवा."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"चेतावणी न देता फॅक्टरी डेटा रीसेट करून Android TV डिव्हाइसचा डेटा मिटवा."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"फॅक्टरी डेटा रीसेट करून कोणत्याही चेतावणीशिवाय इंफोटेनमेंट सिस्टीमचा डेटा मिटवा."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"फॅक्टरी डेटा रीसेट करून चेतावणीशिवाय फोनचा डेटा मिटवा."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"वापरकर्ता डेटा मिटवा"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"प्रोफाइल डेटा मिटवा"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"वापरकर्ता डेटा मिटवा"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"कोणत्याही चेतावणी शिवाय या वापरकर्त्याचा या टॅब्लेटवरील डेटा मिटवा."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"कोणत्याही चेतावणीशिवाय या Android TV डिव्हाइसवरील वापरकर्त्याचा डेटा मिटवा."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"कोणत्याही चेतावणीशिवाय या इंफोटेनमेंट सिस्टीमवरील प्रोफाइलचा डेटा मिटवा."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"कोणत्याही चेतावणी शिवाय या वापरकर्त्याचा या फोनवरील डेटा मिटवा."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"डिव्हाइस समग्र प्रॉक्सी सेट करा"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"धोरण सक्षम असताना वापरण्यासाठी डिव्हाइस समग्र प्रॉक्सी सेट करा. फक्त डिव्हाइस मालक समग्र प्रॉक्सी सेट करु शकतो."</string> diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml index 4daa0512187b..f5368b5beae2 100644 --- a/core/res/res/values-ms/strings.xml +++ b/core/res/res/values-ms/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"Pantau percubaan buka kunci skrin"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Memantau bilangan kata laluan yang tersilap ditaip apabila membuka skrin, dan mengunci tablet atau memadam semua data tablet jika terlalu banyak kesilapan menaip kata laluan."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Pantau bilangan kata laluan salah yang ditaip semasa membuka kunci skrin, dan kunci peranti Android TV anda atau padamkan semua data peranti Android TV jika terlalu banyak kata laluan yang salah ditaip."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Memantau bilangan kata laluan tidak betul yang ditaip semasa membuka kunci skrin dan mengunci sistem maklumat hibur atau memadam semua data sistem maklumat hibur jika terlalu banyak kata laluan yang tidak betul ditaip."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Memantau bilangan kata laluan salah yang ditaip semasa membuka skrin, dan mengunci telefon atau memadam semua data telefon jika terlalu banyak kata laluan salah ditaip."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Pantau bilangan kata laluan tidak betul yang ditaip semasa membuka kunci skrin dan kunci tablet atau padam semua data pengguna ini jika terlalu banyak kata laluan yang tidak betul ditaip."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Pantau bilangan kata laluan salah yang ditaip semasa membuka kunci skrin, dan kunci peranti Android TV anda atau padamkan semua data pengguna ini jika terlalu banyak kata laluan yang salah ditaip."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Memantau bilangan kata laluan tidak betul yang ditaip semasa membuka kunci skrin dan mengunci sistem maklumat hibur atau memadam semua data profil ini jika terlalu banyak kata laluan yang tidak betul ditaip."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Pantau bilangan kata laluan tidak betul yang ditaip semasa membuka kunci skrin dan kunci telefon atau padam semua data pengguna ini jika terlalu banyak kata laluan yang tidak betul ditaip."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"Tukar kunci skrin"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"Tukar kunci skrin."</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"Padamkan semua data"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Memadamkan data tablet tanpa amaran dengan melakukan tetapan semula data kilang."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Padamkan data peranti Android TV anda tanpa amaran dengan melaksanakan tetapan semula data kilang."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Memadam data sistem maklumat hibur tanpa amaran dengan melakukan tetapan semula data kilang."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Padamkan data telefon tanpa amaran dengan melakukan tetapan semula data kilang."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"Padam data pengguna"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Padam data profil"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Padam data pengguna"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Padam data pengguna ini pada tablet ini tanpa amaran."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Padamkan data pengguna ini pada peranti Android TV tanpa amaran."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"Memadam data profil pada sistem maklumat hibur ini tanpa amaran."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"Padam data pengguna ini pada telefon ini tanpa amaran."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Tetapkan proksi global peranti"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Tetapkan proksi global peranti untuk digunakan sementara dasar didayakan. Hanya pemilik peranti boleh menetapkan proksi global."</string> diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml index 886f1eecb03d..8c4ad1faff22 100644 --- a/core/res/res/values-my/strings.xml +++ b/core/res/res/values-my/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"မျက်နှာပြင်လော့ခ်ဖွင့်ရန် ကြိုးပမ်းမှုများကို စောင့်ကြည့်ပါ"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"မျက်နှာပြင်ကို သော့ဖွင့်ရန် အတွက် စကားဝှက် မမှန်မကန် ထည့်သွင်းမှု အရေအတွက်ကို စောင့်ကြည့်လျက်၊ စကားဝှက် ရိုက်ထည့်မှု သိပ်များနေလျှင် တက်ဘလက်ကို သော့ခတ်ရန် သို့မဟုတ် တက်ဘလက် ဒေတာ အားလုံးကို ဖျက်ရန်။"</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"မျက်နှာပြင်ကို လော့ခ်ဖွင့်သည့်အခါ စကားဝှက်မှားယွင်းစွာ ရိုက်သွင်းသည့်အကြိမ်ရေကို စောင့်ကြည့်ပြီး မှားယွင်းသည့်အကြိမ်ရေ အလွန်များလာပါက သင့် Android TV စက်ပစ္စည်းကို လော့ခ်ချခြင်း သို့မဟုတ် သင့် Android TV ရှိ အသုံးပြုသူဒေတာများအားလုံးကို ဖျက်ခြင်းတို့ ပြုလုပ်သွားပါမည်။"</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"ဖန်သားပြင်လော့ခ်ဖွင့်ရန် အတွက် စကားဝှက် မမှန်မကန် ထည့်သွင်းမှု အရေအတွက်ကို စောင့်ကြည့်လျက် စကားဝှက် မမှန်မကန် ရိုက်ထည့်မှု များနေလျှင် သတင်းနှင့်ဖျော်ဖြေရေး စနစ်ကို လော့ခ်ချသည် (သို့) ၎င်း၏ ဒေတာအားလုံးကို ဖျက်သည်။"</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"မျက်နှာပြင်ကို သော့ဖွင့်ရန် အတွက် စကားဝှက် မမှန်မကန် ထည့်သွင်းမှု အရေအတွက်ကို စောင့်ကြည့်လျက်၊ စကားဝှက် ရိုက်ထည့်မှု သိပ်များနေလျှင် ဖုန်းကို သော့ခတ်ရန် သို့မဟုတ် ဖုန်း ဒေတာ အားလုံးကို ဖျက်ရန်။"</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"ဖန်မျက်နှာပြင်အား သော့ဖွင့်စဉ် လျှို့ဝှက်ကုဒ်အမှားများ ရိုက်သွင်းမှုအား စောင့်ကြည့်ရန်နှင့်၊ လျှို့ဝှက်ကုဒ်အမှားများ များစွာ ရိုက်သွင်းပါက တက်ဘလက်အား သော့ချခြင်း သို့မဟုတ် တက်ဘလက်၏ အချက်အလက်များအား ဖျက်ပစ်ခြင်းများ ပြုလုပ်မည်။"</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"မျက်နှာပြင်ကို လော့ခ်ဖွင့်သည့်အခါ စကားဝှက်မှားယွင်းစွာ ရိုက်သွင်းသည့်အကြိမ်ရေကို စောင့်ကြည့်ပြီး မှားယွင်းသည့်အကြိမ်ရေ အလွန်များလာပါက သင့် Android TV စက်ပစ္စည်းကို လော့ခ်ချခြင်း သို့မဟုတ် ဤအသုံးပြုသူဒေတာများအားလုံးကို ဖျက်ခြင်းတို့ ပြုလုပ်သွားပါမည်။"</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"ဖန်သားပြင်လော့ခ်ဖွင့်ရန် အတွက် စကားဝှက် မမှန်မကန် ထည့်သွင်းမှု အရေအတွက်ကို စောင့်ကြည့်လျက် စကားဝှက် မမှန်မကန် ရိုက်ထည့်မှု များနေလျှင် သတင်းနှင့်ဖျော်ဖြေရေး စနစ်ကို လော့ခ်ချသည် (သို့) ဤပရိုဖိုင်၏ ဒေတာအားလုံးကို ဖျက်သည်။"</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"ဖန်မျက်နှာပြင်အား သော့ဖွင့်စဉ် လျှို့ဝှက်ကုဒ်အမှားများ ရိုက်သွင်းမှုအား စောင့်ကြည့်ရန်နှင့်၊ လျှို့ဝှက်ကုဒ်အမှားများ များစွာ ရိုက်သွင်းပါက ဖုန်းအား သော့ချခြင်း သို့မဟုတ် ဖုန်း၏ အချက်အလက်များအား ဖျက်ပစ်ခြင်းများ ပြုလုပ်မည်။"</string> <string name="policylab_resetPassword" msgid="214556238645096520">"ဖန်သားပြင်လော့ခ်ပြောင်းခြင်း"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"ဖန်သားပြင်လော့ခ်ပြောင်းသည်။"</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"ဒေတာအားလုံးအားဖျက်ခြင်း"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"စက်ရုံထုတ် အခြေအနေအား ပြန်ပြောင်းခြင်းဖြင့် တက်ဘလက်ရှိ အချက်အလက်များအား ကြိုတင်သတိပေးမှုမရှိပဲ ဖျက်စီးရန်"</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"စက်ရုံထုတ်အခြေအနေ ပြန်ယူရန် လုပ်ဆောင်ခြင်းဖြင့် သင့် Android TV စက်ပစ္စည်းပေါ်ရှိ ဒေတာများကို သတိမပေးဘဲ ဖျက်လိုက်ပါမည်။"</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"စက်ရုံထုတ်အခြေအနေပြန်ယူခြင်းကို ဆောင်ရွက်ခြင်းဖြင့် သတင်းနှင့်ဖျော်ဖြေရေး စနစ်၏ ဒေတာကို သတိပေးချက် မပေးဘဲ ဖျက်သည်။"</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"စက်ရုံထုတ်အခြေအနေသို့ ပြန်ပြောင်းခြင်းဖြင့် ဖုန်းရှိဒေတာများကို သတိပေးခြင်း မရှိဘဲ ဖျက်သည်။"</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"အသုံးပြုသူဒေတာကို ဖျက်မည်"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"ပရိုဖိုင်ဒေတာ ဖျက်ခြင်း"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"အသုံးပြုသူဒေတာကို ဖျက်မည်"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"သတိပေးခြင်းမရှိဘဲ ဤတက်ဘလက်ပေါ်ရှိ ထိုအသုံးပြုသူ၏ဒေတာအား ဖျက်မည်။"</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"ဤ Android TV စက်ပစ္စည်းပေါ်ရှိ အသုံးပြုသူဒေတာများကို သတိပေးခြင်းမရှိဘဲ ဖျက်ပါမည်။"</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"ဤသတင်းနှင့်ဖျော်ဖြေရေး စနစ်ရှိ ပရိုဖိုင်၏ ဒေတာကို သတိပေးချက် မပေးဘဲ ဖျက်သည်။"</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"သတိပေးခြင်းမရှိဘဲ ဤဖုန်းပေါ်ရှိ ထိုအသုံးပြုသူ၏ဒေတာအား ဖျက်မည်။"</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"တကမာ္ဘလုံးဆိုင်ရာပရော်စီကို သတ်မှတ်ခြင်း"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"ပေါ်လစီအား ဖွင့်ထားချိန်တွင် တစ်ကမ္ဘာလုံးဆိုင်ရာ ပရောက်စီအား အသုံးပြုရန် ကိရိယာကို သတ်မှတ်မည်။ ကိရိယာ၏ ပိုင်ရှင်သာ ကမ္ဘာလုံးဆိုင်ရာ ပရောက်စီကို သတ်မှတ်နိုင်သည်။"</string> diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml index d873c99ae746..397327d27e92 100644 --- a/core/res/res/values-nb/strings.xml +++ b/core/res/res/values-nb/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"Overvåk forsøk på å låse opp skjermen"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Overvåk antall feil passordforsøk ved opplåsing av skjerm, og lås nettbrettet eller slett alle data fra nettbrettet ved for mange feil passordforsøk."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Følg med på hvor mange ganger feil passord skrives inn når skjermen skal låses opp, og lås Android TV-enheten eller tøm alle dataene når feil passord skrives inn for mange ganger."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Overvåk antall feil passord som er skrevet inn ved opplåsing av skjermen, og lås infotainment-systemet eller tøm alle dataene i infotainment-systemet hvis feil passord skrives inn for mange ganger."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Overvåk antall feil passordforsøk ved opplåsing av skjerm, og lås telefonen eller slett alle data fra telefonen ved for mange feil passordforsøk."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Overvåker antallet feil passord som er skrevet inn når skjermen låses opp, og låser nettbrettet eller sletter denne brukerens data når for mange feil passord er skrevet inn."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Følg med på hvor mange ganger feil passord skrives inn når skjermen skal låses opp, og lås Android TV-enheten eller tøm alle dataene til denne brukeren hvis feil passord skrives inn for mange ganger."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Overvåk antall feil passord som er skrevet inn ved opplåsing av skjermen, og lås infotainment-systemet eller tøm alle dataene i denne profilen hvis feil passord skrives inn for mange ganger."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Overvåker antallet feil passord som er skrevet inn når skjermen låses opp, og låser telefonen eller sletter denne brukerens data når for mange feil passord er skrevet inn."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"Endring av skjermlåsen"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"Kan endre skjermlåsen."</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"Sletting av alle data"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Tilbakestill nettbrettets data uten advarsel ved å tilbakestille til fabrikkstandard."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Tøm dataene på Android TV-enheten din uten advarsel ved å tilbakestille til fabrikkstandard."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Tøm dataene i infotainment-systemet uten varsel ved å tilbakestille til fabrikkstandard."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Telefonens data kan slettes uten advarsel ved å tilbakestille til fabrikkstandard."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"Slett brukerdataene"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Tøm profildata"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Slett brukerdataene"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Sletter denne brukerens data på dette nettbrettet uten advarsel."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Tøm dataene til denne brukeren på denne Android TV-enheten uten advarsel."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"Tøm dataene i denne profilen på dette infotainment-systemet uten varsel."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"Sletter denne brukerens data på denne telefonen uten advarsel."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Angi enhetens globale proxy-tjener"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Angir den globale proxy-tjeneren på enheten som skal brukes når regelen er aktivert. Bare eieren av enheten kan angi den globale proxy-tjeneren."</string> diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml index ade87f53f32d..56bcd1a03ac7 100644 --- a/core/res/res/values-ne/strings.xml +++ b/core/res/res/values-ne/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"मनिटरको स्क्रिन अनलक गर्ने प्रयासहरू"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"स्क्रिन अनलक गर्दा गलत पासवर्ड टाइप भएको संख्या निरीक्षण गर्नुहोस् र यदि निकै धेरै गलत पासवर्डहरू टाइप भएका छन भने ट्याब्लेट लक गर्नुहोस् वा ट्याब्लेटका सबै डेटा मेट्नुहोस्।"</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"स्क्रिन अनलक गर्दा गलत पासवर्ड टाइप गरेको सङ्ख्या निरीक्षण गर्नुहोस्, र धेरै पटक गलत पासवर्डहरू टाइप गरिएको खण्डमा आफ्नो Android टिभी यन्त्र लक गर्नुहोस् वा डिभाइसमा भएको सम्पूर्ण डेटा मेटाउनुहोस्।"</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"स्क्रिन अनलक गर्दा कति पटक गलत पासवर्ड टाइप गरिन्छ भन्ने कुरा निगरानी गरियोस् र अत्यन्तै धेरै पटक गलत पासवर्ड टाइप गरिएका खण्डमा यो इन्फोटेनमेन्ट प्रणाली लक गरियोस् वा यस इन्फोटेनमेन्ट प्रणालीका सबै डेटा मेटाइयोस्।"</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"स्क्रिनअनलक गर्दा गलत पासवर्ड टाइप भएको संख्या निरीक्षण गर्नुहोस् र यदि निकै धेरै गलत पासवर्डहरू टाइप भएका छन भने फोन लक गर्नुहोस् वा फोनका सबै डेटा मेट्नुहोस्।"</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"स्क्रिन अनलक गर्दा गलत पासवर्ड टाइप संख्या अनुगमन गर्नुहोस्, र यदि निकै धेरै गलत पासवर्डहरू टाइप गरिएमा ट्याब्लेट लक गर्नुहोस् वा प्रयोगकर्ताको डेटा मेटाउनुहोस्।"</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"स्क्रिन अनलक गर्दा गलत पासवर्ड टाइप गरेको सङ्ख्या निरीक्षण गर्नुहोस्, र धेरै पटक गलत पासवर्डहरू टाइप गरिएको खण्डमा आफ्नो Android टिभी यन्त्र लक गर्नुहोस् वा यो प्रयोगकर्ताको सम्पूर्ण डेटा मेटाउनुहोस्।"</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"स्क्रिन अनलक गर्दा कति पटक गलत पासवर्ड टाइप गरिन्छ भन्ने कुरा निगरानी गरियोस् र अत्यन्तै धेरै पटक गलत पासवर्ड टाइप गरिएका खण्डमा यो इन्फोटेनमेन्ट प्रणाली लक गरियोस् वा यस प्रोफाइलका सबै डेटा मेटाइयोस्।"</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"स्क्रिन अनलक गर्दा गलत पासवर्ड टाइप संख्या अनुगमन गर्नुहोस्, र यदि निकै धेरै गलत पासवर्डहरू टाइप गरिएमा फोन लक गर्नुहोस् वा प्रयोगकर्ताको डेटा मेटाउनुहोस्।"</string> <string name="policylab_resetPassword" msgid="214556238645096520">"स्क्रिन लक परिवर्तन गर्ने"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"स्क्रिन लक परिवर्तन गर्नुहोस्।"</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"सबै डेटा मेट्ने"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"एउटा फ्याक्ट्रि डेटा रिसेट गरेर चेतावनी नआउँदै ट्याबल्टको डेटा मेट्नुहोस्।"</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"फ्याक्ट्री डेटा रिसेट गरेर चेतावनी नदिइकन आफ्नो Android टिभी डिभाइसको डेटा मेटाउनुहोस्।"</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"यो इन्फोटेनमेन्ट प्रणालीको डेटा कुनै चेतावनीविनै फ्याक्ट्री डेटा रिसेट गरेर मेटाइयोस्।"</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"एउटा फ्याक्ट्रि डेटा रिसेट गरेर चेतावनी नदिइकन फोनको डेटा मेट्न।"</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"प्रयोगकर्ता डेटा मेट्नुहोस्"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"प्रोफाइल डेटा मेटाइयोस्"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"प्रयोगकर्ता डेटा मेट्नुहोस्"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"चेतावनी बिना यो ट्याब्लेटमा यस प्रयोगकर्ताको डेटा मेट्नुहोस्।"</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"यो Android टिभी डिभाइसमा भएको यस प्रयोगकर्ताको डेटा चेतावनी नदिइकन मेटाउनुहोस्।"</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"यो इन्फोटेनमेन्ट प्रणालीमा भएको यस प्रोफाइलको डेटा कुनै चेतावनीविनै मेटाइयोस्।"</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"चेतावनी बिना यो फोनमा यस प्रयोगकर्ताको डेटा मेट्नुहोस्।"</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"उपकरण विश्वव्यापी प्रोक्सी मिलाउनुहोस्"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"नीति सक्षम हुँदा प्रयोग गरिनको लागि यन्त्र ग्लोवल प्रोक्सी सेट गर्नुहोस्। केवल यन्त्र मालिकले ग्लोवल प्रोक्सी सेट गर्न सक्नुहुन्छ।"</string> diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml index 9203f39c8b34..832d019a421a 100644 --- a/core/res/res/values-nl/strings.xml +++ b/core/res/res/values-nl/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"Pogingen voor schermontgrendeling bijhouden"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Bijhouden hoe vaak onjuiste wachtwoorden worden ingevoerd wanneer het scherm wordt ontgrendeld en de tablet vergrendelen of alle gegevens op de tablet wissen als te veel onjuiste wachtwoorden worden ingevoerd."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Bijhouden hoe vaak onjuiste wachtwoorden worden ingevoerd wanneer het scherm wordt ontgrendeld en het Android TV-apparaat vergrendelen of alle gegevens van het Android TV-apparaat wissen als te veel onjuiste wachtwoorden worden ingevoerd."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Bijhouden hoe vaak onjuiste wachtwoorden worden getypt als het scherm wordt ontgrendeld, en het infotainmentsysteem vergrendelen of alle gegevens op het infotainmentsysteem wissen als te veel onjuiste wachtwoorden worden getypt."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Bijhouden hoe vaak onjuiste wachtwoorden worden ingevoerd wanneer het scherm wordt ontgrendeld en de telefoon vergrendelen of alle gegevens op de telefoon wissen als te veel onjuiste wachtwoorden worden ingevoerd."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Bijhouden hoe vaak onjuiste wachtwoorden worden ingevoerd wanneer het scherm wordt ontgrendeld en de tablet vergrendelen of alle gegevens van deze gebruiker wissen als te veel onjuiste wachtwoorden worden ingevoerd."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Bijhouden hoe vaak onjuiste wachtwoorden worden ingevoerd wanneer het scherm wordt ontgrendeld en het Android TV-apparaat vergrendelen of alle gegevens van deze gebruiker wissen als te veel onjuiste wachtwoorden worden ingevoerd."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Bijhouden hoe vaak onjuiste wachtwoorden worden getypt als het scherm wordt ontgrendeld, en het infotainmentsysteem vergrendelen of alle gegevens van dit profiel wissen als te veel onjuiste wachtwoorden worden getypt."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Bijhouden hoe vaak onjuiste wachtwoorden worden ingevoerd wanneer het scherm wordt ontgrendeld en de telefoon vergrendelen of alle gegevens van deze gebruiker wissen als te veel onjuiste wachtwoorden worden ingevoerd."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"De schermvergrendeling wijzigen"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"Wijzig de schermvergrendeling."</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"Alle gegevens wissen"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"De gegevens van de tablet zonder waarschuwing wissen door de fabrieksinstellingen te herstellen."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"De gegevens van het Android TV-apparaat zonder waarschuwing wissen door de fabrieksinstellingen terug te zetten."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"De gegevens van het infotainmentsysteem zonder waarschuwing wissen door de fabrieksinstellingen terug te zetten."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Wis de gegevens van de telefoon zonder waarschuwing door de fabrieksinstellingen te herstellen."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"Gebruikersgegevens wissen"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Profielgegevens wissen"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Gebruikersgegevens wissen"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"De gegevens van deze gebruiker op deze tablet zonder waarschuwing wissen."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"De gegevens van deze gebruiker op dit Android TV-apparaat zonder waarschuwing wissen."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"De gegevens van dit profiel op het infotainmentsysteem zonder waarschuwing wissen."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"De gegevens van deze gebruiker op deze telefoon zonder waarschuwing wissen."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Algemene proxy voor het apparaat instellen"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"De algemene proxy voor het apparaat instellen die moet worden gebruikt terwijl het beleid is geactiveerd. Alleen de eigenaar van het apparaat kan de algemene proxy instellen."</string> diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml index bb689908662c..b01eab19b5c8 100644 --- a/core/res/res/values-or/strings.xml +++ b/core/res/res/values-or/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"ସ୍କ୍ରୀନ୍-ଅନଲକ୍ କରିବା ଉଦ୍ୟମ ନୀରିକ୍ଷଣ କରନ୍ତୁ"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"ସ୍କ୍ରୀନ୍ ଅନଲକ୍ କରିବାବେଳେ ଟାଇପ୍ କରିଥିବା ଭୁଲ ପାସୱର୍ଡର ସଂଖ୍ୟାକୁ ନୀରିକ୍ଷଣ କରେ ଏବଂ ଟାବଲେଟ୍କୁ ଲକ୍ କରିଦିଏ କିମ୍ବା ଯଦି ଅନେକ ଭୁଲ ପାସୱର୍ଡ ଟାଇପ୍ କରାଯାଇଥାଏ, ତେବେ ଟାବଲେଟ୍ର ସମସ୍ତ ଡାଟା ଲିଭାଇଦିଏ।"</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"ସ୍କ୍ରିନ୍ ଅନ୍ଲକ୍ କରିବା ସମୟରେ ଟାଇପ୍ କରାଯାଇଥିବା ଭୁଲ ପାସ୍ୱାର୍ଡଗୁଡ଼ିକର ସଂଖ୍ୟାକୁ ନିରୀକ୍ଷଣ କରନ୍ତୁ ଏବଂ ଆପଣଙ୍କର Android TV ଡିଭାଇସ୍କୁ ଲକ୍ କରନ୍ତୁ କିମ୍ବା ଯଦି ଅନେକ ଭୁଲ ପାସ୍ୱାର୍ଡ ଟାଇପ୍ କରାଯାଇଥାଏ, ତେବେ ଆପଣଙ୍କ Android TV ଡିଭାଇସ୍ର ସମସ୍ତ ଡାଟା ଲିଭାଇ ଦିଅନ୍ତୁ।"</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"ସ୍କ୍ରିନ ଅନଲକ କରିବା ସମୟରେ ଟାଇପ କରାଯାଇଥିବା ଭୁଲ ପାସୱାର୍ଡର ସଂଖ୍ୟାକୁ ମନିଟର କରନ୍ତୁ ଏବଂ ଇନଫୋଟେନମେଣ୍ଟ ସିଷ୍ଟମକୁ ଲକ କରନ୍ତୁ କିମ୍ବା ଯଦି ଅନେକଗୁଡ଼ିଏ ଭୁଲ ପାସୱାର୍ଡ ଟାଇପ କରାଯାଇଥାଏ ତେବେ ଇନଫୋଟେନମେଣ୍ଟ ସିଷ୍ଟମର ସମସ୍ତ ଡାଟା ଖାଲି କରନ୍ତୁ।"</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"ସ୍କ୍ରୀନ୍ ଅନଲକ୍ କରିବାବେଳେ ଟାଇପ୍ କରିଥିବା ଭୁଲ ପାସୱର୍ଡର ସଂଖ୍ୟାକୁ ନୀରିକ୍ଷଣ କରେ ଏବଂ ଫୋନ୍କୁ ଲକ୍ କରିଦିଏ କିମ୍ବା ଯଦି ଅନେକ ଭୁଲ ପାସୱର୍ଡ ଟାଇପ୍ କରାଯାଇଥାଏ, ତେବେ ଫୋନ୍ର ସମସ୍ତ ଡାଟା ଲିଭାଇଦିଏ।"</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"ସ୍କ୍ରୀନ୍ ଅନଲକ୍ କରିବାବେଳେ ଟାଇପ୍ କରାଯାଇଥିବା ଭୁଲ ପାସ୍ୱର୍ଡର ସଂଖ୍ୟାକୁ ନୀରିକ୍ଷଣ କରେ ଏବଂ ଟାବଲେଟ୍କୁ ଲକ୍ କରିଦିଏ କିମ୍ବା ଯଦି ଅନେକ ଭୁଲ ପାସ୍ୱର୍ଡ ଟାଇପ୍ କରାଯାଇଥାଏ, ତେବେ ସମସ୍ତ ଡାଟା ଲିଭାଇଦିଏ।"</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"ସ୍କ୍ରିନ୍ ଅନ୍ଲକ୍ କରିବା ସମୟରେ ଟାଇପ୍ କରାଯାଇଥିବା ଭୁଲ ପାସ୍ୱାର୍ଡଗୁଡ଼ିକର ସଂଖ୍ୟାକୁ ନିରୀକ୍ଷଣ କରନ୍ତୁ ଏବଂ ଆପଣଙ୍କର Android TV ଡିଭାଇସ୍କୁ ଲକ୍ କରନ୍ତୁ କିମ୍ବା ଯଦି ଅନେକ ଭୁଲ ପାସ୍ୱାର୍ଡ ଟାଇପ୍ କରାଯାଇଥାଏ, ତେବେ ସମସ୍ତ ଡାଟା ଲିଭାଇ ଦିଅନ୍ତୁ।"</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"ସ୍କ୍ରିନ ଅନଲକ କରିବା ସମୟରେ ଟାଇପ କରାଯାଇଥିବା ଭୁଲ ପାସୱାର୍ଡର ସଂଖ୍ୟାକୁ ମନିଟର କରନ୍ତୁ ଏବଂ ଇନଫୋଟେନମେଣ୍ଟ ସିଷ୍ଟମକୁ ଲକ କରନ୍ତୁ କିମ୍ବା ଯଦି ଅନେକଗୁଡ଼ିଏ ଭୁଲ ପାସୱାର୍ଡ ଟାଇପ କରାଯାଇଥାଏ ତେବେ ଏହି ପ୍ରୋଫାଇଲର ସମସ୍ତ ଡାଟା ଖାଲି କରନ୍ତୁ।"</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"ସ୍କ୍ରୀନ୍ ଅନଲକ୍ କରିବାବେଳେ ଟାଇପ୍ କରାଯାଇଥିବା ଭୁଲ ପାସ୍ୱର୍ଡର ସଂଖ୍ୟାକୁ ନୀରିକ୍ଷଣ କରେ ଏବଂ ଫୋନ୍କୁ ଲକ୍ କରିଦିଏ କିମ୍ବା ଯଦି ଅନେକ ଭୁଲ ପାସ୍ୱର୍ଡ ଟାଇପ୍ କରାଯାଇଥାଏ, ତେବେ ସମସ୍ତ ଡାଟା ଲିଭାଇଦିଏ।"</string> <string name="policylab_resetPassword" msgid="214556238645096520">"ସ୍କ୍ରିନ୍ ଲକ୍ ବଦଳାଏ"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"ସ୍କ୍ରିନ୍ ଲକ୍ ବଦଳାଏ।"</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"ସମସ୍ତ ଡାଟା ଖାଲି କରିବା"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"ବିନା ଚେତାବନୀରେ ଫ୍ୟାକ୍ଟୋରୀ ସେଟିଙ୍ଗ କରାଇ ଟାବ୍ଲେଟ୍ର ଡାଟା ଲିଭାଇଥାଏ।"</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"ଏକ ଫ୍ୟାକ୍ଟୋରୀ ଡାଟା ରିସେଟ୍ କରି ବିନା ଚେତାବନୀରେ ଆପଣଙ୍କର Android TV ଡିଭାଇସ୍ର ଡାଟା ଲିଭାନ୍ତୁ।"</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"ଏକ ଫ୍ୟାକ୍ଟୋରୀ ଡାଟା ରିସେଟ କରି ବିନା ଚେତାବନୀରେ ଇନଫୋଟେନମେଣ୍ଟ ସିଷ୍ଟମର ଡାଟା ଖାଲି କରନ୍ତୁ।"</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"ବିନା ଚେତାବନୀରେ ଫ୍ୟାକ୍ଟୋରୀ ଡାଟା ରିସେଟ୍ କରି ଫୋନ୍ର ଡାଟା ଲିଭାଇଥାଏ।"</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"ୟୁଜର୍ ଡାଟା ଲିଭାନ୍ତୁ"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"ପ୍ରୋଫାଇଲ ଡାଟା ଖାଲି କରନ୍ତୁ"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"ୟୁଜର୍ ଡାଟା ଲିଭାନ୍ତୁ"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"ବିନା ଚେତାବନୀରେ ଏହି ଟାବଲେଟରେ ଥିବା ଏହି ୟୁଜରଙ୍କ ଡାଟା ଲିଭାଇ ଦିଅନ୍ତୁ।"</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"ବିନା ଚେତାବନୀରେ ଏହି Android TV ଡିଭାଇସ୍ରେ ଏହି ଉପଯୋଗକର୍ତ୍ତାଙ୍କ ଡାଟା ଲିଭାଇ ଦିଅନ୍ତୁ।"</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"ବିନା ଚେତାବନୀରେ ଇନଫୋଟେନମେଣ୍ଟ ସିଷ୍ଟମରେ ଥିବା ଏହି ପ୍ରୋଫାଇଲର ଡାଟା ଖାଲି କରନ୍ତୁ।"</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"ବିନା ଚେତାବନୀରେ ଏହି ଫୋନରେ ଥିବା ଏହି ୟୁଜରଙ୍କ ଡାଟା ଲିଭାଇ ଦିଅନ୍ତୁ।"</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"ଗ୍ଲୋବଲ୍ ପ୍ରକ୍ସୀ ଡିଭାଇସ୍କୁ ସେଟ୍ କରନ୍ତୁ"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"ପଲିସୀ ସକ୍ଷମ କରାଯାଇଥିବାବେଳେ ବ୍ୟବହାର କରିବା ପାଇଁ ଗ୍ଲୋବାଲ୍ ପ୍ରକ୍ସୀ ସେଟ୍ କରନ୍ତୁ। କେବଳ ଡିଭାଇସ୍ ମାଲିକ ଗ୍ଲୋବାଲ୍ ପ୍ରକ୍ସୀ ସେଟ୍ କରିପାରିବେ।"</string> diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml index 9b6129f7cf61..487645a617d8 100644 --- a/core/res/res/values-pa/strings.xml +++ b/core/res/res/values-pa/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"ਸਕ੍ਰੀਨ ਅਣਲਾਕ ਕਰਨ ਦੀਆਂ ਕੋਸ਼ਿਸ਼ਾਂ \'ਤੇ ਨਿਗਰਾਨੀ ਰੱਖੋ"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"ਸਕ੍ਰੀਨ ਨੂੰ ਅਣਲਾਕ ਕਰਦੇ ਹੋਏ ਟਾਈਪ ਕੀਤੇ ਗਲਤ ਪਾਸਵਰਡਾਂ ਦੀ ਸੰਖਿਆ ਦਾ ਨਿਰੀਖਣ ਕਰੋ ਅਤੇ ਟੈਬਲੈੱਟ ਨੂੰ ਲਾਕ ਕਰੋ ਜਾਂ ਟੈਬਲੈੱਟ ਦਾ ਸਾਰਾ ਡਾਟਾ ਮਿਟਾਓ, ਜੇਕਰ ਬਹੁਤ ਜ਼ਿਆਦਾ ਗਲਤ ਪਾਸਵਰਡ ਟਾਈਪ ਕੀਤੇ ਹਨ।"</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"ਸਕ੍ਰੀਨ ਨੂੰ ਅਣਲਾਕ ਕਰਦੇ ਹੋਏ ਟਾਈਪ ਕੀਤੇ ਗਲਤ ਪਾਸਵਰਡਾਂ ਦੀ ਸੰਖਿਆ ਦਾ ਨਿਰੀਖਣ ਕਰੋ ਅਤੇ ਆਪਣੇ Android TV ਡੀਵਾਈਸ ਨੂੰ ਲਾਕ ਕਰੋ ਜਾਂ ਆਪਣੇ Android TV ਡੀਵਾਈਸ ਦਾ ਸਾਰਾ ਡਾਟਾ ਮਿਟਾਓ, ਜੇ ਬਹੁਤ ਜ਼ਿਆਦਾ ਗਲਤ ਪਾਸਵਰਡ ਟਾਈਪ ਕੀਤੇ ਹਨ।"</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"ਸਕ੍ਰੀਨ ਨੂੰ ਅਣਲਾਕ ਕਰਦੇ ਸਮੇਂ ਟਾਈਪ ਕੀਤੇ ਗਲਤ ਪਾਸਵਰਡਾਂ ਦੀ ਸੰਖਿਆ ਦੀ ਨਿਗਰਾਨੀ ਕਰੋ ਅਤੇ ਜੇ ਬਹੁਤ ਜ਼ਿਆਦਾ ਗਲਤ ਪਾਸਵਰਡ ਟਾਈਪ ਕੀਤੇ ਹਨ, ਤਾਂ ਵਾਹਨ ਆਡੀਓ ਸਿਸਟਮ ਨੂੰ ਲਾਕ ਕਰੋ ਜਾਂ ਵਾਹਨ ਆਡੀਓ ਸਿਸਟਮ ਦਾ ਸਾਰਾ ਡਾਟਾ ਮਿਟਾਓ।"</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"ਸਕ੍ਰੀਨ ਨੂੰ ਅਣਲਾਕ ਕਰਦੇ ਸਮੇਂ ਟਾਈਪ ਕੀਤੇ ਗਲਤ ਪਾਸਵਰਡਾਂ ਦੀ ਸੰਖਿਆ ਦਾ ਨਿਰੀਖਣ ਕਰੋ ਅਤੇ ਫ਼ੋਨ ਨੂੰ ਲਾਕ ਕਰੋ ਜਾਂ ਫ਼ੋਨ ਦਾ ਸਾਰਾ ਡਾਟਾ ਮਿਟਾਓ ਜੇਕਰ ਬਹੁਤ ਜ਼ਿਆਦਾ ਗਲਤ ਪਾਸਵਰਡ ਟਾਈਪ ਕੀਤੇ ਹਨ।"</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"ਸਕ੍ਰੀਨ ਨੂੰ ਅਣਲਾਕ ਕਰਦੇ ਹੋਏ ਟਾਈਪ ਕੀਤੇ ਗਲਤ ਪਾਸਵਰਡਾਂ ਦੀ ਸੰਖਿਆ ਦਾ ਨਿਰੀਖਣ ਕਰੋ ਅਤੇ ਟੈਬਲੈੱਟ ਨੂੰ ਲਾਕ ਕਰੋ ਜਾਂ ਟੈਬਲੈੱਟ ਦਾ ਸਾਰਾ ਡਾਟਾ ਮਿਟਾਓ, ਜੇਕਰ ਬਹੁਤ ਜ਼ਿਆਦਾ ਗਲਤ ਪਾਸਵਰਡ ਟਾਈਪ ਕੀਤੇ ਹਨ।"</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"ਸਕ੍ਰੀਨ ਨੂੰ ਅਣਲਾਕ ਕਰਦੇ ਹੋਏ ਟਾਈਪ ਕੀਤੇ ਗਲਤ ਪਾਸਵਰਡਾਂ ਦੀ ਸੰਖਿਆ ਦਾ ਨਿਰੀਖਣ ਕਰੋ ਅਤੇ ਆਪਣੇ Android TV ਡੀਵਾਈਸ ਨੂੰ ਲਾਕ ਕਰੋ ਜਾਂ ਇਸ ਵਰਤੋਂਕਾਰ ਦਾ ਸਾਰਾ ਡਾਟਾ ਮਿਟਾਓ, ਜੇ ਬਹੁਤ ਜ਼ਿਆਦਾ ਗਲਤ ਪਾਸਵਰਡ ਟਾਈਪ ਕੀਤੇ ਹਨ।"</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"ਸਕ੍ਰੀਨ ਨੂੰ ਅਣਲਾਕ ਕਰਦੇ ਸਮੇਂ ਟਾਈਪ ਕੀਤੇ ਗਲਤ ਪਾਸਵਰਡਾਂ ਦੀ ਸੰਖਿਆ ਦੀ ਨਿਗਰਾਨੀ ਕਰੋ ਅਤੇ ਜੇ ਬਹੁਤ ਜ਼ਿਆਦਾ ਗਲਤ ਪਾਸਵਰਡ ਟਾਈਪ ਕੀਤੇ ਹਨ, ਤਾਂ ਵਾਹਨ ਆਡੀਓ ਸਿਸਟਮ ਨੂੰ ਲਾਕ ਕਰੋ ਜਾਂ ਇਸ ਪ੍ਰੋਫਾਈਲ ਦਾ ਸਾਰਾ ਡਾਟਾ ਮਿਟਾਓ।"</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"ਸਕ੍ਰੀਨ ਨੂੰ ਅਣਲਾਕ ਕਰਦੇ ਸਮੇਂ ਟਾਈਪ ਕੀਤੇ ਗਲਤ ਪਾਸਵਰਡਾਂ ਦੀ ਸੰਖਿਆ ਦਾ ਨਿਰੀਖਣ ਕਰੋ ਅਤੇ ਫ਼ੋਨ ਨੂੰ ਲਾਕ ਕਰੋ ਜਾਂ ਫ਼ੋਨ ਦਾ ਸਾਰਾ ਡਾਟਾ ਮਿਟਾਓ ਜੇਕਰ ਬਹੁਤ ਜ਼ਿਆਦਾ ਗਲਤ ਪਾਸਵਰਡ ਟਾਈਪ ਕੀਤੇ ਹਨ।"</string> <string name="policylab_resetPassword" msgid="214556238645096520">"ਸਕ੍ਰੀਨ ਲਾਕ ਬਦਲੋ"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"ਸਕ੍ਰੀਨ ਲਾਕ ਬਦਲੋ।"</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"ਸਾਰਾ ਡਾਟਾ ਮਿਟਾਓ"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"ਇੱਕ ਫੈਕਟਰੀ ਡਾਟਾ ਰੀਸੈੱਟ ਕਰਕੇ ਚਿਤਾਵਨੀ ਤੋਂ ਬਿਨਾਂ ਟੈਬਲੈੱਟ ਦਾ ਡਾਟਾ ਮਿਟਾਓ।"</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"ਫੈਕਟਰੀ ਡਾਟਾ ਰੀਸੈੱਟ ਕਰਕੇ ਬਿਨਾਂ ਚਿਤਾਵਨੀ ਦੇ ਤੁਹਾਡੇ Android TV ਡੀਵਾਈਸ ਦਾ ਡਾਟਾ ਮਿਟਾ ਦਿੱਤਾ ਜਾਂਦਾ ਹੈ।"</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"ਫੈਕਟਰੀ ਡਾਟਾ ਰੀਸੈੱਟ ਕਰਕੇ ਚਿਤਾਵਨੀ ਤੋਂ ਬਿਨਾਂ ਵਾਹਨ ਆਡੀਓ ਸਿਸਟਮ ਦਾ ਡਾਟਾ ਮਿਟਾਓ।"</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"ਇੱਕ ਫੈਕਟਰੀ ਡਾਟਾ ਰੀਸੈੱਟ ਕਰਕੇ ਚਿਤਾਵਨੀ ਤੋਂ ਬਿਨਾਂ ਫ਼ੋਨ ਦਾ ਡਾਟਾ ਮਿਟਾਓ।"</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"ਉਪਭੋਗਤਾ ਡਾਟਾ ਮਿਟਾਓ"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"ਪ੍ਰੋਫਾਈਲ ਡਾਟਾ ਮਿਟਾਓ"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"ਉਪਭੋਗਤਾ ਡਾਟਾ ਮਿਟਾਓ"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"ਬਿਨਾਂ ਚਿਤਾਵਨੀ ਦੇ ਇਸ ਟੈਬਲੈੱਟ ਤੇ ਮੌਜੂਦ ਇਸ ਵਰਤੋਂਕਾਰ ਦਾ ਸਾਰਾ ਡਾਟਾ ਮਿਟਾਓ।"</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"ਬਿਨਾਂ ਚਿਤਾਵਨੀ ਦੇ ਇਸ Android TV ਡੀਵਾਈਸ \'ਤੇ ਮੌਜੂਦ ਇਸ ਵਰਤੋਂਕਾਰ ਦਾ ਸਾਰਾ ਡਾਟਾ ਮਿਟਾਓ।"</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"ਇਸ ਵਾਹਨ ਆਡੀਓ ਸਿਸਟਮ \'ਤੇ ਚਿਤਾਵਨੀ ਤੋਂ ਬਿਨਾਂ ਇਸ ਪ੍ਰੋਫਾਈਲ ਦਾ ਡਾਟਾ ਮਿਟਾਓ।"</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"ਬਿਨਾਂ ਚਿਤਾਵਨੀ ਦੇ ਇਸ ਫ਼ੋਨ ਤੇ ਮੌਜੂਦ ਇਸ ਵਰਤੋਂਕਾਰ ਦਾ ਸਾਰਾ ਡਾਟਾ ਮਿਟਾਓ।"</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"ਡੀਵਾਈਸ ਗਲੋਬਲ ਪ੍ਰੌਕਸੀ ਸੈੱਟ ਕਰੋ"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"ਜਦੋਂ ਨੀਤੀ ਚਾਲੂ ਹੋਵੇ ਤਾਂ ਵਰਤੇ ਜਾਣ ਲਈ ਡੀਵਾਈਸ ਗਲੋਬਲ ਪ੍ਰੌਕਸੀ ਸੈੱਟ ਕਰੋ। ਕੇਵਲ ਡੀਵਾਈਸ ਮਾਲਕ ਗਲੋਬਲ ਪ੍ਰੌਕਸੀ ਸੈੱਟ ਕਰ ਸਕਦਾ ਹੈ।"</string> diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml index 586a03a9e7ef..f66d8827e72a 100644 --- a/core/res/res/values-pl/strings.xml +++ b/core/res/res/values-pl/strings.xml @@ -735,9 +735,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"Monitorowanie prób odblokowania ekranu"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Przy odblokowywaniu ekranu monitoruj, ile razy wpisano nieprawidłowe hasło i blokuj tablet lub usuń z niego wszystkie dane, jeśli nieprawidłowe hasło podano zbyt wiele razy."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Monitorowanie liczby nieudanych prób odblokowania ekranu za pomocą hasła oraz blokowanie urządzenia z Androidem TV lub kasowanie z niego wszystkich danych w razie wpisania błędnego hasła zbyt wiele razy."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Monitorowanie przypadków nieprawidłowego wpisania hasła podczas odblokowywania ekranu i blokowanie systemu multimedialno-rozrywkowego lub usuwanie z niego wszystkich danych przy zbyt dużej liczbie błędnych prób."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Przy odblokowywaniu ekranu monitoruje, ile razy wpisano nieprawidłowe hasło, i blokuje telefon lub usuwa z niego wszystkie dane, jeśli nieprawidłowe hasło podano zbyt wiele razy"</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Monitorowanie, ile razy wpisano błędne hasło podczas odblokowywania ekranu, oraz blokowanie tabletu albo kasowanie wszystkich danych tego użytkownika, gdy zbyt wiele razy wpisano błędne hasło."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Monitorowanie, ile razy wpisano błędne hasło podczas odblokowywania ekranu, oraz blokowanie urządzenia z Androidem TV albo kasowanie wszystkich danych tego użytkownika, gdy błędne hasło zostało wpisane zbyt wiele razy."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Monitorowanie przypadków nieprawidłowego wpisania hasła podczas odblokowywania ekranu i blokowanie systemu multimedialno-rozrywkowego lub usuwanie wszystkich danych z profilu przy zbyt dużej liczbie błędnych prób."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Monitorowanie, ile razy wpisano błędne hasło podczas odblokowywania ekranu, oraz blokowanie telefonu albo kasowanie wszystkich danych tego użytkownika, gdy zbyt wiele razy wpisano błędne hasło."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"Zmiana blokady ekranu"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"Pozwala zmienić blokadę ekranu."</string> @@ -746,10 +748,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"Usuwanie wszystkich danych"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Wymazywanie danych z tabletu bez ostrzeżenia przez przywrócenie danych fabrycznych"</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Wymazywanie danych z urządzenia z Androidem TV bez ostrzeżenia przez przywrócenie danych fabrycznych."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Wykasowanie danych z systemu multimedialno-rozrywkowego bez ostrzeżenia przez przywrócenie danych fabrycznych."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Wymazywanie danych z telefonu bez ostrzeżenia przez przywrócenie danych fabrycznych."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"Kasuj dane użytkownika"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Wykasuj dane z profilu"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Kasuj dane użytkownika"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Kasowanie danych tego użytkownika na tym tablecie bez ostrzeżenia."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Kasowanie danych tego użytkownika na tym urządzeniu z Androidem TV bez ostrzeżenia."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"Wykasowanie danych z profilu w tym systemie multimedialno-rozrywkowym bez ostrzeżenia."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"Kasowanie danych tego użytkownika na tym telefonie bez ostrzeżenia."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Ustaw globalny serwer proxy urządzenia"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Ustawianie globalnego serwera proxy urządzenia do użycia przy włączonych zasadach. Tylko właściciel urządzenia może ustawić globalny serwer proxy."</string> diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml index da3164a523ab..026da86bd523 100644 --- a/core/res/res/values-pt-rBR/strings.xml +++ b/core/res/res/values-pt-rBR/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"Monitorar tentativas de desbloqueio de tela"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Monitora quantas vezes a senha foi digitada incorretamente ao desbloquear a tela e bloqueia o telefone ou apaga todos os dados do telefone se a senha for digitada incorretamente muitas vezes."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Monitora o número de senhas incorretas digitadas ao desbloquear a tela e bloqueia o dispositivo Android TV ou limpa todos os dados nele se muitas senhas incorretas forem digitadas."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Monitora quantas vezes a senha foi digitada incorretamente ao desbloquear a tela e bloqueia o sistema de infoentretenimento ou apaga todos os dados desse sistema quando isso acontece muitas vezes."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Monitora quantas vezes a senha foi digitada incorretamente ao desbloquear a tela e bloqueia o telefone ou apaga todos os dados do telefone se a senha for digitada incorretamente muitas vezes."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Monitora o número de senhas incorretas digitadas ao desbloquear a tela e bloqueia o tablet ou limpa todos os dados do usuário se muitas senhas incorretas forem digitadas."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Monitora o número de senhas incorretas digitadas ao desbloquear a tela e bloqueia o dispositivo Android TV ou apaga todos os dados do usuário se muitas senhas incorretas forem digitadas."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Monitora quantas vezes a senha foi digitada incorretamente ao desbloquear a tela e bloqueia o sistema de infoentretenimento ou apaga todos os dados do perfil quando isso acontece muitas vezes."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Monitora o número de senhas incorretas digitadas ao desbloquear a tela e bloqueia o smartphone ou limpa todos os dados do usuário se muitas senhas incorretas forem digitadas."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"Alterar o bloqueio de tela"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"Altera o bloqueio de tela."</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"Apagar todos os dados"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Apague os dados do tablet sem aviso redefinindo a configuração original."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Redefine o dispositivo Android TV para a configuração original e apaga os dados sem aviso."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Apaga os dados sem aviso, redefinindo o sistema de infoentretenimento para a configuração original."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Apaga os dados sem aviso redefinindo o smartphone para a configuração original."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"Limpar dados do usuário"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Apagar dados do perfil"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Limpar dados do usuário"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Limpa os dados do usuário neste tablet sem aviso prévio."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Limpa os dados do usuário neste dispositivo Android TV sem aviso prévio."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"Apaga os dados do perfil do sistema de infoentretenimento sem aviso."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"Limpa os dados do usuário neste smartphone sem aviso prévio."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Definir o proxy global do dispositivo"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Configura o proxy global do dispositivo para ser usado enquanto a política está ativada. Somente o proprietário do dispositivo pode definir o proxy global."</string> diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml index 9163bd779156..68faa445029e 100644 --- a/core/res/res/values-pt-rPT/strings.xml +++ b/core/res/res/values-pt-rPT/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"Monitorizar tentativas de desbloqueio do ecrã"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Monitorizar o número de palavras-passe incorretas escritas ao desbloquear o ecrã e bloquear o tablet ou apagar todos os dados do tablet, se forem escritas demasiadas palavras-passe incorretas."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Monitorizar o número de palavras-passe incorretas introduzidas ao desbloquear o ecrã e bloquear o seu dispositivo Android TV ou apagar todos os dados do mesmo se forem introduzidas demasiadas palavras-passe incorretas."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Monitorize o número de palavras-passe incorretas introduzidas ao desbloquear o ecrã e bloqueie o sistema de infoentretenimento ou apague todos os dados do sistema de infoentretenimento, se forem escritas demasiadas palavras-passe incorretas."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Monitorizar o número de palavras-passe incorretas introduzidas ao desbloquear o ecrã e bloquear o telemóvel ou apagar todos os dados do telemóvel caso tenham sido introduzidas demasiadas palavras-passe."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Monitorizar o número de palavras-passe incorretas introduzidas ao desbloquear o ecrã e bloquear o tablet ou apagar todos os dados deste utilizador se forem introduzidas demasiadas palavras-passe incorretas."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Monitorizar o número de palavras-passe incorretas introduzidas ao desbloquear o ecrã e bloquear o dispositivo Android TV ou apagar todos os dados deste utilizador se forem introduzidas demasiadas palavras-passe incorretas."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Monitorize o número de palavras-passe incorretas introduzidas ao desbloquear o ecrã e bloqueie o sistema de infoentretenimento ou apague todos os dados deste utilizador, se forem introduzidas demasiadas palavras-passe incorretas."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Monitorizar o número de palavras-passe incorretas introduzidas ao desbloquear o ecrã e bloquear o telemóvel ou apagar todos os dados deste utilizador se forem introduzidas demasiadas palavras-passe incorretas."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"Alterar o bloqueio de ecrã"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"Altera o bloqueio de ecrã."</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"Apagar todos os dados"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Apagar os dados do tablet sem avisar através de uma reposição de dados de fábrica."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Apagar os dados do seu dispositivo Android TV sem avisar ao efetuar uma reposição de dados de fábrica."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Apague os dados do sistema de infoentretenimento sem aviso ao executar uma reposição de dados de fábrica."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Apaga os dados do telemóvel sem avisar ao efetuar uma reposição de dados de fábrica."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"Apagar os dados do utilizador"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Apague os dados do perfil"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Apagar os dados do utilizador"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Apagar os dados deste utilizador neste tablet sem aviso."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Apagar os dados deste utilizador neste dispositivo Android TV sem aviso."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"Apague os dados deste perfil neste sistema de infoentretenimento sem aviso."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"Apagar os dados deste utilizador neste telemóvel sem aviso."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Definir o proxy global do aparelho"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Definir o proxy global do dispositivo a utilizar enquanto a política está ativada. Apenas o proprietário do dispositivo pode definir o proxy global."</string> diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml index da3164a523ab..026da86bd523 100644 --- a/core/res/res/values-pt/strings.xml +++ b/core/res/res/values-pt/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"Monitorar tentativas de desbloqueio de tela"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Monitora quantas vezes a senha foi digitada incorretamente ao desbloquear a tela e bloqueia o telefone ou apaga todos os dados do telefone se a senha for digitada incorretamente muitas vezes."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Monitora o número de senhas incorretas digitadas ao desbloquear a tela e bloqueia o dispositivo Android TV ou limpa todos os dados nele se muitas senhas incorretas forem digitadas."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Monitora quantas vezes a senha foi digitada incorretamente ao desbloquear a tela e bloqueia o sistema de infoentretenimento ou apaga todos os dados desse sistema quando isso acontece muitas vezes."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Monitora quantas vezes a senha foi digitada incorretamente ao desbloquear a tela e bloqueia o telefone ou apaga todos os dados do telefone se a senha for digitada incorretamente muitas vezes."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Monitora o número de senhas incorretas digitadas ao desbloquear a tela e bloqueia o tablet ou limpa todos os dados do usuário se muitas senhas incorretas forem digitadas."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Monitora o número de senhas incorretas digitadas ao desbloquear a tela e bloqueia o dispositivo Android TV ou apaga todos os dados do usuário se muitas senhas incorretas forem digitadas."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Monitora quantas vezes a senha foi digitada incorretamente ao desbloquear a tela e bloqueia o sistema de infoentretenimento ou apaga todos os dados do perfil quando isso acontece muitas vezes."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Monitora o número de senhas incorretas digitadas ao desbloquear a tela e bloqueia o smartphone ou limpa todos os dados do usuário se muitas senhas incorretas forem digitadas."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"Alterar o bloqueio de tela"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"Altera o bloqueio de tela."</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"Apagar todos os dados"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Apague os dados do tablet sem aviso redefinindo a configuração original."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Redefine o dispositivo Android TV para a configuração original e apaga os dados sem aviso."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Apaga os dados sem aviso, redefinindo o sistema de infoentretenimento para a configuração original."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Apaga os dados sem aviso redefinindo o smartphone para a configuração original."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"Limpar dados do usuário"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Apagar dados do perfil"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Limpar dados do usuário"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Limpa os dados do usuário neste tablet sem aviso prévio."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Limpa os dados do usuário neste dispositivo Android TV sem aviso prévio."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"Apaga os dados do perfil do sistema de infoentretenimento sem aviso."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"Limpa os dados do usuário neste smartphone sem aviso prévio."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Definir o proxy global do dispositivo"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Configura o proxy global do dispositivo para ser usado enquanto a política está ativada. Somente o proprietário do dispositivo pode definir o proxy global."</string> diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml index 2febb26f6d20..c8ea764bfb19 100644 --- a/core/res/res/values-ro/strings.xml +++ b/core/res/res/values-ro/strings.xml @@ -732,9 +732,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"Să monitorizeze încercările de deblocare a ecranului"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Monitorizați numărul de parole incorecte introduse la deblocarea ecranului și blocați tableta sau ștergeți datele acesteia dacă sunt introduse prea multe parole incorecte."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Monitorizați numărul de parole incorecte introduse la deblocarea ecranului și blocați dispozitivul Android TV sau ștergeți toate datele de pe acesta dacă se introduc prea multe parole incorecte."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Monitorizați numărul de parole incorecte introduse la deblocarea ecranului și blocați sistemul de infotainment sau ștergeți toate datele acestuia dacă sunt introduse prea multe parole incorecte."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Monitorizați numărul de parole incorecte introduse la deblocarea ecranului și blocați telefonul sau ștergeți toate datele acestuia dacă sunt introduse prea multe parole incorecte."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Monitorizați numărul de parole incorecte introduse la deblocarea ecranului și blocați tableta sau ștergeți toate datele acestui utilizator dacă se introduc prea multe parole incorecte."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Monitorizați numărul de parole incorecte introduse la deblocarea ecranului și blocați dispozitivul Android TV sau ștergeți toate datele acestui utilizator dacă se introduc prea multe parole incorecte."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Monitorizați numărul de parole incorecte introduse la deblocarea ecranului și blocați sistemul de infotainment sau ștergeți toate datele acestui profil dacă sunt introduse prea multe parole incorecte."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Monitorizați numărul de parole incorecte introduse la deblocarea ecranului și blocați telefonul sau ștergeți toate datele acestui utilizator dacă se introduc prea multe parole incorecte."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"Să schimbe blocarea ecranului"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"Modificați blocarea ecranului."</string> @@ -743,10 +745,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"Să șteargă toate datele"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Ștergeți datele de pe tabletă fără avertisment, efectuând resetarea configurării din fabrică."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Ștergeți datele de pe dispozitivul Android TV fără avertisment, efectuând o revenire la setările din fabrică."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Ștergeți datele din sistemul de infotainment fără avertisment, prin revenirea la setările din fabrică."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Ștergeți datele din telefon fără avertisment, efectuând resetarea configurării din fabrică."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"Ștergeți datele utilizatorului"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Ștergeți datele de profil"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Ștergeți datele utilizatorului"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Ștergeți datele acestui utilizator de pe această tabletă fără avertisment."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Ștergeți datele acestui utilizator de pe acest dispozitiv Android TV fără avertisment"</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"Ștergeți datele profilului din acest sistem de infotainment fără avertisment."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"Ștergeți datele acestui utilizator de pe acest telefon fără avertisment."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Setați serverul proxy global pentru dispozitiv"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Setați serverul proxy global pentru dispozitiv, care să fie utilizat cât timp politica este activă. Numai proprietarul dispozitivului poate seta serverul proxy global."</string> diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml index 1055a6d3cb98..01626e447d0d 100644 --- a/core/res/res/values-ru/strings.xml +++ b/core/res/res/values-ru/strings.xml @@ -735,9 +735,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"Отслеживание попыток разблокировать экран"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Отслеживает попытки ввода пароля при разблокировке экрана и блокирует планшетный ПК или удаляет с него все данные, если было сделано слишком много таких попыток."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Блокировать устройство Android TV или удалять с него все ваши данные при слишком большом количестве неудачных попыток ввести пароль для разблокировки экрана."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Блокировать информационно-развлекательную систему или удалять из нее все данные, если совершено слишком много неудачных попыток ввести пароль для разблокировки экрана."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Отслеживает попытки ввода пароля при разблокировке экрана и блокирует телефон или удаляет с него все данные, если было сделано слишком много таких попыток."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Отслеживать неверно введенные пароли при разблокировке экрана и блокировать планшет или удалять с него все данные, если сделано слишком много неудачных попыток."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Блокировать устройство Android TV или удалять с него все данные этого пользователя при слишком большом количестве неудачных попыток ввести пароль для разблокировки экрана."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Блокировать информационно-развлекательную систему или удалять все данные профиля, если совершено слишком много неудачных попыток ввести пароль для разблокировки экрана."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Отслеживать неверно введенные пароли при разблокировке экрана и блокировать телефон или удалять с него все данные, если сделано слишком много неудачных попыток."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"Изменение способа блокировки экрана"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"Изменять способ блокировки экрана."</string> @@ -746,10 +748,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"Удаление всех данных"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Удалять все данные на планшетном ПК без предупреждения путем сброса настроек."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Удалять данные с устройства Android TV без предупреждения, выполняя восстановление заводских настроек."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Сбрасывать настройки без предупреждения, таким образом удаляя все данные из информационно-развлекательной системы."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Удалять все данные на телефоне без предупреждения путем сброса настроек."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"Удалить пользовательские данные"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Удаление данных профиля"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Удалить пользовательские данные"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Удалить данные этого пользователя с планшета без предупреждения."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Удалять данные этого пользователя с устройства Android TV без предупреждения."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"Удалять данные профиля из этой информационно-развлекательной системы без предупреждения."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"Удалить данные этого пользователя с телефона без предупреждения."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Глобальный прокси-сервер"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Настроить глобальный прокси-сервер устройства, который будет использоваться при активной политике. Это может сделать только владелец устройства."</string> diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml index 703ad1760d69..15672f6300fb 100644 --- a/core/res/res/values-si/strings.xml +++ b/core/res/res/values-si/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"තිරය අගුළු ඇරීමේ උත්සාහයන් නිරීක්ෂණය කරන්න"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"තිරය අගුළු හැරීමේදී වැරදියට ටයිප් කළ මුරපද ගණන නිරීක්ෂණය කරන්න සහ ටැබ්ලටය අගුළු දමන්න හෝ වැරදි මුරපද බොහෝ ගණනක් ටයිප් කර ඇති නම් ටැබ්ලටයේ සියලු දත්ත මකන්න."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"තිරය අගුලු හරින විට වැරදියට මුරපදය ටයිප් කළ වාර ගණන නිරීක්ෂණය කර, ඉතා වැඩි වාර ගණනක් වැරදි මුරපද ටයිප් කළේ නම් ඔබේ Android TV උපාංගය අගුලු දමන්න නැතහොත් මෙම Android TV උපාංගයෙහි සියලු දත්ත මකන්න."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"තිරය අගුලු හරින විට වැරදියට මුරපදය ටයිප් කළ වාර ගණන නිරීක්ෂණය කර, ඉතා වැඩි වාර ගණනක් වැරදි මුරපද ටයිප් කළේ නම් තොරතුරු විනෝදාස්වාද පද්ධතිය අගුලු දමන්න නැතහොත් මෙම තොරතුරු විනෝදාස්වාද පද්ධතියෙහි සියලු දත්ත මකන්න."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"තිරය අගුළු හැරීමේදී වැරදියට ටයිප් කළ මුරපද ගණන නිරීක්ෂණය කරන්න සහ දුරකථනය අගුළු දමන්න හෝ වැරදි මුරපද බොහෝ ගණනක් ටයිප් කර ඇති නම් දුරකථනයේ සියලු දත්ත මකන්න."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"තිරය අගුලු හරින විට වැරදියට මුරපදය ටයිප් කළ වාර ගණන නිරීක්ෂණය කර, ඉතා වැඩි වාර ගණනක් වැරදි මුරපද ටයිප් කළේ නම් ටැබ්ලටය අගුලු දමන්න නැතහොත් මෙම පරිශීලකයාගේ සියලු දත්ත මකන්න."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"තිරය අගුලු හරින විට වැරදියට මුරපදය ටයිප් කළ වාර ගණන නිරීක්ෂණය කර, ඉතා වැඩි වාර ගණනක් වැරදි මුරපද ටයිප් කළේ නම් ඔබේ Android TV අගුලු දමන්න නැතහොත් මෙම පරිශීලකයාගේ සියලු දත්ත මකන්න."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"තිරය අගුලු හරින විට වැරදියට මුරපදය ටයිප් කළ වාර ගණන නිරීක්ෂණය කර, ඉතා වැඩි වාර ගණනක් වැරදි මුරපද ටයිප් කළේ නම් තොරතුරු විනෝදාස්වාද පද්ධතිය අගුලු දමන්න නැතහොත් මෙම පැතිකඩෙහි සියලු දත්ත මකන්න."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"තිරය අගුලු හරින විට වැරදියට මුරපදය ටයිප් කළ වාර ගණන නිරීක්ෂණය කර, ඉතා වැඩි වාර ගණනක් වැරදි මුරපද ටයිප් කළේ නම් දුරකථනය අගුලු දමන්න නැතහොත් මෙම පරිශීලකයාගේ සියලු දත්ත මකන්න."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"තිර අගුල වෙනස් කරන්න"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"තිර අගුල වෙනස් කරන්න."</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"සියලු දත්ත මකන්න"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"කර්මාන්ත ශාලා දත්ත යළි පිහිටුවීමෙන් පසුව අනතුරු ඇඟවිමකින් තොරවම ටැබ්ලට් දත්ත මකා දමයි."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"කර්මාන්ත ශාලා දත්ත යළි සැකසීමක් සිදු කිරීම මගින්, අනතුරු ඇඟවිමකින් තොරව ඔබේ Android TV දත්ත මකයි."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"අනතුරු ඇඟවීමෙන් තොරව කර්මාන්තශාලා දත්ත යළි සැකසීමක් සිදු කිරීම මගින් තොරතුරු විනෝදාස්වාද පද්ධතියේ දත්ත මකන්න."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"කර්මාන්ත ශාලා දත්ත යළි පිහිටුවීමෙන් පසුව අනතුරු ඇඟවිමකින් තොරවම දුරකථන දත්ත මකා දමයි."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"පරිශීලක දත්ත මකන්න"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"පැතිකඩ දත්ත මකන්න"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"පරිශීලක දත්ත මකන්න"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"අනතුරු ඇඟවීමකින් තොරව මෙම ටැබ්ලටයෙහි මෙම පරිශීලකයාගේ දත්ත මැකීම."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"අනතුරු ඇඟවීමකින් තොරව මෙම Android TV උපාංගයෙහි මෙම පරිශීලකයාගේ දත්ත මැකීම."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"අනතුරු ඇඟවීමෙන් තොරව මෙම තොරතුරු විනෝදාස්වාද පද්ධතියේ මෙම පැතිකඩෙහි දත්ත මකන්න."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"අනතුරු ඇඟවීමකින් තොරව මෙම දුරකථනයෙහි මෙම පරිශීලකයාගේ දත්ත මැකීම."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"උපාංග ගෝලීය නියුතුව සකස් කිරීම"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"ප්රතිපත්තිය සක්රිය අතරතුර ගෝලීය ප්රොක්සි භාවිත කිරීමට උපාංගය සකසන්න. උපාංග හිමිකරුට පමණක් ගෝලීය ප්රොක්සි සැකසිය හැකිය."</string> diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml index 334203cd9997..f94912274758 100644 --- a/core/res/res/values-sk/strings.xml +++ b/core/res/res/values-sk/strings.xml @@ -735,9 +735,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"Sledovanie pokusov o odomknutie obrazovky"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Sledovať počet nesprávnych hesiel zadaných pri odomykaní obrazovky a zamknúť tablet alebo vymazať všetky údaje tabletu v prípade príliš veľkého počtu neplatných pokusov o zadanie hesla."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Sledovanie počtu nesprávnych hesiel zadaných pri odomykaní obrazovky a v prípade, že ich je zadaných príliš mnoho, uzamknutie zariadenia Android TV alebo vymazanie všetkých jeho údajov."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Sledujte počet nesprávnych hesiel zadaných pri odomykaní obrazovky a uzamknite palubný systém alebo vymažte všetky údaje v palubnom systéme v prípade príliš veľkého počtu neplatných pokusov o zadanie hesla."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Sledovať počet nesprávnych hesiel zadaných pri odomykaní obrazovky a zamknúť telefón alebo vymazať všetky údaje v telefóne v prípade príliš veľkého počtu neplatných pokusov o zadanie hesla."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Sledujte počet nesprávnych hesiel zadaných pri odomykaní obrazovky a v prípade, že ich je zadaných príliš mnoho, uzamknite tablet alebo vymažte všetky údaje tohto používateľa."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Sledovanie počtu nesprávnych hesiel zadaných pri odomykaní obrazovky a ak je ich zadaných príliš mnoho, uzamknutie zariadenia Android TV alebo vymazanie všetkých údajov tohto používateľa."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Sledujte počet nesprávnych hesiel zadaných pri odomykaní obrazovky a v prípade, že ich je zadaných príliš mnoho, uzamknite palubný systém alebo vymažte všetky údaje tohto profilu."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Sledujte počet nesprávnych hesiel zadaných pri odomykaní obrazovky a v prípade, že ich je zadaných príliš mnoho, uzamknite telefón alebo vymažte všetky údaje tohto používateľa."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"Zmeniť zámku obrazovky"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"Zmeniť zámku obrazovky."</string> @@ -746,10 +748,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"Vymazať všetky dáta"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Bez predchádzajúceho upozornenia vymazať všetky dáta obnovením výrobných nastavení tabletu."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Vymazanie údajov v zariadení Android TV bez upozornenia obnovením výrobných nastavení."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Vymažte údaje palubného systému bez upozornenia obnovením výrobných nastavení."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Bez predchádzajúceho upozornenia vymazať všetky dáta obnovením výrobných nastavení telefónu."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"Vymazať údaje používateľa"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Vymazanie údajov profilu"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Vymazať údaje používateľa"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Vymažte bez upozornenia údaje tohto používateľa na tomto tablete."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Vymazanie údajov tohto používateľa v tomto zariadení Android TV bez upozornenia."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"Vymažte údaje tohto profilu v tomto palubnom systéme bez upozornenia."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"Vymažte bez upozornenia údaje tohto používateľa na tomto telefóne."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Nastaviť globálny server proxy zariadenia"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Vyberte globálny proxy server, ktorý sa bude používať po aktivácii pravidiel. Nastaviť ho môže iba vlastník zariadenia."</string> diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml index 7e92ebf4fdc7..f336d3cee5ed 100644 --- a/core/res/res/values-sl/strings.xml +++ b/core/res/res/values-sl/strings.xml @@ -735,9 +735,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"Nadzor nad poskusi odklepanja zaslona"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Nadzoruje število nepravilno vnesenih gesel pri odklepanju zaslona in zaklene tablični računalnik ali izbriše vse podatke v njem, če je vnesenih preveč nepravilnih gesel."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Nadzira število vnesenih nepravilnih gesel pri odklepanju zaslona in zaklene napravo Android TV ali izbriše vse podatke v napravi Android TV, če je vnesenih preveč nepravilnih gesel."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Spremljanje števila nepravilno vnesenih gesel pri odklepanju zaslona in zaklenitev informativno-razvedrilnega sistema ali izbris vseh podatkov v njem v primeru preveč vnosov nepravilnih gesel"</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Spremljajte število vnesenih napačnih gesel, s katerimi želite odkleniti zaslon. Če je teh vnosov preveč, zaklenite telefon ali izbrišite vse podatke v njem."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Nadzira število vnesenih nepravilnih gesel pri odklepanju zaslona in zaklene tablični računalnik ali izbriše vse podatke lastnika, če je vnesenih preveč nepravilnih gesel."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Nadzira število vnesenih nepravilnih gesel pri odklepanju zaslona in zaklene napravo Android TV ali izbriše vse podatke tega uporabnika, če je vnesenih preveč nepravilnih gesel."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Spremljanje števila nepravilno vnesenih gesel pri odklepanju zaslona in zaklenitev informativno-razvedrilnega sistema ali izbris vseh podatkov tega profila v primeru preveč vnosov nepravilnih gesel"</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Nadzira število vnesenih nepravilnih gesel pri odklepanju zaslona in zaklene telefon ali izbriše vse podatke lastnika, če je vnesenih preveč nepravilnih gesel."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"Spreminjanje zaklepanja zaslona"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"Spremeni zaklepanje zaslona."</string> @@ -746,10 +748,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"Brisanje vseh podatkov"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Izbris podatkov v tabličnem računalniku brez opozorila s ponastavitvijo na tovarniške nastavitve"</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Brisanje podatkov v napravi Android TV z izvedbo ponastavitve na privzete tovarniške nastavitve brez opozorila."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Izbris podatkov informativno-razvedrilnega sistema brez opozorila s ponastavitvijo na tovarniške nastavitve"</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Izbris podatkov v telefonu brez opozorila s ponastavitvijo na tovarniške nastavitve."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"Izbris podatkov uporabnika"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Izbris podatkov profila"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Izbris podatkov uporabnika"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Izbris podatkov uporabnika v tem tabličnem računalniku brez opozorila."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Izbris podatkov uporabnika v tej napravi Android TV brez opozorila."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"Izbris podatkov tega profila v informativno-razvedrilnem sistemu brez opozorila"</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"Izbris podatkov uporabnika v tem telefonu brez opozorila."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Nastavitev globalnega strežnika proxy za napravo"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Nastavitev globalnega strežnika proxy naprave, ki bo v uporabi, ko je pravilnik omogočen. Samo lastnik naprave lahko nastavi globalni strežnik proxy."</string> diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml index a30396302f31..ce7e8b647245 100644 --- a/core/res/res/values-sq/strings.xml +++ b/core/res/res/values-sq/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"Monitoro tentativat e shkyçjes së ekranit"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Monitoro numrin e fjalëkalimeve të shkruar gabim kur shkyç ekranin. Kyç tabletin ose fshi të gjitha të dhënat e tij, nëse shkruhen shumë fjalëkalime të pasakta."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Monitoro numrin e fjalëkalimeve të shkruara gabim kur shkyç ekranin dhe kyç pajisjen tënde Android TV ose spastro të gjitha të dhënat e pajisjes sate Android TV nëse shkruhen gabim shumë fjalëkalime."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Monitoro numrin e fjalëkalimeve të shkruara gabim kur shkyç ekranin dhe kyç sistemin info-argëtues ose spastro të gjitha të dhënat e tij nëse shkruhen shumë fjalëkalime të gabuara."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Monitoro numrin e fjalëkalimeve të shkruar gabim kur shkyç ekranin. Kyç telefonin ose fshi të gjitha të dhënat e tij, nëse shkruhen shumë fjalëkalime të pasakta."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Monitoro numrin e fjalëkalimeve të shkruara gabim kur shkyç ekranin. Kyçe tabletin ose spastro të gjitha të dhënat e këtij përdoruesi nëse shkruhen shumë fjalëkalime të gabuara."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Monitoro numrin e fjalëkalimeve të shkruara gabim kur shkyç ekranin dhe kyçe pajisjen tënde Android TV ose spastro të gjitha të dhënat e këtij përdoruesi nëse shkruhen shumë fjalëkalime të gabuara."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Monitoro numrin e fjalëkalimeve të shkruara gabim kur shkyç ekranin dhe kyç sistemin info-argëtues ose spastro të gjitha të dhënat e këtij profili nëse shkruhen shumë fjalëkalime të gabuara."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Monitoro numrin e fjalëkalimeve të shkruara gabim kur shkyç ekranin. Kyçe telefonin ose spastro të gjitha të dhënat e këtij përdoruesi nëse shkruhen shumë fjalëkalime të gabuara."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"Ndryshimin e kyçjes së ekranit"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"Ndryshon kyçjen e ekranit."</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"Spastrimin e të gjitha të dhënave"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Fshi të dhënat e tabletit pa paralajmërim duke kryer një rivendosje të të dhënave në gjendje fabrike."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Spastro të dhënat e pajisjes Android TV pa paralajmërim duke kryer një rivendosje të të dhënave në gjendje fabrike."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Spastro të dhënat e sistemit info-argëtues pa paralajmërim kur kryen një rivendosje të të dhënave të fabrikës."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Fshin të dhënat e telefonit pa paralajmërim, duke kryer rivendosje të të dhënave në gjendje fabrike."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"Spatro të dhënat e përdoruesit"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Spastro të dhënat e profilit"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Spatro të dhënat e përdoruesit"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Spastroji të dhënat e këtij përdoruesi në këtë tablet pa paralajmërim."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Spastroji të dhënat e këtij përdoruesi në këtë pajisje Android TV pa paralajmërim."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"Spastro të dhënat e këtij profili në këtë sistem info-argëtues pa paralajmërim."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"Spastroji të dhënat e këtij përdoruesi në këtë telefon pa paralajmërim."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Cakto proxy-in global të pajisjes"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Cakto proxy-in global të pajisjes që të përdoret kur të aktivizohet politika. Vetëm pronari i pajisjes mund ta caktojë proxy-in global."</string> diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml index 7a097d3734a2..b727283b8f4b 100644 --- a/core/res/res/values-sr/strings.xml +++ b/core/res/res/values-sr/strings.xml @@ -732,9 +732,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"Надгледајте покушаје откључавања екрана"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Прати број нетачно унетих лозинки приликом откључавања екрана и закључава таблет или брише податке са таблета ако је нетачна лозинка унета превише пута."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Надгледа број нетачних лозинки унетих при откључавању екрана и закључава Android TV уређај или брише све податке са Android TV уређаја ако се унесе превише нетачних лозинки."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Прати број нетачно унетих лозинки при откључавању екрана и закључава систем за инфо-забаву или брише све податке са система за инфо-забаву ако је нетачна лозинка унета превише пута."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Прати број нетачно унетих лозинки при откључавању екрана и закључава телефон или брише све податке са телефона ако је нетачна лозинка унета превише пута."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Надгледа број нетачних лозинки унетих при откључавању екрана и закључава таблет или брише све податке овог корисника ако се унесе превише нетачних лозинки."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Надгледа број нетачних лозинки унетих при откључавању екрана и закључава Android TV уређај или брише све податке овог корисника ако се унесе превише нетачних лозинки."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Надгледа број нетачних лозинки унетих при откључавању екрана и закључава систем за инфо-забаву или брише све податке овог профила ако се унесе превише нетачних лозинки."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Надгледа број нетачних лозинки унетих при откључавању екрана и закључава телефон или брише све податке овог корисника ако се унесе превише нетачних лозинки."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"Промена закључавања екрана"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"Мења закључавање екрана."</string> @@ -743,10 +745,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"Брисање свих података"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Брисање података на таблету без упозорења ресетовањем на фабричка подешавања."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Брише податке Android TV уређаја без упозорења помоћу ресетовања на фабричка подешавања."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Брише податке на систему за инфо-забаву без упозорења ресетовањем на фабричка подешавања."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Брисање података на телефону без упозорења ресетовањем на фабричка подешавања."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"Обриши податке корисника"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Брисање података профила"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Обриши податке корисника"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Брише податке овог корисника на овом таблету без упозорења."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Брише податке овог корисника на овом Android TV уређају без упозорења."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"Брише податке овог профила на овом систему за инфо-забаву без упозорења."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"Брише податке овог корисника на овом телефону без упозорења."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Подесите глобални прокси сервер уређаја"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Подешава глобални прокси уређаја који ће се користити док су смернице омогућене. Само власник уређаја може да подеси глобални прокси."</string> diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml index 1f1579dace33..742f34177c84 100644 --- a/core/res/res/values-sv/strings.xml +++ b/core/res/res/values-sv/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"Övervaka försök att låsa upp skärmen"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Övervaka antalet felaktiga lösenord som angetts för skärmlåset och lås surfplattan eller ta bort alla data från surfplattan om för många felaktiga försök görs."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Övervaka antalet felaktiga lösenord som skrivits in vid upplåsning av skärmen och lås Android TV-enheten eller rensa all data på Android TV-enheten om för många felaktiga lösenord har skrivits in."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Övervaka antalet felaktiga lösenord som angetts för skärmlåset och lås infotainmentsystemet eller rensa all data från infotainmentsystemet om för många felaktiga försök görs."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Övervaka antalet felaktiga lösenord som angivits för skärmlåset och lås mobilen eller ta bort alla data från mobilen om för många felaktiga försök görs."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Övervaka antalet felaktiga lösenord som skrivits in vid upplåsning av skärmen och lås surfplattan eller rensa alla uppgifter för den här användaren om för många felaktiga lösenord har skrivits in."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Övervaka antalet felaktiga lösenord som skrivits in vid upplåsning av skärmen och lås Android TV-enheten eller rensa alla uppgifter för den här användaren om för många felaktiga lösenord har skrivits in."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Övervaka antalet felaktiga lösenord som angetts för skärmlåset och lås infotainmentsystemet eller rensa all data från profilen om för många felaktiga lösenord har skrivits in."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Övervaka antalet felaktiga lösenord som skrivits in vid upplåsning av skärmen och lås mobilen eller rensa alla uppgifter för den här användaren om för många felaktiga lösenord har skrivits in."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"Ändra skärmlåset"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"Ändra skärmlåset."</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"Radera all data"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Ta bort data från surfplattan utan förvarning genom att återställa standardinställningarna."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Radera data på Android TV-enheten utan förvarning genom att återställa standardinställningarna."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Rensa data från infotainmentsystemet utan förvarning genom att återställa standardinställningarna."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Ta bort data från mobilen utan förvarning genom att återställa standardinställningarna."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"Radera användaruppgifter"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Rensa profildata"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Radera användaruppgifter"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Rensa användarens uppgifter på den här surfplattan utan förvarning."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Radera den här användarens data på den här Android TV-enheten utan förvarning."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"Rensa profilens data i det här infotainmentsystemet utan förvarning."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"Rensa användarens data på den här mobilen utan förvarning."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Ange global proxyserver"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Ange enhetens globala proxy som ska användas när policyn aktiveras. Det är bara enhetens ägare som kan ange global proxy."</string> diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml index 8b2cf779a243..3081bdfd0892 100644 --- a/core/res/res/values-sw/strings.xml +++ b/core/res/res/values-sw/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"Kuhesabu mara ambazo skrini inajaribu kufunguliwa"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Kufuatilia idadi ya manenosiri yasiyo sahihi yatakayoingizwa wakati wa kufungua skrini, na kufunga kompyuta kibao au kufuta data yote iliyomo kama manenosiri mengi yasiyo sahihi yataingizwa."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Fuatilia idadi ya manenosiri yasiyo sahihi yanayowekwa wakati wa kufungua skrini na ufunge kifaa chako cha Android TV au ufute data yake yote ikiwa mtumiaji ataweka manenosiri mengi mno yasiyo sahihi."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Fuatilia idadi ya manenosiri yasiyo sahihi yanayowekwa wakati wa kufungua skrini, na ufunge mfumo wa burudani na habari au ufute data yote kwenye mfumo wa burudani na habari ikiwa manenosiri mengi mno yasiyo sahihi yatawekwa."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Kufuatilia idadi ya manenosiri yasiyo sahihi yatakayoingizwa wakati wa kufungua skrini, na kufunga simu au kufuta data yote iliyomo kama manenosiri mengi sana yasiyo sahihi yataingizwa."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Fuatilia idadi ya manenosiri yasiyo sahihi yaliyoingizwa wakati wa kufungua skrini, na ufunge kompyuta kibao au ufute data yote ya mtumiaji huyu kama ameingiza manenosiri yasiyo sahihi mara nyingi kupita kiasi."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Fuatilia idadi ya manenosiri yasiyo sahihi yanayowekwa wakati wa kufungua skrini na ufunge kifaa chako cha Android TV au ufute data yote ya mtumiaji huyu ikiwa ataweka manenosiri yasiyo sahihi mara nyingi mno."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Fuatilia idadi ya manenosiri yasiyo sahihi yanayowekwa wakati wa kufungua skrini, na ufunge mfumo wa burudani na habari au ufute data yote kwenye wasifu huu ikiwa manenosiri mengi mno yasiyo sahihi yatawekwa."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Fuatilia idadi ya manenosiri yasiyo sahihi yaliyoingizwa wakati wa kufungua skrini, na ufunge simu au ufute data yote ya mtumiaji huyu kama ameingiza manenosiri yasiyo sahihi mara nyingi kupita kiasi."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"Kubadilisha mbinu ya kufunga skrini"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"Kubadilisha mbinu ya kufunga skrini."</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"Kufuta data yote"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Futa data ya kompyuta kibao bila ilani kwa kurejesha mipangilio ambayo kompyuta ilitoka nayo kiwandani."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Futa data ya kifaa chako cha Android TV bila onyo kwa kurejesha data kiliyotoka nayo kiwandani."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Futa data ya mfumo wa burudani na habari bila onyo kwa kurejesha data iliyotoka nayo kiwandani."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Kufuta data ya simu bila ilani kwa kurejesha mipangilio iliyotoka nayo kiwandani."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"Futa data yote ya mtumiaji"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Futa data yote ya wasifu"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Futa data yote ya mtumiaji"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Futa data ya mtumiaji huyu iliyo kwenye kompyuta kibao hii bila ilani."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Futa data ya mtumiaji huyu iliyo kwenye kifaa hiki cha Android TV bila ilani."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"Futa data yote ya wasifu kwenye mfumo huu wa burudani na habari bila onyo."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"Futa data ya mtumiaji huyu iliyo kwenye simu hii bila ilani."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Weka seva mbadala ya ulimwengu kote ya kifaa"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Weka seva mbadala ya ulimwengu ya kifaa itakayotumika wakati sera imewashwa. Ni mmiliki wa kifaa pekee aneyeweza kuweka seva mbadala ya ulimwengu."</string> diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml index b27af3447e66..7b15aec90d26 100644 --- a/core/res/res/values-ta/strings.xml +++ b/core/res/res/values-ta/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"திரையை அன்லாக் செய்வதற்கான முயற்சிகளைக் கண்காணி"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"திரையைத் திறக்கும்போது உள்ளிட்ட தவறான கடவுச்சொற்களின் எண்ணிக்கையைக் கண்காணிக்கும், மேலும் கடவுச்சொற்கள் பலமுறை தவறாக உள்ளிட்டிருந்தால், டேப்லெட்டைப் பூட்டும் அல்லது டேப்லெட்டின் எல்லா தரவையும் அழிக்கும்."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"திரையைத் திறக்கும்போது எத்தனை முறை தவறான கடவுச்சொற்களை உள்ளிட்டீர்கள் என்பதைக் கண்காணிக்கும், பலமுறை தவறாக உள்ளிட்டிருந்தால் Android TVயைப் பூட்டும் அல்லது Android TVயின் அனைத்துத் தரவையும் அழிக்கும்."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"திரையை அன்லாக் செய்யும்போது உள்ளிடப்படும் தவறான கடவுச்சொற்களின் எண்ணிக்கையைக் கண்காணிக்கும். மேலும் கடவுச்சொற்கள் பலமுறை தவறாக உள்ளிடப்பட்டிருந்தால் இன்ஃபோடெயின்மென்ட் சிஸ்டமைப் பூட்டும் அல்லது அதன் அனைத்துத் தரவையும் அழிக்கும்."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"திரையைத் திறக்கும்போது உள்ளிட்ட தவறான கடவுச்சொற்களின் எண்ணிக்கையைக் கண்காணிக்கும், மேலும் கடவுச்சொற்கள் பலமுறை தவறாக உள்ளிட்டிருந்தால், மொபைலைப் பூட்டும் அல்லது மொபைலின் எல்லா தரவையும் அழிக்கும்."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"திரையைத் திறக்கும் போது, எத்தனை முறை தவறான கடவுச்சொல்லை உள்ளிட்டீர்கள் என்பதைக் கண்காணிக்கிறது மற்றும் கடவுச்சொற்களைப் பல முறை தவறாக உள்ளிட்டால், டேப்லெட்டைப் பூட்டும் அல்லது இந்தப் பயனரின் எல்லா தரவையும் அழிக்கும்."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"திரையைத் திறக்கும் போது எத்தனை முறை தவறான கடவுச்சொல்லை உள்ளிட்டீர்கள் என்பதைக் கண்காணிப்பதோடு கடவுச்சொற்களைப் பல முறை தவறாக உள்ளிட்டால் Android TVயைப் பூட்டும் அல்லது இந்தப் பயனரின் அனைத்துத் தரவையும் அழிக்கும்."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"திரையை அன்லாக் செய்யும்போது உள்ளிடப்படும் தவறான கடவுச்சொற்களின் எண்ணிக்கையைக் கண்காணிக்கும். மேலும் கடவுச்சொற்கள் பலமுறை தவறாக உள்ளிடப்பட்டிருந்தால் இன்ஃபோடெயின்மென்ட் சிஸ்டமைப் பூட்டும் அல்லது இந்தச் சுயவிவரத்தின் அனைத்துத் தரவையும் அழிக்கும்."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"திரையைத் திறக்கும் போது, எத்தனை முறை தவறான கடவுச்சொல்லை உள்ளிட்டீர்கள் என்பதைக் கண்காணிக்கிறது மற்றும் கடவுச்சொற்களைப் பல முறை தவறாக உள்ளிட்டால், ஃபோனைப் பூட்டும் அல்லது இந்தப் பயனரின் எல்லா தரவையும் அழிக்கும்."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"திரைப் பூட்டை மாற்றுதல்"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"திரைப் பூட்டை மாற்றும்."</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"எல்லா டேட்டாவையும் அழித்தல்"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"ஆரம்பநிலைத் தரவு மீட்டமைப்பின் மூலம் எச்சரிக்கை வழங்காமல் டேப்லெட்டின் தரவை அழிக்கலாம்."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"தரவின் ஆரம்பநிலைக்கு மீட்டமைப்பதன் மூலம் எச்சரிக்கை செய்யாமல் Android TVயின் தரவை அழிக்கும்."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"தரவின் ஆரம்பநிலை மீட்டமைப்பைச் செயல்படுத்துவதன் மூலம் எச்சரிக்கை எதுவுமின்றி இன்ஃபோடெயின்மென்ட் சிஸ்டமின் தரவை அழிக்கும்."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"ஆரம்பநிலைத் தரவு மீட்டமைப்பின் மூலம் எச்சரிக்கை வழங்காமல் மொபைலின் தரவை அழிக்கலாம்."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"பயனர் தரவை அழி"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"சுயவிவரத் தரவை அழித்தல்"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"பயனர் தரவை அழி"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"எச்சரிக்கை எதுவுமின்றி, டேப்லெட்டில் உள்ள இந்தப் பயனரின் தரவை அழிக்கும்."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"எச்சரிக்கை செய்யாமல் Android TVயில் உள்ள இந்தப் பயனரின் தரவை அழிக்கும்."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"எச்சரிக்கை எதுவுமின்றி இந்த இன்ஃபோடெயின்மென்ட் சிஸ்டத்திலுள்ள இந்தச் சுயவிவரத்தின் தரவை அழிக்கும்."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"எச்சரிக்கை எதுவுமின்றி, ஃபோனில் உள்ள இந்தப் பயனரின் தரவை அழிக்கும்."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"சாதன குளோபல் ப்ராக்ஸியை அமை"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"கொள்கை இயக்கப்பட்டிருக்கும்போது பயன்படுத்த வேண்டிய சாதன குளோபல் ப்ராக்ஸியை அமைக்கவும். சாதன உரிமையாளரால் மட்டுமே குளோபல் ப்ராக்ஸியை அமைக்க முடியும்."</string> diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml index 984eba3a5673..c3bfc1c3782b 100644 --- a/core/res/res/values-te/strings.xml +++ b/core/res/res/values-te/strings.xml @@ -546,7 +546,7 @@ <string name="permlab_nfc" msgid="1904455246837674977">"సమీప క్షేత్ర కమ్యూనికేషన్ను నియంత్రించడం"</string> <string name="permdesc_nfc" msgid="8352737680695296741">"సమీప ఫీల్డ్ కమ్యూనికేషన్ (NFC) ట్యాగ్లు, కార్డులు మరియు రీడర్లతో కమ్యూనికేట్ చేయడానికి యాప్ను అనుమతిస్తుంది."</string> <string name="permlab_disableKeyguard" msgid="3605253559020928505">"మీ స్క్రీన్ లాక్ను నిలిపివేయడం"</string> - <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"కీలాక్ మరియు ఏదైనా అనుబంధించబడిన పాస్వర్డ్ భద్రతను నిలిపివేయడానికి యాప్ను అనుమతిస్తుంది. ఉదాహరణకు, ఇన్కమింగ్ ఫోన్ కాల్ వస్తున్నప్పుడు ఫోన్ కీలాక్ను నిలిపివేస్తుంది, ఆపై కాల్ ముగిసిన తర్వాత కీలాక్ను మళ్లీ ప్రారంభిస్తుంది."</string> + <string name="permdesc_disableKeyguard" msgid="3223710003098573038">"కీలాక్ను, అలాగే ఏదైనా అనుబంధించబడిన పాస్వర్డ్ సెక్యూరిటీని డిజేబుల్ చేయడానికి యాప్ను అనుమతిస్తుంది. ఉదాహరణకు, ఇన్కమింగ్ ఫోన్ కాల్ వస్తున్నప్పుడు ఫోన్ కీలాక్ను డిజేబుల్ చేస్తుంది, ఆపై కాల్ ముగిసిన తర్వాత కీలాక్ను మళ్లీ ఎనేబుల్ చేస్తుంది."</string> <string name="permlab_requestPasswordComplexity" msgid="1808977190557794109">"స్క్రీన్ లాక్ సంక్లిష్టత రిక్వెస్ట్"</string> <string name="permdesc_requestPasswordComplexity" msgid="1130556896836258567">"ఇది మీ స్క్రీన్ లాక్ పాస్వర్డ్ సంక్లిష్టత స్థాయి (తీవ్రంగా ఉండాలా, ఓ మోస్తరుగా ఉండాలా, తక్కువ తీవ్రంగా ఉండాలా లేదా అస్సలు తీవ్రత ఉండకూడదా) తెలుసుకోవడానికి యాప్ను అనుమతిస్తుంది, అంటే పొడుగు ఎంత ఉండాలి, ఏ రకమైన స్క్రీన్ లాక్ పధ్ధతి అనుసరించాలో సూచిస్తుంది. అలాగే, స్క్రీన్ లాక్ పాస్వర్డ్ సంక్లిష్టతను ఏ స్థాయికి సెట్ చేసుకుంటే బాగుంటుందో కూడా వినియోగదారులకు యాప్ సూచించగలదు, కానీ వినియోగదారులు నిరభ్యంతరంగా ఆ సూచనలను పట్టించుకోకుండా వారి ఇష్టం మేరకు చక్కగా సెట్ చేసుకోవచ్చు. ఇంకో ముఖ్య విషయం, స్క్రీన్ లాక్ అన్నది సాదా వచన రూపంలో నిల్వ చేయబడదు, కనుక ఖచ్చితమైన పాస్వర్డ్ ఏమిటనేది యాప్కు తెలియదు."</string> <string name="permlab_useBiometric" msgid="6314741124749633786">"బయోమెట్రిక్ హార్డ్వేర్ని ఉపయోగించు"</string> @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"స్క్రీన్ అన్లాక్ ప్రయత్నాలను పర్యవేక్షించండి"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"టైప్ చేసిన చెల్లని పాస్వర్డ్ల సంఖ్యను పర్యవేక్షిస్తుంది. స్క్రీన్ను అన్లాక్ చేస్తున్నప్పుడు, అనేక సార్లు చెల్లని పాస్వర్డ్లను టైప్ చేస్తే టాబ్లెట్ లాక్ చేయబడుతుంది లేదా టాబ్లెట్లోని మొత్తం డేటా ఎరేజ్ చేయబడుతుంది."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"స్క్రీన్ను అన్లాక్ చేస్తున్నప్పుడు పాస్వర్డ్లను ఎన్నిసార్లు తప్పుగా టైప్ చేశారో పర్యవేక్షిస్తుంది, అలాగే చాలా ఎక్కువసార్లు పాస్వర్డ్లను తప్పుగా టైప్ చేసి ఉంటే మీ Android TV పరికరాన్ని లాక్ చేస్తుంది లేదా మీ Android TV డేటా మొత్తాన్ని తొలగిస్తుంది."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"స్క్రీన్ను అన్లాక్ చేస్తున్నప్పుడు, పాస్వర్డ్ను ఎన్నిసార్లు తప్పుగా టైప్ చేశారో పర్యవేక్షిస్తుంది. ఒకవేళ చాలా ఎక్కువ సార్లు పాస్వర్డ్ను తప్పుగా టైప్ చేసి ఉంటే, సమాచారంతో కూడిన వినోదం సిస్టమ్ను లాక్ చేస్తుంది లేదా సమాచారంతో కూడిన వినోదం సిస్టమ్ డేటాను తొలగించి ఫ్యాక్టరీ రీసెట్ చేస్తుంది."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"టైప్ చేసిన చెల్లని పాస్వర్డ్ల సంఖ్యను పర్యవేక్షిస్తుంది. స్క్రీన్ను అన్లాక్ చేస్తున్నప్పుడు, అనేక సార్లు చెల్లని పాస్వర్డ్లను టైప్ చేస్తే ఫోన్ లాక్ చేయబడుతుంది లేదా ఫోన్లోని మొత్తం డేటా ఎరేజ్ చేయబడుతుంది."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"స్క్రీన్ను అన్లాక్ చేస్తున్నప్పుడు పాస్వర్డ్ను ఎన్నిసార్లు తప్పుగా టైప్ చేశారో పర్యవేక్షిస్తుంది మరియు చాలా ఎక్కువసార్లు పాస్వర్డ్ను తప్పుగా టైప్ చేసి ఉంటే టాబ్లెట్ను లాక్ చేస్తుంది లేదా ఈ వినియోగదారు యొక్క మొత్తం డేటాను తీసివేస్తుంది."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"స్క్రీన్ను అన్లాక్ చేస్తున్నప్పుడు పాస్వర్డ్ను ఎన్నిసార్లు తప్పుగా టైప్ చేశారో పర్యవేక్షిస్తుంది, చాలా ఎక్కువసార్లు పాస్వర్డ్ను తప్పుగా టైప్ చేసి ఉంటే మీ Android TV పరికరాన్ని లాక్ చేస్తుంది లేదా ఈ వినియోగదారు యొక్క మొత్తం డేటాను తీసివేస్తుంది."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"స్క్రీన్ను అన్లాక్ చేస్తున్నప్పుడు పాస్వర్డ్ను ఎన్నిసార్లు తప్పుగా టైప్ చేశారో పర్యవేక్షిస్తుంది. ఒకవేళ చాలా ఎక్కువ సార్లు పాస్వర్డ్ను తప్పుగా టైప్ చేసి ఉంటే, సమాచారంతో కూడిన వినోదం సిస్టమ్ను లాక్ చేస్తుంది లేదా ఈ ప్రొఫైల్కు సంబంధించిన డేటాను తొలగించి ఫ్యాక్టరీ రీసెట్ చేస్తుంది."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"స్క్రీన్ను అన్లాక్ చేస్తున్నప్పుడు పాస్వర్డ్ను ఎన్నిసార్లు తప్పుగా టైప్ చేశారో పర్యవేక్షిస్తుంది మరియు చాలా ఎక్కువసార్లు పాస్వర్డ్ను తప్పుగా టైప్ చేసి ఉంటే ఫోన్ను లాక్ చేస్తుంది లేదా ఈ వినియోగదారు యొక్క మొత్తం డేటాను తీసివేస్తుంది."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"స్క్రీన్ లాక్ మార్చడానికి"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"స్క్రీన్ లాక్ని మారుస్తుంది."</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"మొత్తం డేటాను ఎరేజ్ చేయడానికి"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"ఫ్యాక్టరీ డేటా రీసెట్ను అమలు చేయడం ద్వారా హెచ్చరించకుండానే టాబ్లెట్ డేటాను ఎరేజ్ చేయండి."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"హెచ్చరించకుండానే మీ Android TV పరికరం డేటాను ఫ్యాక్టరీ డేటా రీసెట్ ద్వారా తొలగిస్తుంది."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"ఫ్యాక్టరీ డేటా రీసెట్ను అమలు చేయడం ద్వారా, హెచ్చరిక లేకుండానే సమాచారంతో కూడిన వినోదం సిస్టమ్ డేటాను తొలగించి ఫ్యాక్టరీ రీసెట్ చేయబడుతుంది."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"ఫ్యాక్టరీ డేటా రీసెట్ను అమలు చేయడం ద్వారా హెచ్చరించకుండానే ఫోన్ డేటాను ఎరేజ్ చేస్తుంది."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"వినియోగదారు డేటాను తీసివేయండి"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"ప్రొఫైల్ డేటాను తొలగించండి"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"వినియోగదారు డేటాను తీసివేయండి"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"హెచ్చరిక లేకుండానే ఈ టాబ్లెట్లో ఈ వినియోగదారు డేటాను తీసివేస్తుంది."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"హెచ్చరిక లేకుండానే ఈ Android TV పరికరంలో ఈ వినియోగదారు డేటాను తీసివేస్తుంది."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"హెచ్చరిక లేకుండానే ఈ సమాచారంతో కూడిన వినోదం సిస్టమ్లోని ఈ ప్రొఫైల్ డేటా తొలగించబడుతుంది."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"హెచ్చరిక లేకుండానే ఈ ఫోన్లో ఈ వినియోగదారు డేటాను తీసివేస్తుంది."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"పరికరం గ్లోబల్ ప్రాక్సీని సెట్ చేయండి"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"విధానాన్ని ప్రారంభించినప్పుడు ఉపయోగించడానికి పరికర గ్లోబల్ ప్రాక్సీని సెట్ చేస్తుంది. పరికర యజమాని మాత్రమే గ్లోబల్ ప్రాక్సీని సెట్ చేయగలరు."</string> @@ -1596,7 +1601,7 @@ <string name="data_usage_rapid_title" msgid="2950192123248740375">"అధిక మొబైల్ డేటా వినియోగం"</string> <string name="data_usage_rapid_body" msgid="3886676853263693432">"మీ యాప్లు సాధారణం కంటే ఎక్కువ డేటాని ఉపయోగించాయి"</string> <string name="data_usage_rapid_app_body" msgid="5425779218506513861">"<xliff:g id="APP">%s</xliff:g> సాధారణం కంటే ఎక్కువ డేటాని ఉపయోగించింది"</string> - <string name="ssl_certificate" msgid="5690020361307261997">"భద్రతా సర్టిఫికెట్"</string> + <string name="ssl_certificate" msgid="5690020361307261997">"సెక్యూరిటీ సర్టిఫికెట్"</string> <string name="ssl_certificate_is_valid" msgid="7293675884598527081">"ఈ సర్టిఫికెట్ చెల్లుబాటు అవుతుంది."</string> <string name="issued_to" msgid="5975877665505297662">"దీనికి జారీ చేయబడింది:"</string> <string name="common_name" msgid="1486334593631798443">"సాధారణ పేరు:"</string> diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml index 24725dea3227..c305ec889193 100644 --- a/core/res/res/values-th/strings.xml +++ b/core/res/res/values-th/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"ตรวจสอบความพยายามในการปลดล็อกหน้าจอ"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"ตรวจสอบจำนวนของรหัสผ่านที่พิมพ์ไม่ถูกต้องขณะปลดล็อกหน้าจอ และล็อกแท็บเล็ตหรือลบข้อมูลทั้งหมดในแท็บเล็ตถ้ามีการพิมพ์รหัสผ่านที่ไม่ถูกต้องมากเกินไป"</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"ตรวจสอบรหัสผ่านที่พิมพ์ไม่ถูกต้องเวลาปลดล็อกหน้าจอ และล็อกอุปกรณ์ Android TV หรือลบข้อมูลทั้งหมดของอุปกรณ์ Android TV หากมีการพิมพ์รหัสผ่านไม่ถูกต้องหลายครั้งเกินไป"</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"ตรวจสอบจำนวนครั้งที่พิมพ์รหัสผ่านไม่ถูกต้องเวลาปลดล็อกหน้าจอ และล็อกระบบสาระบันเทิงหรือลบข้อมูลทั้งหมดของระบบสาระบันเทิงหากพิมพ์รหัสผ่านไม่ถูกต้องบ่อยเกินไป"</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"ตรวจสอบจำนวนการพิมพ์รหัสผ่านที่ไม่ถูกต้องขณะปลดล็อกหน้าจอ และล็อกโทรศัพท์หรือลบข้อมูลทั้งหมดในโทรศัพท์ถ้ามีการพิมพ์รหัสผ่านที่ไม่ถูกต้องมากเกินไป"</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"ตรวจสอบจำนวนรหัสผ่านที่พิมพ์ไม่ถูกต้องเวลาปลดล็อกหน้าจอ และล็อกแท็บเล็ตหรือลบข้อมูลทั้งหมดของผู้ใช้นี้หากพิมพ์รหัสผ่านไม่ถูกต้องบ่อยเกินไป"</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"ตรวจสอบจำนวนรหัสผ่านที่พิมพ์ไม่ถูกต้องเวลาปลดล็อกหน้าจอ และล็อกอุปกรณ์ Android TV หรือลบข้อมูลทั้งหมดของผู้ใช้นี้หากพิมพ์รหัสผ่านไม่ถูกต้องหลายครั้งเกินไป"</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"ตรวจสอบจำนวนครั้งที่พิมพ์รหัสผ่านไม่ถูกต้องเวลาปลดล็อกหน้าจอ และล็อกระบบสาระบันเทิงหรือลบข้อมูลทั้งหมดของโปรไฟล์นี้หากพิมพ์รหัสผ่านไม่ถูกต้องบ่อยเกินไป"</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"ตรวจสอบจำนวนรหัสผ่านที่พิมพ์ไม่ถูกต้องเวลาปลดล็อกหน้าจอ และล็อกโทรศัพท์หรือลบข้อมูลทั้งหมดของผู้ใช้นี้หากพิมพ์รหัสผ่านไม่ถูกต้องบ่อยเกินไป"</string> <string name="policylab_resetPassword" msgid="214556238645096520">"เปลี่ยนการล็อกหน้าจอ"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"เปลี่ยนการล็อกหน้าจอ"</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"ลบข้อมูลทั้งหมด"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"ลบข้อมูลของแท็บเล็ตโดยไม่มีการเตือน ด้วยการดำเนินการรีเซ็ตข้อมูลเป็นค่าเริ่มต้น"</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"ลบข้อมูลของอุปกรณ์ Android TV โดยไม่มีการเตือนด้วยการรีเซ็ตข้อมูลเป็นค่าเริ่มต้น"</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"ดำเนินการรีเซ็ตข้อมูลเป็นค่าเริ่มต้นเพื่อลบข้อมูลของระบบสาระบันเทิงโดยไม่มีการเตือน"</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"ลบข้อมูลโทรศัพท์โดยไม่มีการเตือน ด้วยการรีเซ็ตข้อมูลเป็นค่าเริ่มต้น"</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"ลบข้อมูลผู้ใช้"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"ลบข้อมูลโปรไฟล์"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"ลบข้อมูลผู้ใช้"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"ลบข้อมูลของผู้ใช้นี้ในแท็บเล็ตเครื่องนี้โดยไม่มีการเตือน"</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"ลบข้อมูลของผู้ใช้นี้ในอุปกรณ์ Android TV เครื่องนี้โดยไม่มีการเตือน"</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"ลบข้อมูลของโปรไฟล์ดังกล่าวในระบบสาระบันเทิงนี้โดยไม่มีการเตือน"</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"ลบข้อมูลของผู้ใช้นี้ในโทรศัพท์เครื่องนี้โดยไม่มีการเตือน"</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"ตั้งค่าพร็อกซีส่วนกลางของอุปกรณ์"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"ตั้งค่าพร็อกซีส่วนกลางของอุปกรณ์ที่จะใช้ขณะที่เปิดใช้นโยบายอยู่ เฉพาะเจ้าของอุปกรณ์เท่านั้นที่สามารถตั้งค่าพร็อกซีส่วนกลาง"</string> diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml index c85977a86062..8f225a795413 100644 --- a/core/res/res/values-tl/strings.xml +++ b/core/res/res/values-tl/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"Subaybayan ang mga pagsubok sa pag-unlock ng screen"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Subaybayan ang bilang ng mga hindi tamang password na na-type kapag ina-unlock ang screen, at i-lock ang tablet o burahin ang lahat ng data ng tablet kung masyadong maraming hindi tamang password ang na-type."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Subaybayan ang dami ng mga maling password na na-type kapag ina-unlock ang screen, at i-lock ang Android TV device o burahin ang lahat ng data ng Android TV device kung masyadong maraming maling password ang na-type."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Subaybayan ang bilang ng mga maling password kapag ina-unlock ang screen, at i-lock ang infotainment system o burahin ang lahat ng data ng infotainment system kung masyadong maraming maling password ang nata-type."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Subaybayan ang bilang ng mga maling password na na-type kapag ina-unlock ang screen, at i-lock ang telepono o burahin ang lahat ng data ng telepono kung masyadong maraming maling password ang na-type."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Subaybayan ang bilang ng mga maling password na na-type kapag ina-unlock ang screen, at i-lock ang tablet o burahin ang lahat ng data ng user na ito kung masyadong maraming maling password ang nata-type."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Subaybayan ang dami ng mga maling password na na-type kapag ina-unlock ang screen, at i-lock ang iyong Android TV device o burahin ang lahat ng data ng user na ito kung masyadong maraming maling password ang na-type."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Subaybayan ang bilang ng mga maling password na na-type kapag ina-unlock ang screen, at i-lock ang infotainment system o burahin ang lahat ng data ng profile na ito kung masyadong maraming maling password ang nata-type."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Subaybayan ang bilang ng mga maling password na na-type kapag ina-unlock ang screen, at i-lock ang telepono o burahin ang lahat ng data ng user na ito kung masyadong maraming maling password ang nata-type."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"Palitan ang screen lock"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"Palitan ang screen lock."</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"Burahin ang lahat ng data"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Burahin ang data ng tablet nang walang babala sa pamamagitan ng pagsasagawa ng pag-reset ng factory data."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Burahin ang data ng iyong Android TV device nang walang babala sa pamamagitan ng pagsasagawa ng pag-reset ng factory data."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Burahin ang data ng infotainment system nang walang babala sa pamamagitan ng pagsasagawa ng pag-reset ng factory data."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Burahin ang data ng telepono nang walang babala sa pamamagitan ng pagsasagawa ng pag-reset ng factory data."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"Burahin ang data ng user"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Burahin ang data ng profile"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Burahin ang data ng user"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Burahin ang data ng user na ito sa tablet na ito nang walang babala."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Burahin ang data ng user na ito sa Android TV device na ito nang walang babala."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"Burahin ang data ng profile na ito sa infotainment system na ito nang walang babala."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"Burahin ang data ng user na ito sa teleponong ito nang walang babala."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Itakda ang pandaigdigang proxy ng device"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Itakda ang pandaigdigang proxy ng device na gagamitin habang naka-enable ang patakaran. Ang may-ari ng device lang ang makakapagtakda sa pandaigdigang proxy."</string> diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml index c85b7f650252..09a20471c028 100644 --- a/core/res/res/values-tr/strings.xml +++ b/core/res/res/values-tr/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"Ekran kilidini açma denemelerini izle"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Ekran kilidini açarken yapılan yanlış şifre girme denemelerini izler ve çok fazla sayıda yanlış şifre girme denemesi yapılmışsa tableti kilitler veya tabletteki tüm verileri siler."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Ekran kilidi açılırken girilen hatalı şifre sayısını takip eder ve çok fazla sayıda hatalı şifre girildiğinde Android TV cihazınızı kilitler veya Android TV cihazınızın tüm verilerini siler."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Ekran kilidi açılırken girilen hatalı şifre sayısı takip edilir ve çok fazla sayıda hatalı şifre girildiğinde bilgi-eğlence sistemi kilitlenir ya da bilgi-eğlence sistemindeki tüm veriler silinir."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Ekran kilidini açarken yapılan yanlış şifre girişi denemelerini izler ve çok sayıda yanlış şifre girişi denemesi yapılmışsa telefonu kilitler veya telefonun tüm verilerini siler."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Ekran kilidi açılırken girilen hatalı şifre sayısını takip edin ve çok fazla sayıda hatalı şifre girildiğinde tableti kilitleyin veya söz konusu kullanıcının tüm verilerini silin."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Ekran kilidi açılırken girilen hatalı şifre sayısını takip edin ve çok fazla sayıda hatalı şifre girildiğinde Android TV cihazınızı kilitleyin veya söz konusu kullanıcının tüm verilerini silin."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Ekran kilidi açılırken girilen hatalı şifre sayısı takip edilir ve çok fazla sayıda hatalı şifre girildiğinde tablet kilitlenir veya söz konusu kullanıcının tüm verileri silinir."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Ekran kilidi açılırken girilen hatalı şifre sayısını takip edin ve çok fazla sayıda hatalı şifre girildiğinde telefonu kilitleyin veya söz konusu kullanıcının tüm verilerini silin."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"Ekran kilidini değiştirme"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"Ekran kilidini değiştirir."</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"Tüm verileri silme"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Fabrika verilerine sıfırlama işlemi gerçekleştirerek tabletteki verileri uyarıda bulunmadan siler."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Fabrika verilerine sıfırlama işlemi gerçekleştirerek Android TV cihazınızdaki verileri uyarıda bulunmadan siler."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Fabrika verilerine sıfırlama işlemi gerçekleştirerek bilgi-eğlence sistemindeki veriler uyarıda bulunmadan silinir."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Fabrika verilerine sıfırlama işlemi gerçekleştirerek telefondaki verileri uyarıda bulunmadan siler."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"Kullanıcı verilerini sil"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Profil verilerini silme"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Kullanıcı verilerini sil"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Uyarı yapmadan bu kullanıcının bu tabletteki verilerini silin."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Uyarı yapmadan bu kullanıcının bu Android TV cihazındaki verilerini siler."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"Bu bilgi-eğlence sistemindeki bu profilin verileri uyarıda bulunmadan silinir."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"Uyarı yapmadan bu kullanıcının bu telefondaki verilerini siler."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Cihaz genelinde geçerli proxy\'i ayarla"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Politika etkin olduğunda kullanılacak cihaz genelinde geçerli proxy\'yi ayarlar. Genel proxy\'yi yalnızca cihaz sahibi ayarlayabilir."</string> diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml index 8ff65f1b23c4..5f936ed8a85f 100644 --- a/core/res/res/values-uk/strings.xml +++ b/core/res/res/values-uk/strings.xml @@ -735,9 +735,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"Відстежувати спроби розблокування екрана"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Відстежувати кількість неправильних паролів, введених під час розблокування екрана, і блокувати планшетний ПК або стирати всі його дані, якщо введено забагато неправильних паролів."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Відстежуйте кількість неправильних паролів, введених під час розблокування екрана. Блокуйте пристрій Android TV або стирайте всі його дані, якщо пароль введено неправильно забагато разів."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Відстежуйте кількість неправильних паролів, введених під час розблокування екрана, і блокуйте інформаційно-розважальну систему або видаляйте всі її дані, якщо пароль введено неправильно забагато разів."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Відстежувати кількість неправильних паролів, введених під час розблокування екрана, і блокувати телефон або стирати всі його дані, якщо введено забагато неправильних паролів."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Відстежуйте кількість неправильних паролів, введених під час розблокування екрана. Блокуйте планшет або стирайте всі його дані, якщо пароль введено неправильно забагато разів."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Відстежуйте кількість неправильних паролів, введених під час розблокування екрана. Блокуйте пристрій Android TV або стирайте всі дані користувача, якщо пароль введено неправильно забагато разів."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Відстежуйте кількість неправильних паролів, введених під час розблокування екрана, і блокуйте інформаційно-розважальну систему або видаляйте всі дані цього профілю, якщо пароль введено неправильно забагато разів."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Відстежуйте кількість неправильних паролів, введених під час розблокування екрана. Блокуйте телефон або стирайте всі його дані, якщо пароль введено неправильно забагато разів."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"Змінити спосіб розблокування екрана"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"Змінити спосіб розблокування екрана."</string> @@ -746,10 +748,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"Видалити всі дані"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Стирати дані планшетного ПК без попередження, відновлюючи заводські налаштування."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Видаляйте дані пристрою Android TV без попередження шляхом відновлення заводських налаштувань."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Видаляйте всі дані інформаційно-розважальної системи без попередження, відновлюючи заводські налаштування."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Стирати дані телефона без попередження, відновивши заводські налаштування."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"Видалення даних користувача"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Видалити всі дані профілю"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Видалення даних користувача"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Видаляйте дані користувача на цьому планшеті без попередження."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Видаляйте дані користувача на цьому пристрої Android TV без попередження."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"Видаляйте всі дані цієї інформаційно-розважальної системи без попередження."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"Видаляйте дані користувача на цьому телефоні без попередження."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Установ. глоб. проксі пристрою"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Використовуйте глобальний проксі-сервер пристрою, коли це правило ввімкнено. Налаштувати глобальний проксі-сервер може лише власник пристрою."</string> diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml index a189441bbe4f..8d9e20d36951 100644 --- a/core/res/res/values-ur/strings.xml +++ b/core/res/res/values-ur/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"اسکرین غیر مقفل کرنے کی کوششیں مانیٹر کریں"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"اسکرین کو غیر مقفل کرتے وقت ٹائپ کیے گئے غلط پاس ورڈز کی تعداد مانیٹر کریں اور ٹیبلیٹ کو مقفل کریں یا اگر کافی زیادہ غلط پاس ورڈز ٹائپ کیے گئے ہیں تو ٹیبلیٹ کا سبھی ڈیٹا صاف کریں۔"</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"اسکرین کو غیر مقفل کرتے وقت ٹائپ کردہ غلط پاس ورڈز کی تعداد پر نگاہ رکھیں اور اگر بہت زیادہ غلط پاسورڈز ٹائپ کیے جاتے ہیں تو اپنے Android TV آلہ کو مقفل کردیں یا اپنے Android TV آلہ کے ڈیٹا کو مٹادیں۔"</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"اسکرین کو غیر مقفل کرتے وقت ٹائپ کیے گئے غلط پاس ورڈز کی تعداد مانیٹر کریں۔ اور معلوماتی انٹرٹینمنٹ سسٹم کو مقفل کریں یا اگر کافی زیادہ غلط پاس ورڈز ٹائپ کیے گئے ہیں تو معلوماتی انٹرٹینمنٹ سسٹم کا سبھی ڈیٹا صاف کریں۔"</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"اسکرین کو غیر مقفل کرتے وقت ٹائپ کیے گئے غلط پاس ورڈز کی تعداد مانیٹر کریں اور فون کو مقفل کریں یا اگر کافی زیادہ غلط پاس ورڈز ٹائپ کیے گئے ہیں تو فون کا سبھی ڈیٹا صاف کریں۔"</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"اسکرین کو غیر مقفل کرتے وقت ٹائپ کردہ غلط پاس ورڈز کی تعداد پر نگاہ رکھیں اور اگر بہت زیادہ غلط پاس ورڈز ٹائپ کیے جاتے ہیں تو ٹیبلٹ کو مقفل کریں یا اس صارف کا سبھی ڈیٹا ہٹائیں۔"</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"اسکرین کو غیر مقفل کرتے وقت ٹائپ کردہ غلط پاس ورڈز کی تعداد پر نگاہ رکھیں اور اگر بہت زیادہ غلط پاس ورڈز ٹائپ کیے جاتے ہیں تو اپنے Android TV آلہ کو مقفل کریں یا اس صارف کا سبھی ڈیٹا ہٹائیں۔"</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"اسکرین کو غیر مقفل کرتے وقت ٹائپ کردہ غلط پاس ورڈز کی تعداد مانیٹر کریں اور معلوماتی انٹرٹینمنٹ سسٹم کو مقفل کریں اگر بہت زیادہ غلط پاس ورڈز ٹائپ کیے جاتے ہیں تو اس پروفائل کا سبھی ڈیٹا ہٹائیں۔"</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"اسکرین کو غیر مقفل کرتے وقت ٹائپ کردہ غلط پاس ورڈز کی تعداد پر نگاہ رکھیں اور اگر بہت زیادہ غلط پاس ورڈز ٹائپ کیے جاتے ہیں تو فون کو مقفل کریں یا اس صارف کا سبھی ڈیٹا ہٹائیں۔"</string> <string name="policylab_resetPassword" msgid="214556238645096520">"اسکرین لاک تبدیل کریں"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"اسکرین لاک تبدیل کریں۔"</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"سبھی ڈیٹا صاف کریں"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"فیکٹری ڈیٹا ری سیٹ انجام دے کر وارننگ کے بغیر ٹیبلٹ کا ڈیٹا مٹائیں۔"</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"فیکٹری ڈیٹا ری سیٹ کو انجام دے کر انتباہ کیے بغیر اپنے Android TV آلہ کا ڈیٹا مٹائیں۔"</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"فیکٹری ڈیٹا ری سیٹ کو انجام دے کر وارننگ کے بغیر معلوماتی انٹرٹینمنٹ سسٹم کا ڈیٹا صاف کریں۔"</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"فیکٹری ڈیٹا ری سیٹ انجام دے کر وارننگ کے بغیر فون کا ڈیٹا مٹائیں۔"</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"صارف کا ڈیٹا ہٹائیں"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"پروفائل ڈیٹا صاف کریں"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"صارف کا ڈیٹا ہٹائیں"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"وارننگ کے بغیر اس ٹیبلٹ پر موجود اس صارف کا ڈیٹا ہٹائیں۔"</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"انتباہ کے بغیر اس Android TV آلہ پر اس صارف کا ڈیٹا ہٹائیں۔"</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"وارننگ کے بغیر اس معلوماتی انٹرٹینمنٹ سسٹم پر اس پروفائل کا ڈیٹا صاف کریں۔"</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"وارننگ کے بغیر اس فون پر موجود اس صارف کا ڈیٹا ہٹائیں۔"</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"آلہ کی عالمی پراکسی سیٹ کریں"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"پالیسی فعال ہونے پر آلہ کی عالمی پراکسی کو استعمال کیے جانے کیلئے سیٹ کریں۔ صرف آلہ کا مالک ہی عالمی پراکسی سیٹ کر سکتا ہے۔"</string> diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml index 624cf74c30b7..23ab24e0d296 100644 --- a/core/res/res/values-uz/strings.xml +++ b/core/res/res/values-uz/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"Ekranni qulfdan chiqarishga urinishlarni nazorat qilish"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Ekranni qulfini ochishda parolni kiritishga urinishlarni kuzatib boradi va agar parol bir necha marta noto‘g‘ri kiritilsa, planshetni qulflaydi yoki undagi ma’lumotlarni o‘chirib tashlaydi."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Ekran qulfini ochishda kiritilgan xato parollar sonini kuzatib boradi va agar parol juda koʻp marta xato kiritilsa, Android TV qurilmasini qulflaydi yoki undagi barcha maʼlumotlarni oʻchirib tashlaydi."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Ekranni qulfini ochishda parolni kiritishga urinishlarni kuzatib boradi va agar parol bir necha marta xato kiritilsa, axborot-hordiq tizimini qulflaydi yoki undagi maʼlumotlarni oʻchirib tashlaydi."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Ekranni qulfini ochishda parolni kiritishga urinishlarni kuzatib boradi va agar parol bir necha marta noto‘g‘ri kiritilsa, telefonni qulflaydi yoki undagi ma’lumotlarni o‘chirib tashlaydi."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Ekran qulfini ochishda kiritilgan noto‘g‘ri parollar sonini kuzatib boradi va agar parol juda ko‘p marta noto‘g‘ri kiritilsa, planshetni qulflaydi yoki undagi barcha ma’lumotlarni o‘chirib tashlaydi."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Ekran qulfini ochishda kiritilgan xato parollar sonini kuzatib boradi va agar parol juda koʻp marta xato kiritilsa, Android TV qurilmangizni qulflaydi yoki undagi barcha maʼlumotlarni oʻchirib tashlaydi."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Ekran qulfini ochishda parolni kiritishga urinishlarni kuzatib boradi va agar parol bir necha marta xato kiritilsa, axborot-hordiq tizimini qulflaydi yoki undagi barcha profil maʼlumotlarini oʻchirib tashlaydi."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Ekran qulfini ochishda kiritilgan noto‘g‘ri parollar sonini kuzatib boradi va agar parol juda ko‘p marta noto‘g‘ri kiritilsa, telefonni qulflaydi yoki undagi barcha ma’lumotlarni o‘chirib tashlaydi."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"Ekran qulfini almashtirish"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"Ekran qulfini almashtiradi."</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"Hamma narsani tozalash"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Planshetdagi hamma narsani tozalab tashlaydi va uning sozlamalarini asliga qaytaradi."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Android TV qurilmangizdagi hamma narsani tozalab tashlaydi va uning sozlamalarini asliga qaytaradi."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Zavod sozlamalarini qayta tiklash orqali axbirot-hordiq tizimi maʼlumotlarini ogohlantirishsiz oʻchirib tashlansin."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Telefondagi hamma narsani tozalab tashlaydi va uning sozlamalarini asliga qaytaradi."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"Foydalanuvchi ma’lumotlarini o‘chirish"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Profil maʼlumotlarini tozalash"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Foydalanuvchi ma’lumotlarini o‘chirish"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Ushbu planshetdagi foydalanuvchi ma’lumotlarini ogohlantirishsiz o‘chirib tashlaydi."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Bu Android TV qurilmangizdagi foydalanuvchi maʼlumotlarini ogohlantirishsiz oʻchirib tashlaydi."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"Bu profil maʼlumotlari ogohlantirishsiz oʻchirib tashlansin."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"Ushbu telefondagi foydalanuvchi ma’lumotlarini ogohlantirishsiz o‘chirib tashlaydi."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Qurilmaga global proksi o‘rnatish"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Qoida faollashtirilgan vaqtda ishlatiladigan qurilmaning global proksi-serverini o‘rnatadi. Faqat qurilma egasi global proksi-serverini o‘rnatishi mumkin."</string> diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml index 4ae1a17d9922..f360991c6af5 100644 --- a/core/res/res/values-vi/strings.xml +++ b/core/res/res/values-vi/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"Giám sát những lần thử mở khóa màn hình"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Theo dõi số lần nhập mật khẩu không chính xác khi mở khóa màn hình và khóa máy tính bảng hoặc xóa tất cả dữ liệu của máy tính bảng nếu có quá nhiều lần nhập mật khẩu không chính xác."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Giám sát số lần nhập mật khẩu không chính xác khi mở khóa màn hình, đồng thời khóa thiết bị Android TV hoặc xóa tất cả dữ liệu trên thiết bị Android TV nếu bạn nhập mật khẩu sai quá nhiều lần."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Theo dõi số lần nhập sai mật khẩu khi mở khoá màn hình và khoá hệ thống thông tin giải trí hoặc xoá tất cả dữ liệu của hệ thống này nếu có quá nhiều lần nhập sai mật khẩu."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Theo dõi số lần nhập mật khẩu không chính xác khi mở khóa màn hình và khóa điện thoại hoặc xóa tất cả dữ liệu của điện thoại nếu có quá nhiều lần nhập mật khẩu không chính xác."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Giám sát số lần nhập sai mật khẩu khi mở khóa màn hình và khóa máy tính bảng hoặc xóa tất cả dữ liệu của người dùng này nếu nhập sai mật khẩu quá nhiều lần."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Giám sát số lần nhập mật khẩu không chính xác khi mở khóa màn hình, đồng thời khóa thiết bị Android TV hoặc xóa tất cả dữ liệu của người dùng này nếu bạn nhập mật khẩu sai quá nhiều lần."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Theo dõi số lần nhập sai mật khẩu khi mở khoá màn hình và khoá hệ thống thông tin giải trí hoặc xoá tất cả dữ liệu của hồ sơ này nếu có quá nhiều lần nhập sai mật khẩu."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Giám sát số lần nhập sai mật khẩu khi mở khóa màn hình và khóa điện thoại hoặc xóa tất cả dữ liệu của người dùng này nếu nhập sai mật khẩu quá nhiều lần."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"Thay đổi phương thức khóa màn hình"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"Thay đổi phương thức khóa màn hình."</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"Xóa tất cả dữ liệu"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Xóa dữ liệu trên máy tính bảng mà không cần cảnh báo, bằng cách thực hiện thiết lập lại dữ liệu ban đầu."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Xóa dữ liệu trên thiết bị Android TV mà không cảnh báo bằng cách thiết lập lại dữ liệu ban đầu."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Xoá dữ liệu của hệ thống thông tin giải trí mà không cảnh báo bằng cách đặt lại dữ liệu về trạng thái ban đầu."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Xóa dữ liệu trên điện thoại mà không cần cảnh báo, bằng cách thiết lập lại dữ liệu ban đầu."</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"Xóa dữ liệu người dùng"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Xoá dữ liệu hồ sơ"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Xóa dữ liệu người dùng"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Xóa dữ liệu của người dùng trên máy tính bảng này mà không cảnh báo."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Xóa dữ liệu của người dùng này trên thiết bị Android TV mà không cảnh báo."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"Xoá dữ liệu của hồ sơ này trên hệ thống thông tin giải trí này mà không cảnh báo."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"Xóa dữ liệu của người dùng trên điện thoại này mà không cảnh báo."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Đặt proxy chung của điện thoại"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Đặt proxy chung của thiết bị được sử dụng trong khi chính sách bật. Chỉ chủ sở hữu thiết bị mới có thể đặt proxy chung."</string> diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml index d8707640717c..76a61594678c 100644 --- a/core/res/res/values-zh-rCN/strings.xml +++ b/core/res/res/values-zh-rCN/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"监控屏幕解锁尝试次数"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"监视在解锁屏幕时输错密码的次数,如果输错次数过多,则锁定平板电脑或清除其所有数据。"</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"监控用户在解锁屏幕时输错密码的次数;如果用户输错密码的次数超出上限,系统就会锁定 Android TV 设备或清空 Android TV 设备上的所有数据。"</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"监控在解锁屏幕时输错密码的次数,并在输错次数过多时锁定信息娱乐系统或清除信息娱乐系统上的所有数据。"</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"监视在解锁屏幕时输错密码的次数,如果输错次数过多,则锁定手机或清除其所有数据。"</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"监控在解锁屏幕时输错密码的次数,并在输错次数过多时锁定平板电脑或清空此用户的所有数据。"</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"监控用户在解锁屏幕时输错密码的次数;如果用户输错密码的次数超出上限,系统就会锁定 Android TV 设备或清空该用户的所有数据。"</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"监控在解锁屏幕时输错密码的次数,并在输错次数过多时锁定信息娱乐系统或清除此个人资料的所有数据。"</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"监控在解锁屏幕时输错密码的次数,并在输错次数过多时锁定手机或清空此用户的所有数据。"</string> <string name="policylab_resetPassword" msgid="214556238645096520">"更改锁屏方式"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"更改锁屏方式。"</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"清除所有数据"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"恢复出厂设置时,系统会在不发出警告的情况下清除平板电脑上的数据。"</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"不事先发出警告就以恢复出厂设置的方式清空 Android TV 设备中的数据。"</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"在不发出警告的情况下,通过恢复出厂设置来清除信息娱乐系统上的数据。"</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"恢复出厂设置时,系统会在不发出警告的情况下清除手机上的数据。"</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"清空用户数据"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"清除个人资料数据"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"清空用户数据"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"清空此用户在这台平板电脑上的数据,而不事先发出警告。"</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"不事先发出警告就清空此用户在这台 Android TV 设备上的数据。"</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"在不发出警告的情况下,从该信息娱乐系统中清除此个人资料的所有数据。"</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"清空此用户在这部手机上的数据,而不事先发出警告。"</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"设置设备全局代理"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"设置在规范启用时要使用的设备全局代理。只有设备所有者才能设置全局代理。"</string> diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml index deae9a380dc6..32ccfb02e57f 100644 --- a/core/res/res/values-zh-rHK/strings.xml +++ b/core/res/res/values-zh-rHK/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"監控螢幕解鎖嘗試次數"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"監視為螢幕解鎖時輸入錯誤密碼的次數;如果輸入錯誤密碼的次數過多,則會鎖定平板電腦或清除平板電腦的所有資料。"</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"監察螢幕解鎖時錯誤輸入密碼的次數,並在錯誤輸入密碼的次數過多時,將 Android TV 裝置上鎖或清除裝置上的所有資料。"</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"監察螢幕解鎖時錯誤輸入密碼的次數,如果錯誤輸入密碼的次數過多,即鎖定資訊娛樂系統或清除資訊娛樂系統中的所有資料。"</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"監視為螢幕解鎖時輸入錯誤密碼的次數,如果輸入錯誤密碼的次數過多,則會鎖定手機或清除手機的所有資料。"</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"監察螢幕解鎖時錯誤輸入密碼的次數,如果錯誤輸入密碼的次數過多,即鎖定平板電腦或清除這個使用者的資料。"</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"監察螢幕解鎖密碼輸入錯誤的次數,並在密碼輸入錯誤的次數超出上限時將 Android TV 裝置上鎖,或清除該使用者的所有資料。"</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"監察螢幕解鎖時錯誤輸入密碼的次數,如果錯誤輸入密碼的次數過多,即鎖定資訊娛樂系統或清除這個設定檔的所有資料。"</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"監察螢幕解鎖時錯誤輸入密碼的次數,如果錯誤輸入密碼的次數過多,即鎖定手機或清除這個使用者的資料。"</string> <string name="policylab_resetPassword" msgid="214556238645096520">"變更螢幕鎖定"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"變更螢幕鎖定。"</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"清除所有資料"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"重設平板電腦為原廠設定,在不提出警告的情況下直接清除平板電腦的資料。"</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"系統可將 Android TV 裝置回復原廠設定,在沒有警告的情況下清除裝置的資料。"</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"回復資訊娛樂系統為原廠設定,在不提出警告的情況下直接清除資訊娛樂系統的資料。"</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"重設手機為原廠設定,在不提出警告的情況下直接清除手機的資料。"</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"清除使用者資料"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"清除個人檔案資料"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"清除使用者資料"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"清除這個使用者在這部平板電腦上的資料而不作警告。"</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"在沒有警告的情況下,清除這位使用者在此 Android TV 裝置上的資料。"</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"在不提出警告的情況下直接清除此設定檔在資訊娛樂系統上的資料。"</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"清除這個使用者在這部手機上的資料而不作警告。"</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"設定裝置的全域代理伺服器"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"設定政策啟用時所要使用的裝置全域代理伺服器,只有裝置擁有者可以設定全域代理伺服器。"</string> diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml index f621a67a1bf1..54d3d2eae454 100644 --- a/core/res/res/values-zh-rTW/strings.xml +++ b/core/res/res/values-zh-rTW/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"監控螢幕解鎖嘗試次數"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"監控螢幕解鎖時密碼輸入錯誤的次數;如果密碼輸入錯誤的次數過多,則會鎖住平板電腦或全部清除平板電腦中的資料。"</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"監控螢幕解鎖密碼輸入錯誤的次數。如果輸入錯誤的次數超過上限,系統會將 Android TV 裝置鎖定,或清除 Android TV 裝置的所有資料。"</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"監控密碼輸入錯誤的次數。解鎖螢幕時,如果密碼輸入錯誤次數過多,系統就會鎖住資訊娛樂系統或清除資訊娛樂系統的所有資料。"</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"監控螢幕解鎖時密碼輸入錯誤的次數;如果密碼輸入錯誤的次數過多,則會鎖住手機或清除手機的所有資料。"</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"監控螢幕解鎖密碼輸入錯誤的次數;如果輸入錯誤的次數超過上限,系統會將平板電腦鎖定,或將這個使用者的資料全部清除。"</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"監控螢幕解鎖密碼輸入錯誤的次數。如果輸入錯誤的次數超過上限,系統會將 Android TV 裝置鎖定,或清除這位使用者的所有資料。"</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"監控螢幕解鎖時的密碼輸入錯誤次數。如果錯誤次數過多,系統就會鎖住資訊娛樂系統或清除這個設定檔的所有資料。"</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"監控螢幕解鎖密碼輸入錯誤的次數;如果輸入錯誤的次數超過上限,系統會將手機鎖定,或將這個使用者的資料全部清除。"</string> <string name="policylab_resetPassword" msgid="214556238645096520">"變更鎖定螢幕方式"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"變更鎖定螢幕方式。"</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"清除所有資料"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"恢復原廠設定,不提出警告就直接清除平板電腦的資料。"</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"在沒有事先警告的情況下讓系統恢復原廠設定,清除 Android TV 裝置上的資料。"</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"不事先警告就透過恢復原廠設定的方式清除資訊娛樂系統的資料。"</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"恢復原廠設定,不提出警告就直接清除手機的資料。"</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"清除使用者資料"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"清除設定檔資料"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"清除使用者資料"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"將這個使用者的資料從這台平板電腦中清除,而不事先發出警告。"</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"在沒有事先警告的情況下,將這位使用者的資料從這部 Android TV 裝置中清除。"</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"不事先警告就從這個資訊娛樂系統上清除這個設定檔的資料。"</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"將這個使用者的資料從這支手機中清除,而不事先發出警告。"</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"設定裝置全域 Proxy"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"設定政策啟用時要使用的裝置全域 Proxy。只有裝置擁有者可以設定全域 Proxy。"</string> diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml index a193ef0e5cff..e1576d8ab3a3 100644 --- a/core/res/res/values-zu/strings.xml +++ b/core/res/res/values-zu/strings.xml @@ -729,9 +729,11 @@ <string name="policylab_watchLogin" msgid="7599669460083719504">"Qapha imizamo yokuvula isikrini sakho"</string> <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Bheka inani lamaphasiwedi angafanele athayishiwe uma kuvulwa iskrini bese kuvalwa ithebhulethi noma kususwe yonke idatha yethebhulethi uma kubhalwe amaphasiwedi amaningi angalungile."</string> <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Ngamela inombolo yamaphasiwedi angalungile athayiphiwe uma kuvulwa isikrini, nokukhiya idivayisi yakho ye-Android TV noma ukususa yonke idatha yedivayisi yakho ye-Android TV uma amaphasiwedi amaningi angalungile athayiphiwe."</string> + <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Qaphela inombolo yamaphasiwedi angalungile athayiphiwe uma kuvulwa isikrini, uphinde ukhiye isistimu ye-infotainment noma usule yonke idatha yesistimu ye-infotainment uma ngabe kuthayiphwa amaphasiwedi amaningi angalungile."</string> <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Bheka isibalo samaphasiwedi ngalungile afakiwe uma uvula iskrini bese uvala ucingo noma ususe yonke imininingwane yocingo uma kubhalwe amaphasiwedi amaningi angalungile."</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Qaphela inombolo yamaphasiwedi angalungile athayiphwe uma kuvulwa isikrini, uphinde ukhiye ithebulethi noma usule yonke idatha yalo msebenzisi uma ngabe kuthayiphwe amaphasiwedi amaningi kakhulu angalungile."</string> <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Qaphela inombolo yamaphasiwedi angalungile athayiphiwe uma kuvulwa isikrini, uphinde ukhiye idivayisi yakho ye-Android TV noma usule yonke idatha yalo msebenzisi uma ngabe kuthayiphwe amaphasiwedi amaningi kakhulu angalungile."</string> + <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Qaphela inombolo yamaphasiwedi angalungile athayiphwe uma kuvulwa isikrini, uphinde ukhiye isistimu ye-infotainment noma usule yonke idatha yaleli phrofayela uma kuthayiphwe amaphasiwedi amaningi kakhulu angalungile."</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Qaphela inombolo yamaphasiwedi angalungile athayiphiwe uma kuvulwa isikrini, uphinde ukhiye ifoni noma usule yonke idatha yalo msebenzisi uma ngabe kuthayiphwe amaphasiwedi amaningi kakhulu angalungile."</string> <string name="policylab_resetPassword" msgid="214556238645096520">"Guqula ukukhiya isikrini"</string> <string name="policydesc_resetPassword" msgid="4626419138439341851">"Guqula ukukhiya isikrini."</string> @@ -740,10 +742,13 @@ <string name="policylab_wipeData" msgid="1359485247727537311">"Sula yonke idatha"</string> <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Sula idatha yethebhulethi ngaphandle kwesaziso, ngokwenza ukusetha kabusha kwemboni."</string> <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Sula idatha yakho yedivayisi ye-Android TV ngaphandle kokuxwayisa ngokwenza ukusetha kwedatha kwefekthri."</string> + <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Sula idatha isistimu ye-infotainment ngaphandle kokuxwayisa ngokwenza ukusetha kabusha kwasekuqaleni kwedatha."</string> <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Sula idatha yefoni ngaphandle kwesixwayiso, ngokwenza ukuhlela kabusha idatha yemboni"</string> - <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"Sula idatha yomsebenzisi"</string> + <string name="policylab_wipeData_secondaryUser" product="automotive" msgid="115034358520328373">"Sula idatha yephrofayela"</string> + <string name="policylab_wipeData_secondaryUser" product="default" msgid="413813645323433166">"Sula idatha yomsebenzisi"</string> <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"Sula idatha yalo msebenzisi kule thebulethi ngaphandle kwesexwayiso."</string> <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2293713284515865200">"Sula le datha yomsebenzisi kule divayisi ye-Android TV ngaphandle kwesexwayiso."</string> + <string name="policydesc_wipeData_secondaryUser" product="automotive" msgid="4658832487305780879">"Sula idatha yale phrofayela kule sistimu ye-infotainment ngaphandle kwesixwayiso."</string> <string name="policydesc_wipeData_secondaryUser" product="default" msgid="2788325512167208654">"Sula idatha yalo msebenzisi kule foni ngaphandle kwesexwayiso."</string> <string name="policylab_setGlobalProxy" msgid="215332221188670221">"Misa ummelelii jikelele yedivaysi"</string> <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"Setha ummeleli womhlaba wonke wedivayisi ozosetshenziswa ngenkathi inqubomgomo inikwe amandla. Ngumnikazi wedivayisi kuphela ongasetha ummeleli womhlaba wonke."</string> diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java index df0c64c810c6..9f48c06da385 100644 --- a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java +++ b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java @@ -532,7 +532,7 @@ public class TransactionParcelTests { } @Override - public void scheduleCrash(String s, int i) throws RemoteException { + public void scheduleCrash(String s, int i, Bundle extras) throws RemoteException { } @Override diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json index 8ccf02caf8c0..6bfbd8d55ab0 100644 --- a/data/etc/services.core.protolog.json +++ b/data/etc/services.core.protolog.json @@ -889,6 +889,12 @@ "group": "WM_DEBUG_REMOTE_ANIMATIONS", "at": "com\/android\/server\/wm\/NonAppWindowAnimationAdapter.java" }, + "-1145384901": { + "message": "shouldWaitAnimatingExit: isTransition: %s", + "level": "DEBUG", + "group": "WM_DEBUG_APP_TRANSITIONS", + "at": "com\/android\/server\/wm\/WindowState.java" + }, "-1142279614": { "message": "Looking for focus: %s, flags=%d, canReceive=%b, reason=%s", "level": "VERBOSE", @@ -1273,6 +1279,12 @@ "group": "WM_DEBUG_SCREEN_ON", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, + "-743856570": { + "message": "shouldWaitAnimatingExit: isAnimating: %s", + "level": "DEBUG", + "group": "WM_DEBUG_APP_TRANSITIONS", + "at": "com\/android\/server\/wm\/WindowState.java" + }, "-743431900": { "message": "Configuration no differences in %s", "level": "VERBOSE", @@ -1777,6 +1789,12 @@ "group": "WM_DEBUG_SYNC_ENGINE", "at": "com\/android\/server\/wm\/BLASTSyncEngine.java" }, + "-208825711": { + "message": "shouldWaitAnimatingExit: isWallpaperTarget: %s", + "level": "DEBUG", + "group": "WM_DEBUG_APP_TRANSITIONS", + "at": "com\/android\/server\/wm\/WindowState.java" + }, "-198463978": { "message": "updateRotationUnchecked: alwaysSendConfiguration=%b forceRelayout=%b", "level": "VERBOSE", @@ -2989,6 +3007,12 @@ "group": "WM_DEBUG_REMOTE_ANIMATIONS", "at": "com\/android\/server\/wm\/WallpaperAnimationAdapter.java" }, + "1087494661": { + "message": "Clear window stuck on animatingExit status: %s", + "level": "WARN", + "group": "WM_DEBUG_APP_TRANSITIONS", + "at": "com\/android\/server\/wm\/WindowState.java" + }, "1088929964": { "message": "onLockTaskPackagesUpdated: starting new locktask task=%s", "level": "DEBUG", diff --git a/graphics/java/android/graphics/BLASTBufferQueue.java b/graphics/java/android/graphics/BLASTBufferQueue.java index fca4de91a352..2393eaf32e9a 100644 --- a/graphics/java/android/graphics/BLASTBufferQueue.java +++ b/graphics/java/android/graphics/BLASTBufferQueue.java @@ -38,6 +38,7 @@ public final class BLASTBufferQueue { long frameNumber); private static native void nativeSetTransactionCompleteCallback(long ptr, long frameNumber, TransactionCompleteCallback callback); + private static native long nativeGetLastAcquiredFrameNum(long ptr); /** * Callback sent to {@link #setTransactionCompleteCallback(long, TransactionCompleteCallback)} @@ -140,4 +141,7 @@ public final class BLASTBufferQueue { nativeMergeWithNextTransaction(mNativeObject, nativeTransaction, frameNumber); } + public long getLastAcquiredFrameNum() { + return nativeGetLastAcquiredFrameNum(mNativeObject); + } } diff --git a/graphics/java/android/graphics/HardwareRenderer.java b/graphics/java/android/graphics/HardwareRenderer.java index c3b1cd74d29b..14ad74e12618 100644 --- a/graphics/java/android/graphics/HardwareRenderer.java +++ b/graphics/java/android/graphics/HardwareRenderer.java @@ -388,7 +388,8 @@ public class HardwareRenderer { */ public @NonNull FrameRenderRequest setFrameCommitCallback(@NonNull Executor executor, @NonNull Runnable frameCommitCallback) { - setFrameCompleteCallback(frameNr -> executor.execute(frameCommitCallback)); + nSetFrameCommitCallback(mNativeProxy, + didProduceBuffer -> executor.execute(frameCommitCallback)); return this; } @@ -609,6 +610,11 @@ public class HardwareRenderer { } /** @hide */ + public void setFrameCommitCallback(FrameCommitCallback callback) { + nSetFrameCommitCallback(mNativeProxy, callback); + } + + /** @hide */ public void setFrameCompleteCallback(FrameCompleteCallback callback) { nSetFrameCompleteCallback(mNativeProxy, callback); } @@ -904,13 +910,27 @@ public class HardwareRenderer { * * @hide */ - public interface FrameCompleteCallback { + public interface FrameCommitCallback { /** - * Invoked after a frame draw + * Invoked after a new frame was drawn * - * @param frameNr The id of the frame that was drawn. + * @param didProduceBuffer The draw successfully produced a new buffer. + */ + void onFrameCommit(boolean didProduceBuffer); + } + + /** + * Interface used to be notified when RenderThread has finished an attempt to draw. This doesn't + * mean a new frame has drawn, specifically if there's nothing new to draw, but only that + * RenderThread had a chance to draw a frame. + * + * @hide + */ + public interface FrameCompleteCallback { + /** + * Invoked after a frame draw was attempted. */ - void onFrameComplete(long frameNr); + void onFrameComplete(); } /** @@ -1362,6 +1382,9 @@ public class HardwareRenderer { private static native void nSetFrameCallback(long nativeProxy, FrameDrawingCallback callback); + private static native void nSetFrameCommitCallback(long nativeProxy, + FrameCommitCallback callback); + private static native void nSetFrameCompleteCallback(long nativeProxy, FrameCompleteCallback callback); diff --git a/libs/WindowManager/Shell/OWNERS b/libs/WindowManager/Shell/OWNERS deleted file mode 100644 index e2c67fd8f8d4..000000000000 --- a/libs/WindowManager/Shell/OWNERS +++ /dev/null @@ -1,4 +0,0 @@ -# sysui owners -hwwang@google.com -winsonc@google.com -madym@google.com diff --git a/libs/WindowManager/Shell/res/color/taskbar_background.xml b/libs/WindowManager/Shell/res/color/taskbar_background.xml new file mode 100644 index 000000000000..329e5b9b31a0 --- /dev/null +++ b/libs/WindowManager/Shell/res/color/taskbar_background.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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. + --> +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:color="@android:color/system_neutral1_500" android:lStar="35" /> +</selector>
\ No newline at end of file diff --git a/libs/WindowManager/Shell/res/values-in/strings.xml b/libs/WindowManager/Shell/res/values-in/strings.xml index e48885573282..6432aeff4630 100644 --- a/libs/WindowManager/Shell/res/values-in/strings.xml +++ b/libs/WindowManager/Shell/res/values-in/strings.xml @@ -20,8 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Tutup"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Luaskan"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Setelan"</string> - <!-- no translation found for pip_phone_enter_split (7042877263880641911) --> - <skip /> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"Masuk ke mode layar terpisah"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> adalah picture-in-picture"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Jika Anda tidak ingin <xliff:g id="NAME">%s</xliff:g> menggunakan fitur ini, ketuk untuk membuka setelan dan menonaktifkannya."</string> diff --git a/libs/WindowManager/Shell/res/values-mn/strings.xml b/libs/WindowManager/Shell/res/values-mn/strings.xml index afe8584955e9..8b8cb95d1e9b 100644 --- a/libs/WindowManager/Shell/res/values-mn/strings.xml +++ b/libs/WindowManager/Shell/res/values-mn/strings.xml @@ -20,8 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Хаах"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Дэлгэх"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Тохиргоо"</string> - <!-- no translation found for pip_phone_enter_split (7042877263880641911) --> - <skip /> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"Хуваасан дэлгэцийг оруулна уу"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Цэс"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> дэлгэцэн доторх дэлгэцэд байна"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Та <xliff:g id="NAME">%s</xliff:g>-д энэ онцлогийг ашиглуулахыг хүсэхгүй байвал тохиргоог нээгээд, үүнийг унтраана уу."</string> diff --git a/libs/WindowManager/Shell/res/values-ms/strings.xml b/libs/WindowManager/Shell/res/values-ms/strings.xml index b495fef54710..5493ce5a4fab 100644 --- a/libs/WindowManager/Shell/res/values-ms/strings.xml +++ b/libs/WindowManager/Shell/res/values-ms/strings.xml @@ -20,8 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Tutup"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Kembangkan"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Tetapan"</string> - <!-- no translation found for pip_phone_enter_split (7042877263880641911) --> - <skip /> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"Masuk skrin pisah"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> terdapat dalam gambar dalam gambar"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Jika anda tidak mahu <xliff:g id="NAME">%s</xliff:g> menggunakan ciri ini, ketik untuk membuka tetapan dan matikan ciri."</string> diff --git a/libs/WindowManager/Shell/res/values-my/strings.xml b/libs/WindowManager/Shell/res/values-my/strings.xml index 2849137b0151..e1d17f88fb9b 100644 --- a/libs/WindowManager/Shell/res/values-my/strings.xml +++ b/libs/WindowManager/Shell/res/values-my/strings.xml @@ -20,8 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"ပိတ်ရန်"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"ချဲ့ရန်"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"ဆက်တင်များ"</string> - <!-- no translation found for pip_phone_enter_split (7042877263880641911) --> - <skip /> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"မျက်နှာပြင် ခွဲ၍ပြသခြင်းသို့ ဝင်ရန်"</string> <string name="pip_menu_title" msgid="5393619322111827096">"မီနူး"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> သည် နှစ်ခုထပ်၍ကြည့်ခြင်း ဖွင့်ထားသည်"</string> <string name="pip_notification_message" msgid="8854051911700302620">"<xliff:g id="NAME">%s</xliff:g> အား ဤဝန်ဆောင်မှုကို အသုံးမပြုစေလိုလျှင် ဆက်တင်ကိုဖွင့်ရန် တို့ပြီး ၎င်းဝန်ဆောင်မှုကို ပိတ်လိုက်ပါ။"</string> diff --git a/libs/WindowManager/Shell/res/values-sq/strings.xml b/libs/WindowManager/Shell/res/values-sq/strings.xml index 2b0b551c65c9..7382a480fb1e 100644 --- a/libs/WindowManager/Shell/res/values-sq/strings.xml +++ b/libs/WindowManager/Shell/res/values-sq/strings.xml @@ -20,8 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Mbyll"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Zgjero"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Cilësimet"</string> - <!-- no translation found for pip_phone_enter_split (7042877263880641911) --> - <skip /> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"Hyr në ekranin e ndarë"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menyja"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> është në figurë brenda figurës"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Nëse nuk dëshiron që <xliff:g id="NAME">%s</xliff:g> ta përdorë këtë funksion, trokit për të hapur cilësimet dhe për ta çaktivizuar."</string> diff --git a/libs/WindowManager/Shell/res/values-th/strings.xml b/libs/WindowManager/Shell/res/values-th/strings.xml index 563ec2ffa2be..06b04f145772 100644 --- a/libs/WindowManager/Shell/res/values-th/strings.xml +++ b/libs/WindowManager/Shell/res/values-th/strings.xml @@ -20,8 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"ปิด"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"ขยาย"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"การตั้งค่า"</string> - <!-- no translation found for pip_phone_enter_split (7042877263880641911) --> - <skip /> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"เข้าสู่โหมดแบ่งหน้าจอ"</string> <string name="pip_menu_title" msgid="5393619322111827096">"เมนู"</string> <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> ใช้การแสดงภาพซ้อนภาพ"</string> <string name="pip_notification_message" msgid="8854051911700302620">"หากคุณไม่ต้องการให้ <xliff:g id="NAME">%s</xliff:g> ใช้ฟีเจอร์นี้ ให้แตะเพื่อเปิดการตั้งค่าแล้วปิดฟีเจอร์"</string> diff --git a/libs/WindowManager/Shell/res/values-tl/strings.xml b/libs/WindowManager/Shell/res/values-tl/strings.xml index a9a36bbb6a49..62642c18937e 100644 --- a/libs/WindowManager/Shell/res/values-tl/strings.xml +++ b/libs/WindowManager/Shell/res/values-tl/strings.xml @@ -20,8 +20,7 @@ <string name="pip_phone_close" msgid="5783752637260411309">"Isara"</string> <string name="pip_phone_expand" msgid="2579292903468287504">"Palawakin"</string> <string name="pip_phone_settings" msgid="5468987116750491918">"Mga Setting"</string> - <!-- no translation found for pip_phone_enter_split (7042877263880641911) --> - <skip /> + <string name="pip_phone_enter_split" msgid="7042877263880641911">"Pumasok sa split screen"</string> <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string> <string name="pip_notification_title" msgid="1347104727641353453">"Nasa picture-in-picture ang <xliff:g id="NAME">%s</xliff:g>"</string> <string name="pip_notification_message" msgid="8854051911700302620">"Kung ayaw mong magamit ni <xliff:g id="NAME">%s</xliff:g> ang feature na ito, i-tap upang buksan ang mga setting at i-off ito."</string> diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java index 75bc46125324..8e98b82088dc 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java @@ -29,6 +29,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager.RunningTaskInfo; import android.app.TaskInfo; +import android.app.WindowConfiguration; import android.content.Context; import android.content.LocusId; import android.content.pm.ActivityInfo; @@ -122,6 +123,16 @@ public class ShellTaskOrganizer extends TaskOrganizer implements } /** + * Callbacks for events in which the focus has changed. + */ + public interface FocusListener { + /** + * Notifies when the task which is focused has changed. + */ + void onFocusTaskChanged(RunningTaskInfo taskInfo); + } + + /** * Keys map from either a task id or {@link TaskListenerType}. * @see #addListenerForTaskId * @see #addListenerForType @@ -142,6 +153,8 @@ public class ShellTaskOrganizer extends TaskOrganizer implements /** @see #addLocusIdListener */ private final ArraySet<LocusIdListener> mLocusIdListeners = new ArraySet<>(); + private final ArraySet<FocusListener> mFocusListeners = new ArraySet<>(); + private final Object mLock = new Object(); private StartingWindowController mStartingWindow; @@ -155,6 +168,9 @@ public class ShellTaskOrganizer extends TaskOrganizer implements @Nullable private final Optional<RecentTasksController> mRecentTasks; + @Nullable + private RunningTaskInfo mLastFocusedTaskInfo; + public ShellTaskOrganizer(ShellExecutor mainExecutor, Context context) { this(null /* taskOrganizerController */, mainExecutor, context, null /* sizeCompatUI */, Optional.empty() /* recentTasksController */); @@ -200,6 +216,14 @@ public class ShellTaskOrganizer extends TaskOrganizer implements } } + @Override + public void unregisterOrganizer() { + super.unregisterOrganizer(); + if (mStartingWindow != null) { + mStartingWindow.clearAllWindows(); + } + } + public void createRootTask(int displayId, int windowingMode, TaskListener listener) { ProtoLog.v(WM_SHELL_TASK_ORG, "createRootTask() displayId=%d winMode=%d listener=%s", displayId, windowingMode, listener.toString()); @@ -331,6 +355,27 @@ public class ShellTaskOrganizer extends TaskOrganizer implements } } + /** + * Adds a listener to be notified for task focus changes. + */ + public void addFocusListener(FocusListener listener) { + synchronized (mLock) { + mFocusListeners.add(listener); + if (mLastFocusedTaskInfo != null) { + listener.onFocusTaskChanged(mLastFocusedTaskInfo); + } + } + } + + /** + * Removes listener. + */ + public void removeLocusIdListener(FocusListener listener) { + synchronized (mLock) { + mFocusListeners.remove(listener); + } + } + @Override public void addStartingWindow(StartingWindowInfo info, IBinder appToken) { if (mStartingWindow != null) { @@ -422,6 +467,18 @@ public class ShellTaskOrganizer extends TaskOrganizer implements mRecentTasks.ifPresent(recentTasks -> recentTasks.onTaskWindowingModeChanged(taskInfo)); } + // TODO (b/207687679): Remove check for HOME once bug is fixed + final boolean isFocusedOrHome = taskInfo.isFocused + || (taskInfo.topActivityType == WindowConfiguration.ACTIVITY_TYPE_HOME + && taskInfo.isVisible); + final boolean focusTaskChanged = (mLastFocusedTaskInfo == null + || mLastFocusedTaskInfo.taskId != taskInfo.taskId) && isFocusedOrHome; + if (focusTaskChanged) { + for (int i = 0; i < mFocusListeners.size(); i++) { + mFocusListeners.valueAt(i).onFocusTaskChanged(taskInfo); + } + mLastFocusedTaskInfo = taskInfo; + } } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/OWNERS b/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/OWNERS new file mode 100644 index 000000000000..4d9b520e3f0e --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/OWNERS @@ -0,0 +1,2 @@ +# WM shell sub-modules apppair owner +chenghsiuchang@google.com diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java index 300319a2f78f..b40021ec82a7 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java @@ -32,6 +32,7 @@ import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.annotation.SuppressLint; +import android.app.ActivityManager; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; @@ -529,9 +530,10 @@ public class BubbleStackView extends FrameLayout // Otherwise, we either tapped the stack (which means we're collapsed // and should expand) or the currently selected bubble (we're expanded // and should collapse). - if (!maybeShowStackEdu()) { + if (!maybeShowStackEdu() && !mShowedUserEducationInTouchListenerActive) { mBubbleData.setExpanded(!mBubbleData.isExpanded()); } + mShowedUserEducationInTouchListenerActive = false; } } }; @@ -549,6 +551,14 @@ public class BubbleStackView extends FrameLayout return true; } + mShowedUserEducationInTouchListenerActive = false; + if (maybeShowStackEdu()) { + mShowedUserEducationInTouchListenerActive = true; + return true; + } else if (isStackEduShowing()) { + mStackEduView.hide(false /* fromExpansion */); + } + // If the manage menu is visible, just hide it. if (mShowingManage) { showManageMenu(false /* show */); @@ -607,7 +617,8 @@ public class BubbleStackView extends FrameLayout // If we're expanding or collapsing, ignore all touch events. if (mIsExpansionAnimating // Also ignore events if we shouldn't be draggable. - || (mPositioner.showingInTaskbar() && !mIsExpanded)) { + || (mPositioner.showingInTaskbar() && !mIsExpanded) + || mShowedUserEducationInTouchListenerActive) { return; } @@ -628,7 +639,7 @@ public class BubbleStackView extends FrameLayout mExpandedAnimationController.dragBubbleOut( v, viewInitialX + dx, viewInitialY + dy); } else { - if (mStackEduView != null) { + if (isStackEduShowing()) { mStackEduView.hide(false /* fromExpansion */); } mStackAnimationController.moveStackFromTouch( @@ -646,6 +657,10 @@ public class BubbleStackView extends FrameLayout || (mPositioner.showingInTaskbar() && !mIsExpanded)) { return; } + if (mShowedUserEducationInTouchListenerActive) { + mShowedUserEducationInTouchListenerActive = false; + return; + } // First, see if the magnetized object consumes the event - if so, the bubble was // released in the target or flung out of it, and we should ignore the event. @@ -738,6 +753,7 @@ public class BubbleStackView extends FrameLayout private ImageView mManageSettingsIcon; private TextView mManageSettingsText; private boolean mShowingManage = false; + private boolean mShowedUserEducationInTouchListenerActive = false; private PhysicsAnimator.SpringConfig mManageSpringConfig = new PhysicsAnimator.SpringConfig( SpringForce.STIFFNESS_MEDIUM, SpringForce.DAMPING_RATIO_LOW_BOUNCY); private BubblePositioner mPositioner; @@ -929,10 +945,12 @@ public class BubbleStackView extends FrameLayout showManageMenu(false /* show */); } else if (mManageEduView != null && mManageEduView.getVisibility() == VISIBLE) { mManageEduView.hide(); - } else if (mStackEduView != null && mStackEduView.getVisibility() == VISIBLE) { + } else if (isStackEduShowing()) { mStackEduView.hide(false /* isExpanding */); } else if (mBubbleData.isExpanded()) { mBubbleData.setExpanded(false); + } else { + maybeShowStackEdu(); } }); @@ -1116,6 +1134,9 @@ public class BubbleStackView extends FrameLayout * Whether the educational view should show for the expanded view "manage" menu. */ private boolean shouldShowManageEdu() { + if (ActivityManager.isRunningInTestHarness()) { + return false; + } final boolean seen = getPrefBoolean(ManageEducationViewKt.PREF_MANAGED_EDUCATION); final boolean shouldShow = (!seen || BubbleDebugConfig.forceShowUserEducation(mContext)) && mExpandedBubble != null; @@ -1140,6 +1161,9 @@ public class BubbleStackView extends FrameLayout * Whether education view should show for the collapsed stack. */ private boolean shouldShowStackEdu() { + if (ActivityManager.isRunningInTestHarness()) { + return false; + } final boolean seen = getPrefBoolean(StackEducationViewKt.PREF_STACK_EDUCATION); final boolean shouldShow = !seen || BubbleDebugConfig.forceShowUserEducation(mContext); if (BubbleDebugConfig.DEBUG_USER_EDUCATION) { @@ -1157,7 +1181,7 @@ public class BubbleStackView extends FrameLayout * @return true if education view for collapsed stack should show and was not showing before. */ private boolean maybeShowStackEdu() { - if (!shouldShowStackEdu()) { + if (!shouldShowStackEdu() || isExpanded()) { return false; } if (mStackEduView == null) { @@ -1168,9 +1192,13 @@ public class BubbleStackView extends FrameLayout return mStackEduView.show(mPositioner.getDefaultStartPosition()); } + private boolean isStackEduShowing() { + return mStackEduView != null && mStackEduView.getVisibility() == VISIBLE; + } + // Recreates & shows the education views. Call when a theme/config change happens. private void updateUserEdu() { - if (mStackEduView != null && mStackEduView.getVisibility() == VISIBLE) { + if (isStackEduShowing()) { removeView(mStackEduView); mStackEduView = new StackEducationView(mContext, mPositioner, mBubbleController); addView(mStackEduView); @@ -1852,7 +1880,7 @@ public class BubbleStackView extends FrameLayout cancelDelayedExpandCollapseSwitchAnimations(); final boolean showVertically = mPositioner.showBubblesVertically(); mIsExpanded = true; - if (mStackEduView != null) { + if (isStackEduShowing()) { mStackEduView.hide(true /* fromExpansion */); } beforeExpandedViewAnimation(); @@ -2390,7 +2418,7 @@ public class BubbleStackView extends FrameLayout if (flyoutMessage == null || flyoutMessage.message == null || !bubble.showFlyout() - || (mStackEduView != null && mStackEduView.getVisibility() == VISIBLE) + || isStackEduShowing() || isExpanded() || mIsExpansionAnimating || mIsGestureInProgress @@ -2512,7 +2540,7 @@ public class BubbleStackView extends FrameLayout * them. */ public void getTouchableRegion(Rect outRect) { - if (mStackEduView != null && mStackEduView.getVisibility() == VISIBLE) { + if (isStackEduShowing()) { // When user education shows then capture all touches outRect.set(0, 0, getWidth(), getHeight()); return; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/OWNERS b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/OWNERS new file mode 100644 index 000000000000..8271014d290e --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/OWNERS @@ -0,0 +1,2 @@ +# WM shell sub-module bubble owner +madym@google.com diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/StackEducationView.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/StackEducationView.kt index f6a90b7a76cd..3846de73842d 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/StackEducationView.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/StackEducationView.kt @@ -125,6 +125,7 @@ class StackEducationView constructor( * @return true if user education was shown, false otherwise. */ fun show(stackPosition: PointF): Boolean { + isHiding = false if (visibility == VISIBLE) return false controller.updateWindowFlagsForBackpress(true /* interceptBack */) @@ -164,6 +165,7 @@ class StackEducationView constructor( */ fun hide(isExpanding: Boolean) { if (visibility != VISIBLE || isHiding) return + isHiding = true controller.updateWindowFlagsForBackpress(false /* interceptBack */) animate() diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java index d07fff3cce79..3579bf441390 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java @@ -321,6 +321,16 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange mSplitLayoutHandler.onLayoutSizeChanged(this); } + /** Sets divide position base on the ratio within root bounds. */ + public void setDivideRatio(float ratio) { + final int position = isLandscape() + ? mRootBounds.left + (int) (mRootBounds.width() * ratio) + : mRootBounds.top + (int) (mRootBounds.height() * ratio); + DividerSnapAlgorithm.SnapTarget snapTarget = + mDividerSnapAlgorithm.calculateNonDismissingSnapTarget(position); + setDividePosition(snapTarget.position); + } + /** Resets divider position. */ public void resetDividerPosition() { mDividePosition = mDividerSnapAlgorithm.getMiddleTarget().position; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java index 6b622044d25d..9500e8aecb57 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java @@ -56,6 +56,7 @@ import com.android.wm.shell.common.annotations.ShellMainThread; import com.android.wm.shell.common.annotations.ShellSplashscreenThread; import com.android.wm.shell.displayareahelper.DisplayAreaHelper; import com.android.wm.shell.displayareahelper.DisplayAreaHelperController; +import com.android.wm.shell.draganddrop.DragAndDrop; import com.android.wm.shell.draganddrop.DragAndDropController; import com.android.wm.shell.freeform.FreeformTaskListener; import com.android.wm.shell.fullscreen.FullscreenTaskListener; @@ -156,8 +157,16 @@ public abstract class WMShellBaseModule { @WMSingleton @Provides static DragAndDropController provideDragAndDropController(Context context, - DisplayController displayController, UiEventLogger uiEventLogger) { - return new DragAndDropController(context, displayController, uiEventLogger); + DisplayController displayController, UiEventLogger uiEventLogger, + IconProvider iconProvider, @ShellMainThread ShellExecutor mainExecutor) { + return new DragAndDropController(context, displayController, uiEventLogger, iconProvider, + mainExecutor); + } + + @WMSingleton + @Provides + static DragAndDrop provideDragAndDrop(DragAndDropController dragAndDropController) { + return dragAndDropController.asDragAndDrop(); } @WMSingleton diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java index 46c7b508d6e8..f562fd9cf1af 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java @@ -241,10 +241,11 @@ public class WMShellModule { static PhonePipMenuController providesPipPhoneMenuController(Context context, PipBoundsState pipBoundsState, PipMediaController pipMediaController, SystemWindows systemWindows, + Optional<SplitScreenController> splitScreenOptional, @ShellMainThread ShellExecutor mainExecutor, @ShellMainThread Handler mainHandler) { return new PhonePipMenuController(context, pipBoundsState, pipMediaController, - systemWindows, mainExecutor, mainHandler); + systemWindows, splitScreenOptional, mainExecutor, mainHandler); } @WMSingleton diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDrop.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDrop.java new file mode 100644 index 000000000000..edeff6e37182 --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDrop.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2020 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.wm.shell.draganddrop; + +import android.content.res.Configuration; + +import com.android.wm.shell.common.annotations.ExternalThread; + +/** + * Interface for telling DragAndDrop stuff. + */ +@ExternalThread +public interface DragAndDrop { + + /** Called when the theme changes. */ + void onThemeChanged(); + + /** Called when the configuration changes. */ + void onConfigChanged(Configuration newConfig); +} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java index d2b4711d30af..101295d246bc 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java @@ -41,7 +41,6 @@ import android.content.res.Configuration; import android.graphics.PixelFormat; import android.util.Slog; import android.util.SparseArray; -import android.view.Display; import android.view.DragEvent; import android.view.LayoutInflater; import android.view.SurfaceControl; @@ -53,8 +52,10 @@ import android.widget.FrameLayout; import com.android.internal.logging.InstanceId; import com.android.internal.logging.UiEventLogger; import com.android.internal.protolog.common.ProtoLog; +import com.android.launcher3.icons.IconProvider; import com.android.wm.shell.R; import com.android.wm.shell.common.DisplayController; +import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.protolog.ShellProtoLogGroup; import com.android.wm.shell.splitscreen.SplitScreenController; @@ -71,16 +72,26 @@ public class DragAndDropController implements DisplayController.OnDisplaysChange private final Context mContext; private final DisplayController mDisplayController; private final DragAndDropEventLogger mLogger; + private final IconProvider mIconProvider; private SplitScreenController mSplitScreen; + private ShellExecutor mMainExecutor; + private DragAndDropImpl mImpl; private final SparseArray<PerDisplay> mDisplayDropTargets = new SparseArray<>(); private final SurfaceControl.Transaction mTransaction = new SurfaceControl.Transaction(); public DragAndDropController(Context context, DisplayController displayController, - UiEventLogger uiEventLogger) { + UiEventLogger uiEventLogger, IconProvider iconProvider, ShellExecutor mainExecutor) { mContext = context; mDisplayController = displayController; mLogger = new DragAndDropEventLogger(uiEventLogger); + mIconProvider = iconProvider; + mMainExecutor = mainExecutor; + mImpl = new DragAndDropImpl(); + } + + public DragAndDrop asDragAndDrop() { + return mImpl; } public void initialize(Optional<SplitScreenController> splitscreen) { @@ -117,7 +128,7 @@ public class DragAndDropController implements DisplayController.OnDisplaysChange R.layout.global_drop_target, null); rootView.setOnDragListener(this); rootView.setVisibility(View.INVISIBLE); - DragLayout dragLayout = new DragLayout(context, mSplitScreen); + DragLayout dragLayout = new DragLayout(context, mSplitScreen, mIconProvider); rootView.addView(dragLayout, new FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT)); try { @@ -267,6 +278,18 @@ public class DragAndDropController implements DisplayController.OnDisplaysChange return mimeTypes; } + private void onThemeChange() { + for (int i = 0; i < mDisplayDropTargets.size(); i++) { + mDisplayDropTargets.get(i).dragLayout.onThemeChange(); + } + } + + private void onConfigChanged(Configuration newConfig) { + for (int i = 0; i < mDisplayDropTargets.size(); i++) { + mDisplayDropTargets.get(i).dragLayout.onConfigChanged(newConfig); + } + } + private static class PerDisplay { final int displayId; final Context context; @@ -287,4 +310,21 @@ public class DragAndDropController implements DisplayController.OnDisplaysChange dragLayout = dl; } } + + private class DragAndDropImpl implements DragAndDrop { + + @Override + public void onThemeChanged() { + mMainExecutor.execute(() -> { + DragAndDropController.this.onThemeChange(); + }); + } + + @Override + public void onConfigChanged(Configuration newConfig) { + mMainExecutor.execute(() -> { + DragAndDropController.this.onConfigChanged(newConfig); + }); + } + } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java index fbf04d6f3fff..d2bd28e0f753 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java @@ -37,8 +37,6 @@ import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_SPL import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_SPLIT_LEFT; import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_SPLIT_RIGHT; import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_SPLIT_TOP; -import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_SIDE; -import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_UNDEFINED; import android.app.ActivityManager; import android.app.ActivityTaskManager; @@ -66,7 +64,6 @@ import androidx.annotation.VisibleForTesting; import com.android.internal.logging.InstanceId; import com.android.wm.shell.common.DisplayLayout; import com.android.wm.shell.common.split.SplitLayout.SplitPosition; -import com.android.wm.shell.splitscreen.SplitScreen.StageType; import com.android.wm.shell.splitscreen.SplitScreenController; import java.lang.annotation.Retention; @@ -198,29 +195,23 @@ public class DragAndDropPolicy { return; } - final boolean inSplitScreen = mSplitScreen != null && mSplitScreen.isSplitScreenVisible(); final boolean leftOrTop = target.type == TYPE_SPLIT_TOP || target.type == TYPE_SPLIT_LEFT; - @StageType int stage = STAGE_TYPE_UNDEFINED; @SplitPosition int position = SPLIT_POSITION_UNDEFINED; if (target.type != TYPE_FULLSCREEN && mSplitScreen != null) { // Update launch options for the split side we are targeting. position = leftOrTop ? SPLIT_POSITION_TOP_OR_LEFT : SPLIT_POSITION_BOTTOM_OR_RIGHT; - if (!inSplitScreen) { - // Launch in the side stage if we are not in split-screen already. - stage = STAGE_TYPE_SIDE; - } // Add some data for logging splitscreen once it is invoked mSplitScreen.logOnDroppedToSplit(position, mLoggerSessionId); } final ClipDescription description = data.getDescription(); final Intent dragData = mSession.dragData; - startClipDescription(description, dragData, stage, position); + startClipDescription(description, dragData, position); } private void startClipDescription(ClipDescription description, Intent intent, - @StageType int stage, @SplitPosition int position) { + @SplitPosition int position) { final boolean isTask = description.hasMimeType(MIMETYPE_APPLICATION_TASK); final boolean isShortcut = description.hasMimeType(MIMETYPE_APPLICATION_SHORTCUT); final Bundle opts = intent.hasExtra(EXTRA_ACTIVITY_OPTIONS) @@ -228,15 +219,15 @@ public class DragAndDropPolicy { if (isTask) { final int taskId = intent.getIntExtra(EXTRA_TASK_ID, INVALID_TASK_ID); - mStarter.startTask(taskId, stage, position, opts); + mStarter.startTask(taskId, position, opts); } else if (isShortcut) { final String packageName = intent.getStringExtra(EXTRA_PACKAGE_NAME); final String id = intent.getStringExtra(EXTRA_SHORTCUT_ID); final UserHandle user = intent.getParcelableExtra(EXTRA_USER); - mStarter.startShortcut(packageName, id, stage, position, opts, user); + mStarter.startShortcut(packageName, id, position, opts, user); } else { mStarter.startIntent(intent.getParcelableExtra(EXTRA_PENDING_INTENT), - null, stage, position, opts); + null, position, opts); } } @@ -291,12 +282,10 @@ public class DragAndDropPolicy { * Interface for actually committing the task launches. */ public interface Starter { - void startTask(int taskId, @StageType int stage, @SplitPosition int position, - @Nullable Bundle options); - void startShortcut(String packageName, String shortcutId, @StageType int stage, - @SplitPosition int position, @Nullable Bundle options, UserHandle user); - void startIntent(PendingIntent intent, Intent fillInIntent, - @StageType int stage, @SplitPosition int position, + void startTask(int taskId, @SplitPosition int position, @Nullable Bundle options); + void startShortcut(String packageName, String shortcutId, @SplitPosition int position, + @Nullable Bundle options, UserHandle user); + void startIntent(PendingIntent intent, Intent fillInIntent, @SplitPosition int position, @Nullable Bundle options); void enterSplitScreen(int taskId, boolean leftOrTop); @@ -319,8 +308,7 @@ public class DragAndDropPolicy { } @Override - public void startTask(int taskId, int stage, int position, - @Nullable Bundle options) { + public void startTask(int taskId, int position, @Nullable Bundle options) { try { ActivityTaskManager.getService().startActivityFromRecents(taskId, options); } catch (RemoteException e) { @@ -329,7 +317,7 @@ public class DragAndDropPolicy { } @Override - public void startShortcut(String packageName, String shortcutId, int stage, int position, + public void startShortcut(String packageName, String shortcutId, int position, @Nullable Bundle options, UserHandle user) { try { LauncherApps launcherApps = @@ -342,8 +330,8 @@ public class DragAndDropPolicy { } @Override - public void startIntent(PendingIntent intent, @Nullable Intent fillInIntent, int stage, - int position, @Nullable Bundle options) { + public void startIntent(PendingIntent intent, @Nullable Intent fillInIntent, int position, + @Nullable Bundle options) { try { intent.send(mContext, 0, fillInIntent, null, null, null, options); } catch (PendingIntent.CanceledException e) { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java index efc9ed0f75b2..20d8054f6e90 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java @@ -16,78 +16,138 @@ package com.android.wm.shell.draganddrop; -import static com.android.wm.shell.animation.Interpolators.FAST_OUT_LINEAR_IN; -import static com.android.wm.shell.animation.Interpolators.FAST_OUT_SLOW_IN; -import static com.android.wm.shell.animation.Interpolators.LINEAR; -import static com.android.wm.shell.animation.Interpolators.LINEAR_OUT_SLOW_IN; +import static android.app.StatusBarManager.DISABLE_NONE; + +import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_TOP_OR_LEFT; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ObjectAnimator; +import android.annotation.SuppressLint; +import android.app.ActivityManager; +import android.app.ActivityTaskManager; +import android.app.StatusBarManager; import android.content.ClipData; import android.content.Context; -import android.graphics.Canvas; +import android.content.res.Configuration; +import android.graphics.Color; import android.graphics.Insets; -import android.graphics.Rect; import android.graphics.drawable.Drawable; +import android.os.RemoteException; import android.view.DragEvent; import android.view.SurfaceControl; -import android.view.View; +import android.view.ViewGroup; import android.view.WindowInsets; import android.view.WindowInsets.Type; - -import androidx.annotation.NonNull; +import android.widget.LinearLayout; import com.android.internal.logging.InstanceId; import com.android.internal.protolog.common.ProtoLog; +import com.android.launcher3.icons.IconProvider; import com.android.wm.shell.R; import com.android.wm.shell.common.DisplayLayout; import com.android.wm.shell.protolog.ShellProtoLogGroup; import com.android.wm.shell.splitscreen.SplitScreenController; import java.util.ArrayList; +import java.util.List; /** * Coordinates the visible drop targets for the current drag. */ -public class DragLayout extends View { +public class DragLayout extends LinearLayout { + + // While dragging the status bar is hidden. + private static final int HIDE_STATUS_BAR_FLAGS = StatusBarManager.DISABLE_NOTIFICATION_ICONS + | StatusBarManager.DISABLE_NOTIFICATION_ALERTS + | StatusBarManager.DISABLE_CLOCK + | StatusBarManager.DISABLE_SYSTEM_INFO; private final DragAndDropPolicy mPolicy; + private final SplitScreenController mSplitScreenController; + private final IconProvider mIconProvider; + private final StatusBarManager mStatusBarManager; private DragAndDropPolicy.Target mCurrentTarget = null; - private DropOutlineDrawable mDropOutline; + private DropZoneView mDropZoneView1; + private DropZoneView mDropZoneView2; + private int mDisplayMargin; private Insets mInsets = Insets.NONE; private boolean mIsShowing; private boolean mHasDropped; - public DragLayout(Context context, SplitScreenController splitscreen) { + @SuppressLint("WrongConstant") + public DragLayout(Context context, SplitScreenController splitScreenController, + IconProvider iconProvider) { super(context); - mPolicy = new DragAndDropPolicy(context, splitscreen); + mSplitScreenController = splitScreenController; + mIconProvider = iconProvider; + mPolicy = new DragAndDropPolicy(context, splitScreenController); + mStatusBarManager = context.getSystemService(StatusBarManager.class); + mDisplayMargin = context.getResources().getDimensionPixelSize( R.dimen.drop_layout_display_margin); - mDropOutline = new DropOutlineDrawable(context); - setBackground(mDropOutline); - setWillNotDraw(false); + + mDropZoneView1 = new DropZoneView(context); + mDropZoneView2 = new DropZoneView(context); + addView(mDropZoneView1, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT)); + addView(mDropZoneView2, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT)); + ((LayoutParams) mDropZoneView1.getLayoutParams()).weight = 1; + ((LayoutParams) mDropZoneView2.getLayoutParams()).weight = 1; + updateContainerMargins(); } @Override public WindowInsets onApplyWindowInsets(WindowInsets insets) { mInsets = insets.getInsets(Type.systemBars() | Type.displayCutout()); recomputeDropTargets(); + + final int orientation = getResources().getConfiguration().orientation; + if (orientation == Configuration.ORIENTATION_LANDSCAPE) { + mDropZoneView1.setBottomInset(mInsets.bottom); + mDropZoneView2.setBottomInset(mInsets.bottom); + } else if (orientation == Configuration.ORIENTATION_PORTRAIT) { + mDropZoneView1.setBottomInset(0); + mDropZoneView2.setBottomInset(mInsets.bottom); + } return super.onApplyWindowInsets(insets); } - @Override - protected boolean verifyDrawable(@NonNull Drawable who) { - return who == mDropOutline || super.verifyDrawable(who); + public void onThemeChange() { + mDropZoneView1.onThemeChange(); + mDropZoneView2.onThemeChange(); } - @Override - protected void onDraw(Canvas canvas) { - if (mCurrentTarget != null) { - mDropOutline.draw(canvas); + public void onConfigChanged(Configuration newConfig) { + final int orientation = getResources().getConfiguration().orientation; + if (orientation == Configuration.ORIENTATION_LANDSCAPE + && getOrientation() != HORIZONTAL) { + setOrientation(LinearLayout.HORIZONTAL); + updateContainerMargins(); + } else if (orientation == Configuration.ORIENTATION_PORTRAIT + && getOrientation() != VERTICAL) { + setOrientation(LinearLayout.VERTICAL); + updateContainerMargins(); + } + } + + private void updateContainerMargins() { + final int orientation = getResources().getConfiguration().orientation; + final float halfMargin = mDisplayMargin / 2f; + if (orientation == Configuration.ORIENTATION_LANDSCAPE) { + mDropZoneView1.setContainerMargin( + mDisplayMargin, mDisplayMargin, halfMargin, mDisplayMargin); + mDropZoneView2.setContainerMargin( + halfMargin, mDisplayMargin, mDisplayMargin, mDisplayMargin); + } else if (orientation == Configuration.ORIENTATION_PORTRAIT) { + mDropZoneView1.setContainerMargin( + mDisplayMargin, mDisplayMargin, mDisplayMargin, halfMargin); + mDropZoneView2.setContainerMargin( + mDisplayMargin, halfMargin, mDisplayMargin, mDisplayMargin); } } @@ -104,6 +164,43 @@ public class DragLayout extends View { mPolicy.start(displayLayout, initialData, loggerSessionId); mHasDropped = false; mCurrentTarget = null; + + List<ActivityManager.RunningTaskInfo> tasks = null; + // Figure out the splashscreen info for the existing task(s). + try { + tasks = ActivityTaskManager.getService().getTasks(2, + false /* filterOnlyVisibleRecents */, + false /* keepIntentExtra */); + } catch (RemoteException e) { + // don't show an icon / will just use the defaults + } + if (tasks != null && !tasks.isEmpty()) { + ActivityManager.RunningTaskInfo taskInfo1 = tasks.get(0); + Drawable icon1 = mIconProvider.getIcon(taskInfo1.topActivityInfo); + int bgColor1 = getResizingBackgroundColor(taskInfo1); + + boolean alreadyInSplit = mSplitScreenController != null + && mSplitScreenController.isSplitScreenVisible(); + if (alreadyInSplit && tasks.size() > 1) { + ActivityManager.RunningTaskInfo taskInfo2 = tasks.get(1); + Drawable icon2 = mIconProvider.getIcon(taskInfo2.topActivityInfo); + int bgColor2 = getResizingBackgroundColor(taskInfo2); + + // figure out which task is on which side + int splitPosition1 = mSplitScreenController.getSplitPosition(taskInfo1.taskId); + boolean isTask1TopOrLeft = splitPosition1 == SPLIT_POSITION_TOP_OR_LEFT; + if (isTask1TopOrLeft) { + mDropZoneView1.setAppInfo(bgColor1, icon1); + mDropZoneView2.setAppInfo(bgColor2, icon2); + } else { + mDropZoneView2.setAppInfo(bgColor1, icon1); + mDropZoneView1.setAppInfo(bgColor2, icon2); + } + } else { + mDropZoneView1.setAppInfo(bgColor1, icon1); + mDropZoneView2.setAppInfo(bgColor1, icon1); + } + } } public void show() { @@ -139,20 +236,14 @@ public class DragLayout extends View { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DRAG_AND_DROP, "Current target: %s", target); if (target == null) { // Animating to no target - mDropOutline.startVisibilityAnimation(false, LINEAR); - Rect finalBounds = new Rect(mCurrentTarget.drawRegion); - finalBounds.inset(mDisplayMargin, mDisplayMargin); - mDropOutline.startBoundsAnimation(finalBounds, FAST_OUT_LINEAR_IN); + animateSplitContainers(false, null /* animCompleteCallback */); } else if (mCurrentTarget == null) { // Animating to first target - mDropOutline.startVisibilityAnimation(true, LINEAR); - Rect initialBounds = new Rect(target.drawRegion); - initialBounds.inset(mDisplayMargin, mDisplayMargin); - mDropOutline.setRegionBounds(initialBounds); - mDropOutline.startBoundsAnimation(target.drawRegion, LINEAR_OUT_SLOW_IN); + animateSplitContainers(true, null /* animCompleteCallback */); + animateHighlight(target); } else { - // Bounds change - mDropOutline.startBoundsAnimation(target.drawRegion, FAST_OUT_SLOW_IN); + // Switching between targets + animateHighlight(target); } mCurrentTarget = target; } @@ -163,26 +254,7 @@ public class DragLayout extends View { */ public void hide(DragEvent event, Runnable hideCompleteCallback) { mIsShowing = false; - ObjectAnimator alphaAnimator = mDropOutline.startVisibilityAnimation(false, LINEAR); - ObjectAnimator boundsAnimator = null; - if (mCurrentTarget != null) { - Rect finalBounds = new Rect(mCurrentTarget.drawRegion); - finalBounds.inset(mDisplayMargin, mDisplayMargin); - boundsAnimator = mDropOutline.startBoundsAnimation(finalBounds, FAST_OUT_LINEAR_IN); - } - - if (hideCompleteCallback != null) { - ObjectAnimator lastAnim = boundsAnimator != null - ? boundsAnimator - : alphaAnimator; - lastAnim.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - hideCompleteCallback.run(); - } - }); - } - + animateSplitContainers(false, hideCompleteCallback); mCurrentTarget = null; } @@ -201,4 +273,49 @@ public class DragLayout extends View { hide(event, dropCompleteCallback); return handledDrop; } + + private void animateSplitContainers(boolean visible, Runnable animCompleteCallback) { + mStatusBarManager.disable(visible + ? HIDE_STATUS_BAR_FLAGS + : DISABLE_NONE); + mDropZoneView1.setShowingMargin(visible); + mDropZoneView2.setShowingMargin(visible); + ObjectAnimator animator = mDropZoneView1.getAnimator(); + if (animCompleteCallback != null) { + if (animator != null) { + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + animCompleteCallback.run(); + } + }); + } else { + // If there's no animator the animation is done so run immediately + animCompleteCallback.run(); + } + } + } + + private void animateHighlight(DragAndDropPolicy.Target target) { + if (target.type == DragAndDropPolicy.Target.TYPE_SPLIT_LEFT + || target.type == DragAndDropPolicy.Target.TYPE_SPLIT_TOP) { + mDropZoneView1.setShowingHighlight(true); + mDropZoneView1.setShowingSplash(false); + + mDropZoneView2.setShowingHighlight(false); + mDropZoneView2.setShowingSplash(true); + } else if (target.type == DragAndDropPolicy.Target.TYPE_SPLIT_RIGHT + || target.type == DragAndDropPolicy.Target.TYPE_SPLIT_BOTTOM) { + mDropZoneView1.setShowingHighlight(false); + mDropZoneView1.setShowingSplash(true); + + mDropZoneView2.setShowingHighlight(true); + mDropZoneView2.setShowingSplash(false); + } + } + + private static int getResizingBackgroundColor(ActivityManager.RunningTaskInfo taskInfo) { + final int taskBgColor = taskInfo.taskDescription.getBackgroundColor(); + return Color.valueOf(taskBgColor == -1 ? Color.WHITE : taskBgColor).toArgb(); + } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DropZoneView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DropZoneView.java new file mode 100644 index 000000000000..2f47af57d496 --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DropZoneView.java @@ -0,0 +1,313 @@ +/* + * 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.wm.shell.draganddrop; + +import static com.android.wm.shell.animation.Interpolators.FAST_OUT_SLOW_IN; + +import android.animation.ObjectAnimator; +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Path; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.util.FloatProperty; +import android.util.IntProperty; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; +import android.widget.ImageView; + +import androidx.annotation.Nullable; + +import com.android.internal.policy.ScreenDecorationsUtils; +import com.android.wm.shell.R; + +/** + * Renders a drop zone area for items being dragged. + */ +public class DropZoneView extends FrameLayout { + + private static final int SPLASHSCREEN_ALPHA_INT = (int) (255 * 0.90f); + private static final int HIGHLIGHT_ALPHA_INT = 255; + private static final int MARGIN_ANIMATION_ENTER_DURATION = 400; + private static final int MARGIN_ANIMATION_EXIT_DURATION = 250; + + private static final FloatProperty<DropZoneView> INSETS = + new FloatProperty<DropZoneView>("insets") { + @Override + public void setValue(DropZoneView v, float percent) { + v.setMarginPercent(percent); + } + + @Override + public Float get(DropZoneView v) { + return v.getMarginPercent(); + } + }; + + private static final IntProperty<ColorDrawable> SPLASHSCREEN_ALPHA = + new IntProperty<ColorDrawable>("splashscreen") { + @Override + public void setValue(ColorDrawable d, int alpha) { + d.setAlpha(alpha); + } + + @Override + public Integer get(ColorDrawable d) { + return d.getAlpha(); + } + }; + + private static final IntProperty<ColorDrawable> HIGHLIGHT_ALPHA = + new IntProperty<ColorDrawable>("highlight") { + @Override + public void setValue(ColorDrawable d, int alpha) { + d.setAlpha(alpha); + } + + @Override + public Integer get(ColorDrawable d) { + return d.getAlpha(); + } + }; + + private final Path mPath = new Path(); + private final float[] mContainerMargin = new float[4]; + private float mCornerRadius; + private float mBottomInset; + private int mMarginColor; // i.e. color used for negative space like the container insets + private int mHighlightColor; + + private boolean mShowingHighlight; + private boolean mShowingSplash; + private boolean mShowingMargin; + + // TODO: might be more seamless to animate between splash/highlight color instead of 2 separate + private ObjectAnimator mSplashAnimator; + private ObjectAnimator mHighlightAnimator; + private ObjectAnimator mMarginAnimator; + private float mMarginPercent; + + // Renders a highlight or neutral transparent color + private ColorDrawable mDropZoneDrawable; + // Renders the translucent splashscreen with the app icon in the middle + private ImageView mSplashScreenView; + private ColorDrawable mSplashBackgroundDrawable; + // Renders the margin / insets around the dropzone container + private MarginView mMarginView; + + public DropZoneView(Context context) { + this(context, null); + } + + public DropZoneView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public DropZoneView(Context context, AttributeSet attrs, int defStyleAttr) { + this(context, attrs, defStyleAttr, 0); + } + + public DropZoneView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + setContainerMargin(0, 0, 0, 0); // make sure it's populated + + mCornerRadius = ScreenDecorationsUtils.getWindowCornerRadius(context); + mMarginColor = getResources().getColor(R.color.taskbar_background); + mHighlightColor = getResources().getColor(android.R.color.system_accent1_500); + + mDropZoneDrawable = new ColorDrawable(); + mDropZoneDrawable.setColor(mHighlightColor); + mDropZoneDrawable.setAlpha(0); + setBackgroundDrawable(mDropZoneDrawable); + + mSplashScreenView = new ImageView(context); + mSplashScreenView.setScaleType(ImageView.ScaleType.CENTER); + mSplashBackgroundDrawable = new ColorDrawable(); + mSplashBackgroundDrawable.setColor(Color.WHITE); + mSplashBackgroundDrawable.setAlpha(SPLASHSCREEN_ALPHA_INT); + mSplashScreenView.setBackgroundDrawable(mSplashBackgroundDrawable); + addView(mSplashScreenView, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT)); + mSplashScreenView.setAlpha(0f); + + mMarginView = new MarginView(context); + addView(mMarginView, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT)); + } + + public void onThemeChange() { + mCornerRadius = ScreenDecorationsUtils.getWindowCornerRadius(getContext()); + mMarginColor = getResources().getColor(R.color.taskbar_background); + mHighlightColor = getResources().getColor(android.R.color.system_accent1_500); + + final int alpha = mDropZoneDrawable.getAlpha(); + mDropZoneDrawable.setColor(mHighlightColor); + mDropZoneDrawable.setAlpha(alpha); + + if (mMarginPercent > 0) { + mMarginView.invalidate(); + } + } + + /** Sets the desired margins around the drop zone container when fully showing. */ + public void setContainerMargin(float left, float top, float right, float bottom) { + mContainerMargin[0] = left; + mContainerMargin[1] = top; + mContainerMargin[2] = right; + mContainerMargin[3] = bottom; + if (mMarginPercent > 0) { + mMarginView.invalidate(); + } + } + + /** Sets the bottom inset so the drop zones are above bottom navigation. */ + public void setBottomInset(float bottom) { + mBottomInset = bottom; + ((LayoutParams) mSplashScreenView.getLayoutParams()).bottomMargin = (int) bottom; + if (mMarginPercent > 0) { + mMarginView.invalidate(); + } + } + + /** Sets the color and icon to use for the splashscreen when shown. */ + public void setAppInfo(int splashScreenColor, Drawable appIcon) { + mSplashBackgroundDrawable.setColor(splashScreenColor); + mSplashScreenView.setImageDrawable(appIcon); + } + + /** @return an active animator for this view if one exists. */ + @Nullable + public ObjectAnimator getAnimator() { + if (mMarginAnimator != null && mMarginAnimator.isRunning()) { + return mMarginAnimator; + } else if (mHighlightAnimator != null && mHighlightAnimator.isRunning()) { + return mHighlightAnimator; + } else if (mSplashAnimator != null && mSplashAnimator.isRunning()) { + return mSplashAnimator; + } + return null; + } + + /** Animates the splashscreen to show or hide. */ + public void setShowingSplash(boolean showingSplash) { + if (mShowingSplash != showingSplash) { + mShowingSplash = showingSplash; + animateSplashToState(); + } + } + + /** Animates the highlight indicating the zone is hovered on or not. */ + public void setShowingHighlight(boolean showingHighlight) { + if (mShowingHighlight != showingHighlight) { + mShowingHighlight = showingHighlight; + animateHighlightToState(); + } + } + + /** Animates the margins around the drop zone to show or hide. */ + public void setShowingMargin(boolean visible) { + if (mShowingMargin != visible) { + mShowingMargin = visible; + animateMarginToState(); + } + if (!mShowingMargin) { + setShowingHighlight(false); + setShowingSplash(false); + } + } + + private void animateSplashToState() { + if (mSplashAnimator != null) { + mSplashAnimator.cancel(); + } + mSplashAnimator = ObjectAnimator.ofInt(mSplashBackgroundDrawable, + SPLASHSCREEN_ALPHA, + mSplashBackgroundDrawable.getAlpha(), + mShowingSplash ? SPLASHSCREEN_ALPHA_INT : 0); + if (!mShowingSplash) { + mSplashAnimator.setInterpolator(FAST_OUT_SLOW_IN); + } + mSplashAnimator.start(); + mSplashScreenView.animate().alpha(mShowingSplash ? 1f : 0f).start(); + } + + private void animateHighlightToState() { + if (mHighlightAnimator != null) { + mHighlightAnimator.cancel(); + } + mHighlightAnimator = ObjectAnimator.ofInt(mDropZoneDrawable, + HIGHLIGHT_ALPHA, + mDropZoneDrawable.getAlpha(), + mShowingHighlight ? HIGHLIGHT_ALPHA_INT : 0); + if (!mShowingHighlight) { + mHighlightAnimator.setInterpolator(FAST_OUT_SLOW_IN); + } + mHighlightAnimator.start(); + } + + private void animateMarginToState() { + if (mMarginAnimator != null) { + mMarginAnimator.cancel(); + } + mMarginAnimator = ObjectAnimator.ofFloat(this, INSETS, + mMarginPercent, + mShowingMargin ? 1f : 0f); + mMarginAnimator.setInterpolator(FAST_OUT_SLOW_IN); + mMarginAnimator.setDuration(mShowingMargin + ? MARGIN_ANIMATION_ENTER_DURATION + : MARGIN_ANIMATION_EXIT_DURATION); + mMarginAnimator.start(); + } + + private void setMarginPercent(float percent) { + if (percent != mMarginPercent) { + mMarginPercent = percent; + mMarginView.invalidate(); + } + } + + private float getMarginPercent() { + return mMarginPercent; + } + + /** Simple view that draws a rounded rect margin around its contents. **/ + private class MarginView extends View { + + MarginView(Context context) { + super(context); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + mPath.reset(); + mPath.addRoundRect(mContainerMargin[0] * mMarginPercent, + mContainerMargin[1] * mMarginPercent, + getWidth() - (mContainerMargin[2] * mMarginPercent), + getHeight() - (mContainerMargin[3] * mMarginPercent) - mBottomInset, + mCornerRadius * mMarginPercent, + mCornerRadius * mMarginPercent, + Path.Direction.CW); + mPath.setFillType(Path.FillType.INVERSE_EVEN_ODD); + canvas.clipPath(mPath); + canvas.drawColor(mMarginColor); + } + } +} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java index 5c8e7d03eb01..52ff21bc3172 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java @@ -16,7 +16,6 @@ package com.android.wm.shell.freeform; -import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.content.pm.PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT; import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT; @@ -28,7 +27,6 @@ import android.provider.Settings; import android.util.Slog; import android.util.SparseArray; import android.view.SurfaceControl; -import android.window.WindowContainerTransaction; import com.android.internal.protolog.common.ProtoLog; import com.android.wm.shell.ShellTaskOrganizer; @@ -85,13 +83,6 @@ public class FreeformTaskListener implements ShellTaskOrganizer.TaskListener { Slog.e(TAG, "Task already vanished: #" + taskInfo.taskId); return; } - - // Clears windowing mode and window bounds to let the task inherits from its new parent. - final WindowContainerTransaction wct = new WindowContainerTransaction(); - wct.setBounds(taskInfo.token, null) - .setWindowingMode(taskInfo.token, WINDOWING_MODE_UNDEFINED); - mSyncQueue.queue(wct); - ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Freeform Task Vanished: #%d", taskInfo.taskId); mTasks.remove(taskInfo.taskId); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OWNERS b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OWNERS new file mode 100644 index 000000000000..41177f01b208 --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OWNERS @@ -0,0 +1,2 @@ +# WM shell sub-module one handed mode owner +lbill@google.com diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/OWNERS b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/OWNERS new file mode 100644 index 000000000000..afddfab99a2b --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/OWNERS @@ -0,0 +1,2 @@ +# WM shell sub-module pip owner +hwwang@google.com diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipMenuController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipMenuController.java index 8d9ad4d1b96c..caa1f017082b 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipMenuController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipMenuController.java @@ -90,6 +90,11 @@ public interface PipMenuController { default void updateMenuBounds(Rect destinationBounds) {} /** + * Update when the current focused task changes. + */ + default void onFocusTaskChanged(RunningTaskInfo taskInfo) {} + + /** * Returns a default LayoutParams for the PIP Menu. * @param width the PIP stack width. * @param height the PIP stack height. diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java index 6cc5f09827af..854fc60e15e8 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java @@ -98,7 +98,7 @@ import java.util.function.IntConsumer; * see also {@link PipMotionHelper}. */ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, - DisplayController.OnDisplaysChangedListener { + DisplayController.OnDisplaysChangedListener, ShellTaskOrganizer.FocusListener { private static final String TAG = PipTaskOrganizer.class.getSimpleName(); private static final boolean DEBUG = false; /** @@ -286,6 +286,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, mMainExecutor.execute(() -> { mTaskOrganizer.addListenerForType(this, TASK_LISTENER_TYPE_PIP); }); + mTaskOrganizer.addFocusListener(this); mPipTransitionController.setPipOrganizer(this); displayController.addDisplayWindowListener(this); } @@ -772,6 +773,11 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, } @Override + public void onFocusTaskChanged(ActivityManager.RunningTaskInfo taskInfo) { + mPipMenuController.onFocusTaskChanged(taskInfo); + } + + @Override public boolean supportSizeCompatUI() { // PIP doesn't support size compat. return false; @@ -1249,11 +1255,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, } else if (isOutPipDirection(direction)) { // If we are animating to fullscreen or split screen, then we need to reset the // override bounds on the task to ensure that the task "matches" the parent's bounds. - if (direction == TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN) { - taskBounds = destinationBounds; - } else { - taskBounds = null; - } + taskBounds = null; applyWindowingModeChangeOnExit(wct, direction); } else { // Just a resize in PIP @@ -1282,6 +1284,9 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, } private boolean isPipTopLeft() { + if (!mSplitScreenOptional.isPresent()) { + return false; + } final Rect topLeft = new Rect(); final Rect bottomRight = new Rect(); mSplitScreenOptional.get().getStageBounds(topLeft, bottomRight); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipMenuController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipMenuController.java index 5687f4d62444..eb512afa644d 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipMenuController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipMenuController.java @@ -19,6 +19,7 @@ package com.android.wm.shell.pip.phone; import static android.view.WindowManager.SHELL_ROOT_LAYER_PIP; import android.annotation.Nullable; +import android.app.ActivityManager; import android.app.RemoteAction; import android.content.Context; import android.content.pm.ParceledListSlice; @@ -43,10 +44,12 @@ import com.android.wm.shell.pip.PipBoundsState; import com.android.wm.shell.pip.PipMediaController; import com.android.wm.shell.pip.PipMediaController.ActionListener; import com.android.wm.shell.pip.PipMenuController; +import com.android.wm.shell.splitscreen.SplitScreenController; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; +import java.util.Optional; /** * Manages the PiP menu view which can show menu options or a scrim. @@ -114,6 +117,7 @@ public class PhonePipMenuController implements PipMenuController { private final ArrayList<Listener> mListeners = new ArrayList<>(); private final SystemWindows mSystemWindows; + private final Optional<SplitScreenController> mSplitScreenController; private ParceledListSlice<RemoteAction> mAppActions; private ParceledListSlice<RemoteAction> mMediaActions; private SyncRtSurfaceTransactionApplier mApplier; @@ -145,6 +149,7 @@ public class PhonePipMenuController implements PipMenuController { public PhonePipMenuController(Context context, PipBoundsState pipBoundsState, PipMediaController mediaController, SystemWindows systemWindows, + Optional<SplitScreenController> splitScreenOptional, ShellExecutor mainExecutor, Handler mainHandler) { mContext = context; mPipBoundsState = pipBoundsState; @@ -152,6 +157,7 @@ public class PhonePipMenuController implements PipMenuController { mSystemWindows = systemWindows; mMainExecutor = mainExecutor; mMainHandler = mainHandler; + mSplitScreenController = splitScreenOptional; } public boolean isMenuVisible() { @@ -180,7 +186,8 @@ public class PhonePipMenuController implements PipMenuController { if (mPipMenuView != null) { detachPipMenuView(); } - mPipMenuView = new PipMenuView(mContext, this, mMainExecutor, mMainHandler); + mPipMenuView = new PipMenuView(mContext, this, mMainExecutor, mMainHandler, + mSplitScreenController); mSystemWindows.addView(mPipMenuView, getPipMenuLayoutParams(MENU_WINDOW_TITLE, 0 /* width */, 0 /* height */), 0, SHELL_ROOT_LAYER_PIP); @@ -209,6 +216,13 @@ public class PhonePipMenuController implements PipMenuController { updateMenuLayout(destinationBounds); } + @Override + public void onFocusTaskChanged(ActivityManager.RunningTaskInfo taskInfo) { + if (mPipMenuView != null) { + mPipMenuView.onFocusTaskChanged(taskInfo); + } + } + /** * Tries to grab a surface control from {@link PipMenuView}. If this isn't available for some * reason (ie. the window isn't ready yet, thus {@link android.view.ViewRootImpl} is diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java index b209699c1a19..82e827398bb7 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java @@ -16,6 +16,7 @@ package com.android.wm.shell.pip.phone; +import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; import static android.provider.Settings.ACTION_PICTURE_IN_PICTURE_SETTINGS; @@ -32,8 +33,10 @@ import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.annotation.IntDef; +import android.app.ActivityManager; import android.app.PendingIntent.CanceledException; import android.app.RemoteAction; +import android.app.WindowConfiguration; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -61,11 +64,13 @@ import com.android.wm.shell.R; import com.android.wm.shell.animation.Interpolators; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.pip.PipUtils; +import com.android.wm.shell.splitscreen.SplitScreenController; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.List; +import java.util.Optional; /** * Translucent window that gets started on top of a task in PIP to allow the user to control it. @@ -105,6 +110,7 @@ public class PipMenuView extends FrameLayout { private boolean mAllowMenuTimeout = true; private boolean mAllowTouches = true; private int mDismissFadeOutDurationMs; + private boolean mFocusedTaskAllowSplitScreen; private final List<RemoteAction> mActions = new ArrayList<>(); @@ -116,6 +122,7 @@ public class PipMenuView extends FrameLayout { private AnimatorSet mMenuContainerAnimator; private PhonePipMenuController mController; + private Optional<SplitScreenController> mSplitScreenControllerOptional; private ValueAnimator.AnimatorUpdateListener mMenuBgUpdateListener = new ValueAnimator.AnimatorUpdateListener() { @@ -144,12 +151,14 @@ public class PipMenuView extends FrameLayout { protected PipMenuIconsAlgorithm mPipMenuIconsAlgorithm; public PipMenuView(Context context, PhonePipMenuController controller, - ShellExecutor mainExecutor, Handler mainHandler) { + ShellExecutor mainExecutor, Handler mainHandler, + Optional<SplitScreenController> splitScreenController) { super(context, null, 0); mContext = context; mController = controller; mMainExecutor = mainExecutor; mMainHandler = mainHandler; + mSplitScreenControllerOptional = splitScreenController; mAccessibilityManager = context.getSystemService(AccessibilityManager.class); inflate(context, R.layout.pip_menu, this); @@ -255,6 +264,15 @@ public class PipMenuView extends FrameLayout { return super.dispatchGenericMotionEvent(event); } + public void onFocusTaskChanged(ActivityManager.RunningTaskInfo taskInfo) { + final boolean isSplitScreen = mSplitScreenControllerOptional.isPresent() + && mSplitScreenControllerOptional.get().isTaskInSplitScreen(taskInfo.taskId); + mFocusedTaskAllowSplitScreen = isSplitScreen + || (taskInfo.getWindowingMode() == WINDOWING_MODE_FULLSCREEN + && taskInfo.supportsSplitScreenMultiWindow + && taskInfo.topActivityType != WindowConfiguration.ACTIVITY_TYPE_HOME); + } + void showMenu(int menuState, Rect stackBounds, boolean allowMenuTimeout, boolean resizeMenuOnShow, boolean withDelay, boolean showResizeHandle) { mAllowMenuTimeout = allowMenuTimeout; @@ -278,7 +296,8 @@ public class PipMenuView extends FrameLayout { ObjectAnimator dismissAnim = ObjectAnimator.ofFloat(mDismissButton, View.ALPHA, mDismissButton.getAlpha(), 1f); ObjectAnimator enterSplitAnim = ObjectAnimator.ofFloat(mEnterSplitButton, View.ALPHA, - mEnterSplitButton.getAlpha(), ENABLE_ENTER_SPLIT ? 1f : 0f); + mEnterSplitButton.getAlpha(), + ENABLE_ENTER_SPLIT && mFocusedTaskAllowSplitScreen ? 1f : 0f); if (menuState == MENU_STATE_FULL) { mMenuContainerAnimator.playTogether(menuAnim, settingsAnim, dismissAnim, enterSplitAnim); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ISplitScreen.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ISplitScreen.aidl index 3d3a63057dde..3cfa541c1c86 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ISplitScreen.aidl +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ISplitScreen.aidl @@ -65,32 +65,33 @@ interface ISplitScreen { /** * Starts a task in a stage. */ - oneway void startTask(int taskId, int stage, int position, in Bundle options) = 7; + oneway void startTask(int taskId, int position, in Bundle options) = 7; /** * Starts a shortcut in a stage. */ - oneway void startShortcut(String packageName, String shortcutId, int stage, int position, + oneway void startShortcut(String packageName, String shortcutId, int position, in Bundle options, in UserHandle user) = 8; /** * Starts an activity in a stage. */ - oneway void startIntent(in PendingIntent intent, in Intent fillInIntent, int stage, - int position, in Bundle options) = 9; + oneway void startIntent(in PendingIntent intent, in Intent fillInIntent, int position, + in Bundle options) = 9; /** * Starts tasks simultaneously in one transition. */ oneway void startTasks(int mainTaskId, in Bundle mainOptions, int sideTaskId, - in Bundle sideOptions, int sidePosition, in RemoteTransition remoteTransition) = 10; + in Bundle sideOptions, int sidePosition, float splitRatio, + in RemoteTransition remoteTransition) = 10; /** * Version of startTasks using legacy transition system. */ oneway void startTasksWithLegacyTransition(int mainTaskId, in Bundle mainOptions, int sideTaskId, in Bundle sideOptions, int sidePosition, - in RemoteAnimationAdapter adapter) = 11; + float splitRatio, in RemoteAnimationAdapter adapter) = 11; /** * Blocking call that notifies and gets additional split-screen targets when entering diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/OWNERS b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/OWNERS new file mode 100644 index 000000000000..7237d2bde39f --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/OWNERS @@ -0,0 +1,2 @@ +# WM shell sub-modules splitscreen owner +chenghsiuchang@google.com diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java index 6b42ed775fb7..0261df4b291b 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java @@ -183,6 +183,15 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, return mStageCoordinator.isSplitScreenVisible(); } + public boolean isTaskInSplitScreen(int taskId) { + return isSplitScreenVisible() + && mStageCoordinator.getStageOfTask(taskId) != STAGE_TYPE_UNDEFINED; + } + + public @SplitPosition int getSplitPosition(int taskId) { + return mStageCoordinator.getSplitPosition(taskId); + } + public boolean moveToSideStage(int taskId, @SplitPosition int sideStagePosition) { return moveToStage(taskId, STAGE_TYPE_SIDE, sideStagePosition, new WindowContainerTransaction()); @@ -256,9 +265,9 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, mStageCoordinator.unregisterSplitScreenListener(listener); } - public void startTask(int taskId, @SplitScreen.StageType int stage, - @SplitPosition int position, @Nullable Bundle options) { - options = mStageCoordinator.resolveStartStage(stage, position, options, null /* wct */); + public void startTask(int taskId, @SplitPosition int position, @Nullable Bundle options) { + options = mStageCoordinator.resolveStartStage(STAGE_TYPE_UNDEFINED, position, options, + null /* wct */); try { final WindowContainerTransaction evictWct = new WindowContainerTransaction(); @@ -273,10 +282,10 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, } } - public void startShortcut(String packageName, String shortcutId, - @SplitScreen.StageType int stage, @SplitPosition int position, + public void startShortcut(String packageName, String shortcutId, @SplitPosition int position, @Nullable Bundle options, UserHandle user) { - options = mStageCoordinator.resolveStartStage(stage, position, options, null /* wct */); + options = mStageCoordinator.resolveStartStage(STAGE_TYPE_UNDEFINED, position, options, + null /* wct */); final WindowContainerTransaction evictWct = new WindowContainerTransaction(); mStageCoordinator.prepareEvictChildTasks(position, evictWct); @@ -291,20 +300,18 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, } } - public void startIntent(PendingIntent intent, Intent fillInIntent, - @SplitScreen.StageType int stage, @SplitPosition int position, + public void startIntent(PendingIntent intent, Intent fillInIntent, @SplitPosition int position, @Nullable Bundle options) { if (!Transitions.ENABLE_SHELL_TRANSITIONS) { - startIntentLegacy(intent, fillInIntent, stage, position, options); + startIntentLegacy(intent, fillInIntent, position, options); return; } - mStageCoordinator.startIntent(intent, fillInIntent, stage, position, options, + mStageCoordinator.startIntent(intent, fillInIntent, STAGE_TYPE_UNDEFINED, position, options, null /* remote */); } private void startIntentLegacy(PendingIntent intent, Intent fillInIntent, - @SplitScreen.StageType int stage, @SplitPosition int position, - @Nullable Bundle options) { + @SplitPosition int position, @Nullable Bundle options) { final WindowContainerTransaction evictWct = new WindowContainerTransaction(); mStageCoordinator.prepareEvictChildTasks(position, evictWct); @@ -338,7 +345,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, }; final WindowContainerTransaction wct = new WindowContainerTransaction(); - options = mStageCoordinator.resolveStartStage(stage, position, options, wct); + options = mStageCoordinator.resolveStartStage(STAGE_TYPE_UNDEFINED, position, options, wct); wct.sendPendingIntent(intent, fillInIntent, options); mSyncQueue.queue(transition, WindowManager.TRANSIT_OPEN, wct); } @@ -595,49 +602,48 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, } @Override - public void startTask(int taskId, int stage, int position, @Nullable Bundle options) { + public void startTask(int taskId, int position, @Nullable Bundle options) { executeRemoteCallWithTaskPermission(mController, "startTask", (controller) -> { - controller.startTask(taskId, stage, position, options); + controller.startTask(taskId, position, options); }); } @Override public void startTasksWithLegacyTransition(int mainTaskId, @Nullable Bundle mainOptions, int sideTaskId, @Nullable Bundle sideOptions, @SplitPosition int sidePosition, - RemoteAnimationAdapter adapter) { + float splitRatio, RemoteAnimationAdapter adapter) { executeRemoteCallWithTaskPermission(mController, "startTasks", (controller) -> controller.mStageCoordinator.startTasksWithLegacyTransition( mainTaskId, mainOptions, sideTaskId, sideOptions, sidePosition, - adapter)); + splitRatio, adapter)); } @Override public void startTasks(int mainTaskId, @Nullable Bundle mainOptions, int sideTaskId, @Nullable Bundle sideOptions, - @SplitPosition int sidePosition, + @SplitPosition int sidePosition, float splitRatio, @Nullable RemoteTransition remoteTransition) { executeRemoteCallWithTaskPermission(mController, "startTasks", (controller) -> controller.mStageCoordinator.startTasks(mainTaskId, mainOptions, - sideTaskId, sideOptions, sidePosition, remoteTransition)); + sideTaskId, sideOptions, sidePosition, splitRatio, remoteTransition)); } @Override - public void startShortcut(String packageName, String shortcutId, int stage, int position, + public void startShortcut(String packageName, String shortcutId, int position, @Nullable Bundle options, UserHandle user) { executeRemoteCallWithTaskPermission(mController, "startShortcut", (controller) -> { - controller.startShortcut(packageName, shortcutId, stage, position, - options, user); + controller.startShortcut(packageName, shortcutId, position, options, user); }); } @Override - public void startIntent(PendingIntent intent, Intent fillInIntent, int stage, int position, + public void startIntent(PendingIntent intent, Intent fillInIntent, int position, @Nullable Bundle options) { executeRemoteCallWithTaskPermission(mController, "startIntent", (controller) -> { - controller.startIntent(intent, fillInIntent, stage, position, options); + controller.startIntent(intent, fillInIntent, position, options); }); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java index a3726d46d2a4..8ce58ae333f8 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java @@ -274,6 +274,17 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, return mSideStageListener.mVisible && mMainStageListener.mVisible; } + @SplitScreen.StageType + int getStageOfTask(int taskId) { + if (mMainStage.containsTask(taskId)) { + return STAGE_TYPE_MAIN; + } else if (mSideStage.containsTask(taskId)) { + return STAGE_TYPE_SIDE; + } + + return STAGE_TYPE_UNDEFINED; + } + boolean moveToStage(ActivityManager.RunningTaskInfo task, @SplitScreen.StageType int stageType, @SplitPosition int stagePosition, WindowContainerTransaction wct) { StageTaskListener targetStage; @@ -322,7 +333,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, /** Starts 2 tasks in one transition. */ void startTasks(int mainTaskId, @Nullable Bundle mainOptions, int sideTaskId, - @Nullable Bundle sideOptions, @SplitPosition int sidePosition, + @Nullable Bundle sideOptions, @SplitPosition int sidePosition, float splitRatio, @Nullable RemoteTransition remoteTransition) { final WindowContainerTransaction wct = new WindowContainerTransaction(); mainOptions = mainOptions != null ? mainOptions : new Bundle(); @@ -334,6 +345,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, mMainStage.activate(getMainStageBounds(), wct, false /* reparent */); mSideStage.setBounds(getSideStageBounds(), wct); + mSplitLayout.setDivideRatio(splitRatio); // Make sure the launch options will put tasks in the corresponding split roots addActivityOptions(mainOptions, mMainStage); addActivityOptions(sideOptions, mSideStage); @@ -349,7 +361,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, /** Starts 2 tasks in one legacy transition. */ void startTasksWithLegacyTransition(int mainTaskId, @Nullable Bundle mainOptions, int sideTaskId, @Nullable Bundle sideOptions, @SplitPosition int sidePosition, - RemoteAnimationAdapter adapter) { + float splitRatio, RemoteAnimationAdapter adapter) { final WindowContainerTransaction wct = new WindowContainerTransaction(); // Need to add another wrapper here in shell so that we can inject the divider bar // and also manage the process elevation via setRunningRemote @@ -404,6 +416,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, sideOptions = sideOptions != null ? sideOptions : new Bundle(); setSideStagePosition(sidePosition, wct); + mSplitLayout.setDivideRatio(splitRatio); // Build a request WCT that will launch both apps such that task 0 is on the main stage // while task 1 is on the side stage. mMainStage.activate(getMainStageBounds(), wct, false /* reparent */); @@ -449,12 +462,15 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, @androidx.annotation.Nullable WindowContainerTransaction wct) { switch (stage) { case STAGE_TYPE_UNDEFINED: { - // Use the stage of the specified position is valid. if (position != SPLIT_POSITION_UNDEFINED) { - if (position == getSideStagePosition()) { - options = resolveStartStage(STAGE_TYPE_SIDE, position, options, wct); + if (mMainStage.isActive()) { + // Use the stage of the specified position + options = resolveStartStage( + position == mSideStagePosition ? STAGE_TYPE_SIDE : STAGE_TYPE_MAIN, + position, options, wct); } else { - options = resolveStartStage(STAGE_TYPE_MAIN, position, options, wct); + // Use the side stage as default to active split screen + options = resolveStartStage(STAGE_TYPE_SIDE, position, options, wct); } } else { // Exit split-screen and launch fullscreen since stage wasn't specified. @@ -665,6 +681,16 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, outBottomOrRightBounds.set(mSplitLayout.getBounds2()); } + @SplitPosition + int getSplitPosition(int taskId) { + if (mSideStage.getTopVisibleChildTaskId() == taskId) { + return getSideStagePosition(); + } else if (mMainStage.getTopVisibleChildTaskId() == taskId) { + return getMainStagePosition(); + } + return SPLIT_POSITION_UNDEFINED; + } + private void addActivityOptions(Bundle opts, StageTaskListener stage) { opts.putParcelable(KEY_LAUNCH_ROOT_TASK_TOKEN, stage.mRootTaskInfo.token); } @@ -767,7 +793,9 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, if (mMainStageListener.mHasRootTask && mSideStageListener.mHasRootTask) { final WindowContainerTransaction wct = new WindowContainerTransaction(); // Make the stages adjacent to each other so they occlude what's behind them. - wct.setAdjacentRoots(mMainStage.mRootTaskInfo.token, mSideStage.mRootTaskInfo.token); + wct.setAdjacentRoots(mMainStage.mRootTaskInfo.token, mSideStage.mRootTaskInfo.token, + true /* moveTogether */); + wct.setLaunchAdjacentFlagRoot(mSideStage.mRootTaskInfo.token); mTaskOrganizer.applyTransaction(wct); } } @@ -775,6 +803,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, private void onStageRootTaskVanished(StageListenerImpl stageListener) { if (stageListener == mMainStageListener || stageListener == mSideStageListener) { final WindowContainerTransaction wct = new WindowContainerTransaction(); + wct.clearLaunchAdjacentFlagRoot(mSideStage.mRootTaskInfo.token); // Deactivate the main stage if it no longer has a root task. mMainStage.deactivate(wct); mTaskOrganizer.applyTransaction(wct); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/stagesplit/OWNERS b/libs/WindowManager/Shell/src/com/android/wm/shell/stagesplit/OWNERS new file mode 100644 index 000000000000..264e88f32bff --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/stagesplit/OWNERS @@ -0,0 +1,2 @@ +# WM shell sub-modules stagesplit owner +chenghsiuchang@google.com diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/stagesplit/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/stagesplit/SplitScreenController.java index 94db9cd958a3..ad2b988a67ff 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/stagesplit/SplitScreenController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/stagesplit/SplitScreenController.java @@ -22,6 +22,7 @@ import static android.view.RemoteAnimationTarget.MODE_OPENING; import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission; import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_BOTTOM_OR_RIGHT; import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_TOP_OR_LEFT; +import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_UNDEFINED; import android.app.ActivityManager; import android.app.ActivityTaskManager; @@ -208,9 +209,9 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, mStageCoordinator.unregisterSplitScreenListener(listener); } - public void startTask(int taskId, @SplitScreen.StageType int stage, - @SplitPosition int position, @Nullable Bundle options) { - options = mStageCoordinator.resolveStartStage(stage, position, options, null /* wct */); + public void startTask(int taskId, @SplitPosition int position, @Nullable Bundle options) { + options = mStageCoordinator.resolveStartStage(STAGE_TYPE_UNDEFINED, position, options, + null /* wct */); try { ActivityTaskManager.getService().startActivityFromRecents(taskId, options); @@ -219,10 +220,10 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, } } - public void startShortcut(String packageName, String shortcutId, - @SplitScreen.StageType int stage, @SplitPosition int position, + public void startShortcut(String packageName, String shortcutId, @SplitPosition int position, @Nullable Bundle options, UserHandle user) { - options = mStageCoordinator.resolveStartStage(stage, position, options, null /* wct */); + options = mStageCoordinator.resolveStartStage(STAGE_TYPE_UNDEFINED, position, options, + null /* wct */); try { LauncherApps launcherApps = @@ -234,20 +235,18 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, } } - public void startIntent(PendingIntent intent, Intent fillInIntent, - @SplitScreen.StageType int stage, @SplitPosition int position, + public void startIntent(PendingIntent intent, Intent fillInIntent, @SplitPosition int position, @Nullable Bundle options) { if (!Transitions.ENABLE_SHELL_TRANSITIONS) { - startIntentLegacy(intent, fillInIntent, stage, position, options); + startIntentLegacy(intent, fillInIntent, position, options); return; } - mStageCoordinator.startIntent(intent, fillInIntent, stage, position, options, + mStageCoordinator.startIntent(intent, fillInIntent, STAGE_TYPE_UNDEFINED, position, options, null /* remote */); } private void startIntentLegacy(PendingIntent intent, Intent fillInIntent, - @SplitScreen.StageType int stage, @SplitPosition int position, - @Nullable Bundle options) { + @SplitPosition int position, @Nullable Bundle options) { LegacyTransitions.ILegacyTransition transition = new LegacyTransitions.ILegacyTransition() { @Override public void onAnimationStart(int transit, RemoteAnimationTarget[] apps, @@ -275,7 +274,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, } }; WindowContainerTransaction wct = new WindowContainerTransaction(); - options = mStageCoordinator.resolveStartStage(stage, position, options, wct); + options = mStageCoordinator.resolveStartStage(STAGE_TYPE_UNDEFINED, position, options, wct); wct.sendPendingIntent(intent, fillInIntent, options); mSyncQueue.queue(transition, WindowManager.TRANSIT_OPEN, wct); } @@ -539,7 +538,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, public void startTask(int taskId, int stage, int position, @Nullable Bundle options) { executeRemoteCallWithTaskPermission(mController, "startTask", (controller) -> { - controller.startTask(taskId, stage, position, options); + controller.startTask(taskId, position, options); }); } @@ -568,7 +567,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, @Nullable Bundle options, UserHandle user) { executeRemoteCallWithTaskPermission(mController, "startShortcut", (controller) -> { - controller.startShortcut(packageName, shortcutId, stage, position, + controller.startShortcut(packageName, shortcutId, position, options, user); }); } @@ -578,7 +577,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, @Nullable Bundle options) { executeRemoteCallWithTaskPermission(mController, "startIntent", (controller) -> { - controller.startIntent(intent, fillInIntent, stage, position, options); + controller.startIntent(intent, fillInIntent, position, options); }); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/stagesplit/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/stagesplit/StageCoordinator.java index 60a6cd78c4fc..47eb271800c3 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/stagesplit/StageCoordinator.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/stagesplit/StageCoordinator.java @@ -634,7 +634,8 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, mUseLegacySplit = mContext.getResources().getBoolean(R.bool.config_useLegacySplit); final WindowContainerTransaction wct = new WindowContainerTransaction(); // Make the stages adjacent to each other so they occlude what's behind them. - wct.setAdjacentRoots(mMainStage.mRootTaskInfo.token, mSideStage.mRootTaskInfo.token); + wct.setAdjacentRoots(mMainStage.mRootTaskInfo.token, mSideStage.mRootTaskInfo.token, + true /* moveTogether */); // Only sets side stage as launch-adjacent-flag-root when the device is not using legacy // split to prevent new split behavior confusing users. diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashScreenExitAnimation.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashScreenExitAnimation.java index 003d8a3f2fef..e7b5744dd21b 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashScreenExitAnimation.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashScreenExitAnimation.java @@ -72,6 +72,7 @@ public class SplashScreenExitAnimation implements Animator.AnimatorListener { private final int mAppRevealDuration; private final int mAnimationDuration; private final float mIconStartAlpha; + private final float mBrandingStartAlpha; private final TransactionPool mTransactionPool; private ValueAnimator mMainAnimator; @@ -94,9 +95,17 @@ public class SplashScreenExitAnimation implements Animator.AnimatorListener { || iconView.getLayoutParams().height == 0) { mIconFadeOutDuration = 0; mIconStartAlpha = 0; + mBrandingStartAlpha = 0; mAppRevealDelay = 0; } else { iconView.setLayerType(View.LAYER_TYPE_HARDWARE, null); + // The branding view could only exists when the icon is present. + final View brandingView = view.getBrandingView(); + if (brandingView != null) { + mBrandingStartAlpha = brandingView.getAlpha(); + } else { + mBrandingStartAlpha = 0; + } mIconFadeOutDuration = context.getResources().getInteger( R.integer.starting_window_app_reveal_icon_fade_out_duration); mAppRevealDelay = context.getResources().getInteger( @@ -334,13 +343,21 @@ public class SplashScreenExitAnimation implements Animator.AnimatorListener { // ignore } - private void onAnimationProgress(float linearProgress) { - View iconView = mSplashScreenView.getIconView(); + private void onFadeOutProgress(float linearProgress) { + final float iconProgress = ICON_INTERPOLATOR.getInterpolation( + getProgress(linearProgress, 0 /* delay */, mIconFadeOutDuration)); + final View iconView = mSplashScreenView.getIconView(); + final View brandingView = mSplashScreenView.getBrandingView(); if (iconView != null) { - final float iconProgress = ICON_INTERPOLATOR.getInterpolation( - getProgress(linearProgress, 0 /* delay */, mIconFadeOutDuration)); iconView.setAlpha(mIconStartAlpha * (1 - iconProgress)); } + if (brandingView != null) { + brandingView.setAlpha(mBrandingStartAlpha * (1 - iconProgress)); + } + } + + private void onAnimationProgress(float linearProgress) { + onFadeOutProgress(linearProgress); final float revealLinearProgress = getProgress(linearProgress, mAppRevealDelay, mAppRevealDuration); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java index bd4869670bec..270107c01335 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java @@ -134,7 +134,8 @@ public class StartingSurfaceDrawer { mDisplayManager.getDisplay(DEFAULT_DISPLAY); } - private final SparseArray<StartingWindowRecord> mStartingWindowRecords = new SparseArray<>(); + @VisibleForTesting + final SparseArray<StartingWindowRecord> mStartingWindowRecords = new SparseArray<>(); /** * Records of {@link SurfaceControlViewHost} where the splash screen icon animation is @@ -464,8 +465,24 @@ public class StartingSurfaceDrawer { Slog.d(TAG, "Task start finish, remove starting surface for task " + removalInfo.taskId); } - removeWindowSynced(removalInfo); + removeWindowSynced(removalInfo, false /* immediately */); + } + /** + * Clear all starting windows immediately. + */ + public void clearAllWindows() { + if (DEBUG_SPLASH_SCREEN || DEBUG_TASK_SNAPSHOT) { + Slog.d(TAG, "Clear all starting windows immediately"); + } + final int taskSize = mStartingWindowRecords.size(); + final int[] taskIds = new int[taskSize]; + for (int i = taskSize - 1; i >= 0; --i) { + taskIds[i] = mStartingWindowRecords.keyAt(i); + } + for (int i = taskSize - 1; i >= 0; --i) { + removeWindowNoAnimate(taskIds[i]); + } } /** @@ -550,7 +567,8 @@ public class StartingSurfaceDrawer { return shouldSaveView; } - private void saveSplashScreenRecord(IBinder appToken, int taskId, View view, + @VisibleForTesting + void saveSplashScreenRecord(IBinder appToken, int taskId, View view, @StartingWindowType int suggestType) { final StartingWindowRecord tView = new StartingWindowRecord(appToken, view, null/* TaskSnapshotWindow */, suggestType); @@ -559,19 +577,18 @@ public class StartingSurfaceDrawer { private void removeWindowNoAnimate(int taskId) { mTmpRemovalInfo.taskId = taskId; - removeWindowSynced(mTmpRemovalInfo); + removeWindowSynced(mTmpRemovalInfo, true /* immediately */); } void onImeDrawnOnTask(int taskId) { final StartingWindowRecord record = mStartingWindowRecords.get(taskId); if (record != null && record.mTaskSnapshotWindow != null && record.mTaskSnapshotWindow.hasImeSurface()) { - record.mTaskSnapshotWindow.removeImmediately(); + removeWindowNoAnimate(taskId); } - mStartingWindowRecords.remove(taskId); } - protected void removeWindowSynced(StartingWindowRemovalInfo removalInfo) { + protected void removeWindowSynced(StartingWindowRemovalInfo removalInfo, boolean immediately) { final int taskId = removalInfo.taskId; final StartingWindowRecord record = mStartingWindowRecords.get(taskId); if (record != null) { @@ -580,7 +597,8 @@ public class StartingSurfaceDrawer { Slog.v(TAG, "Removing splash screen window for task: " + taskId); } if (record.mContentView != null) { - if (record.mSuggestType == STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN) { + if (immediately + || record.mSuggestType == STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN) { removeWindowInner(record.mDecorView, false); } else { if (removalInfo.playRevealAnimation) { @@ -604,8 +622,12 @@ public class StartingSurfaceDrawer { if (DEBUG_TASK_SNAPSHOT) { Slog.v(TAG, "Removing task snapshot window for " + taskId); } - record.mTaskSnapshotWindow.scheduleRemove( - () -> mStartingWindowRecords.remove(taskId), removalInfo.deferRemoveForIme); + if (immediately) { + record.mTaskSnapshotWindow.removeImmediately(); + } else { + record.mTaskSnapshotWindow.scheduleRemove(() -> + mStartingWindowRecords.remove(taskId), removalInfo.deferRemoveForIme); + } } } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java index e98a3e87c0b7..b0a66059a466 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java @@ -29,9 +29,7 @@ import android.app.TaskInfo; import android.content.Context; import android.graphics.Color; import android.os.IBinder; -import android.os.RemoteException; import android.os.Trace; -import android.util.Slog; import android.util.SparseIntArray; import android.window.StartingWindowInfo; import android.window.StartingWindowInfo.StartingWindowType; @@ -199,6 +197,18 @@ public class StartingWindowController implements RemoteCallable<StartingWindowCo } /** + * Clear all starting window immediately, called this method when releasing the task organizer. + */ + public void clearAllWindows() { + mSplashScreenExecutor.execute(() -> { + mStartingSurfaceDrawer.clearAllWindows(); + synchronized (mTaskBackgroundColors) { + mTaskBackgroundColors.clear(); + } + }); + } + + /** * The interface for calls from outside the Shell, within the host process. */ private class StartingSurfaceImpl implements StartingSurface { diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java index 73eebad040d8..453050fcfab4 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java @@ -106,6 +106,12 @@ public class SplitLayoutTests extends ShellTestCase { } @Test + public void testSetDivideRatio() { + mSplitLayout.setDivideRatio(0.5f); + verify(mSplitLayoutHandler).onLayoutSizeChanged(any(SplitLayout.class)); + } + + @Test public void testOnDoubleTappedDivider() { mSplitLayout.onDoubleTappedDivider(); verify(mSplitLayoutHandler).onDoubleTappedDivider(); diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropControllerTest.java index bfa2c92f6679..9f745208d3ed 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropControllerTest.java @@ -30,7 +30,9 @@ import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.internal.logging.UiEventLogger; +import com.android.launcher3.icons.IconProvider; import com.android.wm.shell.common.DisplayController; +import com.android.wm.shell.common.ShellExecutor; import org.junit.Before; import org.junit.Test; @@ -59,8 +61,8 @@ public class DragAndDropControllerTest { @Before public void setUp() throws RemoteException { MockitoAnnotations.initMocks(this); - - mController = new DragAndDropController(mContext, mDisplayController, mUiEventLogger); + mController = new DragAndDropController(mContext, mDisplayController, mUiEventLogger, + mock(IconProvider.class), mock(ShellExecutor.class)); } @Test diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropPolicyTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropPolicyTest.java index 734b97b69c87..7fbffc9b4853 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropPolicyTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropPolicyTest.java @@ -32,8 +32,6 @@ import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_SPL import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_SPLIT_LEFT; import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_SPLIT_RIGHT; import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_SPLIT_TOP; -import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_SIDE; -import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_UNDEFINED; import static junit.framework.Assert.assertTrue; import static junit.framework.Assert.fail; @@ -149,7 +147,6 @@ public class DragAndDropPolicyTest { mSplitPrimaryAppTask = createTaskInfo(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD); - setInSplitScreen(false); setRunningTask(mFullscreenAppTask); } @@ -198,10 +195,6 @@ public class DragAndDropPolicyTest { : ActivityInfo.RESIZE_MODE_UNRESIZEABLE; } - private void setInSplitScreen(boolean inSplitscreen) { - doReturn(inSplitscreen).when(mSplitScreenStarter).isSplitScreenVisible(); - } - @Test public void testDragAppOverFullscreenHome_expectOnlyFullscreenTarget() { setRunningTask(mHomeTask); @@ -211,7 +204,7 @@ public class DragAndDropPolicyTest { mPolicy.handleDrop(filterTargetByType(targets, TYPE_FULLSCREEN), mActivityClipData); verify(mSplitScreenStarter).startIntent(any(), any(), - eq(STAGE_TYPE_UNDEFINED), eq(SPLIT_POSITION_UNDEFINED), any()); + eq(SPLIT_POSITION_UNDEFINED), any()); } @Test @@ -223,12 +216,12 @@ public class DragAndDropPolicyTest { mPolicy.handleDrop(filterTargetByType(targets, TYPE_SPLIT_LEFT), mActivityClipData); verify(mSplitScreenStarter).startIntent(any(), any(), - eq(STAGE_TYPE_SIDE), eq(SPLIT_POSITION_TOP_OR_LEFT), any()); + eq(SPLIT_POSITION_TOP_OR_LEFT), any()); reset(mSplitScreenStarter); mPolicy.handleDrop(filterTargetByType(targets, TYPE_SPLIT_RIGHT), mActivityClipData); verify(mSplitScreenStarter).startIntent(any(), any(), - eq(STAGE_TYPE_SIDE), eq(SPLIT_POSITION_BOTTOM_OR_RIGHT), any()); + eq(SPLIT_POSITION_BOTTOM_OR_RIGHT), any()); } @Test @@ -240,64 +233,12 @@ public class DragAndDropPolicyTest { mPolicy.handleDrop(filterTargetByType(targets, TYPE_SPLIT_TOP), mActivityClipData); verify(mSplitScreenStarter).startIntent(any(), any(), - eq(STAGE_TYPE_SIDE), eq(SPLIT_POSITION_TOP_OR_LEFT), any()); + eq(SPLIT_POSITION_TOP_OR_LEFT), any()); reset(mSplitScreenStarter); mPolicy.handleDrop(filterTargetByType(targets, TYPE_SPLIT_BOTTOM), mActivityClipData); verify(mSplitScreenStarter).startIntent(any(), any(), - eq(STAGE_TYPE_SIDE), eq(SPLIT_POSITION_BOTTOM_OR_RIGHT), any()); - } - - @Test - public void testDragAppOverSplitApp_expectSplitTargets_DropLeft() { - setInSplitScreen(true); - setRunningTask(mSplitPrimaryAppTask); - mPolicy.start(mLandscapeDisplayLayout, mActivityClipData, mLoggerSessionId); - ArrayList<Target> targets = assertExactTargetTypes( - mPolicy.getTargets(mInsets), TYPE_SPLIT_LEFT, TYPE_SPLIT_RIGHT); - - mPolicy.handleDrop(filterTargetByType(targets, TYPE_SPLIT_LEFT), mActivityClipData); - verify(mSplitScreenStarter).startIntent(any(), any(), - eq(STAGE_TYPE_UNDEFINED), eq(SPLIT_POSITION_TOP_OR_LEFT), any()); - } - - @Test - public void testDragAppOverSplitApp_expectSplitTargets_DropRight() { - setInSplitScreen(true); - setRunningTask(mSplitPrimaryAppTask); - mPolicy.start(mLandscapeDisplayLayout, mActivityClipData, mLoggerSessionId); - ArrayList<Target> targets = assertExactTargetTypes( - mPolicy.getTargets(mInsets), TYPE_SPLIT_LEFT, TYPE_SPLIT_RIGHT); - - mPolicy.handleDrop(filterTargetByType(targets, TYPE_SPLIT_RIGHT), mActivityClipData); - verify(mSplitScreenStarter).startIntent(any(), any(), - eq(STAGE_TYPE_UNDEFINED), eq(SPLIT_POSITION_BOTTOM_OR_RIGHT), any()); - } - - @Test - public void testDragAppOverSplitAppPhone_expectVerticalSplitTargets_DropTop() { - setInSplitScreen(true); - setRunningTask(mSplitPrimaryAppTask); - mPolicy.start(mPortraitDisplayLayout, mActivityClipData, mLoggerSessionId); - ArrayList<Target> targets = assertExactTargetTypes( - mPolicy.getTargets(mInsets), TYPE_SPLIT_TOP, TYPE_SPLIT_BOTTOM); - - mPolicy.handleDrop(filterTargetByType(targets, TYPE_SPLIT_TOP), mActivityClipData); - verify(mSplitScreenStarter).startIntent(any(), any(), - eq(STAGE_TYPE_UNDEFINED), eq(SPLIT_POSITION_TOP_OR_LEFT), any()); - } - - @Test - public void testDragAppOverSplitAppPhone_expectVerticalSplitTargets_DropBottom() { - setInSplitScreen(true); - setRunningTask(mSplitPrimaryAppTask); - mPolicy.start(mPortraitDisplayLayout, mActivityClipData, mLoggerSessionId); - ArrayList<Target> targets = assertExactTargetTypes( - mPolicy.getTargets(mInsets), TYPE_SPLIT_TOP, TYPE_SPLIT_BOTTOM); - - mPolicy.handleDrop(filterTargetByType(targets, TYPE_SPLIT_BOTTOM), mActivityClipData); - verify(mSplitScreenStarter).startIntent(any(), any(), - eq(STAGE_TYPE_UNDEFINED), eq(SPLIT_POSITION_BOTTOM_OR_RIGHT), any()); + eq(SPLIT_POSITION_BOTTOM_OR_RIGHT), any()); } @Test diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java index ef14d84c6a09..8128bbe3709e 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java @@ -21,6 +21,7 @@ import static android.view.Display.DEFAULT_DISPLAY; import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_BOTTOM_OR_RIGHT; import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_TOP_OR_LEFT; +import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_UNDEFINED; import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_MAIN; import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_SIDE; import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_UNDEFINED; @@ -28,10 +29,13 @@ import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.clearInvocations; +import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -105,7 +109,8 @@ public class StageCoordinatorTests extends ShellTestCase { @Before public void setup() { MockitoAnnotations.initMocks(this); - mStageCoordinator = createStageCoordinator(/* splitLayout */ null); + mStageCoordinator = spy(createStageCoordinator(/* splitLayout */ null)); + doNothing().when(mStageCoordinator).updateActivityOptions(any(), anyInt()); when(mSplitLayout.getBounds1()).thenReturn(mBounds1); when(mSplitLayout.getBounds2()).thenReturn(mBounds2); @@ -224,6 +229,63 @@ public class StageCoordinatorTests extends ShellTestCase { verify(mMainStage).deactivate(any(WindowContainerTransaction.class), eq(false)); } + @Test + public void testResolveStartStage_beforeSplitActivated_setsStagePosition() { + mStageCoordinator.setSideStagePosition(SPLIT_POSITION_TOP_OR_LEFT, null /* wct */); + + mStageCoordinator.resolveStartStage(STAGE_TYPE_UNDEFINED, SPLIT_POSITION_BOTTOM_OR_RIGHT, + null /* options */, null /* wct */); + assertEquals(mStageCoordinator.getSideStagePosition(), SPLIT_POSITION_BOTTOM_OR_RIGHT); + verify(mStageCoordinator).updateActivityOptions(any(), eq(SPLIT_POSITION_BOTTOM_OR_RIGHT)); + + mStageCoordinator.resolveStartStage(STAGE_TYPE_UNDEFINED, SPLIT_POSITION_TOP_OR_LEFT, + null /* options */, null /* wct */); + assertEquals(mStageCoordinator.getSideStagePosition(), SPLIT_POSITION_TOP_OR_LEFT); + verify(mStageCoordinator).updateActivityOptions(any(), eq(SPLIT_POSITION_TOP_OR_LEFT)); + } + + @Test + public void testResolveStartStage_afterSplitActivated_retrievesStagePosition() { + when(mMainStage.isActive()).thenReturn(true); + mStageCoordinator.setSideStagePosition(SPLIT_POSITION_TOP_OR_LEFT, null /* wct */); + + mStageCoordinator.resolveStartStage(STAGE_TYPE_UNDEFINED, SPLIT_POSITION_TOP_OR_LEFT, + null /* options */, null /* wct */); + assertEquals(mStageCoordinator.getSideStagePosition(), SPLIT_POSITION_TOP_OR_LEFT); + verify(mStageCoordinator).updateActivityOptions(any(), eq(SPLIT_POSITION_TOP_OR_LEFT)); + + mStageCoordinator.resolveStartStage(STAGE_TYPE_UNDEFINED, SPLIT_POSITION_BOTTOM_OR_RIGHT, + null /* options */, null /* wct */); + assertEquals(mStageCoordinator.getMainStagePosition(), SPLIT_POSITION_BOTTOM_OR_RIGHT); + verify(mStageCoordinator).updateActivityOptions(any(), eq(SPLIT_POSITION_BOTTOM_OR_RIGHT)); + } + + @Test + public void testResolveStartStage_setsSideStagePosition() { + mStageCoordinator.setSideStagePosition(SPLIT_POSITION_TOP_OR_LEFT, null /* wct */); + + mStageCoordinator.resolveStartStage(STAGE_TYPE_SIDE, SPLIT_POSITION_BOTTOM_OR_RIGHT, + null /* options */, null /* wct */); + assertEquals(mStageCoordinator.getSideStagePosition(), SPLIT_POSITION_BOTTOM_OR_RIGHT); + + mStageCoordinator.resolveStartStage(STAGE_TYPE_MAIN, SPLIT_POSITION_BOTTOM_OR_RIGHT, + null /* options */, null /* wct */); + assertEquals(mStageCoordinator.getMainStagePosition(), SPLIT_POSITION_BOTTOM_OR_RIGHT); + } + + @Test + public void testResolveStartStage_retrievesStagePosition() { + mStageCoordinator.setSideStagePosition(SPLIT_POSITION_TOP_OR_LEFT, null /* wct */); + + mStageCoordinator.resolveStartStage(STAGE_TYPE_SIDE, SPLIT_POSITION_UNDEFINED, + null /* options */, null /* wct */); + assertEquals(mStageCoordinator.getSideStagePosition(), SPLIT_POSITION_TOP_OR_LEFT); + + mStageCoordinator.resolveStartStage(STAGE_TYPE_MAIN, SPLIT_POSITION_UNDEFINED, + null /* options */, null /* wct */); + assertEquals(mStageCoordinator.getMainStagePosition(), SPLIT_POSITION_BOTTOM_OR_RIGHT); + } + private StageCoordinator createStageCoordinator(SplitLayout splitLayout) { return new SplitTestUtils.TestStageCoordinator(mContext, DEFAULT_DISPLAY, mSyncQueue, mRootTDAOrganizer, mTaskOrganizer, mMainStage, mSideStage, diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java index 70b7c6793492..d92b12e60780 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java @@ -31,6 +31,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -117,16 +118,19 @@ public class StartingSurfaceDrawerTests { WindowManager.LayoutParams params, int suggestType) { // listen for addView mAddWindowForTask = taskId; + saveSplashScreenRecord(appToken, taskId, view, suggestType); // Do not wait for background color return false; } @Override - protected void removeWindowSynced(StartingWindowRemovalInfo removalInfo) { + protected void removeWindowSynced(StartingWindowRemovalInfo removalInfo, + boolean immediately) { // listen for removeView if (mAddWindowForTask == removalInfo.taskId) { mAddWindowForTask = 0; } + mStartingWindowRecords.remove(removalInfo.taskId); } } @@ -179,7 +183,7 @@ public class StartingSurfaceDrawerTests { removalInfo.taskId = windowInfo.taskInfo.taskId; mStartingSurfaceDrawer.removeStartingWindow(removalInfo); waitHandlerIdle(mTestHandler); - verify(mStartingSurfaceDrawer).removeWindowSynced(any()); + verify(mStartingSurfaceDrawer).removeWindowSynced(any(), eq(false)); assertEquals(mStartingSurfaceDrawer.mAddWindowForTask, 0); } @@ -267,11 +271,32 @@ public class StartingSurfaceDrawerTests { // Verify the task snapshot with IME snapshot will be removed when received the real IME // drawn callback. + // makeTaskSnapshotWindow shall call removeWindowSynced before there add a new + // StartingWindowRecord for the task. mStartingSurfaceDrawer.onImeDrawnOnTask(1); - verify(mockSnapshotWindow).removeImmediately(); + verify(mStartingSurfaceDrawer, times(2)) + .removeWindowSynced(any(), eq(true)); } } + @Test + public void testClearAllWindows() { + final int taskId = 1; + final StartingWindowInfo windowInfo = + createWindowInfo(taskId, android.R.style.Theme); + mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo, mBinder, + STARTING_WINDOW_TYPE_SPLASH_SCREEN); + waitHandlerIdle(mTestHandler); + verify(mStartingSurfaceDrawer).addWindow(eq(taskId), eq(mBinder), any(), any(), any(), + eq(STARTING_WINDOW_TYPE_SPLASH_SCREEN)); + assertEquals(mStartingSurfaceDrawer.mAddWindowForTask, taskId); + + mStartingSurfaceDrawer.clearAllWindows(); + waitHandlerIdle(mTestHandler); + verify(mStartingSurfaceDrawer).removeWindowSynced(any(), eq(true)); + assertEquals(mStartingSurfaceDrawer.mStartingWindowRecords.size(), 0); + } + private StartingWindowInfo createWindowInfo(int taskId, int themeResId) { StartingWindowInfo windowInfo = new StartingWindowInfo(); final ActivityInfo info = new ActivityInfo(); diff --git a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp index 54367b8334cb..b5536ad4830d 100644 --- a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp +++ b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp @@ -73,6 +73,10 @@ struct { } gFrameDrawingCallback; struct { + jmethodID onFrameCommit; +} gFrameCommitCallback; + +struct { jmethodID onFrameComplete; } gFrameCompleteCallback; @@ -101,22 +105,21 @@ private: JavaVM* mVm; }; -class FrameCompleteWrapper : public LightRefBase<FrameCompleteWrapper> { +class FrameCommitWrapper : public LightRefBase<FrameCommitWrapper> { public: - explicit FrameCompleteWrapper(JNIEnv* env, jobject jobject) { + explicit FrameCommitWrapper(JNIEnv* env, jobject jobject) { env->GetJavaVM(&mVm); mObject = env->NewGlobalRef(jobject); LOG_ALWAYS_FATAL_IF(!mObject, "Failed to make global ref"); } - ~FrameCompleteWrapper() { - releaseObject(); - } + ~FrameCommitWrapper() { releaseObject(); } - void onFrameComplete(int64_t frameNr) { + void onFrameCommit(bool didProduceBuffer) { if (mObject) { - ATRACE_FORMAT("frameComplete %" PRId64, frameNr); - getenv(mVm)->CallVoidMethod(mObject, gFrameCompleteCallback.onFrameComplete, frameNr); + ATRACE_FORMAT("frameCommit success=%d", didProduceBuffer); + getenv(mVm)->CallVoidMethod(mObject, gFrameCommitCallback.onFrameCommit, + didProduceBuffer); releaseObject(); } } @@ -637,15 +640,33 @@ static void android_view_ThreadedRenderer_setFrameCallback(JNIEnv* env, } } +static void android_view_ThreadedRenderer_setFrameCommitCallback(JNIEnv* env, jobject clazz, + jlong proxyPtr, jobject callback) { + RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); + if (!callback) { + proxy->setFrameCommitCallback(nullptr); + } else { + sp<FrameCommitWrapper> wrapper = new FrameCommitWrapper{env, callback}; + proxy->setFrameCommitCallback( + [wrapper](bool didProduceBuffer) { wrapper->onFrameCommit(didProduceBuffer); }); + } +} + static void android_view_ThreadedRenderer_setFrameCompleteCallback(JNIEnv* env, jobject clazz, jlong proxyPtr, jobject callback) { RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); if (!callback) { proxy->setFrameCompleteCallback(nullptr); } else { - sp<FrameCompleteWrapper> wrapper = new FrameCompleteWrapper{env, callback}; - proxy->setFrameCompleteCallback([wrapper](int64_t frameNr) { - wrapper->onFrameComplete(frameNr); + RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); + JavaVM* vm = nullptr; + LOG_ALWAYS_FATAL_IF(env->GetJavaVM(&vm) != JNI_OK, "Unable to get Java VM"); + auto globalCallbackRef = + std::make_shared<JGlobalRefHolder>(vm, env->NewGlobalRef(callback)); + proxy->setFrameCompleteCallback([globalCallbackRef]() { + JNIEnv* env = getenv(globalCallbackRef->vm()); + env->CallVoidMethod(globalCallbackRef->object(), + gFrameCompleteCallback.onFrameComplete); }); } } @@ -929,6 +950,8 @@ static const JNINativeMethod gMethods[] = { (void*)android_view_ThreadedRenderer_setPrepareSurfaceControlForWebviewCallback}, {"nSetFrameCallback", "(JLandroid/graphics/HardwareRenderer$FrameDrawingCallback;)V", (void*)android_view_ThreadedRenderer_setFrameCallback}, + {"nSetFrameCommitCallback", "(JLandroid/graphics/HardwareRenderer$FrameCommitCallback;)V", + (void*)android_view_ThreadedRenderer_setFrameCommitCallback}, {"nSetFrameCompleteCallback", "(JLandroid/graphics/HardwareRenderer$FrameCompleteCallback;)V", (void*)android_view_ThreadedRenderer_setFrameCompleteCallback}, @@ -994,10 +1017,15 @@ int register_android_view_ThreadedRenderer(JNIEnv* env) { gFrameDrawingCallback.onFrameDraw = GetMethodIDOrDie(env, frameCallbackClass, "onFrameDraw", "(J)V"); + jclass frameCommitClass = + FindClassOrDie(env, "android/graphics/HardwareRenderer$FrameCommitCallback"); + gFrameCommitCallback.onFrameCommit = + GetMethodIDOrDie(env, frameCommitClass, "onFrameCommit", "(Z)V"); + jclass frameCompleteClass = FindClassOrDie(env, "android/graphics/HardwareRenderer$FrameCompleteCallback"); - gFrameCompleteCallback.onFrameComplete = GetMethodIDOrDie(env, frameCompleteClass, - "onFrameComplete", "(J)V"); + gFrameCompleteCallback.onFrameComplete = + GetMethodIDOrDie(env, frameCompleteClass, "onFrameComplete", "()V"); void* handle_ = dlopen("libandroid.so", RTLD_NOW | RTLD_NODELETE); fromSurface = (ANW_fromSurface)dlsym(handle_, "ANativeWindow_fromSurface"); diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp index 2f3a509831d1..a066e6f7c693 100644 --- a/libs/hwui/renderthread/CanvasContext.cpp +++ b/libs/hwui/renderthread/CanvasContext.cpp @@ -491,10 +491,10 @@ nsecs_t CanvasContext::draw() { // Notify the callbacks, even if there's nothing to draw so they aren't waiting // indefinitely waitOnFences(); - for (auto& func : mFrameCompleteCallbacks) { - std::invoke(func, mFrameNumber); + for (auto& func : mFrameCommitCallbacks) { + std::invoke(func, false /* didProduceBuffer */); } - mFrameCompleteCallbacks.clear(); + mFrameCommitCallbacks.clear(); return 0; } @@ -603,10 +603,10 @@ nsecs_t CanvasContext::draw() { #endif if (didSwap) { - for (auto& func : mFrameCompleteCallbacks) { - std::invoke(func, frameCompleteNr); + for (auto& func : mFrameCommitCallbacks) { + std::invoke(func, true /* didProduceBuffer */); } - mFrameCompleteCallbacks.clear(); + mFrameCommitCallbacks.clear(); } if (requireSwap) { diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h index 6dbfcc349d50..9df429badd5e 100644 --- a/libs/hwui/renderthread/CanvasContext.h +++ b/libs/hwui/renderthread/CanvasContext.h @@ -187,8 +187,8 @@ public: IRenderPipeline* getRenderPipeline() { return mRenderPipeline.get(); } - void addFrameCompleteListener(std::function<void(int64_t)>&& func) { - mFrameCompleteCallbacks.push_back(std::move(func)); + void addFrameCommitListener(std::function<void(bool)>&& func) { + mFrameCommitCallbacks.push_back(std::move(func)); } void setPictureCapturedCallback(const std::function<void(sk_sp<SkPicture>&&)>& callback) { @@ -320,7 +320,7 @@ private: std::vector<std::future<void>> mFrameFences; std::unique_ptr<IRenderPipeline> mRenderPipeline; - std::vector<std::function<void(int64_t)>> mFrameCompleteCallbacks; + std::vector<std::function<void(bool)>> mFrameCommitCallbacks; // If set to true, we expect that callbacks into onSurfaceStatsAvailable bool mExpectSurfaceStats = false; diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp index e7081df2b558..94aedd0f43be 100644 --- a/libs/hwui/renderthread/DrawFrameTask.cpp +++ b/libs/hwui/renderthread/DrawFrameTask.cpp @@ -150,16 +150,18 @@ void DrawFrameTask::run() { canUnblockUiThread = syncFrameState(info); canDrawThisFrame = info.out.canDrawThisFrame; - if (mFrameCompleteCallback) { - mContext->addFrameCompleteListener(std::move(mFrameCompleteCallback)); - mFrameCompleteCallback = nullptr; + if (mFrameCommitCallback) { + mContext->addFrameCommitListener(std::move(mFrameCommitCallback)); + mFrameCommitCallback = nullptr; } } // Grab a copy of everything we need CanvasContext* context = mContext; - std::function<void(int64_t)> callback = std::move(mFrameCallback); + std::function<void(int64_t)> frameCallback = std::move(mFrameCallback); + std::function<void()> frameCompleteCallback = std::move(mFrameCompleteCallback); mFrameCallback = nullptr; + mFrameCompleteCallback = nullptr; int64_t intendedVsync = mFrameInfo[static_cast<int>(FrameInfoIndex::IntendedVsync)]; int64_t frameDeadline = mFrameInfo[static_cast<int>(FrameInfoIndex::FrameDeadline)]; int64_t frameStartTime = mFrameInfo[static_cast<int>(FrameInfoIndex::FrameStartTime)]; @@ -170,9 +172,9 @@ void DrawFrameTask::run() { } // Even if we aren't drawing this vsync pulse the next frame number will still be accurate - if (CC_UNLIKELY(callback)) { + if (CC_UNLIKELY(frameCallback)) { context->enqueueFrameWork( - [callback, frameNr = context->getFrameNumber()]() { callback(frameNr); }); + [frameCallback, frameNr = context->getFrameNumber()]() { frameCallback(frameNr); }); } nsecs_t dequeueBufferDuration = 0; @@ -189,6 +191,10 @@ void DrawFrameTask::run() { context->waitOnFences(); } + if (CC_UNLIKELY(frameCompleteCallback)) { + std::invoke(frameCompleteCallback); + } + if (!canUnblockUiThread) { unblockUiThread(); } diff --git a/libs/hwui/renderthread/DrawFrameTask.h b/libs/hwui/renderthread/DrawFrameTask.h index 6a61a2bb645f..e3ea802b07b9 100644 --- a/libs/hwui/renderthread/DrawFrameTask.h +++ b/libs/hwui/renderthread/DrawFrameTask.h @@ -81,7 +81,11 @@ public: mFrameCallback = std::move(callback); } - void setFrameCompleteCallback(std::function<void(int64_t)>&& callback) { + void setFrameCommitCallback(std::function<void(bool)>&& callback) { + mFrameCommitCallback = std::move(callback); + } + + void setFrameCompleteCallback(std::function<void()>&& callback) { mFrameCompleteCallback = std::move(callback); } @@ -123,7 +127,8 @@ private: int64_t mFrameInfo[UI_THREAD_FRAME_INFO_SIZE]; std::function<void(int64_t)> mFrameCallback; - std::function<void(int64_t)> mFrameCompleteCallback; + std::function<void(bool)> mFrameCommitCallback; + std::function<void()> mFrameCompleteCallback; nsecs_t mLastDequeueBufferDuration = 0; nsecs_t mLastTargetWorkDuration = 0; diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp index c485ce2781e5..72d4ac5081e6 100644 --- a/libs/hwui/renderthread/RenderProxy.cpp +++ b/libs/hwui/renderthread/RenderProxy.cpp @@ -326,7 +326,11 @@ void RenderProxy::setFrameCallback(std::function<void(int64_t)>&& callback) { mDrawFrameTask.setFrameCallback(std::move(callback)); } -void RenderProxy::setFrameCompleteCallback(std::function<void(int64_t)>&& callback) { +void RenderProxy::setFrameCommitCallback(std::function<void(bool)>&& callback) { + mDrawFrameTask.setFrameCommitCallback(std::move(callback)); +} + +void RenderProxy::setFrameCompleteCallback(std::function<void()>&& callback) { mDrawFrameTask.setFrameCompleteCallback(std::move(callback)); } diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h index 2b5405c82563..6417b38df064 100644 --- a/libs/hwui/renderthread/RenderProxy.h +++ b/libs/hwui/renderthread/RenderProxy.h @@ -124,7 +124,8 @@ public: const std::function<bool(int64_t, int64_t, int64_t)>& callback); void setPrepareSurfaceControlForWebviewCallback(const std::function<void()>& callback); void setFrameCallback(std::function<void(int64_t)>&& callback); - void setFrameCompleteCallback(std::function<void(int64_t)>&& callback); + void setFrameCommitCallback(std::function<void(bool)>&& callback); + void setFrameCompleteCallback(std::function<void()>&& callback); void addFrameMetricsObserver(FrameMetricsObserver* observer); void removeFrameMetricsObserver(FrameMetricsObserver* observer); diff --git a/packages/PackageInstaller/res/values-te/strings.xml b/packages/PackageInstaller/res/values-te/strings.xml index 806734ffa997..33543fdefd48 100644 --- a/packages/PackageInstaller/res/values-te/strings.xml +++ b/packages/PackageInstaller/res/values-te/strings.xml @@ -80,9 +80,9 @@ <string name="wear_not_allowed_dlg_text" msgid="704615521550939237">"Wearలో ఇన్స్టాల్/అన్ఇన్స్టాల్ చర్యలకు మద్దతు లేదు."</string> <string name="message_staging" msgid="8032722385658438567">"యాప్ను సిద్ధం చేస్తుంది…"</string> <string name="app_name_unknown" msgid="6881210203354323926">"తెలియదు"</string> - <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"మీ భద్రత దృష్ట్యా, ఈ సోర్సు నుండి తెలియని యాప్లను ఇన్స్టాల్ చేయడానికి మీ టాబ్లెట్ ప్రస్తుతం అనుమతించబడదు. మీరు దీన్ని సెట్టింగ్లలో మార్చవచ్చు."</string> - <string name="untrusted_external_source_warning" product="tv" msgid="7057271609532508035">"మీ భద్రత దృష్ట్యా, ఈ సోర్సు నుండి తెలియని యాప్లను ఇన్స్టాల్ చేయడానికి మీ టీవీ ప్రస్తుతం అనుమతించబడదు. మీరు దీన్ని సెట్టింగ్లలో మార్చవచ్చు."</string> - <string name="untrusted_external_source_warning" product="default" msgid="8444191224459138919">"మీ భద్రత దృష్ట్యా, ఈ సోర్సు నుండి తెలియని యాప్లను ఇన్స్టాల్ చేయడానికి మీ ఫోన్ ప్రస్తుతం అనుమతించబడదు. మీరు దీన్ని సెట్టింగ్లలో మార్చవచ్చు."</string> + <string name="untrusted_external_source_warning" product="tablet" msgid="7067510047443133095">"మీ సెక్యూరిటీ దృష్ట్యా, ఈ సోర్సు నుండి తెలియని యాప్లను ఇన్స్టాల్ చేయడానికి మీ టాబ్లెట్ ప్రస్తుతం అనుమతించబడదు. మీరు దీన్ని సెట్టింగ్లలో మార్చవచ్చు."</string> + <string name="untrusted_external_source_warning" product="tv" msgid="7057271609532508035">"మీ సెక్యూరిటీ దృష్ట్యా, ఈ సోర్సు నుండి తెలియని యాప్లను ఇన్స్టాల్ చేయడానికి మీ టీవీ ప్రస్తుతం అనుమతించబడదు. మీరు దీన్ని సెట్టింగ్లలో మార్చవచ్చు."</string> + <string name="untrusted_external_source_warning" product="default" msgid="8444191224459138919">"మీ సెక్యూరిటీ దృష్ట్యా, ఈ సోర్సు నుండి తెలియని యాప్లను ఇన్స్టాల్ చేయడానికి మీ ఫోన్ ప్రస్తుతం అనుమతించబడదు. మీరు దీన్ని సెట్టింగ్లలో మార్చవచ్చు."</string> <string name="anonymous_source_warning" product="default" msgid="2784902545920822500">"తెలియని యాప్లు మీ ఫోన్ పైన, వ్యక్తిగత డేటా పైన దాడి చేయడానికి ఎక్కువగా అవకాశం ఉంటుంది. ఈ యాప్ను ఇన్స్టాల్ చేయడం ద్వారా, దాని వినియోగంతో మీ ఫోన్కు ఏదైనా నష్టం జరిగితే లేదా మీ డేటాను కోల్పోతే అందుకు మీరే బాధ్యత వహిస్తారని అంగీకరిస్తున్నారు."</string> <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"మీ టాబ్లెట్ మరియు వ్యక్తిగత డేటాపై తెలియని యాప్లు దాడి చేయడానికి ఎక్కువ అవకాశం ఉంది. మీరు ఈ యాప్ను ఇన్స్టాల్ చేయడం ద్వారా, దీనిని ఉపయోగించడం వలన మీ టాబ్లెట్కు ఏదైనా హాని జరిగినా లేదా డేటా కోల్పోయినా బాధ్యత మీదేనని అంగీకరిస్తున్నారు."</string> <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"మీ టీవీ మరియు వ్యక్తిగత డేటాపై తెలియని యాప్లు దాడి చేయడానికి ఎక్కువ అవకాశం ఉంది. మీరు ఈ యాప్ను ఇన్స్టాల్ చేయడం ద్వారా, దీనిని ఉపయోగించడం వలన మీ టీవీకి ఏదైనా హాని జరిగినా లేదా డేటా కోల్పోయినా బాధ్యత మీదేనని అంగీకరిస్తున్నారు."</string> diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java index 9cd7083a2a11..c30c742fd9d9 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java @@ -98,6 +98,10 @@ public class SettingsBackupAgent extends BackupAgentHelper { private static final String KEY_WIFI_NEW_CONFIG = "wifi_new_config"; private static final String KEY_DEVICE_SPECIFIC_CONFIG = "device_specific_config"; private static final String KEY_SIM_SPECIFIC_SETTINGS = "sim_specific_settings"; + // Restoring sim-specific data backed up from newer Android version to Android 12 was causing a + // fatal crash. Creating a backup with a different key will prevent Android 12 versions from + // restoring this data. + private static final String KEY_SIM_SPECIFIC_SETTINGS_2 = "sim_specific_settings_2"; // Versioning of the state file. Increment this version // number any time the set of state items is altered. @@ -253,7 +257,7 @@ public class SettingsBackupAgent extends BackupAgentHelper { deviceSpecificInformation, data); stateChecksums[STATE_SIM_SPECIFIC_SETTINGS] = writeIfChanged(stateChecksums[STATE_SIM_SPECIFIC_SETTINGS], - KEY_SIM_SPECIFIC_SETTINGS, simSpecificSettingsData, data); + KEY_SIM_SPECIFIC_SETTINGS_2, simSpecificSettingsData, data); writeNewChecksums(stateChecksums, newState); } @@ -395,6 +399,9 @@ public class SettingsBackupAgent extends BackupAgentHelper { break; case KEY_SIM_SPECIFIC_SETTINGS: + // Intentional fall through so that sim-specific backups from Android 12 will + // also be restored on newer Android versions. + case KEY_SIM_SPECIFIC_SETTINGS_2: byte[] restoredSimSpecificSettings = new byte[size]; data.readEntityData(restoredSimSpecificSettings, 0, size); restoreSimSpecificSettings(restoredSimSpecificSettings); diff --git a/packages/SystemUI/animation/res/anim/launch_host_dialog_enter.xml b/packages/SystemUI/animation/res/anim/launch_dialog_enter.xml index c6b87d38f7da..c6b87d38f7da 100644 --- a/packages/SystemUI/animation/res/anim/launch_host_dialog_enter.xml +++ b/packages/SystemUI/animation/res/anim/launch_dialog_enter.xml diff --git a/packages/SystemUI/animation/res/anim/launch_host_dialog_exit.xml b/packages/SystemUI/animation/res/anim/launch_dialog_exit.xml index a0f441eaeed4..a0f441eaeed4 100644 --- a/packages/SystemUI/animation/res/anim/launch_host_dialog_exit.xml +++ b/packages/SystemUI/animation/res/anim/launch_dialog_exit.xml diff --git a/packages/SystemUI/animation/res/values/ids.xml b/packages/SystemUI/animation/res/values/ids.xml index c4cb89fecccb..ef60a248f79a 100644 --- a/packages/SystemUI/animation/res/values/ids.xml +++ b/packages/SystemUI/animation/res/values/ids.xml @@ -16,5 +16,4 @@ --> <resources> <item type="id" name="launch_animation_running"/> - <item type="id" name="dialog_content_parent" /> </resources>
\ No newline at end of file diff --git a/packages/SystemUI/animation/res/values/styles.xml b/packages/SystemUI/animation/res/values/styles.xml index ad06c9192bc3..3b3f7f6128fa 100644 --- a/packages/SystemUI/animation/res/values/styles.xml +++ b/packages/SystemUI/animation/res/values/styles.xml @@ -15,15 +15,10 @@ limitations under the License. --> <resources> - <style name="HostDialogTheme"> - <item name="android:windowAnimationStyle">@style/Animation.HostDialog</item> - <item name="android:windowIsFloating">false</item> - <item name="android:backgroundDimEnabled">true</item> - <item name="android:navigationBarColor">@android:color/transparent</item> - </style> - - <style name="Animation.HostDialog" parent="@android:style/Animation"> - <item name="android:windowEnterAnimation">@anim/launch_host_dialog_enter</item> - <item name="android:windowExitAnimation">@anim/launch_host_dialog_exit</item> + <!-- An animation used by DialogLaunchAnimator to make a dialog appear instantly (to animate --> + <!-- in-window) and disappear by fading out (when the exit into view is disabled). --> + <style name="Animation.LaunchAnimation" parent="@android:style/Animation"> + <item name="android:windowEnterAnimation">@anim/launch_dialog_enter</item> + <item name="android:windowExitAnimation">@anim/launch_dialog_exit</item> </style> </resources>
\ No newline at end of file diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt index 9aad2783ba2d..de82ebdc6b1c 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt +++ b/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt @@ -24,23 +24,19 @@ import android.content.Context import android.graphics.Color import android.graphics.Rect import android.os.Looper +import android.service.dreams.IDreamManager import android.util.Log import android.util.MathUtils import android.view.GhostView -import android.view.Gravity import android.view.View import android.view.ViewGroup +import android.view.ViewGroup.LayoutParams.MATCH_PARENT import android.view.ViewTreeObserver.OnPreDrawListener -import android.view.WindowInsets import android.view.WindowManager -import android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR -import android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN -import android.view.WindowManagerPolicyConstants import android.widget.FrameLayout import kotlin.math.roundToInt private const val TAG = "DialogLaunchAnimator" -private val DIALOG_CONTENT_PARENT_ID = R.id.dialog_content_parent /** * A class that allows dialogs to be started in a seamless way from a view that is transforming @@ -49,7 +45,7 @@ private val DIALOG_CONTENT_PARENT_ID = R.id.dialog_content_parent class DialogLaunchAnimator( private val context: Context, private val launchAnimator: LaunchAnimator, - private val hostDialogProvider: HostDialogProvider + private val dreamManager: IDreamManager ) { private companion object { private val TAG_LAUNCH_ANIMATION_RUNNING = R.id.launch_animation_running @@ -63,40 +59,38 @@ class DialogLaunchAnimator( private val openedDialogs = hashSetOf<AnimatedDialog>() /** - * Show [dialog] by expanding it from [view]. If [animateBackgroundBoundsChange] is true, then - * the background of the dialog will be animated when the dialog bounds change. + * Show [dialog] by expanding it from [view]. If [view] is a view inside another dialog that was + * shown using this method, then we will animate from that dialog instead. * - * Caveats: When calling this function, the dialog content view will actually be stolen and - * attached to a different dialog (and thus a different window) which means that the actual - * dialog window will never be drawn. Moreover, unless [dialog] is a [ListenableDialog], you - * must call dismiss(), hide() and show() on the [Dialog] returned by this function to actually - * dismiss, hide or show the dialog. + * If [animateBackgroundBoundsChange] is true, then the background of the dialog will be + * animated when the dialog bounds change. + * + * Caveats: When calling this function and [dialog] is not a fullscreen dialog, then it will be + * made fullscreen and 2 views will be inserted between the dialog DecorView and its children. */ @JvmOverloads fun showFromView( dialog: Dialog, view: View, animateBackgroundBoundsChange: Boolean = false - ): Dialog { + ) { if (Looper.myLooper() != Looper.getMainLooper()) { throw IllegalStateException( "showFromView must be called from the main thread and dialog must be created in " + "the main thread") } - // If the parent of the view we are launching from is the background of some other animated - // dialog, then this means the caller intent is to launch a dialog from another dialog. In - // this case, we also animate the parent (which is the dialog background). + // If the view we are launching from belongs to another dialog, then this means the caller + // intent is to launch a dialog from another dialog. val animatedParent = openedDialogs - .firstOrNull { it.dialogContentParent == view.parent } - val parentHostDialog = animatedParent?.hostDialog - val animateFrom = animatedParent?.dialogContentParent ?: view + .firstOrNull { it.dialog.window.decorView.viewRootImpl == view.viewRootImpl } + val animateFrom = animatedParent?.dialogContentWithBackground ?: view // Make sure we don't run the launch animation from the same view twice at the same time. if (animateFrom.getTag(TAG_LAUNCH_ANIMATION_RUNNING) != null) { Log.e(TAG, "Not running dialog launch animation as there is already one running") dialog.show() - return dialog + return } animateFrom.setTag(TAG_LAUNCH_ANIMATION_RUNNING, true) @@ -104,82 +98,36 @@ class DialogLaunchAnimator( val animatedDialog = AnimatedDialog( context, launchAnimator, - hostDialogProvider, + dreamManager, animateFrom, onDialogDismissed = { openedDialogs.remove(it) }, - originalDialog = dialog, + dialog = dialog, animateBackgroundBoundsChange, - openedDialogs.firstOrNull { it.hostDialog == parentHostDialog } + animatedParent ) - val hostDialog = animatedDialog.hostDialog - openedDialogs.add(animatedDialog) - - // If the dialog is dismissed/hidden/shown, then we should actually dismiss/hide/show the - // host dialog. - if (dialog is ListenableDialog) { - dialog.addListener(object : DialogListener { - override fun onDismiss(reason: DialogListener.DismissReason) { - dialog.removeListener(this) - - // We disable the exit animation if we are dismissing the dialog because the - // device is being locked, otherwise the animation looks bad if AOD is enabled. - // If AOD is disabled the screen will directly becomes black and we won't see - // the animation anyways. - if (reason == DialogListener.DismissReason.DEVICE_LOCKED) { - animatedDialog.exitAnimationDisabled = true - } - - hostDialog.dismiss() - } - - override fun onHide() { - if (animatedDialog.ignoreNextCallToHide) { - animatedDialog.ignoreNextCallToHide = false - return - } - - hostDialog.hide() - } - - override fun onShow() { - hostDialog.show() - - // We don't actually want to show the original dialog, so hide it. - animatedDialog.ignoreNextCallToHide = true - dialog.hide() - } - - override fun onSizeChanged() { - animatedDialog.onOriginalDialogSizeChanged() - } - - override fun prepareForStackDismiss() { - animatedDialog.touchSurface = animatedDialog.prepareForStackDismiss() - } - }) - } + openedDialogs.add(animatedDialog) animatedDialog.start() - return hostDialog } /** - * Launch [dialog] from a [parentHostDialog] as returned by [showFromView]. This will allow - * for dismissing the whole stack. - * - * This will return a new host dialog, with the same caveat as [showFromView]. + * Launch [dialog] from [another dialog][animateFrom] that was shown using [showFromView]. This + * will allow for dismissing the whole stack. * - * @see DialogListener.prepareForStackDismiss + * @see dismissStack */ fun showFromDialog( dialog: Dialog, - parentHostDialog: Dialog, + animateFrom: Dialog, animateBackgroundBoundsChange: Boolean = false - ): Dialog { - val view = parentHostDialog.findViewById<ViewGroup>(DIALOG_CONTENT_PARENT_ID) - ?.getChildAt(0) - ?: throw IllegalStateException("No dialog content parent found in host dialog") - return showFromView(dialog, view, animateBackgroundBoundsChange) + ) { + val view = openedDialogs + .firstOrNull { it.dialog == animateFrom } + ?.dialogContentWithBackground + ?: throw IllegalStateException( + "The animateFrom dialog was not animated using " + + "DialogLaunchAnimator.showFrom(View|Dialog)") + showFromView(dialog, view, animateBackgroundBoundsChange) } /** @@ -195,69 +143,23 @@ class DialogLaunchAnimator( fun disableAllCurrentDialogsExitAnimations() { openedDialogs.forEach { it.exitAnimationDisabled = true } } -} -interface HostDialogProvider { /** - * Create a host dialog that will be used to host a launch animation. This host dialog must: - * 1. call [onCreateCallback] in its onCreate() method, e.g. right after calling - * super.onCreate(). - * 2. call [dismissOverride] instead of doing any dismissing logic. The actual dismissing - * logic should instead be done inside the lambda passed to [dismissOverride], which will - * be called after the exit animation. - * 3. Be full screen, i.e. have a window matching its parent size. - * - * See SystemUIHostDialogProvider for an example of implementation. + * Dismiss [dialog]. If it was launched from another dialog using [showFromView], also dismiss + * the stack of dialogs, animating back to the original touchSurface. */ - fun createHostDialog( - context: Context, - theme: Int, - onCreateCallback: () -> Unit, - dismissOverride: (() -> Unit) -> Unit - ): Dialog -} - -/** A dialog to/from which we can add/remove listeners. */ -interface ListenableDialog { - /** Add [listener] to the listeners. */ - fun addListener(listener: DialogListener) - - /** Remove [listener] from the listeners. */ - fun removeListener(listener: DialogListener) -} - -interface DialogListener { - /** The reason why a dialog was dismissed. */ - enum class DismissReason { - UNKNOWN, - - /** The device was locked, which dismissed this dialog. */ - DEVICE_LOCKED, + fun dismissStack(dialog: Dialog) { + openedDialogs + .firstOrNull { it.dialog == dialog } + ?.let { it.touchSurface = it.prepareForStackDismiss() } + dialog.dismiss() } - - /** Called when this dialog dismiss() is called. */ - fun onDismiss(reason: DismissReason) - - /** Called when this dialog hide() is called. */ - fun onHide() - - /** Called when this dialog show() is called. */ - fun onShow() - - /** - * Call before dismissing a stack of dialogs (dialogs launched from dialogs), so the topmost - * can animate directly into the original `touchSurface`. - */ - fun prepareForStackDismiss() - - /** Called when this dialog size might have changed, e.g. because of configuration changes. */ - fun onSizeChanged() } private class AnimatedDialog( private val context: Context, private val launchAnimator: LaunchAnimator, - hostDialogProvider: HostDialogProvider, + private val dreamManager: IDreamManager, /** The view that triggered the dialog after being tapped. */ var touchSurface: View, @@ -268,37 +170,33 @@ private class AnimatedDialog( */ private val onDialogDismissed: (AnimatedDialog) -> Unit, - /** The original dialog whose content will be shown and animate in/out in [hostDialog]. */ - private val originalDialog: Dialog, + /** The dialog to show and animate. */ + val dialog: Dialog, /** Whether we should animate the dialog background when its bounds change. */ private val animateBackgroundBoundsChange: Boolean, - /** Launch animation corresponding to the parent [hostDialog]. */ + /** Launch animation corresponding to the parent [AnimatedDialog]. */ private val parentAnimatedDialog: AnimatedDialog? = null ) { /** - * The fullscreen dialog to which we will add the content view [originalDialogView] of - * [originalDialog]. - */ - val hostDialog = hostDialogProvider.createHostDialog( - context, R.style.HostDialogTheme, this::onHostDialogCreated, this::onHostDialogDismissed) - - /** The root content view of [hostDialog]. */ - private val hostDialogRoot = FrameLayout(context) + * The DecorView of this dialog window. + * + * Note that we access this DecorView lazily to avoid accessing it before the dialog is created, + * which can sometimes cause crashes (e.g. with the Cast dialog). + */ + private val decorView by lazy { dialog.window!!.decorView as ViewGroup } /** - * The parent of the original dialog content view, that serves as a fake window that will have - * the same size as the original dialog window and to which we will set the original dialog - * window background. + * The dialog content with its background. When animating a fullscreen dialog, this is just the + * first ViewGroup of the dialog that has a background. When animating a normal (not fullscreen) + * dialog, this is an additional view that serves as a fake window that will have the same size + * as the dialog window initially had and to which we will set the dialog window background. */ - val dialogContentParent = FrameLayout(context).apply { - id = DIALOG_CONTENT_PARENT_ID - } + var dialogContentWithBackground: ViewGroup? = null /** - * The background color of [originalDialogView], taking into consideration the [originalDialog] - * window background color. + * The background color of [dialog], taking into consideration its window background color. */ private var originalDialogBackgroundColor = Color.BLACK @@ -311,75 +209,182 @@ private class AnimatedDialog( private var isDismissing = false private var dismissRequested = false - var ignoreNextCallToHide = false var exitAnimationDisabled = false private var isTouchSurfaceGhostDrawn = false private var isOriginalDialogViewLaidOut = false - private var backgroundLayoutListener = if (animateBackgroundBoundsChange) { + + /** A layout listener to animate the dialog height change. */ + private val backgroundLayoutListener = if (animateBackgroundBoundsChange) { AnimatedBoundsLayoutListener() } else { null } + /* + * A layout listener in case the dialog (window) size changes (for instance because of a + * configuration change) to ensure that the dialog stays full width. + */ + private var decorViewLayoutListener: View.OnLayoutChangeListener? = null + fun start() { - // Show the host (fullscreen) dialog, to which we will add the stolen dialog view. - hostDialog.show() + // Create the dialog so that its onCreate() method is called, which usually sets the dialog + // content. + dialog.create() + + val window = dialog.window!! + val isWindowFullScreen = + window.attributes.width == MATCH_PARENT && window.attributes.height == MATCH_PARENT + val dialogContentWithBackground = if (isWindowFullScreen) { + // If the dialog window is already fullscreen, then we look for the first ViewGroup that + // has a background (and is not the DecorView, which always has a background) and + // animate towards that ViewGroup given that this is probably what represents the actual + // dialog view. + var viewGroupWithBackground: ViewGroup? = null + for (i in 0 until decorView.childCount) { + viewGroupWithBackground = findFirstViewGroupWithBackground(decorView.getChildAt(i)) + if (viewGroupWithBackground != null) { + break + } + } - // Steal the dialog view. We do that by showing it but preventing it from drawing, then - // hiding it as soon as its content is available. - stealOriginalDialogContentView(then = this::showDialogFromView) - } + // Animate that view with the background. Throw if we didn't find one, because otherwise + // it's not clear what we should animate. + viewGroupWithBackground + ?: throw IllegalStateException("Unable to find ViewGroup with background") + } else { + // We will make the dialog window (and therefore its DecorView) fullscreen to make it + // possible to animate outside its bounds. + // + // Before that, we add a new View as a child of the DecorView with the same size and + // gravity as that DecorView, then we add all original children of the DecorView to that + // new View. Finally we remove the background of the DecorView and add it to the new + // View, then we make the DecorView fullscreen. This new View now acts as a fake (non + // fullscreen) window. + // + // On top of that, we also add a fullscreen transparent background between the DecorView + // and the view that we added so that we can dismiss the dialog when this view is + // clicked. This is necessary because DecorView overrides onTouchEvent and therefore we + // can't set the click listener directly on the (now fullscreen) DecorView. + val fullscreenTransparentBackground = FrameLayout(context) + decorView.addView( + fullscreenTransparentBackground, + 0 /* index */, + FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT) + ) - private fun onHostDialogCreated() { - // Make the dialog fullscreen with a transparent background. - hostDialog.setContentView( - hostDialogRoot, - ViewGroup.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.MATCH_PARENT + val dialogContentWithBackground = FrameLayout(context) + dialogContentWithBackground.background = decorView.background + + // Make the window background transparent. Note that setting the window (or DecorView) + // background drawable to null leads to issues with background color (not being + // transparent) or with insets that are not refreshed. Therefore we need to set it to + // something not null, hence we are using android.R.color.transparent here. + window.setBackgroundDrawableResource(android.R.color.transparent) + + // Close the dialog when clicking outside of it. + fullscreenTransparentBackground.setOnClickListener { dialog.dismiss() } + dialogContentWithBackground.isClickable = true + + fullscreenTransparentBackground.addView( + dialogContentWithBackground, + FrameLayout.LayoutParams( + window.attributes.width, + window.attributes.height, + window.attributes.gravity + ) ) - ) - val window = hostDialog.window - ?: throw IllegalStateException("There is no window associated to the host dialog") - window.setBackgroundDrawableResource(android.R.color.transparent) - - // If we are using gesture navigation, then we can overlay the navigation/task bars with - // the host dialog. - val navigationMode = context.resources.getInteger( - com.android.internal.R.integer.config_navBarInteractionMode) - if (navigationMode == WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL) { - window.attributes.fitInsetsTypes = window.attributes.fitInsetsTypes and - WindowInsets.Type.navigationBars().inv() - window.addFlags(FLAG_LAYOUT_IN_SCREEN or FLAG_LAYOUT_INSET_DECOR) - window.setDecorFitsSystemWindows(false) + // Move all original children of the DecorView to the new View we just added. + for (i in 1 until decorView.childCount) { + val view = decorView.getChildAt(1) + decorView.removeViewAt(1) + dialogContentWithBackground.addView(view) + } + + // Make the window fullscreen and add a layout listener to ensure it stays fullscreen. + window.setLayout(MATCH_PARENT, MATCH_PARENT) + decorViewLayoutListener = View.OnLayoutChangeListener { + v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom -> + if (window.attributes.width != MATCH_PARENT || + window.attributes.height != MATCH_PARENT) { + // The dialog size changed, copy its size to dialogContentWithBackground and + // make the dialog window full screen again. + val layoutParams = dialogContentWithBackground.layoutParams + layoutParams.width = window.attributes.width + layoutParams.height = window.attributes.height + dialogContentWithBackground.layoutParams = layoutParams + window.setLayout(MATCH_PARENT, MATCH_PARENT) + } + } + decorView.addOnLayoutChangeListener(decorViewLayoutListener) + + dialogContentWithBackground } + this.dialogContentWithBackground = dialogContentWithBackground + + val background = dialogContentWithBackground.background + originalDialogBackgroundColor = + GhostedViewLaunchAnimatorController.findGradientDrawable(background) + ?.color + ?.defaultColor ?: Color.BLACK + + // Make the background view invisible until we start the animation. + dialogContentWithBackground.visibility = View.INVISIBLE + + // Make sure the dialog is visible instantly and does not do any window animation. + window.attributes.windowAnimations = R.style.Animation_LaunchAnimation + + // Start the animation once the background view is properly laid out. + dialogContentWithBackground.addOnLayoutChangeListener(object : View.OnLayoutChangeListener { + override fun onLayoutChange( + v: View, + left: Int, + top: Int, + right: Int, + bottom: Int, + oldLeft: Int, + oldTop: Int, + oldRight: Int, + oldBottom: Int + ) { + dialogContentWithBackground.removeOnLayoutChangeListener(this) + + isOriginalDialogViewLaidOut = true + maybeStartLaunchAnimation() + } + }) // Disable the dim. We will enable it once we start the animation. window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND) + // Override the dialog dismiss() so that we can animate the exit before actually dismissing + // the dialog. + dialog.setDismissOverride(this::onDialogDismissed) + + // Show the dialog. + dialog.show() + // Add a temporary touch surface ghost as soon as the window is ready to draw. This - // temporary ghost will be drawn together with the touch surface, but in the host dialog + // temporary ghost will be drawn together with the touch surface, but in the dialog // window. Once it is drawn, we will make the touch surface invisible, and then start the // animation. We do all this synchronization to avoid flicker that would occur if we made // the touch surface invisible too early (before its ghost is drawn), leading to one or more // frames with a hole instead of the touch surface (or its ghost). - hostDialogRoot.viewTreeObserver.addOnPreDrawListener(object : OnPreDrawListener { + decorView.viewTreeObserver.addOnPreDrawListener(object : OnPreDrawListener { override fun onPreDraw(): Boolean { - hostDialogRoot.viewTreeObserver.removeOnPreDrawListener(this) + decorView.viewTreeObserver.removeOnPreDrawListener(this) addTemporaryTouchSurfaceGhost() return true } }) - hostDialogRoot.invalidate() + decorView.invalidate() } private fun addTemporaryTouchSurfaceGhost() { // Create a ghost of the touch surface (which will make the touch surface invisible) and add - // it to the host dialog. We will wait for this ghost to be drawn before starting the - // animation. - val ghost = GhostView.addGhost(touchSurface, hostDialogRoot) + // it to the dialog. We will wait for this ghost to be drawn before starting the animation. + val ghost = GhostView.addGhost(touchSurface, decorView) // The ghost of the touch surface was just created, so the touch surface was made invisible. // We make it visible again until the ghost is actually drawn. @@ -415,125 +420,23 @@ private class AnimatedDialog( touchSurface.invalidate() } - /** Get the content view of [originalDialog] and pass it to [then]. */ - private fun stealOriginalDialogContentView(then: (View) -> Unit) { - // The original dialog content view will be attached to android.R.id.content when the dialog - // is shown, so we show the dialog and add an observer to get the view but also prevents the - // original dialog from being drawn. - val androidContent = originalDialog.findViewById<ViewGroup>(android.R.id.content) - ?: throw IllegalStateException("Dialog does not have any android.R.id.content view") - - androidContent.viewTreeObserver.addOnPreDrawListener( - object : OnPreDrawListener { - override fun onPreDraw(): Boolean { - if (androidContent.childCount == 1) { - androidContent.viewTreeObserver.removeOnPreDrawListener(this) - - // Hide the animated dialog. Because of the dialog listener set up - // earlier, this would also hide the host dialog, but in this case we - // need to keep the host dialog visible. - ignoreNextCallToHide = true - originalDialog.hide() - - then(androidContent.getChildAt(0)) - return false - } - - // Never draw the original dialog content. - return false - } - }) - originalDialog.show() - } - - private fun showDialogFromView(dialogView: View) { - // Close the dialog when clicking outside of it. - hostDialogRoot.setOnClickListener { hostDialog.dismiss() } - dialogView.isClickable = true - - // Set the background of the window dialog to the dialog itself. - // TODO(b/193634619): Support dialog windows without background. - // TODO(b/193634619): Support dialog whose background comes from the content view instead of - // the window. - val typedArray = - originalDialog.context.obtainStyledAttributes(com.android.internal.R.styleable.Window) - val backgroundRes = - typedArray.getResourceId(com.android.internal.R.styleable.Window_windowBackground, 0) - typedArray.recycle() - if (backgroundRes == 0) { - throw IllegalStateException("Dialogs with no backgrounds on window are not supported") + private fun findFirstViewGroupWithBackground(view: View): ViewGroup? { + if (view !is ViewGroup) { + return null } - // Add a parent view to the original dialog view to which we will set the original dialog - // window background. This View serves as a fake window with background, so that we are sure - // that we don't override the dialog view paddings with the window background that usually - // has insets. - dialogContentParent.setBackgroundResource(backgroundRes) - hostDialogRoot.addView( - dialogContentParent, - - // We give it the size of its original dialog window. - FrameLayout.LayoutParams( - originalDialog.window.attributes.width, - originalDialog.window.attributes.height, - Gravity.CENTER - ) - ) - - // Make the dialog view parent invisible for now, to make sure it's not drawn yet. - dialogContentParent.visibility = View.INVISIBLE - - val background = dialogContentParent.background!! - originalDialogBackgroundColor = - GhostedViewLaunchAnimatorController.findGradientDrawable(background) - ?.color - ?.defaultColor ?: Color.BLACK - - // Add the dialog view to its parent (that has the original window background). - (dialogView.parent as? ViewGroup)?.removeView(dialogView) - dialogContentParent.addView( - dialogView, - - // It should match its parent size, which is sized the same as the original dialog - // window. - FrameLayout.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.MATCH_PARENT - ) - ) - - // Start the animation when the dialog is laid out in the center of the host dialog. - dialogContentParent.addOnLayoutChangeListener(object : View.OnLayoutChangeListener { - override fun onLayoutChange( - view: View, - left: Int, - top: Int, - right: Int, - bottom: Int, - oldLeft: Int, - oldTop: Int, - oldRight: Int, - oldBottom: Int - ) { - dialogContentParent.removeOnLayoutChangeListener(this) + if (view.background != null) { + return view + } - isOriginalDialogViewLaidOut = true - maybeStartLaunchAnimation() + for (i in 0 until view.childCount) { + val match = findFirstViewGroupWithBackground(view.getChildAt(i)) + if (match != null) { + return match } - }) - } - - fun onOriginalDialogSizeChanged() { - // The dialog is the single child of the root. - if (hostDialogRoot.childCount != 1) { - return } - val dialogView = hostDialogRoot.getChildAt(0) - val layoutParams = dialogView.layoutParams as? FrameLayout.LayoutParams ?: return - layoutParams.width = originalDialog.window.attributes.width - layoutParams.height = originalDialog.window.attributes.height - dialogView.layoutParams = layoutParams + return null } private fun maybeStartLaunchAnimation() { @@ -542,7 +445,7 @@ private class AnimatedDialog( } // Show the background dim. - hostDialog.window.addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND) + dialog.window.addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND) startAnimation( isLaunching = true, @@ -564,22 +467,23 @@ private class AnimatedDialog( // dismiss was called during the animation, dismiss again now to actually // dismiss. if (dismissRequested) { - hostDialog.dismiss() + dialog.dismiss() } // If necessary, we animate the dialog background when its bounds change. We do it // at the end of the launch animation, because the lauch animation already correctly // handles bounds changes. if (backgroundLayoutListener != null) { - dialogContentParent.addOnLayoutChangeListener(backgroundLayoutListener) + dialogContentWithBackground!! + .addOnLayoutChangeListener(backgroundLayoutListener) } } ) } - private fun onHostDialogDismissed(actualDismiss: () -> Unit) { + private fun onDialogDismissed() { if (Looper.myLooper() != Looper.getMainLooper()) { - context.mainExecutor.execute { onHostDialogDismissed(actualDismiss) } + context.mainExecutor.execute { onDialogDismissed() } return } @@ -594,23 +498,29 @@ private class AnimatedDialog( } isDismissing = true - hideDialogIntoView { instantDismiss: Boolean -> - if (instantDismiss) { - originalDialog.hide() - hostDialog.hide() + hideDialogIntoView { animationRan: Boolean -> + if (animationRan) { + // Instantly dismiss the dialog if we ran the animation into view. If it was + // skipped, dismiss() will run the window animation (which fades out the dialog). + dialog.hide() } - originalDialog.dismiss() - actualDismiss() + dialog.setDismissOverride(null) + dialog.dismiss() } } /** - * Hide the dialog into the touch surface and call [dismissDialogs] when the animation is done - * (passing instantDismiss=true) or if it's skipped (passing instantDismiss=false) to actually - * dismiss the dialogs. + * Hide the dialog into the touch surface and call [onAnimationFinished] when the animation is + * done (passing animationRan=true) or if it's skipped (passing animationRan=false) to actually + * dismiss the dialog. */ - private fun hideDialogIntoView(dismissDialogs: (Boolean) -> Unit) { + private fun hideDialogIntoView(onAnimationFinished: (Boolean) -> Unit) { + // Remove the layout change listener we have added to the DecorView earlier. + if (decorViewLayoutListener != null) { + decorView.removeOnLayoutChangeListener(decorViewLayoutListener) + } + if (!shouldAnimateDialogIntoView()) { Log.i(TAG, "Skipping animation of dialog into the touch surface") @@ -622,7 +532,7 @@ private class AnimatedDialog( touchSurface.visibility = View.VISIBLE } - dismissDialogs(false /* instantDismiss */) + onAnimationFinished(false /* instantDismiss */) onDialogDismissed(this@AnimatedDialog) return } @@ -631,23 +541,25 @@ private class AnimatedDialog( isLaunching = false, onLaunchAnimationStart = { // Remove the dim background as soon as we start the animation. - hostDialog.window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND) + dialog.window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND) }, onLaunchAnimationEnd = { // Make sure we allow the touch surface to change its visibility again. (touchSurface as? LaunchableView)?.setShouldBlockVisibilityChanges(false) touchSurface.visibility = View.VISIBLE - dialogContentParent.visibility = View.INVISIBLE + val dialogContentWithBackground = this.dialogContentWithBackground!! + dialogContentWithBackground.visibility = View.INVISIBLE if (backgroundLayoutListener != null) { - dialogContentParent.removeOnLayoutChangeListener(backgroundLayoutListener) + dialogContentWithBackground + .removeOnLayoutChangeListener(backgroundLayoutListener) } // The animated ghost was just removed. We create a temporary ghost that will be // removed only once we draw the touch surface, to avoid flickering that would // happen when removing the ghost too early (before the touch surface is drawn). - GhostView.addGhost(touchSurface, hostDialogRoot) + GhostView.addGhost(touchSurface, decorView) touchSurface.viewTreeObserver.addOnPreDrawListener(object : OnPreDrawListener { override fun onPreDraw(): Boolean { @@ -656,7 +568,7 @@ private class AnimatedDialog( // Now that the touch surface was drawn, we can remove the temporary ghost // and instantly dismiss the dialog. GhostView.removeGhost(touchSurface) - dismissDialogs(true /* instantDismiss */) + onAnimationFinished(true /* instantDismiss */) onDialogDismissed(this@AnimatedDialog) return true @@ -672,14 +584,14 @@ private class AnimatedDialog( onLaunchAnimationStart: () -> Unit = {}, onLaunchAnimationEnd: () -> Unit = {} ) { - // Create 2 ghost controllers to animate both the dialog and the touch surface in the host + // Create 2 ghost controllers to animate both the dialog and the touch surface in the // dialog. - val startView = if (isLaunching) touchSurface else dialogContentParent - val endView = if (isLaunching) dialogContentParent else touchSurface + val startView = if (isLaunching) touchSurface else dialogContentWithBackground!! + val endView = if (isLaunching) dialogContentWithBackground!! else touchSurface val startViewController = GhostedViewLaunchAnimatorController(startView) val endViewController = GhostedViewLaunchAnimatorController(endView) - startViewController.launchContainer = hostDialogRoot - endViewController.launchContainer = hostDialogRoot + startViewController.launchContainer = decorView + endViewController.launchContainer = decorView val endState = endViewController.createAnimatorState() val controller = object : LaunchAnimator.Controller { @@ -736,7 +648,15 @@ private class AnimatedDialog( } private fun shouldAnimateDialogIntoView(): Boolean { - if (exitAnimationDisabled) { + // Don't animate if the dialog was previously hidden using hide() or if we disabled the exit + // animation. + if (exitAnimationDisabled || !dialog.isShowing) { + return false + } + + // If we are dreaming, the dialog was probably closed because of that so we don't animate + // into the touchSurface. + if (dreamManager.isDreaming) { return false } @@ -837,9 +757,9 @@ private class AnimatedDialog( return touchSurface } parentAnimatedDialog.exitAnimationDisabled = true - parentAnimatedDialog.originalDialog.hide() + parentAnimatedDialog.dialog.hide() val view = parentAnimatedDialog.prepareForStackDismiss() - parentAnimatedDialog.originalDialog.dismiss() + parentAnimatedDialog.dialog.dismiss() // Make the touch surface invisible, so we end up animating to it when we actually // dismiss the stack view.visibility = View.INVISIBLE diff --git a/packages/SystemUI/res-keyguard/values-te/strings.xml b/packages/SystemUI/res-keyguard/values-te/strings.xml index 30f3c8329a01..dfb0c81cb957 100644 --- a/packages/SystemUI/res-keyguard/values-te/strings.xml +++ b/packages/SystemUI/res-keyguard/values-te/strings.xml @@ -86,9 +86,9 @@ <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"పరికరాన్ని పునఃప్రారంభించిన తర్వాత నమూనాను గీయాలి"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"డివైజ్ను పునఃప్రారంభించిన తర్వాత పిన్ నమోదు చేయాలి"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"పరికరాన్ని పునఃప్రారంభించిన తర్వాత పాస్వర్డ్ను నమోదు చేయాలి"</string> - <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"అదనపు భద్రత కోసం నమూనాని గీయాలి"</string> - <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"అదనపు భద్రత కోసం పిన్ నమోదు చేయాలి"</string> - <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"అదనపు భద్రత కోసం పాస్వర్డ్ని నమోదు చేయాలి"</string> + <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"అదనపు సెక్యూరిటీ కోసం ఆకృతి అవసరం"</string> + <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"అదనపు సెక్యూరిటీ కోసం పిన్ ఎంటర్ చేయాలి"</string> + <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"అదనపు సెక్యూరిటీ కోసం పాస్వర్డ్ను ఎంటర్ చేయాలి"</string> <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"పరికరం నిర్వాహకుల ద్వారా లాక్ చేయబడింది"</string> <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"పరికరం మాన్యువల్గా లాక్ చేయబడింది"</string> <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"గుర్తించలేదు"</string> diff --git a/packages/SystemUI/res/layout/alert_dialog_title_systemui.xml b/packages/SystemUI/res/layout/alert_dialog_title_systemui.xml index 480ba001fae1..88f13b451bbe 100644 --- a/packages/SystemUI/res/layout/alert_dialog_title_systemui.xml +++ b/packages/SystemUI/res/layout/alert_dialog_title_systemui.xml @@ -45,9 +45,8 @@ android:tint="?androidprv:attr/colorAccentPrimaryVariant" /> - <com.android.internal.widget.DialogTitle + <TextView android:id="@*android:id/alertTitle" - android:singleLine="true" android:ellipsize="end" android:layout_width="match_parent" android:layout_height="wrap_content" diff --git a/packages/SystemUI/res/layout/internet_connectivity_dialog.xml b/packages/SystemUI/res/layout/internet_connectivity_dialog.xml index 98518c2bbf97..e90a6446c47b 100644 --- a/packages/SystemUI/res/layout/internet_connectivity_dialog.xml +++ b/packages/SystemUI/res/layout/internet_connectivity_dialog.xml @@ -34,6 +34,7 @@ <TextView android:id="@+id/internet_dialog_title" + android:ellipsize="end" android:gravity="center_vertical|center_horizontal" android:layout_width="wrap_content" android:layout_height="32dp" @@ -154,12 +155,18 @@ <TextView android:id="@+id/mobile_summary" style="@style/InternetDialog.NetworkSummary"/> + <TextView + android:id="@+id/airplane_mode_summary" + android:text="@string/airplane_mode" + android:visibility="gone" + style="@style/InternetDialog.NetworkSummary"/> </LinearLayout> <View android:id="@+id/mobile_toggle_divider" android:layout_width="1dp" android:layout_height="28dp" + android:layout_marginStart="7dp" android:layout_marginEnd="16dp" android:layout_gravity="center_vertical" android:background="?android:attr/textColorSecondary"/> @@ -185,7 +192,7 @@ <LinearLayout android:id="@+id/turn_on_wifi_layout" style="@style/InternetDialog.Network" - android:layout_height="72dp" + android:layout_height="@dimen/internet_dialog_wifi_network_height" android:gravity="center" android:clickable="false" android:focusable="false"> @@ -227,7 +234,7 @@ <LinearLayout android:id="@+id/wifi_connected_layout" style="@style/InternetDialog.Network" - android:layout_height="72dp" + android:layout_height="@dimen/internet_dialog_wifi_network_height" android:paddingStart="20dp" android:paddingEnd="24dp" android:background="@drawable/settingslib_switch_bar_bg_on" @@ -249,7 +256,7 @@ android:orientation="vertical" android:clickable="false" android:layout_width="wrap_content" - android:layout_height="72dp" + android:layout_height="@dimen/internet_dialog_wifi_network_height" android:layout_marginEnd="30dp" android:layout_weight="1" android:gravity="start|center_vertical"> @@ -370,27 +377,60 @@ android:clickable="true"/> </LinearLayout> </LinearLayout> - <FrameLayout - android:id="@+id/done_layout" - android:layout_width="67dp" + android:id="@+id/button_layout" + android:orientation="horizontal" + android:layout_width="match_parent" android:layout_height="48dp" - android:layout_marginTop="8dp" + android:layout_marginStart="24dp" android:layout_marginEnd="24dp" + android:layout_marginTop="8dp" android:layout_marginBottom="34dp" - android:layout_gravity="end|center_vertical" - android:clickable="true" - android:focusable="true"> - <Button - android:text="@string/inline_done_button" - style="@*android:style/Widget.DeviceDefault.Button.Borderless.Colored" - android:layout_width="match_parent" - android:layout_height="36dp" - android:layout_gravity="center" - android:textAppearance="@style/TextAppearance.InternetDialog" - android:textSize="14sp" - android:background="@drawable/internet_dialog_footer_background" - android:clickable="false"/> + android:clickable="false" + android:focusable="false"> + + <FrameLayout + android:id="@+id/apm_layout" + android:layout_width="wrap_content" + android:layout_height="48dp" + android:clickable="true" + android:focusable="true" + android:layout_gravity="start|center_vertical" + android:orientation="vertical"> + <Button + android:text="@string/turn_off_airplane_mode" + android:ellipsize="end" + style="@*android:style/Widget.DeviceDefault.Button.Borderless.Colored" + android:layout_width="wrap_content" + android:layout_height="36dp" + android:layout_gravity="start|center_vertical" + android:textAppearance="@style/TextAppearance.InternetDialog" + android:textSize="14sp" + android:background="@drawable/internet_dialog_footer_background" + android:clickable="false"/> + </FrameLayout> + + <FrameLayout + android:id="@+id/done_layout" + android:layout_width="wrap_content" + android:layout_height="48dp" + android:layout_marginStart="16dp" + android:clickable="true" + android:focusable="true" + android:layout_gravity="end|center_vertical" + android:orientation="vertical"> + <Button + android:text="@string/inline_done_button" + android:ellipsize="end" + style="@*android:style/Widget.DeviceDefault.Button.Borderless.Colored" + android:layout_width="67dp" + android:layout_height="36dp" + android:layout_gravity="end|center_vertical" + android:textAppearance="@style/TextAppearance.InternetDialog" + android:textSize="14sp" + android:background="@drawable/internet_dialog_footer_background" + android:clickable="false"/> + </FrameLayout> </FrameLayout> </LinearLayout> </androidx.core.widget.NestedScrollView> diff --git a/packages/SystemUI/res/layout/internet_list_item.xml b/packages/SystemUI/res/layout/internet_list_item.xml index 868331ec830f..f6a213662a18 100644 --- a/packages/SystemUI/res/layout/internet_list_item.xml +++ b/packages/SystemUI/res/layout/internet_list_item.xml @@ -25,7 +25,7 @@ <LinearLayout android:id="@+id/wifi_list" style="@style/InternetDialog.Network" - android:layout_height="72dp" + android:layout_height="@dimen/internet_dialog_wifi_network_height" android:paddingStart="20dp" android:paddingEnd="24dp"> <FrameLayout @@ -45,7 +45,7 @@ android:orientation="vertical" android:clickable="false" android:layout_width="wrap_content" - android:layout_height="72dp" + android:layout_height="@dimen/internet_dialog_wifi_network_height" android:layout_marginEnd="30dp" android:layout_weight="1" android:gravity="start|center_vertical"> diff --git a/packages/SystemUI/res/layout/keyguard_bottom_area.xml b/packages/SystemUI/res/layout/keyguard_bottom_area.xml index 8dbd59d42ab7..759670e01e71 100644 --- a/packages/SystemUI/res/layout/keyguard_bottom_area.xml +++ b/packages/SystemUI/res/layout/keyguard_bottom_area.xml @@ -17,7 +17,6 @@ <com.android.systemui.statusbar.phone.KeyguardBottomAreaView xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui" android:id="@+id/keyguard_bottom_area" android:layout_height="match_parent" android:layout_width="match_parent" @@ -114,7 +113,8 @@ android:layout_height="match_parent"> <include layout="@layout/keyguard_bottom_area_overlay" /> - </FrameLayout> + <include layout="@layout/ambient_indication" + android:id="@+id/ambient_indication_container" /> </com.android.systemui.statusbar.phone.KeyguardBottomAreaView> diff --git a/packages/SystemUI/res/layout/qs_user_detail_item.xml b/packages/SystemUI/res/layout/qs_user_detail_item.xml index 91b11fcc3c26..3a0df2863819 100644 --- a/packages/SystemUI/res/layout/qs_user_detail_item.xml +++ b/packages/SystemUI/res/layout/qs_user_detail_item.xml @@ -37,8 +37,8 @@ android:layout_height="@dimen/qs_framed_avatar_size" android:layout_marginBottom="7dp" systemui:frameWidth="6dp" - systemui:badgeDiameter="18dp" - systemui:badgeMargin="1dp" + systemui:badgeDiameter="15dp" + systemui:badgeMargin="5dp" systemui:framePadding="-1dp" systemui:frameColor="@color/qs_user_avatar_frame"/> diff --git a/packages/SystemUI/res/layout/screen_record_dialog.xml b/packages/SystemUI/res/layout/screen_record_dialog.xml index e43a149a6cd9..6c5ad5060495 100644 --- a/packages/SystemUI/res/layout/screen_record_dialog.xml +++ b/packages/SystemUI/res/layout/screen_record_dialog.xml @@ -93,41 +93,6 @@ android:id="@+id/screenrecord_audio_switch" style="@style/ScreenRecord.Switch"/> </LinearLayout> - - <LinearLayout - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="horizontal" - android:layout_marginTop="@dimen/screenrecord_option_padding"> - <ImageView - android:layout_width="@dimen/screenrecord_option_icon_size" - android:layout_height="@dimen/screenrecord_option_icon_size" - android:layout_weight="0" - android:src="@drawable/ic_touch" - android:tint="?android:attr/textColorSecondary" - android:layout_gravity="center" - android:layout_marginRight="@dimen/screenrecord_option_padding"/> - <TextView - android:layout_width="0dp" - android:layout_height="wrap_content" - android:minHeight="48dp" - android:layout_weight="1" - android:layout_gravity="fill_vertical" - android:gravity="center_vertical" - android:text="@string/screenrecord_taps_label" - android:textAppearance="?android:attr/textAppearanceMedium" - android:fontFamily="@*android:string/config_headlineFontFamily" - android:textColor="?android:attr/textColorPrimary" - android:importantForAccessibility="no"/> - <Switch - android:layout_width="wrap_content" - android:minWidth="48dp" - android:layout_height="48dp" - android:layout_weight="0" - android:id="@+id/screenrecord_taps_switch" - android:contentDescription="@string/screenrecord_taps_label" - style="@style/ScreenRecord.Switch"/> - </LinearLayout> </LinearLayout> <!-- Buttons --> diff --git a/packages/SystemUI/res/layout/split_shade_header.xml b/packages/SystemUI/res/layout/split_shade_header.xml index f2c5b7bd491c..b6e96ceeaf20 100644 --- a/packages/SystemUI/res/layout/split_shade_header.xml +++ b/packages/SystemUI/res/layout/split_shade_header.xml @@ -83,6 +83,17 @@ android:layout_width="wrap_content" android:layout_height="match_parent" systemui:textAppearance="@style/TextAppearance.QS.Status" /> + <FrameLayout + android:id="@+id/privacy_container" + android:layout_width="0dp" + android:layout_height="match_parent" + android:minHeight="48dp" + android:layout_weight="1" + android:paddingStart="16dp"> + + <include layout="@layout/ongoing_privacy_chip" /> + + </FrameLayout> </LinearLayout> </FrameLayout> diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml index 82186c13394e..591d8f52c4be 100644 --- a/packages/SystemUI/res/layout/status_bar_expanded.xml +++ b/packages/SystemUI/res/layout/status_bar_expanded.xml @@ -119,9 +119,6 @@ systemui:layout_constraintEnd_toEndOf="parent" /> - <include layout="@layout/ambient_indication" - android:id="@+id/ambient_indication_container" /> - <include layout="@layout/photo_preview_overlay" /> <include diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml index 5d582b11f645..d6ef84fe59a0 100644 --- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml +++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml @@ -669,7 +669,7 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"Neke funkcije su ograničene dok se telefon ne ohladi.\nDodirnite za više informacija"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"Telefon će automatski pokušati da se ohladi. I dalje ćete moći da koristite telefon, ali će sporije reagovati.\n\nKada se telefon ohladi, normalno će raditi."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Pogledajte upozorenja"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Isključite punjač iz napajanja"</string> + <string name="high_temp_alarm_title" msgid="2359958549570161495">"Isključite punjač iz struje"</string> <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"Došlo je do problema sa punjenjem ovog uređaja. Isključite adapter iz napajanja i budite pažljivi jer kabl može da bude topao."</string> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"Pogledajte upozorenja"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Leva prečica"</string> diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml index 48d5bb10fc39..14bb304e97ea 100644 --- a/packages/SystemUI/res/values-in/strings.xml +++ b/packages/SystemUI/res/values-in/strings.xml @@ -69,8 +69,7 @@ <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Mengambil screenshot tidak diizinkan oleh aplikasi atau organisasi"</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"Edit"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"Mengedit screenshot"</string> - <!-- no translation found for screenshot_share_description (2861628935812656612) --> - <skip /> + <string name="screenshot_share_description" msgid="2861628935812656612">"Bagikan screenshot"</string> <string name="screenshot_scroll_label" msgid="2930198809899329367">"Ambil lebih banyak"</string> <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Menutup screenshot"</string> <string name="screenshot_preview_description" msgid="7606510140714080474">"Pratinjau screenshot"</string> diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml index 90977cfa5978..a7f492ef42a4 100644 --- a/packages/SystemUI/res/values-ms/strings.xml +++ b/packages/SystemUI/res/values-ms/strings.xml @@ -69,8 +69,7 @@ <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Pengambilan tangkapan skrin tidak dibenarkan oleh apl atau organisasi anda"</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"Edit"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"Edit tangkapan skrin"</string> - <!-- no translation found for screenshot_share_description (2861628935812656612) --> - <skip /> + <string name="screenshot_share_description" msgid="2861628935812656612">"Kongsi tangkapan skrin"</string> <string name="screenshot_scroll_label" msgid="2930198809899329367">"Tangkap lebih banyak"</string> <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Ketepikan tangkapan skrin"</string> <string name="screenshot_preview_description" msgid="7606510140714080474">"Pratonton tangkapan skrin"</string> diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml index a9db25437ebe..15160cc08e5d 100644 --- a/packages/SystemUI/res/values-my/strings.xml +++ b/packages/SystemUI/res/values-my/strings.xml @@ -69,8 +69,7 @@ <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ဖန်သားပြင်ဓာတ်ပုံရိုက်ကူးခြင်းကို ဤအက်ပ် သို့မဟုတ် သင်၏အဖွဲ့အစည်းက ခွင့်မပြုပါ"</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"တည်းဖြတ်ရန်"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"ဖန်သားပြင်ဓာတ်ပုံကို တည်းဖြတ်သည်"</string> - <!-- no translation found for screenshot_share_description (2861628935812656612) --> - <skip /> + <string name="screenshot_share_description" msgid="2861628935812656612">"ဖန်သားပြင်ဓာတ်ပုံကို မျှဝေနိုင်သည်"</string> <string name="screenshot_scroll_label" msgid="2930198809899329367">"နောက်ထပ် ရိုက်ကူးရန်"</string> <string name="screenshot_dismiss_description" msgid="4702341245899508786">"ဖန်သားပြင်ဓာတ်ပုံကို ပယ်သည်"</string> <string name="screenshot_preview_description" msgid="7606510140714080474">"ဖန်သားပြင်ဓာတ်ပုံ အစမ်းကြည့်ရှုခြင်း"</string> diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml index 54fa293541ab..bb731b7eaae1 100644 --- a/packages/SystemUI/res/values-ru/strings.xml +++ b/packages/SystemUI/res/values-ru/strings.xml @@ -69,8 +69,7 @@ <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Не удалось сделать скриншот: нет разрешения от приложения или организации."</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"Изменить"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"Изменить скриншот"</string> - <!-- no translation found for screenshot_share_description (2861628935812656612) --> - <skip /> + <string name="screenshot_share_description" msgid="2861628935812656612">"Поделиться скриншотом"</string> <string name="screenshot_scroll_label" msgid="2930198809899329367">"Увеличить площадь скриншота"</string> <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Закрыть скриншот"</string> <string name="screenshot_preview_description" msgid="7606510140714080474">"Предварительный просмотр скриншота"</string> @@ -125,7 +124,7 @@ <string name="biometric_dialog_face_icon_description_confirmed" msgid="7918067993953940778">"Подтверждено"</string> <string name="biometric_dialog_tap_confirm" msgid="9166350738859143358">"Нажмите \"Подтвердить\""</string> <string name="biometric_dialog_authenticated" msgid="7337147327545272484">"Аутентификация выполнена"</string> - <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"Использовать PIN-код"</string> + <string name="biometric_dialog_use_pin" msgid="8385294115283000709">"PIN-код"</string> <string name="biometric_dialog_use_pattern" msgid="2315593393167211194">"Использовать графический ключ"</string> <string name="biometric_dialog_use_password" msgid="3445033859393474779">"Использовать пароль"</string> <string name="biometric_dialog_wrong_pin" msgid="1878539073972762803">"Неверный PIN-код."</string> diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml index f540f11824c5..4fd78564123c 100644 --- a/packages/SystemUI/res/values-sq/strings.xml +++ b/packages/SystemUI/res/values-sq/strings.xml @@ -69,8 +69,7 @@ <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Nxjerrja e pamjeve të ekranit nuk lejohet nga aplikacioni ose organizata jote."</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"Modifiko"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"Modifiko pamjen e ekranit"</string> - <!-- no translation found for screenshot_share_description (2861628935812656612) --> - <skip /> + <string name="screenshot_share_description" msgid="2861628935812656612">"Ndaj pamjen e ekranit"</string> <string name="screenshot_scroll_label" msgid="2930198809899329367">"Regjistro më shumë"</string> <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Hiq pamjen e ekranit"</string> <string name="screenshot_preview_description" msgid="7606510140714080474">"Pamja paraprake e imazhit"</string> diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml index e0ef5e2d82af..7e8059d21c21 100644 --- a/packages/SystemUI/res/values-sr/strings.xml +++ b/packages/SystemUI/res/values-sr/strings.xml @@ -669,7 +669,7 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"Неке функције су ограничене док се телефон не охлади.\nДодирните за више информација"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"Телефон ће аутоматски покушати да се охлади. И даље ћете моћи да користите телефон, али ће спорије реаговати.\n\nКада се телефон охлади, нормално ће радити."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Погледајте упозорења"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Искључите пуњач из напајања"</string> + <string name="high_temp_alarm_title" msgid="2359958549570161495">"Искључите пуњач из струје"</string> <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"Дошло је до проблема са пуњењем овог уређаја. Искључите адаптер из напајања и будите пажљиви јер кабл може да буде топао."</string> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"Погледајте упозорења"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Лева пречица"</string> diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml index 2f74a830407d..641471ad30c9 100644 --- a/packages/SystemUI/res/values-th/strings.xml +++ b/packages/SystemUI/res/values-th/strings.xml @@ -69,8 +69,7 @@ <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"แอปหรือองค์กรของคุณไม่อนุญาตให้จับภาพหน้าจอ"</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"แก้ไข"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"แก้ไขภาพหน้าจอ"</string> - <!-- no translation found for screenshot_share_description (2861628935812656612) --> - <skip /> + <string name="screenshot_share_description" msgid="2861628935812656612">"แชร์ภาพหน้าจอ"</string> <string name="screenshot_scroll_label" msgid="2930198809899329367">"จับภาพได้มากขึ้น"</string> <string name="screenshot_dismiss_description" msgid="4702341245899508786">"ปิดภาพหน้าจอ"</string> <string name="screenshot_preview_description" msgid="7606510140714080474">"ตัวอย่างภาพหน้าจอ"</string> diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml index 7b5934007c16..65817b9d317f 100644 --- a/packages/SystemUI/res/values-tl/strings.xml +++ b/packages/SystemUI/res/values-tl/strings.xml @@ -69,8 +69,7 @@ <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Hindi pinahihintulutan ng app o ng iyong organisasyon ang pagkuha ng mga screenshot"</string> <string name="screenshot_edit_label" msgid="8754981973544133050">"I-edit"</string> <string name="screenshot_edit_description" msgid="3333092254706788906">"I-edit ang screenshot"</string> - <!-- no translation found for screenshot_share_description (2861628935812656612) --> - <skip /> + <string name="screenshot_share_description" msgid="2861628935812656612">"Ibahagi ang screenshot"</string> <string name="screenshot_scroll_label" msgid="2930198809899329367">"Mag-capture pa"</string> <string name="screenshot_dismiss_description" msgid="4702341245899508786">"I-dismiss ang screenshot"</string> <string name="screenshot_preview_description" msgid="7606510140714080474">"Preview ng screenshot"</string> diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index e00b9410a8a7..475f70fa9fdc 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -595,6 +595,17 @@ 280 </integer> + <!-- Haptic feedback intensity for ticks used for the udfps dwell time --> + <item name="config_udfpsTickIntensity" translatable="false" format="float" + type="dimen">.5</item> + + <!-- Haptic feedback delay between ticks used for udfps dwell time --> + <integer name="config_udfpsTickDelay" translatable="false">25</integer> + + <!-- Haptic feedback tick type - if true, uses VibrationEffect.Composition.PRIMITIVE_LOW_TICK + else uses VibrationEffect.Composition.PRIMITIVE_TICK --> + <bool name="config_udfpsUseLowTick">true</bool> + <!-- package name of a built-in camera app to use to restrict implicit intent resolution when the double-press power gesture is used. Ignored if empty. --> <string translatable="false" name="config_cameraGesturePackage"></string> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index a2fd669c69fd..1938e48e859a 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -1243,6 +1243,8 @@ <!-- Internet panel related dimensions --> <dimen name="internet_dialog_list_max_height">662dp</dimen> + <!-- The height of the WiFi network in Internet panel. --> + <dimen name="internet_dialog_wifi_network_height">72dp</dimen> <!-- The width of large/content heavy dialogs (e.g. Internet, Media output, etc) --> <dimen name="large_dialog_width">@dimen/match_parent</dimen> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 879726650b88..4dc52e7540be 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -2336,6 +2336,8 @@ <string name="to_switch_networks_disconnect_ethernet">To switch networks, disconnect ethernet</string> <!-- Message to describe "Wi-Fi scan always available feature" when Wi-Fi is off and Wi-Fi scanning is on. [CHAR LIMIT=NONE] --> <string name="wifi_scan_notify_message">To improve device experience, apps and services can still scan for Wi\u2011Fi networks at any time, even when Wi\u2011Fi is off. You can change this in Wi\u2011Fi scanning settings. <annotation id="link">Change</annotation></string> + <!-- Provider Model: Description of the airplane mode button. [CHAR LIMIT=60] --> + <string name="turn_off_airplane_mode">Turn off airplane mode</string> <!-- Title for User Switch dialog. [CHAR LIMIT=20] --> <string name="qs_user_switch_dialog_title">Select user</string> diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml index 3c7b53a8e6db..92985ded8a91 100644 --- a/packages/SystemUI/res/values/styles.xml +++ b/packages/SystemUI/res/values/styles.xml @@ -373,11 +373,11 @@ <item name="android:windowIsFloating">true</item> </style> - <style name="Theme.SystemUI.Dialog.GlobalActionsLite" parent="@android:style/Theme.DeviceDefault.Light.NoActionBar.Fullscreen"> - <item name="android:windowIsFloating">true</item> + <style name="Theme.SystemUI.Dialog.GlobalActionsLite" parent="Theme.SystemUI.Dialog"> + <!-- Settings windowFullscreen: true is necessary to be able to intercept touch events --> + <!-- that would otherwise be intercepted by the Shade. --> + <item name="android:windowFullscreen">true</item> <item name="android:windowBackground">@android:color/transparent</item> - <item name="android:backgroundDimEnabled">true</item> - <item name="android:windowCloseOnTouchOutside">true</item> </style> <style name="QSBorderlessButton"> @@ -837,7 +837,6 @@ <style name="Widget.SliceView.Panel"> <item name="titleSize">16sp</item> <item name="rowStyle">@style/SliceRow</item> - <item name="android:background">?android:attr/colorBackgroundFloating</item> </style> <style name="SliceRow"> diff --git a/packages/SystemUI/shared/src/com/android/systemui/navigationbar/buttons/KeyButtonRipple.java b/packages/SystemUI/shared/src/com/android/systemui/navigationbar/buttons/KeyButtonRipple.java index 07ad0c8a5120..8aa3abac831f 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/navigationbar/buttons/KeyButtonRipple.java +++ b/packages/SystemUI/shared/src/com/android/systemui/navigationbar/buttons/KeyButtonRipple.java @@ -51,6 +51,9 @@ public class KeyButtonRipple extends Drawable { private static final Interpolator ALPHA_OUT_INTERPOLATOR = new PathInterpolator(0f, 0f, 0.8f, 1f); + @DimenRes + private final int mMaxWidthResource; + private Paint mRipplePaint; private CanvasProperty<Float> mLeftProp; private CanvasProperty<Float> mTopProp; @@ -90,10 +93,17 @@ public class KeyButtonRipple extends Drawable { private Type mType = Type.ROUNDED_RECT; public KeyButtonRipple(Context ctx, View targetView, @DimenRes int maxWidthResource) { + mMaxWidthResource = maxWidthResource; mMaxWidth = ctx.getResources().getDimensionPixelSize(maxWidthResource); mTargetView = targetView; } + public void updateResources() { + mMaxWidth = mTargetView.getContext().getResources() + .getDimensionPixelSize(mMaxWidthResource); + invalidateSelf(); + } + public void setDarkIntensity(float darkIntensity) { mDark = darkIntensity >= 0.5f; } diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/FloatingRotationButton.java b/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/FloatingRotationButton.java index cbf739732361..857cc4620ebd 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/FloatingRotationButton.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/FloatingRotationButton.java @@ -21,6 +21,8 @@ import android.annotation.IdRes; import android.annotation.LayoutRes; import android.annotation.StringRes; import android.content.Context; +import android.content.pm.ActivityInfo; +import android.content.pm.ActivityInfo.Config; import android.content.res.Resources; import android.graphics.PixelFormat; import android.graphics.drawable.AnimatedVectorDrawable; @@ -29,12 +31,12 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; +import android.view.WindowManager.LayoutParams; import android.view.animation.AccelerateDecelerateInterpolator; import android.widget.FrameLayout; import androidx.core.view.OneShotPreDrawListener; -import com.android.systemui.shared.R; import com.android.systemui.shared.rotation.FloatingRotationButtonPositionCalculator.Position; /** @@ -48,7 +50,21 @@ public class FloatingRotationButton implements RotationButton { private final ViewGroup mKeyButtonContainer; private final FloatingRotationButtonView mKeyButtonView; - private final int mContainerSize; + private int mContainerSize; + private final Context mContext; + + @StringRes + private final int mContentDescriptionResource; + @DimenRes + private final int mMinMarginResource; + @DimenRes + private final int mRoundedContentPaddingResource; + @DimenRes + private final int mTaskbarLeftMarginResource; + @DimenRes + private final int mTaskbarBottomMarginResource; + @DimenRes + private final int mButtonDiameterResource; private AnimatedVectorDrawable mAnimatedDrawable; private boolean mIsShowing; @@ -58,13 +74,13 @@ public class FloatingRotationButton implements RotationButton { private boolean mIsTaskbarVisible = false; private boolean mIsTaskbarStashed = false; - private final FloatingRotationButtonPositionCalculator mPositionCalculator; + private FloatingRotationButtonPositionCalculator mPositionCalculator; private RotationButtonController mRotationButtonController; private RotationButtonUpdatesCallback mUpdatesCallback; private Position mPosition; - public FloatingRotationButton(Context context, @StringRes int contentDescription, + public FloatingRotationButton(Context context, @StringRes int contentDescriptionResource, @LayoutRes int layout, @IdRes int keyButtonId, @DimenRes int minMargin, @DimenRes int roundedContentPadding, @DimenRes int taskbarLeftMargin, @DimenRes int taskbarBottomMargin, @DimenRes int buttonDiameter, @@ -73,24 +89,37 @@ public class FloatingRotationButton implements RotationButton { mKeyButtonContainer = (ViewGroup) LayoutInflater.from(context).inflate(layout, null); mKeyButtonView = mKeyButtonContainer.findViewById(keyButtonId); mKeyButtonView.setVisibility(View.VISIBLE); - mKeyButtonView.setContentDescription(context.getString(contentDescription)); + mKeyButtonView.setContentDescription(context.getString(contentDescriptionResource)); mKeyButtonView.setRipple(rippleMaxWidth); - Resources res = context.getResources(); + mContext = context; + + mContentDescriptionResource = contentDescriptionResource; + mMinMarginResource = minMargin; + mRoundedContentPaddingResource = roundedContentPadding; + mTaskbarLeftMarginResource = taskbarLeftMargin; + mTaskbarBottomMarginResource = taskbarBottomMargin; + mButtonDiameterResource = buttonDiameter; + + updateDimensionResources(); + } + + private void updateDimensionResources() { + Resources res = mContext.getResources(); int defaultMargin = Math.max( - res.getDimensionPixelSize(minMargin), - res.getDimensionPixelSize(roundedContentPadding)); + res.getDimensionPixelSize(mMinMarginResource), + res.getDimensionPixelSize(mRoundedContentPaddingResource)); int taskbarMarginLeft = - res.getDimensionPixelSize(taskbarLeftMargin); + res.getDimensionPixelSize(mTaskbarLeftMarginResource); int taskbarMarginBottom = - res.getDimensionPixelSize(taskbarBottomMargin); + res.getDimensionPixelSize(mTaskbarBottomMarginResource); mPositionCalculator = new FloatingRotationButtonPositionCalculator(defaultMargin, taskbarMarginLeft, taskbarMarginBottom); - final int diameter = res.getDimensionPixelSize(buttonDiameter); + final int diameter = res.getDimensionPixelSize(mButtonDiameterResource); mContainerSize = diameter + Math.max(defaultMargin, Math.max(taskbarMarginLeft, taskbarMarginBottom)); } @@ -119,32 +148,10 @@ public class FloatingRotationButton implements RotationButton { } mIsShowing = true; - int flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; - - // TODO(b/200103245): add new window type that has z-index above - // TYPE_NAVIGATION_BAR_PANEL as currently it could be below the taskbar which has - // the same window type - final WindowManager.LayoutParams lp = new WindowManager.LayoutParams( - mContainerSize, - mContainerSize, - 0, 0, WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL, flags, - PixelFormat.TRANSLUCENT); - - lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS; - lp.setTitle("FloatingRotationButton"); - lp.setFitInsetsTypes(0 /*types */); - - mDisplayRotation = mWindowManager.getDefaultDisplay().getRotation(); - mPosition = mPositionCalculator - .calculatePosition(mDisplayRotation, mIsTaskbarVisible, mIsTaskbarStashed); - lp.gravity = mPosition.getGravity(); - ((FrameLayout.LayoutParams) mKeyButtonView.getLayoutParams()).gravity = - mPosition.getGravity(); + final LayoutParams layoutParams = adjustViewPositionAndCreateLayoutParams(); + mWindowManager.addView(mKeyButtonContainer, layoutParams); - updateTranslation(mPosition, /* animate */ false); - - mWindowManager.addView(mKeyButtonContainer, lp); if (mAnimatedDrawable != null) { mAnimatedDrawable.reset(); mAnimatedDrawable.start(); @@ -232,6 +239,53 @@ public class FloatingRotationButton implements RotationButton { } } + /** + * Updates resources that could be changed in runtime, should be called on configuration + * change with changes diff integer mask + * @param configurationChanges - configuration changes with flags from ActivityInfo e.g. + * {@link android.content.pm.ActivityInfo#CONFIG_DENSITY} + */ + public void onConfigurationChanged(@Config int configurationChanges) { + if ((configurationChanges & ActivityInfo.CONFIG_DENSITY) != 0 + || (configurationChanges & ActivityInfo.CONFIG_SCREEN_SIZE) != 0) { + updateDimensionResources(); + + if (mIsShowing) { + final LayoutParams layoutParams = adjustViewPositionAndCreateLayoutParams(); + mWindowManager.updateViewLayout(mKeyButtonContainer, layoutParams); + } + } + + if ((configurationChanges & ActivityInfo.CONFIG_LOCALE) != 0) { + mKeyButtonView.setContentDescription(mContext.getString(mContentDescriptionResource)); + } + } + + private LayoutParams adjustViewPositionAndCreateLayoutParams() { + final LayoutParams lp = new LayoutParams( + mContainerSize, + mContainerSize, + /* xpos */ 0, /* ypos */ 0, LayoutParams.TYPE_NAVIGATION_BAR_PANEL, + LayoutParams.FLAG_NOT_FOCUSABLE, + PixelFormat.TRANSLUCENT); + + lp.privateFlags |= LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS; + lp.setTitle("FloatingRotationButton"); + lp.setFitInsetsTypes(/* types */ 0); + + mDisplayRotation = mWindowManager.getDefaultDisplay().getRotation(); + mPosition = mPositionCalculator + .calculatePosition(mDisplayRotation, mIsTaskbarVisible, mIsTaskbarStashed); + + lp.gravity = mPosition.getGravity(); + ((FrameLayout.LayoutParams) mKeyButtonView.getLayoutParams()).gravity = + mPosition.getGravity(); + + updateTranslation(mPosition, /* animate */ false); + + return lp; + } + private void updateTranslation(Position position, boolean animate) { final int translationX = position.getTranslationX(); final int translationY = position.getTranslationY(); diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/FloatingRotationButtonView.java b/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/FloatingRotationButtonView.java index c5f8fc15b3b7..a4b6451caaea 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/FloatingRotationButtonView.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/FloatingRotationButtonView.java @@ -17,6 +17,8 @@ package com.android.systemui.shared.rotation; import android.content.Context; +import android.content.pm.ActivityInfo; +import android.content.res.Configuration; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; @@ -37,12 +39,15 @@ public class FloatingRotationButtonView extends ImageView { private KeyButtonRipple mRipple; private final Paint mOvalBgPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG); + private final Configuration mLastConfiguration; + public FloatingRotationButtonView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public FloatingRotationButtonView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); + mLastConfiguration = getResources().getConfiguration(); setClickable(true); @@ -63,6 +68,17 @@ public class FloatingRotationButtonView extends ImageView { } } + @Override + protected void onConfigurationChanged(Configuration newConfig) { + final int changes = mLastConfiguration.updateFrom(newConfig); + if ((changes & ActivityInfo.CONFIG_SCREEN_SIZE) != 0 + || ((changes & ActivityInfo.CONFIG_DENSITY) != 0)) { + if (mRipple != null) { + mRipple.updateResources(); + } + } + } + public void setColors(int lightColor, int darkColor) { getDrawable().setColorFilter(new PorterDuffColorFilter(lightColor, PorterDuff.Mode.SRC_IN)); diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java b/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java index 2dbd5dee76aa..78867f7220af 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java @@ -481,7 +481,9 @@ public class RotationButtonController { * orientation overview. */ public void setSkipOverrideUserLockPrefsOnce() { - mSkipOverrideUserLockPrefsOnce = true; + // If live-tile is enabled (recents animation keeps running in overview), there is no + // activity switch so the display rotation is not changed, then it is no need to skip. + mSkipOverrideUserLockPrefsOnce = !mIsRecentsAnimationRunning; } private boolean shouldOverrideUserLockPrefs(final int rotation) { diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java index 3ebd652b3467..598325ce44f3 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java @@ -320,6 +320,10 @@ public class KeyguardHostViewController extends ViewController<KeyguardHostView> mKeyguardSecurityContainerController.showPrimarySecurityScreen(false); } + /** + * Fades and translates in/out the security screen. + * @param fraction amount of the screen that should show. + */ public void setExpansion(float fraction) { float alpha = MathUtils.map(KeyguardBouncer.ALPHA_EXPANSION_THRESHOLD, 1, 1, 0, fraction); mView.setAlpha(MathUtils.constrain(alpha, 0f, 1f)); diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index b56d189d3ab3..ba6771644db1 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -144,7 +144,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab private static final boolean DEBUG_FACE = Build.IS_DEBUGGABLE; private static final boolean DEBUG_FINGERPRINT = Build.IS_DEBUGGABLE; private static final boolean DEBUG_SPEW = false; - private static final int FINGERPRINT_LOCKOUT_RESET_DELAY_MS = 600; + private static final int BIOMETRIC_LOCKOUT_RESET_DELAY_MS = 600; private static final String ACTION_FACE_UNLOCK_STARTED = "com.android.facelock.FACE_UNLOCK_STARTED"; @@ -201,6 +201,19 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab private static final int BIOMETRIC_STATE_CANCELLING = 2; /** + * Action indicating keyguard *can* start biometric authentiation. + */ + private static final int BIOMETRIC_ACTION_START = 0; + /** + * Action indicating keyguard *can* stop biometric authentiation. + */ + private static final int BIOMETRIC_ACTION_STOP = 1; + /** + * Action indicating keyguard *can* start or stop biometric authentiation. + */ + private static final int BIOMETRIC_ACTION_UPDATE = 2; + + /** * Biometric state: During cancelling we got another request to start listening, so when we * receive the cancellation done signal, we should start listening again. */ @@ -339,13 +352,13 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab private final Runnable mFpCancelNotReceived = () -> { Log.e(TAG, "Fp cancellation not received, transitioning to STOPPED"); mFingerprintRunningState = BIOMETRIC_STATE_STOPPED; - updateFingerprintListeningState(); + updateFingerprintListeningState(BIOMETRIC_ACTION_STOP); }; private final Runnable mFaceCancelNotReceived = () -> { Log.e(TAG, "Face cancellation not received, transitioning to STOPPED"); mFaceRunningState = BIOMETRIC_STATE_STOPPED; - updateFaceListeningState(); + updateFaceListeningState(BIOMETRIC_ACTION_STOP); }; private final Handler mHandler; @@ -365,7 +378,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab public void onChanged(boolean enabled, int userId) throws RemoteException { mHandler.post(() -> { mBiometricEnabledForUser.put(userId, enabled); - updateBiometricListeningState(); + updateBiometricListeningState(BIOMETRIC_ACTION_UPDATE); }); } }; @@ -415,7 +428,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab private final KeyguardListenQueue mListenModels = new KeyguardListenQueue(); private static int sCurrentUser; - private Runnable mUpdateBiometricListeningState = this::updateBiometricListeningState; public synchronized static void setCurrentUser(int currentUser) { sCurrentUser = currentUser; @@ -428,8 +440,17 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab @Override public void onTrustChanged(boolean enabled, int userId, int flags) { Assert.isMainThread(); + boolean wasTrusted = mUserHasTrust.get(userId, false); mUserHasTrust.put(userId, enabled); - updateBiometricListeningState(); + // If there was no change in trusted state, make sure we are not authenticating. + // TrustManager sends an onTrustChanged whenever a user unlocks keyguard, for + // this reason we need to make sure to not authenticate. + if (wasTrusted == enabled) { + updateBiometricListeningState(BIOMETRIC_ACTION_STOP); + } else if (!enabled) { + updateBiometricListeningState(BIOMETRIC_ACTION_START); + } + for (int i = 0; i < mCallbacks.size(); i++) { KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); if (cb != null) { @@ -594,7 +615,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab */ public void setCredentialAttempted() { mCredentialAttempted = true; - updateBiometricListeningState(); + // Do not update face listening state in case of false authentication attempts. + updateFingerprintListeningState(BIOMETRIC_ACTION_UPDATE); } /** @@ -602,7 +624,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab */ public void setKeyguardGoingAway(boolean goingAway) { mKeyguardGoingAway = goingAway; - updateBiometricListeningState(); + updateBiometricListeningState(BIOMETRIC_ACTION_UPDATE); } /** @@ -610,7 +632,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab */ public void setKeyguardOccluded(boolean occluded) { mKeyguardOccluded = occluded; - updateBiometricListeningState(); + updateBiometricListeningState(BIOMETRIC_ACTION_UPDATE); } @@ -622,7 +644,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab */ public void requestFaceAuthOnOccludingApp(boolean request) { mOccludingAppRequestingFace = request; - updateFaceListeningState(); + updateFaceListeningState(BIOMETRIC_ACTION_UPDATE); } /** @@ -633,7 +655,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab */ public void requestFingerprintAuthOnOccludingApp(boolean request) { mOccludingAppRequestingFp = request; - updateFingerprintListeningState(); + updateFingerprintListeningState(BIOMETRIC_ACTION_UPDATE); } /** @@ -641,7 +663,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab */ public void onCameraLaunched() { mSecureCameraLaunched = true; - updateBiometricListeningState(); + updateBiometricListeningState(BIOMETRIC_ACTION_UPDATE); } /** @@ -676,7 +698,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab } // Don't send cancel if authentication succeeds mFingerprintCancelSignal = null; - updateBiometricListeningState(); + updateBiometricListeningState(BIOMETRIC_ACTION_UPDATE); for (int i = 0; i < mCallbacks.size(); i++) { KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); if (cb != null) { @@ -772,7 +794,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab Log.w(TAG, "Retrying fingerprint after HW unavailable, attempt " + mHardwareFingerprintUnavailableRetryCount); if (mFpm.isHardwareDetected()) { - updateFingerprintListeningState(); + updateFingerprintListeningState(BIOMETRIC_ACTION_UPDATE); } else if (mHardwareFingerprintUnavailableRetryCount < HAL_ERROR_RETRY_MAX) { mHardwareFingerprintUnavailableRetryCount++; mHandler.postDelayed(mRetryFingerprintAuthentication, HAL_ERROR_RETRY_TIMEOUT); @@ -792,7 +814,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab if (msgId == FingerprintManager.FINGERPRINT_ERROR_CANCELED && mFingerprintRunningState == BIOMETRIC_STATE_CANCELLING_RESTARTING) { setFingerprintRunningState(BIOMETRIC_STATE_STOPPED); - updateFingerprintListeningState(); + updateFingerprintListeningState(BIOMETRIC_ACTION_UPDATE); } else { setFingerprintRunningState(BIOMETRIC_STATE_STOPPED); } @@ -813,7 +835,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab lockedOutStateChanged |= !mFingerprintLockedOut; mFingerprintLockedOut = true; if (isUdfpsEnrolled()) { - updateFingerprintListeningState(); + updateFingerprintListeningState(BIOMETRIC_ACTION_UPDATE); } } @@ -840,10 +862,11 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab // that the events will arrive in a particular order. Add a delay here in case // an unlock is in progress. In this is a normal unlock the extra delay won't // be noticeable. - mHandler.postDelayed(this::updateFingerprintListeningState, - FINGERPRINT_LOCKOUT_RESET_DELAY_MS); + mHandler.postDelayed(() -> { + updateFingerprintListeningState(BIOMETRIC_ACTION_UPDATE); + }, BIOMETRIC_LOCKOUT_RESET_DELAY_MS); } else { - updateFingerprintListeningState(); + updateFingerprintListeningState(BIOMETRIC_ACTION_UPDATE); } if (changed) { @@ -887,7 +910,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab } // Don't send cancel if authentication succeeds mFaceCancelSignal = null; - updateBiometricListeningState(); + updateBiometricListeningState(BIOMETRIC_ACTION_UPDATE); for (int i = 0; i < mCallbacks.size(); i++) { KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); if (cb != null) { @@ -980,7 +1003,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab public void run() { Log.w(TAG, "Retrying face after HW unavailable, attempt " + mHardwareFaceUnavailableRetryCount); - updateFaceListeningState(); + updateFaceListeningState(BIOMETRIC_ACTION_UPDATE); } }; @@ -997,7 +1020,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab if (msgId == FaceManager.FACE_ERROR_CANCELED && mFaceRunningState == BIOMETRIC_STATE_CANCELLING_RESTARTING) { setFaceRunningState(BIOMETRIC_STATE_STOPPED); - updateFaceListeningState(); + updateFaceListeningState(BIOMETRIC_ACTION_UPDATE); } else { setFaceRunningState(BIOMETRIC_STATE_STOPPED); } @@ -1035,7 +1058,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab boolean changed = mFaceLockedOutPermanent; mFaceLockedOutPermanent = false; - updateFaceListeningState(); + mHandler.postDelayed(() -> { + updateFaceListeningState(BIOMETRIC_ACTION_UPDATE); + }, BIOMETRIC_LOCKOUT_RESET_DELAY_MS); if (changed) { notifyLockedOutStateChanged(BiometricSourceType.FACE); @@ -1288,7 +1313,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab @VisibleForTesting void setAssistantVisible(boolean assistantVisible) { mAssistantVisible = assistantVisible; - updateBiometricListeningState(); + updateBiometricListeningState(BIOMETRIC_ACTION_UPDATE); } static class DisplayClientState { @@ -1627,7 +1652,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab protected void handleStartedWakingUp() { Trace.beginSection("KeyguardUpdateMonitor#handleStartedWakingUp"); Assert.isMainThread(); - updateBiometricListeningState(); + updateBiometricListeningState(BIOMETRIC_ACTION_UPDATE); for (int i = 0; i < mCallbacks.size(); i++) { KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); if (cb != null) { @@ -1648,7 +1673,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab } } mGoingToSleep = true; - updateBiometricListeningState(); + updateBiometricListeningState(BIOMETRIC_ACTION_UPDATE); } protected void handleFinishedGoingToSleep(int arg1) { @@ -1660,7 +1685,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab cb.onFinishedGoingToSleep(arg1); } } - updateBiometricListeningState(); + updateBiometricListeningState(BIOMETRIC_ACTION_UPDATE); } private void handleScreenTurnedOn() { @@ -1697,7 +1722,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab cb.onDreamingStateChanged(mIsDreaming); } } - updateBiometricListeningState(); + updateBiometricListeningState(BIOMETRIC_ACTION_UPDATE); } private void handleUserInfoChanged(int userId) { @@ -1888,7 +1913,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab setAssistantVisible((boolean) msg.obj); break; case MSG_BIOMETRIC_AUTHENTICATION_CONTINUE: - updateBiometricListeningState(); + updateBiometricListeningState(BIOMETRIC_ACTION_UPDATE); break; case MSG_DEVICE_POLICY_MANAGER_STATE_CHANGED: updateLogoutEnabled(); @@ -2006,10 +2031,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab @Override public void onEnrollmentsChanged() { - mainExecutor.execute(() -> updateBiometricListeningState()); + mainExecutor.execute(() -> updateBiometricListeningState(BIOMETRIC_ACTION_UPDATE)); } }); - updateBiometricListeningState(); + updateBiometricListeningState(BIOMETRIC_ACTION_UPDATE); if (mFpm != null) { mFpm.addLockoutResetCallback(mFingerprintLockoutResetCallback); } @@ -2123,12 +2148,12 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab mHandler.sendEmptyMessage(MSG_AIRPLANE_MODE_CHANGED); } - private void updateBiometricListeningState() { - updateFingerprintListeningState(); - updateFaceListeningState(); + private void updateBiometricListeningState(int action) { + updateFingerprintListeningState(action); + updateFaceListeningState(action); } - private void updateFingerprintListeningState() { + private void updateFingerprintListeningState(int action) { // If this message exists, we should not authenticate again until this message is // consumed by the handler if (mHandler.hasMessages(MSG_BIOMETRIC_AUTHENTICATION_CONTINUE)) { @@ -2140,8 +2165,16 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab final boolean runningOrRestarting = mFingerprintRunningState == BIOMETRIC_STATE_RUNNING || mFingerprintRunningState == BIOMETRIC_STATE_CANCELLING_RESTARTING; if (runningOrRestarting && !shouldListenForFingerprint) { + if (action == BIOMETRIC_ACTION_START) { + Log.v(TAG, "Ignoring stopListeningForFingerprint()"); + return; + } stopListeningForFingerprint(); } else if (!runningOrRestarting && shouldListenForFingerprint) { + if (action == BIOMETRIC_ACTION_STOP) { + Log.v(TAG, "Ignoring startListeningForFingerprint()"); + return; + } startListeningForFingerprint(); } } @@ -2170,7 +2203,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab return; } mAuthInterruptActive = active; - updateFaceListeningState(); + updateFaceListeningState(BIOMETRIC_ACTION_UPDATE); } /** @@ -2181,7 +2214,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab public void requestFaceAuth(boolean userInitiatedRequest) { if (DEBUG) Log.d(TAG, "requestFaceAuth() userInitiated=" + userInitiatedRequest); mIsFaceAuthUserRequested |= userInitiatedRequest; - updateFaceListeningState(); + updateFaceListeningState(BIOMETRIC_ACTION_UPDATE); } public boolean isFaceAuthUserRequested() { @@ -2195,7 +2228,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab stopListeningForFace(); } - private void updateFaceListeningState() { + private void updateFaceListeningState(int action) { // If this message exists, we should not authenticate again until this message is // consumed by the handler if (mHandler.hasMessages(MSG_BIOMETRIC_AUTHENTICATION_CONTINUE)) { @@ -2204,9 +2237,17 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab mHandler.removeCallbacks(mRetryFaceAuthentication); boolean shouldListenForFace = shouldListenForFace(); if (mFaceRunningState == BIOMETRIC_STATE_RUNNING && !shouldListenForFace) { + if (action == BIOMETRIC_ACTION_START) { + Log.v(TAG, "Ignoring stopListeningForFace()"); + return; + } mIsFaceAuthUserRequested = false; stopListeningForFace(); } else if (mFaceRunningState != BIOMETRIC_STATE_RUNNING && shouldListenForFace) { + if (action == BIOMETRIC_ACTION_STOP) { + Log.v(TAG, "Ignoring startListeningForFace()"); + return; + } startListeningForFace(); } } @@ -2414,7 +2455,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab mLockIconPressed = true; final int userId = getCurrentUser(); mUserFaceAuthenticated.put(userId, null); - updateFaceListeningState(); + updateFaceListeningState(BIOMETRIC_ACTION_UPDATE); mStrongAuthTracker.onStrongAuthRequiredChanged(userId); } @@ -2590,7 +2631,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab */ private void handleDevicePolicyManagerStateChanged(int userId) { Assert.isMainThread(); - updateFingerprintListeningState(); + updateFingerprintListeningState(BIOMETRIC_ACTION_UPDATE); updateSecondaryLockscreenRequirement(userId); for (int i = 0; i < mCallbacks.size(); i++) { KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); @@ -2880,7 +2921,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab cb.onKeyguardVisibilityChangedRaw(showing); } } - updateBiometricListeningState(); + updateBiometricListeningState(BIOMETRIC_ACTION_UPDATE); } /** Notifies that the occluded state changed. */ @@ -2902,7 +2943,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab */ private void handleKeyguardReset() { if (DEBUG) Log.d(TAG, "handleKeyguardReset"); - updateBiometricListeningState(); + updateBiometricListeningState(BIOMETRIC_ACTION_UPDATE); mNeedsSlowUnlockTransition = resolveNeedsSlowUnlockTransition(); } @@ -2948,7 +2989,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab cb.onKeyguardBouncerChanged(mBouncer); } } - updateBiometricListeningState(); + updateBiometricListeningState(BIOMETRIC_ACTION_UPDATE); } /** @@ -3068,7 +3109,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab public void setSwitchingUser(boolean switching) { mSwitchingUser = switching; // Since this comes in on a binder thread, we need to post if first - mHandler.post(mUpdateBiometricListeningState); + mHandler.post(() -> { + updateBiometricListeningState(BIOMETRIC_ACTION_UPDATE); + }); } private void sendUpdates(KeyguardUpdateMonitorCallback callback) { diff --git a/packages/SystemUI/src/com/android/keyguard/LockIconView.java b/packages/SystemUI/src/com/android/keyguard/LockIconView.java index 68132f4c598b..b2ecc6140460 100644 --- a/packages/SystemUI/src/com/android/keyguard/LockIconView.java +++ b/packages/SystemUI/src/com/android/keyguard/LockIconView.java @@ -18,6 +18,7 @@ package com.android.keyguard; import android.content.Context; import android.content.res.ColorStateList; +import android.graphics.Color; import android.graphics.PointF; import android.graphics.RectF; import android.graphics.drawable.Drawable; @@ -30,6 +31,7 @@ import androidx.annotation.IntDef; import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; +import com.android.internal.graphics.ColorUtils; import com.android.settingslib.Utils; import com.android.systemui.Dumpable; import com.android.systemui.R; @@ -82,14 +84,18 @@ public class LockIconView extends FrameLayout implements Dumpable { void updateColorAndBackgroundVisibility() { if (mUseBackground && mLockIcon.getDrawable() != null) { - mLockIconColor = Utils.getColorAttrDefaultColor(getContext(), - android.R.attr.textColorPrimary); + mLockIconColor = ColorUtils.blendARGB( + Utils.getColorAttrDefaultColor(getContext(), android.R.attr.textColorPrimary), + Color.WHITE, + mDozeAmount); mBgView.setBackground(getContext().getDrawable(R.drawable.fingerprint_bg)); mBgView.setAlpha(1f - mDozeAmount); mBgView.setVisibility(View.VISIBLE); } else { - mLockIconColor = Utils.getColorAttrDefaultColor(getContext(), - R.attr.wallpaperTextColorAccent); + mLockIconColor = ColorUtils.blendARGB( + Utils.getColorAttrDefaultColor(getContext(), R.attr.wallpaperTextColorAccent), + Color.WHITE, + mDozeAmount); mBgView.setVisibility(View.GONE); } diff --git a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java index 88476398e09d..163392314cfc 100644 --- a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java @@ -661,24 +661,36 @@ public class LockIconViewController extends ViewController<LockIconView> impleme * @return whether to intercept the touch event */ public boolean onTouchEvent(MotionEvent event, Runnable onGestureDetectedRunnable) { - if (mSensorTouchLocation.contains((int) event.getX(), (int) event.getY()) - && (mView.getVisibility() == View.VISIBLE - || (mAodFp != null && mAodFp.getVisibility() == View.VISIBLE))) { + if (onInterceptTouchEvent(event)) { mOnGestureDetectedRunnable = onGestureDetectedRunnable; mGestureDetector.onTouchEvent(event); + return true; } - // we continue to intercept all following touches until we see MotionEvent.ACTION_CANCEL UP - // or MotionEvent.ACTION_UP. this is to avoid passing the touch to NPV - // after the lock icon disappears on device entry - if (mDownDetected) { - if (event.getAction() == MotionEvent.ACTION_CANCEL - || event.getAction() == MotionEvent.ACTION_UP) { - mDownDetected = false; - } + mDownDetected = false; + return false; + } + + /** + * Intercepts the touch if the onDown event and current event are within this lock icon view's + * bounds. + */ + public boolean onInterceptTouchEvent(MotionEvent event) { + if (!inLockIconArea(event) || !isClickable()) { + return false; + } + + if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { return true; } - return false; + + return mDownDetected; + } + + private boolean inLockIconArea(MotionEvent event) { + return mSensorTouchLocation.contains((int) event.getX(), (int) event.getY()) + && (mView.getVisibility() == View.VISIBLE + || (mAodFp != null && mAodFp.getVisibility() == View.VISIBLE)); } private boolean isClickable() { diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java index d37dcafde92a..bb0e79fe23a8 100644 --- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java +++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java @@ -121,7 +121,8 @@ public class SystemUIFactory { .setDisplayAreaHelper(mWMComponent.getDisplayAreaHelper()) .setTaskSurfaceHelper(mWMComponent.getTaskSurfaceHelper()) .setRecentTasks(mWMComponent.getRecentTasks()) - .setSizeCompatUI(Optional.of(mWMComponent.getSizeCompatUI())); + .setSizeCompatUI(Optional.of(mWMComponent.getSizeCompatUI())) + .setDragAndDrop(Optional.of(mWMComponent.getDragAndDrop())); } else { // TODO: Call on prepareSysUIComponentBuilder but not with real components. Other option // is separating this logic into newly creating SystemUITestsFactory. @@ -140,7 +141,8 @@ public class SystemUIFactory { .setStartingSurface(Optional.ofNullable(null)) .setTaskSurfaceHelper(Optional.ofNullable(null)) .setRecentTasks(Optional.ofNullable(null)) - .setSizeCompatUI(Optional.ofNullable(null)); + .setSizeCompatUI(Optional.ofNullable(null)) + .setDragAndDrop(Optional.ofNullable(null)); } mSysUIComponent = builder.build(); if (mInitializeComponents) { diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/SecureSettingsContentObserver.java b/packages/SystemUI/src/com/android/systemui/accessibility/SecureSettingsContentObserver.java index c941d662dfd9..e4e0da6a2310 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/SecureSettingsContentObserver.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/SecureSettingsContentObserver.java @@ -71,7 +71,9 @@ public abstract class SecureSettingsContentObserver<T> { public void addListener(@NonNull T listener) { Objects.requireNonNull(listener, "listener must be non-null"); - mListeners.add(listener); + if (!mListeners.contains(listener)) { + mListeners.add(listener); + } if (mListeners.size() == 1) { mContentResolver.registerContentObserver( diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuController.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuController.java index cff6cf1f53f1..cc5a792e89a1 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuController.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuController.java @@ -98,7 +98,8 @@ public class AccessibilityFloatingMenuController implements mAccessibilityButtonModeObserver = accessibilityButtonModeObserver; mKeyguardUpdateMonitor = keyguardUpdateMonitor; - init(); + mIsKeyguardVisible = false; + mIsAccessibilityManagerServiceReady = false; } /** @@ -124,9 +125,8 @@ public class AccessibilityFloatingMenuController implements handleFloatingMenuVisibility(mIsKeyguardVisible, mBtnMode, mBtnTargets); } - private void init() { - mIsKeyguardVisible = false; - mIsAccessibilityManagerServiceReady = false; + /** Initializes the AccessibilityFloatingMenuController configurations. */ + public void init() { mBtnMode = mAccessibilityButtonModeObserver.getCurrentAccessibilityButtonMode(); mBtnTargets = mAccessibilityButtonTargetsObserver.getCurrentAccessibilityButtonTargets(); registerContentObservers(); diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java index 9ce0e94cca18..09f2af4a86da 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java @@ -163,7 +163,10 @@ public class UdfpsController implements DozeReceiver { private boolean mOnFingerDown; private boolean mAttemptedToDismissKeyguard; private Set<Callback> mCallbacks = new HashSet<>(); - private final VibrationEffect mLowTick; + + // by default, use low tick + private int mPrimitiveTick = VibrationEffect.Composition.PRIMITIVE_LOW_TICK; + private final VibrationEffect mTick; @VisibleForTesting public static final AudioAttributes VIBRATION_SONIFICATION_ATTRIBUTES = @@ -572,7 +575,7 @@ public class UdfpsController implements DozeReceiver { mConfigurationController = configurationController; mSystemClock = systemClock; mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController; - mLowTick = lowTick(); + mTick = lowTick(); mSensorProps = findFirstUdfps(); // At least one UDFPS sensor exists @@ -608,22 +611,31 @@ public class UdfpsController implements DozeReceiver { } private VibrationEffect lowTick() { + boolean useLowTickDefault = mContext.getResources() + .getBoolean(R.bool.config_udfpsUseLowTick); + if (Settings.Global.getFloat( + mContext.getContentResolver(), + "tick-low", useLowTickDefault ? 1 : 0) == 0) { + mPrimitiveTick = VibrationEffect.Composition.PRIMITIVE_TICK; + } float tickIntensity = Settings.Global.getFloat( - mContext.getContentResolver(), "low-tick-intensity", .5f); - VibrationEffect.Composition composition = VibrationEffect.startComposition(); - composition.addPrimitive(VibrationEffect.Composition.PRIMITIVE_LOW_TICK, - tickIntensity, 0); + mContext.getContentResolver(), + "tick-intensity", + mContext.getResources().getFloat(R.dimen.config_udfpsTickIntensity)); int tickDelay = Settings.Global.getInt( - mContext.getContentResolver(), "low-tick-delay", 25); + mContext.getContentResolver(), + "tick-delay", + mContext.getResources().getInteger(R.integer.config_udfpsTickDelay)); + + VibrationEffect.Composition composition = VibrationEffect.startComposition(); + composition.addPrimitive(mPrimitiveTick, tickIntensity, 0); int primitives = 1000 / tickDelay; float[] rampUp = new float[]{.48f, .58f, .69f, .83f}; for (int i = 0; i < rampUp.length; i++) { - composition.addPrimitive(VibrationEffect.Composition.PRIMITIVE_LOW_TICK, - tickIntensity * rampUp[i], tickDelay); + composition.addPrimitive(mPrimitiveTick, tickIntensity * rampUp[i], tickDelay); } for (int i = rampUp.length; i < primitives; i++) { - composition.addPrimitive(VibrationEffect.Composition.PRIMITIVE_LOW_TICK, - tickIntensity, tickDelay); + composition.addPrimitive(mPrimitiveTick, tickIntensity, tickDelay); } return composition.compose(); } @@ -637,7 +649,7 @@ public class UdfpsController implements DozeReceiver { mVibrator.vibrate( Process.myUid(), mContext.getOpPackageName(), - mLowTick, + mTick, "udfps-onStart-tick", VIBRATION_SONIFICATION_ATTRIBUTES); } diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java index 5fdf026b86f3..c5d3a70676d0 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java @@ -32,6 +32,7 @@ import com.android.wm.shell.TaskViewFactory; import com.android.wm.shell.apppairs.AppPairs; import com.android.wm.shell.bubbles.Bubbles; import com.android.wm.shell.displayareahelper.DisplayAreaHelper; +import com.android.wm.shell.draganddrop.DragAndDrop; import com.android.wm.shell.hidedisplaycutout.HideDisplayCutout; import com.android.wm.shell.legacysplitscreen.LegacySplitScreen; import com.android.wm.shell.onehanded.OneHanded; @@ -111,6 +112,9 @@ public interface SysUIComponent { @BindsInstance Builder setSizeCompatUI(Optional<SizeCompatUI> s); + @BindsInstance + Builder setDragAndDrop(Optional<DragAndDrop> d); + SysUIComponent build(); } diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java index fd3fcdd1d58a..12786f278a16 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java @@ -66,7 +66,6 @@ import com.android.systemui.statusbar.notification.row.dagger.NotificationShelfC import com.android.systemui.statusbar.phone.ShadeController; import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.phone.dagger.StatusBarComponent; -import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentComponent; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.HeadsUpManager; import com.android.systemui.statusbar.policy.ZenModeController; @@ -125,7 +124,6 @@ import dagger.Provides; }, subcomponents = { StatusBarComponent.class, - StatusBarFragmentComponent.class, NotificationRowComponent.class, DozeComponent.class, ExpandableNotificationRowComponent.class, diff --git a/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java index 543ba8f9b854..90a3ad225f51 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java @@ -29,6 +29,7 @@ import com.android.wm.shell.dagger.TvWMShellModule; import com.android.wm.shell.dagger.WMShellModule; import com.android.wm.shell.dagger.WMSingleton; import com.android.wm.shell.displayareahelper.DisplayAreaHelper; +import com.android.wm.shell.draganddrop.DragAndDrop; import com.android.wm.shell.hidedisplaycutout.HideDisplayCutout; import com.android.wm.shell.legacysplitscreen.LegacySplitScreen; import com.android.wm.shell.onehanded.OneHanded; @@ -119,4 +120,7 @@ public interface WMComponent { @WMSingleton SizeCompatUI getSizeCompatUI(); + + @WMSingleton + DragAndDrop getDragAndDrop(); } diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java index ad472326555e..ff14064834d7 100644 --- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java +++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java @@ -31,8 +31,6 @@ import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_G import android.animation.Animator; import android.animation.AnimatorListenerAdapter; -import android.animation.AnimatorSet; -import android.animation.ObjectAnimator; import android.annotation.Nullable; import android.app.ActivityManager; import android.app.Dialog; @@ -56,6 +54,7 @@ import android.graphics.Color; import android.graphics.drawable.Drawable; import android.media.AudioManager; import android.os.Binder; +import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Message; @@ -80,8 +79,6 @@ import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; -import android.view.Window; -import android.view.WindowInsets; import android.view.WindowManager; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; @@ -112,7 +109,7 @@ import com.android.internal.widget.LockPatternUtils; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.systemui.MultiListLayout; import com.android.systemui.MultiListLayout.MultiListAdapter; -import com.android.systemui.animation.Interpolators; +import com.android.systemui.animation.DialogLaunchAnimator; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.colorextraction.SysuiColorExtractor; import com.android.systemui.dagger.qualifiers.Background; @@ -123,6 +120,7 @@ import com.android.systemui.plugins.GlobalActionsPanelPlugin; import com.android.systemui.scrim.ScrimDrawable; import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.phone.StatusBar; +import com.android.systemui.statusbar.phone.SystemUIDialog; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.telephony.TelephonyListenerManager; @@ -239,6 +237,7 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene private int mSmallestScreenWidthDp; private final Optional<StatusBar> mStatusBarOptional; private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; + private final DialogLaunchAnimator mDialogLaunchAnimator; @VisibleForTesting public enum GlobalActionsEvent implements UiEventLogger.UiEventEnum { @@ -343,10 +342,11 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene UiEventLogger uiEventLogger, RingerModeTracker ringerModeTracker, SysUiState sysUiState, - @Main Handler handler, + @Main Handler handler, PackageManager packageManager, Optional<StatusBar> statusBarOptional, - KeyguardUpdateMonitor keyguardUpdateMonitor) { + KeyguardUpdateMonitor keyguardUpdateMonitor, + DialogLaunchAnimator dialogLaunchAnimator) { mContext = context; mWindowManagerFuncs = windowManagerFuncs; mAudioManager = audioManager; @@ -377,6 +377,7 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene mSmallestScreenWidthDp = resources.getConfiguration().smallestScreenWidthDp; mStatusBarOptional = statusBarOptional; mKeyguardUpdateMonitor = keyguardUpdateMonitor; + mDialogLaunchAnimator = dialogLaunchAnimator; // receive broadcasts IntentFilter filter = new IntentFilter(); @@ -435,11 +436,14 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene } /** - * Show the global actions dialog (creating if necessary) + * Show the global actions dialog (creating if necessary) or hide it if it's already showing. * - * @param keyguardShowing True if keyguard is showing + * @param keyguardShowing True if keyguard is showing + * @param isDeviceProvisioned True if device is provisioned + * @param view The view from which we should animate the dialog when showing it */ - public void showOrHideDialog(boolean keyguardShowing, boolean isDeviceProvisioned) { + public void showOrHideDialog(boolean keyguardShowing, boolean isDeviceProvisioned, + @Nullable View view) { mKeyguardShowing = keyguardShowing; mDeviceProvisioned = isDeviceProvisioned; if (mDialog != null && mDialog.isShowing()) { @@ -451,7 +455,7 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene mDialog.dismiss(); mDialog = null; } else { - handleShow(); + handleShow(view); } } @@ -483,7 +487,7 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene } } - protected void handleShow() { + protected void handleShow(@Nullable View view) { awakenIfNecessary(); mDialog = createDialog(); prepareDialog(); @@ -493,8 +497,13 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene attrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; mDialog.getWindow().setAttributes(attrs); // Don't acquire soft keyboard focus, to avoid destroying state when capturing bugreports - mDialog.getWindow().setFlags(FLAG_ALT_FOCUSABLE_IM, FLAG_ALT_FOCUSABLE_IM); - mDialog.show(); + mDialog.getWindow().addFlags(FLAG_ALT_FOCUSABLE_IM); + + if (view != null) { + mDialogLaunchAnimator.showFromView(mDialog, view); + } else { + mDialog.show(); + } mWindowManagerFuncs.onGlobalActionsShown(); } @@ -643,7 +652,7 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene } } - protected void onRotate() { + protected void onRefresh() { // re-allocate actions between main and overflow lists this.createActionItems(); } @@ -667,7 +676,7 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene com.android.systemui.R.style.Theme_SystemUI_Dialog_GlobalActionsLite, mAdapter, mOverflowAdapter, mSysuiColorExtractor, mStatusBarService, mNotificationShadeWindowController, - mSysUiState, this::onRotate, mKeyguardShowing, mPowerAdapter, mUiEventLogger, + mSysUiState, this::onRefresh, mKeyguardShowing, mPowerAdapter, mUiEventLogger, mStatusBarOptional, mKeyguardUpdateMonitor, mLockPatternUtils); dialog.setOnDismissListener(this); @@ -702,14 +711,6 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene } @Override - public void onUiModeChanged() { - mContext.getTheme().applyStyle(mContext.getThemeResId(), true); - if (mDialog != null && mDialog.isShowing()) { - mDialog.refreshDialog(); - } - } - - @Override public void onConfigChanged(Configuration newConfig) { if (mDialog != null && mDialog.isShowing() && (newConfig.smallestScreenWidthDp != mSmallestScreenWidthDp)) { @@ -717,6 +718,7 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene mDialog.refreshDialog(); } } + /** * Implements {@link GlobalActionsPanelPlugin.Callbacks#dismissGlobalActionsMenu()}, which is * called when the quick access wallet requests dismissal. @@ -1363,6 +1365,10 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene final Action action = mAdapter.getItem(position); if (action instanceof LongPressAction) { if (mDialog != null) { + // Usually clicking an item shuts down the phone, locks, or starts an activity. + // We don't want to animate back into the power button when that happens, so we + // disable the dialog animation before dismissing. + mDialogLaunchAnimator.disableAllCurrentDialogsExitAnimations(); mDialog.dismiss(); } else { Log.w(TAG, "Action long-clicked while mDialog is null."); @@ -1379,6 +1385,10 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene if (mDialog != null) { // don't dismiss the dialog if we're opening the power options menu if (!(item instanceof PowerOptionsAction)) { + // Usually clicking an item shuts down the phone, locks, or starts an + // activity. We don't want to animate back into the power button when that + // happens, so we disable the dialog animation before dismissing. + mDialogLaunchAnimator.disableAllCurrentDialogsExitAnimations(); mDialog.dismiss(); } } else { @@ -1446,6 +1456,10 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene final Action action = getItem(position); if (action instanceof LongPressAction) { if (mDialog != null) { + // Usually clicking an item shuts down the phone, locks, or starts an activity. + // We don't want to animate back into the power button when that happens, so we + // disable the dialog animation before dismissing. + mDialogLaunchAnimator.disableAllCurrentDialogsExitAnimations(); mDialog.dismiss(); } else { Log.w(TAG, "Action long-clicked while mDialog is null."); @@ -1459,6 +1473,10 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene Action item = getItem(position); if (!(item instanceof SilentModeTriStateAction)) { if (mDialog != null) { + // Usually clicking an item shuts down the phone, locks, or starts an activity. + // We don't want to animate back into the power button when that happens, so we + // disable the dialog animation before dismissing. + mDialogLaunchAnimator.disableAllCurrentDialogsExitAnimations(); mDialog.dismiss(); } else { Log.w(TAG, "Action clicked while mDialog is null."); @@ -1510,6 +1528,10 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene final Action action = getItem(position); if (action instanceof LongPressAction) { if (mDialog != null) { + // Usually clicking an item shuts down the phone, locks, or starts an activity. + // We don't want to animate back into the power button when that happens, so we + // disable the dialog animation before dismissing. + mDialogLaunchAnimator.disableAllCurrentDialogsExitAnimations(); mDialog.dismiss(); } else { Log.w(TAG, "Action long-clicked while mDialog is null."); @@ -1523,6 +1545,10 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene Action item = getItem(position); if (!(item instanceof SilentModeTriStateAction)) { if (mDialog != null) { + // Usually clicking an item shuts down the phone, locks, or starts an activity. + // We don't want to animate back into the power button when that happens, so we + // disable the dialog animation before dismissing. + mDialogLaunchAnimator.disableAllCurrentDialogsExitAnimations(); mDialog.dismiss(); } else { Log.w(TAG, "Action clicked while mDialog is null."); @@ -2066,7 +2092,9 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene case MESSAGE_DISMISS: if (mDialog != null) { if (SYSTEM_DIALOG_REASON_DREAM.equals(msg.obj)) { - mDialog.completeDismiss(); + // Hide instantly. + mDialog.hide(); + mDialog.dismiss(); } else { mDialog.dismiss(); } @@ -2113,7 +2141,7 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene } @VisibleForTesting - static class ActionsDialogLite extends Dialog implements DialogInterface, + static class ActionsDialogLite extends SystemUIDialog implements DialogInterface, ColorExtractor.OnColorsChangedListener { protected final Context mContext; @@ -2126,13 +2154,12 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene protected Drawable mBackgroundDrawable; protected final SysuiColorExtractor mColorExtractor; private boolean mKeyguardShowing; - protected boolean mShowing; protected float mScrimAlpha; protected final NotificationShadeWindowController mNotificationShadeWindowController; protected final SysUiState mSysUiState; private ListPopupWindow mOverflowPopup; private Dialog mPowerOptionsDialog; - protected final Runnable mOnRotateCallback; + protected final Runnable mOnRefreshCallback; private UiEventLogger mUiEventLogger; private GestureDetector mGestureDetector; private Optional<StatusBar> mStatusBarOptional; @@ -2151,7 +2178,7 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene } @Override - public boolean onSingleTapConfirmed(MotionEvent e) { + public boolean onSingleTapUp(MotionEvent e) { // Close without opening shade mUiEventLogger.log(GlobalActionsEvent.GA_CLOSE_TAP_OUTSIDE); cancel(); @@ -2189,11 +2216,13 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene MyOverflowAdapter overflowAdapter, SysuiColorExtractor sysuiColorExtractor, IStatusBarService statusBarService, NotificationShadeWindowController notificationShadeWindowController, - SysUiState sysuiState, Runnable onRotateCallback, boolean keyguardShowing, + SysUiState sysuiState, Runnable onRefreshCallback, boolean keyguardShowing, MyPowerOptionsAdapter powerAdapter, UiEventLogger uiEventLogger, Optional<StatusBar> statusBarOptional, KeyguardUpdateMonitor keyguardUpdateMonitor, LockPatternUtils lockPatternUtils) { - super(context, themeRes); + // We set dismissOnDeviceLock to false because we have a custom broadcast receiver to + // dismiss this dialog when the device is locked. + super(context, themeRes, false /* dismissOnDeviceLock */); mContext = context; mAdapter = adapter; mOverflowAdapter = overflowAdapter; @@ -2202,36 +2231,32 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene mStatusBarService = statusBarService; mNotificationShadeWindowController = notificationShadeWindowController; mSysUiState = sysuiState; - mOnRotateCallback = onRotateCallback; + mOnRefreshCallback = onRefreshCallback; mKeyguardShowing = keyguardShowing; mUiEventLogger = uiEventLogger; mStatusBarOptional = statusBarOptional; mKeyguardUpdateMonitor = keyguardUpdateMonitor; mLockPatternUtils = lockPatternUtils; - mGestureDetector = new GestureDetector(mContext, mGestureListener); + } - // Window initialization - Window window = getWindow(); - window.requestFeature(Window.FEATURE_NO_TITLE); - // Inflate the decor view, so the attributes below are not overwritten by the theme. - window.getDecorView(); - window.getAttributes().systemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_STABLE - | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION; - window.setLayout(MATCH_PARENT, MATCH_PARENT); - window.addFlags( - WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN - | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR - | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED - | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED); - window.setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY); - window.getAttributes().setFitInsetsTypes(0 /* types */); - setTitle(R.string.global_actions); - + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); initializeLayout(); } @Override + protected int getWidth() { + return MATCH_PARENT; + } + + @Override + protected int getHeight() { + return MATCH_PARENT; + } + + @Override public boolean onTouchEvent(MotionEvent event) { return mGestureDetector.onTouchEvent(event) || super.onTouchEvent(event); } @@ -2371,7 +2396,8 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene message.animate() .alpha(0f) .setDuration(TOAST_FADE_TIME) - .setStartDelay(visibleTime); + .setStartDelay(visibleTime) + .setListener(null); } }); } @@ -2423,122 +2449,32 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene @Override public void show() { super.show(); - // split this up so we can override but still call Dialog.show - showDialog(); - } - - protected void showDialog() { - mShowing = true; mNotificationShadeWindowController.setRequestTopUi(true, TAG); mSysUiState.setFlag(SYSUI_STATE_GLOBAL_ACTIONS_SHOWING, true) .commitUpdate(mContext.getDisplayId()); - - ViewGroup root = (ViewGroup) mGlobalActionsLayout.getRootView(); - root.setOnApplyWindowInsetsListener((v, windowInsets) -> { - root.setPadding(windowInsets.getStableInsetLeft(), - windowInsets.getStableInsetTop(), - windowInsets.getStableInsetRight(), - windowInsets.getStableInsetBottom()); - return WindowInsets.CONSUMED; - }); - - mBackgroundDrawable.setAlpha(0); - float xOffset = mGlobalActionsLayout.getAnimationOffsetX(); - ObjectAnimator alphaAnimator = - ObjectAnimator.ofFloat(mContainer, "alpha", 0f, 1f); - alphaAnimator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN); - alphaAnimator.setDuration(183); - alphaAnimator.addUpdateListener((animation) -> { - float animatedValue = animation.getAnimatedFraction(); - int alpha = (int) (animatedValue * mScrimAlpha * 255); - mBackgroundDrawable.setAlpha(alpha); - }); - - ObjectAnimator xAnimator = - ObjectAnimator.ofFloat(mContainer, "translationX", xOffset, 0f); - xAnimator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN); - xAnimator.setDuration(350); - - AnimatorSet animatorSet = new AnimatorSet(); - animatorSet.playTogether(alphaAnimator, xAnimator); - animatorSet.start(); } @Override public void dismiss() { - dismissWithAnimation(() -> { - dismissInternal(); - }); - } - - protected void dismissInternal() { - mContainer.setTranslationX(0); - ObjectAnimator alphaAnimator = - ObjectAnimator.ofFloat(mContainer, "alpha", 1f, 0f); - alphaAnimator.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN); - alphaAnimator.setDuration(233); - alphaAnimator.addUpdateListener((animation) -> { - float animatedValue = 1f - animation.getAnimatedFraction(); - int alpha = (int) (animatedValue * mScrimAlpha * 255); - mBackgroundDrawable.setAlpha(alpha); - }); - - float xOffset = mGlobalActionsLayout.getAnimationOffsetX(); - ObjectAnimator xAnimator = - ObjectAnimator.ofFloat(mContainer, "translationX", 0f, xOffset); - xAnimator.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN); - xAnimator.setDuration(350); - - AnimatorSet animatorSet = new AnimatorSet(); - animatorSet.playTogether(alphaAnimator, xAnimator); - animatorSet.addListener(new AnimatorListenerAdapter() { - public void onAnimationEnd(Animator animation) { - completeDismiss(); - } - }); - - animatorSet.start(); - - // close first, as popup windows will not fade during the animation - dismissOverflow(false); - dismissPowerOptions(false); - } + dismissOverflow(); + dismissPowerOptions(); - void dismissWithAnimation(Runnable animation) { - if (!mShowing) { - return; - } - mShowing = false; - animation.run(); - } - - protected void completeDismiss() { - mShowing = false; - dismissOverflow(true); - dismissPowerOptions(true); mNotificationShadeWindowController.setRequestTopUi(false, TAG); mSysUiState.setFlag(SYSUI_STATE_GLOBAL_ACTIONS_SHOWING, false) .commitUpdate(mContext.getDisplayId()); + super.dismiss(); } - protected final void dismissOverflow(boolean immediate) { + protected final void dismissOverflow() { if (mOverflowPopup != null) { - if (immediate) { - mOverflowPopup.dismissImmediate(); - } else { - mOverflowPopup.dismiss(); - } + mOverflowPopup.dismiss(); } } - protected final void dismissPowerOptions(boolean immediate) { + protected final void dismissPowerOptions() { if (mPowerOptionsDialog != null) { - if (immediate) { - mPowerOptionsDialog.dismiss(); - } else { - mPowerOptionsDialog.dismiss(); - } + mPowerOptionsDialog.dismiss(); } } @@ -2574,20 +2510,18 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene } public void refreshDialog() { - // ensure dropdown menus are dismissed before re-initializing the dialog - dismissOverflow(true); - dismissPowerOptions(true); + mOnRefreshCallback.run(); - // re-create dialog - initializeLayout(); + // Dismiss the dropdown menus. + dismissOverflow(); + dismissPowerOptions(); + + // Update the list as the max number of items per row has probably changed. mGlobalActionsLayout.updateList(); } public void onRotate(int from, int to) { - if (mShowing) { - mOnRotateCallback.run(); - refreshDialog(); - } + refreshDialog(); } } } diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java index c4508e043c7d..96ae646ac7f9 100644 --- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java +++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java @@ -82,7 +82,7 @@ public class GlobalActionsImpl implements GlobalActions, CommandQueue.Callbacks if (mDisabled) return; mGlobalActionsDialog = mGlobalActionsDialogLazy.get(); mGlobalActionsDialog.showOrHideDialog(mKeyguardStateController.isShowing(), - mDeviceProvisionedController.isDeviceProvisioned()); + mDeviceProvisionedController.isDeviceProvisioned(), null /* view */); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewController.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewController.java index a424674ed252..d73d9cdb7d40 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewController.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewController.java @@ -19,6 +19,7 @@ package com.android.systemui.keyguard; import android.annotation.Nullable; import android.content.res.ColorStateList; import android.graphics.Color; +import android.os.SystemClock; import android.text.TextUtils; import androidx.annotation.IntDef; @@ -40,13 +41,24 @@ import java.util.List; import java.util.Map; /** - * Rotates through messages to show on the keyguard bottom area on the lock screen - * NOTE: This controller should not be used on AoD to avoid waking up the AP too often. + * Animates through messages to show on the keyguard bottom area on the lock screen. + * Utilizes a {@link KeyguardIndicationTextView} for animations. This class handles the rotating + * nature of the messages including: + * - ensuring a message is shown for its minimum amount of time. Minimum time is determined by + * {@link KeyguardIndication#getMinVisibilityMillis()} + * - showing the next message after a default of 3.5 seconds before animating to the next + * - statically showing a single message if there is only one message to show + * - showing certain messages immediately, assuming te current message has been shown for + * at least {@link KeyguardIndication#getMinVisibilityMillis()}. For example, transient and + * biometric messages are meant to be shown immediately. + * - ending animations when dozing begins, and resuming when dozing ends. Rotating messages on + * AoD is undesirable since it wakes up the AP too often. */ public class KeyguardIndicationRotateTextViewController extends ViewController<KeyguardIndicationTextView> implements Dumpable { public static String TAG = "KgIndicationRotatingCtrl"; private static final long DEFAULT_INDICATION_SHOW_LENGTH = 3500; // milliseconds + public static final long IMPORTANT_MSG_MIN_DURATION = 2000L + 600L; // 2000ms + [Y in duration] private final StatusBarStateController mStatusBarStateController; private final float mMaxAlpha; @@ -62,6 +74,8 @@ public class KeyguardIndicationRotateTextViewController extends // List of indication types to show. The next indication to show is always at index 0 private final List<Integer> mIndicationQueue = new LinkedList<>(); private @IndicationType int mCurrIndicationType = INDICATION_TYPE_NONE; + private CharSequence mCurrMessage; + private long mLastIndicationSwitch; private boolean mIsDozing; @@ -94,17 +108,19 @@ public class KeyguardIndicationRotateTextViewController extends * Update the indication type with the given String. * @param type of indication * @param newIndication message to associate with this indication type - * @param showImmediately if true: shows this indication message immediately. Else, the text - * associated with this type is updated and will show when its turn in - * the IndicationQueue comes around. + * @param showAsap if true: shows this indication message as soon as possible. If false, + * the text associated with this type is updated and will show when its turn + * in the IndicationQueue comes around. */ public void updateIndication(@IndicationType int type, KeyguardIndication newIndication, - boolean updateImmediately) { + boolean showAsap) { if (type == INDICATION_TYPE_REVERSE_CHARGING) { // temporarily don't show here, instead use AmbientContainer b/181049781 return; } - final boolean hasPreviousIndication = mIndicationMessages.get(type) != null; + long minShowDuration = getMinVisibilityMillis(mIndicationMessages.get(mCurrIndicationType)); + final boolean hasPreviousIndication = mIndicationMessages.get(type) != null + && !TextUtils.isEmpty(mIndicationMessages.get(type).getMessage()); final boolean hasNewIndication = newIndication != null; if (!hasNewIndication) { mIndicationMessages.remove(type); @@ -121,25 +137,46 @@ public class KeyguardIndicationRotateTextViewController extends return; } - final boolean showNow = updateImmediately - || mCurrIndicationType == INDICATION_TYPE_NONE - || mCurrIndicationType == type; + long currTime = SystemClock.uptimeMillis(); + long timeSinceLastIndicationSwitch = currTime - mLastIndicationSwitch; + boolean currMsgShownForMinTime = timeSinceLastIndicationSwitch >= minShowDuration; if (hasNewIndication) { - if (showNow) { + if (mCurrIndicationType == INDICATION_TYPE_NONE || mCurrIndicationType == type) { showIndication(type); + } else if (showAsap) { + if (currMsgShownForMinTime) { + showIndication(type); + } else { + mIndicationQueue.removeIf(x -> x == type); + mIndicationQueue.add(0 /* index */, type /* type */); + scheduleShowNextIndication(minShowDuration - timeSinceLastIndicationSwitch); + } } else if (!isNextIndicationScheduled()) { - scheduleShowNextIndication(); + long nextShowTime = Math.max( + getMinVisibilityMillis(mIndicationMessages.get(type)), + DEFAULT_INDICATION_SHOW_LENGTH); + if (timeSinceLastIndicationSwitch >= nextShowTime) { + showIndication(type); + } else { + scheduleShowNextIndication( + nextShowTime - timeSinceLastIndicationSwitch); + } } return; } + // current indication is updated to empty if (mCurrIndicationType == type && !hasNewIndication - && updateImmediately) { - if (mShowNextIndicationRunnable != null) { - mShowNextIndicationRunnable.runImmediately(); + && showAsap) { + if (currMsgShownForMinTime) { + if (mShowNextIndicationRunnable != null) { + mShowNextIndicationRunnable.runImmediately(); + } else { + showIndication(INDICATION_TYPE_NONE); + } } else { - showIndication(INDICATION_TYPE_NONE); + scheduleShowNextIndication(minShowDuration - timeSinceLastIndicationSwitch); } } } @@ -164,11 +201,10 @@ public class KeyguardIndicationRotateTextViewController extends * - will continue to be in the rotation of messages shown until hideTransient is called. */ public void showTransient(CharSequence newIndication) { - final long inAnimationDuration = 600L; // see KeyguardIndicationTextView.getYInDuration updateIndication(INDICATION_TYPE_TRANSIENT, new KeyguardIndication.Builder() .setMessage(newIndication) - .setMinVisibilityMillis(2000L + inAnimationDuration) + .setMinVisibilityMillis(IMPORTANT_MSG_MIN_DURATION) .setTextColor(mInitialTextColorState) .build(), /* showImmediately */true); @@ -189,6 +225,15 @@ public class KeyguardIndicationRotateTextViewController extends } /** + * Clears all messages in the queue and sets the current message to an empty string. + */ + public void clearMessages() { + mCurrIndicationType = INDICATION_TYPE_NONE; + mIndicationQueue.clear(); + mView.clearMessages(); + } + + /** * Immediately show the passed indication type and schedule the next indication to show. * Will re-add this indication to be re-shown after all other indications have been * rotated through. @@ -196,27 +241,52 @@ public class KeyguardIndicationRotateTextViewController extends private void showIndication(@IndicationType int type) { cancelScheduledIndication(); + final CharSequence previousMessage = mCurrMessage; + final @IndicationType int previousIndicationType = mCurrIndicationType; mCurrIndicationType = type; + mCurrMessage = mIndicationMessages.get(type) != null + ? mIndicationMessages.get(type).getMessage() + : null; + mIndicationQueue.removeIf(x -> x == type); if (mCurrIndicationType != INDICATION_TYPE_NONE) { mIndicationQueue.add(type); // re-add to show later } - mView.switchIndication(mIndicationMessages.get(type)); + mLastIndicationSwitch = SystemClock.uptimeMillis(); + if (!TextUtils.equals(previousMessage, mCurrMessage) + || previousIndicationType != mCurrIndicationType) { + mView.switchIndication(mIndicationMessages.get(type)); + } // only schedule next indication if there's more than just this indication in the queue if (mCurrIndicationType != INDICATION_TYPE_NONE && mIndicationQueue.size() > 1) { - scheduleShowNextIndication(); + scheduleShowNextIndication(Math.max( + getMinVisibilityMillis(mIndicationMessages.get(type)), + DEFAULT_INDICATION_SHOW_LENGTH)); } } + private long getMinVisibilityMillis(KeyguardIndication indication) { + if (indication == null) { + return 0; + } + + if (indication.getMinVisibilityMillis() == null) { + return 0; + } + + return indication.getMinVisibilityMillis(); + } + protected boolean isNextIndicationScheduled() { return mShowNextIndicationRunnable != null; } - private void scheduleShowNextIndication() { + + private void scheduleShowNextIndication(long msUntilShowNextMsg) { cancelScheduledIndication(); - mShowNextIndicationRunnable = new ShowNextIndication(DEFAULT_INDICATION_SHOW_LENGTH); + mShowNextIndicationRunnable = new ShowNextIndication(msUntilShowNextMsg); } private void cancelScheduledIndication() { @@ -292,7 +362,9 @@ public class KeyguardIndicationRotateTextViewController extends } } + // only used locally to stop showing any messages & stop the rotating messages static final int INDICATION_TYPE_NONE = -1; + public static final int INDICATION_TYPE_OWNER_INFO = 0; public static final int INDICATION_TYPE_DISCLOSURE = 1; public static final int INDICATION_TYPE_LOGOUT = 2; @@ -303,6 +375,7 @@ public class KeyguardIndicationRotateTextViewController extends public static final int INDICATION_TYPE_RESTING = 7; public static final int INDICATION_TYPE_USER_LOCKED = 8; public static final int INDICATION_TYPE_REVERSE_CHARGING = 10; + public static final int INDICATION_TYPE_BIOMETRIC_MESSAGE = 11; @IntDef({ INDICATION_TYPE_NONE, @@ -316,6 +389,7 @@ public class KeyguardIndicationRotateTextViewController extends INDICATION_TYPE_RESTING, INDICATION_TYPE_USER_LOCKED, INDICATION_TYPE_REVERSE_CHARGING, + INDICATION_TYPE_BIOMETRIC_MESSAGE }) @Retention(RetentionPolicy.SOURCE) public @interface IndicationType{} diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt index d54b1514abf7..b85f10726040 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt @@ -37,7 +37,7 @@ import javax.inject.Provider private const val TAG = "MediaCarouselController" private val settingsIntent = Intent().setAction(ACTION_MEDIA_CONTROLS_SETTINGS) -private const val DEBUG = false +private val DEBUG = Log.isLoggable(TAG, Log.DEBUG) /** * Class that is responsible for keeping the view carousel up to date. @@ -209,41 +209,56 @@ class MediaCarouselController @Inject constructor( oldKey: String?, data: MediaData, immediately: Boolean, - isSsReactivated: Boolean + receivedSmartspaceCardLatency: Int ) { if (addOrUpdatePlayer(key, oldKey, data)) { // Log card received if a new resumable media card is added MediaPlayerData.getMediaPlayer(key)?.let { + /* ktlint-disable max-line-length */ logSmartspaceCardReported(759, // SMARTSPACE_CARD_RECEIVED it.mInstanceId, it.mUid, /* isRecommendationCard */ false, - it.surfaceForSmartspaceLogging, + intArrayOf( + SysUiStatsLog.SMART_SPACE_CARD_REPORTED__DISPLAY_SURFACE__SHADE, + SysUiStatsLog.SMART_SPACE_CARD_REPORTED__DISPLAY_SURFACE__LOCKSCREEN), rank = MediaPlayerData.getMediaPlayerIndex(key)) + /* ktlint-disable max-line-length */ } - } - if (isSsReactivated) { - // If resumable media is reactivated by headphone connection, update instance - // id for each card and log a receive event. + if (mediaCarouselScrollHandler.visibleToUser && + mediaCarouselScrollHandler.visibleMediaIndex + == MediaPlayerData.getMediaPlayerIndex(key)) { + logSmartspaceImpression(mediaCarouselScrollHandler.qsExpanded) + } + } else if (receivedSmartspaceCardLatency != 0) { + // Log resume card received if resumable media card is reactivated and + // resume card is ranked first MediaPlayerData.players().forEachIndexed { index, it -> if (it.recommendationViewHolder == null) { it.mInstanceId = SmallHash.hash(it.mUid + systemClock.currentTimeMillis().toInt()) + it.mIsImpressed = false + /* ktlint-disable max-line-length */ logSmartspaceCardReported(759, // SMARTSPACE_CARD_RECEIVED it.mInstanceId, it.mUid, /* isRecommendationCard */ false, - it.surfaceForSmartspaceLogging, - rank = index) + intArrayOf( + SysUiStatsLog.SMART_SPACE_CARD_REPORTED__DISPLAY_SURFACE__SHADE, + SysUiStatsLog.SMART_SPACE_CARD_REPORTED__DISPLAY_SURFACE__LOCKSCREEN), + rank = index, + receivedLatencyMillis = receivedSmartspaceCardLatency) + /* ktlint-disable max-line-length */ } } + // If media container area already visible to the user, log impression for + // reactivated card. + if (mediaCarouselScrollHandler.visibleToUser && + !mediaCarouselScrollHandler.qsExpanded) { + logSmartspaceImpression(mediaCarouselScrollHandler.qsExpanded) + } } - if (mediaCarouselScrollHandler.visibleToUser && - isSsReactivated && !mediaCarouselScrollHandler.qsExpanded) { - // It could happen that reactived media player isn't visible to user because - // of it is a resumption card. - logSmartspaceImpression(mediaCarouselScrollHandler.qsExpanded) - } + val canRemove = data.isPlaying?.let { !it } ?: data.isClearable && !data.active if (canRemove && !Utils.useMediaResumption(context)) { // This view isn't playing, let's remove this! This happens e.g when @@ -262,28 +277,51 @@ class MediaCarouselController @Inject constructor( override fun onSmartspaceMediaDataLoaded( key: String, data: SmartspaceMediaData, - shouldPrioritize: Boolean + shouldPrioritize: Boolean, + isSsReactivated: Boolean ) { if (DEBUG) Log.d(TAG, "Loading Smartspace media update") if (data.isActive) { + if (isSsReactivated && shouldPrioritize) { + // Log resume card received if resumable media card is reactivated and + // recommendation card is valid and ranked first + MediaPlayerData.players().forEachIndexed { index, it -> + if (it.recommendationViewHolder == null) { + it.mInstanceId = SmallHash.hash(it.mUid + + systemClock.currentTimeMillis().toInt()) + it.mIsImpressed = false + /* ktlint-disable max-line-length */ + logSmartspaceCardReported(759, // SMARTSPACE_CARD_RECEIVED + it.mInstanceId, + it.mUid, + /* isRecommendationCard */ false, + intArrayOf( + SysUiStatsLog.SMART_SPACE_CARD_REPORTED__DISPLAY_SURFACE__SHADE, + SysUiStatsLog.SMART_SPACE_CARD_REPORTED__DISPLAY_SURFACE__LOCKSCREEN), + rank = index, + receivedLatencyMillis = (systemClock.currentTimeMillis() - data.headphoneConnectionTimeMillis).toInt()) + /* ktlint-disable max-line-length */ + } + } + } addSmartspaceMediaRecommendations(key, data, shouldPrioritize) MediaPlayerData.getMediaPlayer(key)?.let { + /* ktlint-disable max-line-length */ logSmartspaceCardReported(759, // SMARTSPACE_CARD_RECEIVED it.mInstanceId, it.mUid, /* isRecommendationCard */ true, - it.surfaceForSmartspaceLogging, - rank = MediaPlayerData.getMediaPlayerIndex(key)) - - if (mediaCarouselScrollHandler.visibleToUser && - mediaCarouselScrollHandler.visibleMediaIndex == - MediaPlayerData.getMediaPlayerIndex(key)) { - logSmartspaceCardReported(800, // SMARTSPACE_CARD_SEEN - it.mInstanceId, - it.mUid, - /* isRecommendationCard */ true, - it.surfaceForSmartspaceLogging) - } + intArrayOf( + SysUiStatsLog.SMART_SPACE_CARD_REPORTED__DISPLAY_SURFACE__SHADE, + SysUiStatsLog.SMART_SPACE_CARD_REPORTED__DISPLAY_SURFACE__LOCKSCREEN), + rank = MediaPlayerData.getMediaPlayerIndex(key), + receivedLatencyMillis = (systemClock.currentTimeMillis() - data.headphoneConnectionTimeMillis).toInt()) + /* ktlint-disable max-line-length */ + } + if (mediaCarouselScrollHandler.visibleToUser && + mediaCarouselScrollHandler.visibleMediaIndex + == MediaPlayerData.getMediaPlayerIndex(key)) { + logSmartspaceImpression(mediaCarouselScrollHandler.qsExpanded) } } else { onSmartspaceMediaDataRemoved(data.targetId, immediately = true) @@ -718,7 +756,8 @@ class MediaCarouselController @Inject constructor( mediaControlPanel.mInstanceId, mediaControlPanel.mUid, isRecommendationCard, - mediaControlPanel.surfaceForSmartspaceLogging) + intArrayOf(mediaControlPanel.surfaceForSmartspaceLogging)) + mediaControlPanel.mIsImpressed = true } } @@ -731,12 +770,15 @@ class MediaCarouselController @Inject constructor( * instanceId * @param uid uid for the application that media comes from * @param isRecommendationCard whether the card is media recommendation - * @param surface which display surface the media card is on (e.g. lockscreen, shade) + * @param surfaces list of display surfaces the media card is on (e.g. lockscreen, shade) when + * the event happened * @param interactedSubcardRank the rank for interacted media item for recommendation card, -1 * for tapping on card but not on any media item, 0 for first media item, 1 for second, etc. * @param interactedSubcardCardinality how many media items were shown to the user when there * is user interaction * @param rank the rank for media card in the media carousel, starting from 0 + * @param receivedLatencyMillis latency in milliseconds for card received events. E.g. latency + * between headphone connection to sysUI displays media recommendation card * */ fun logSmartspaceCardReported( @@ -744,10 +786,11 @@ class MediaCarouselController @Inject constructor( instanceId: Int, uid: Int, isRecommendationCard: Boolean, - surface: Int, + surfaces: IntArray, interactedSubcardRank: Int = 0, interactedSubcardCardinality: Int = 0, - rank: Int = mediaCarouselScrollHandler.visibleMediaIndex + rank: Int = mediaCarouselScrollHandler.visibleMediaIndex, + receivedLatencyMillis: Int = 0 ) { // Only log media resume card when Smartspace data is available if (!isRecommendationCard && @@ -756,50 +799,52 @@ class MediaCarouselController @Inject constructor( return } - /* ktlint-disable max-line-length */ - SysUiStatsLog.write(SysUiStatsLog.SMARTSPACE_CARD_REPORTED, - eventId, - instanceId, - // Deprecated, replaced with AiAi feature type so we don't need to create logging - // card type for each new feature. - SysUiStatsLog.SMART_SPACE_CARD_REPORTED__CARD_TYPE__UNKNOWN_CARD, - surface, - rank, - mediaContent.getChildCount(), - if (isRecommendationCard) - 15 // MEDIA_RECOMMENDATION - else - 31, // MEDIA_RESUME - uid, - interactedSubcardRank, - interactedSubcardCardinality, - 0 // received_latency_millis - ) - /* ktlint-disable max-line-length */ + val cardinality = mediaContent.getChildCount() + surfaces.forEach { surface -> + /* ktlint-disable max-line-length */ + SysUiStatsLog.write(SysUiStatsLog.SMARTSPACE_CARD_REPORTED, + eventId, + instanceId, + // Deprecated, replaced with AiAi feature type so we don't need to create logging + // card type for each new feature. + SysUiStatsLog.SMART_SPACE_CARD_REPORTED__CARD_TYPE__UNKNOWN_CARD, + surface, + rank, + cardinality, + if (isRecommendationCard) + 15 // MEDIA_RECOMMENDATION + else + 31, // MEDIA_RESUME + uid, + interactedSubcardRank, + interactedSubcardCardinality, + receivedLatencyMillis + ) + /* ktlint-disable max-line-length */ + if (DEBUG) { + Log.d(TAG, "Log Smartspace card event id: $eventId instance id: $instanceId" + + " surface: $surface rank: $rank cardinality: $cardinality " + + "isRecommendationCard: $isRecommendationCard uid: $uid " + + "interactedSubcardRank: $interactedSubcardRank " + + "interactedSubcardCardinality: $interactedSubcardCardinality " + + "received_latency_millis: $receivedLatencyMillis") + } + } } private fun onSwipeToDismiss() { - val recommendation = MediaPlayerData.players().filter { - it.recommendationViewHolder != null - } - // Use -1 as rank value to indicate user swipe to dismiss the card - if (!recommendation.isEmpty()) { - logSmartspaceCardReported(761, // SMARTSPACE_CARD_DISMISS - recommendation.get(0).mInstanceId, - recommendation.get(0).mUid, - true, - recommendation.get(0).surfaceForSmartspaceLogging, - rank = -1) - } else { - val visibleMediaIndex = mediaCarouselScrollHandler.visibleMediaIndex - if (MediaPlayerData.players().size > visibleMediaIndex) { - val player = MediaPlayerData.players().elementAt(visibleMediaIndex) + MediaPlayerData.players().forEachIndexed { + index, it -> + if (it.mIsImpressed) { logSmartspaceCardReported(761, // SMARTSPACE_CARD_DISMISS - player.mInstanceId, - player.mUid, - false, - player.surfaceForSmartspaceLogging, + it.mInstanceId, + it.mUid, + it.recommendationViewHolder != null, + intArrayOf(it.surfaceForSmartspaceLogging), + // Use -1 as rank value to indicate user swipe to dismiss the card rank = -1) + // Reset card impressed state when swipe to dismissed + it.mIsImpressed = false } } mediaManager.onSwipeToDismiss() diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java index e73eb66a51bf..f66eb5ba008a 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java +++ b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java @@ -59,6 +59,7 @@ import com.android.systemui.plugins.FalsingManager; import com.android.systemui.shared.system.SysUiStatsLog; import com.android.systemui.statusbar.phone.KeyguardDismissUtil; import com.android.systemui.util.animation.TransitionLayout; +import com.android.systemui.util.time.SystemClock; import java.net.URISyntaxException; import java.util.List; @@ -121,6 +122,9 @@ public class MediaControlPanel { private MediaCarouselController mMediaCarouselController; private final MediaOutputDialogFactory mMediaOutputDialogFactory; private final FalsingManager mFalsingManager; + // Used for swipe-to-dismiss logging. + protected boolean mIsImpressed = false; + private SystemClock mSystemClock; /** * Initialize a new control panel @@ -134,7 +138,7 @@ public class MediaControlPanel { SeekBarViewModel seekBarViewModel, Lazy<MediaDataManager> lazyMediaDataManager, KeyguardDismissUtil keyguardDismissUtil, MediaOutputDialogFactory mediaOutputDialogFactory, MediaCarouselController mediaCarouselController, - FalsingManager falsingManager) { + FalsingManager falsingManager, SystemClock systemClock) { mContext = context; mBackgroundExecutor = backgroundExecutor; mActivityStarter = activityStarter; @@ -145,6 +149,8 @@ public class MediaControlPanel { mMediaOutputDialogFactory = mediaOutputDialogFactory; mMediaCarouselController = mediaCarouselController; mFalsingManager = falsingManager; + mSystemClock = systemClock; + loadDimens(); mSeekBarViewModel.setLogSmartspaceClick(() -> { @@ -291,7 +297,10 @@ public class MediaControlPanel { } catch (PackageManager.NameNotFoundException e) { Log.e(TAG, "Unable to look up package name", e); } - mInstanceId = SmallHash.hash(mUid); + // Only assigns instance id if it's unassigned. + if (mInstanceId == -1) { + mInstanceId = SmallHash.hash(mUid + (int) mSystemClock.currentTimeMillis()); + } mBackgroundColor = data.getBackgroundColor(); if (mToken == null || !mToken.equals(token)) { @@ -885,7 +894,7 @@ public class MediaControlPanel { mInstanceId, mUid, isRecommendationCard, - getSurfaceForSmartspaceLogging(), + new int[]{getSurfaceForSmartspaceLogging()}, interactedSubcardRank, interactedSubcardCardinality); } diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataCombineLatest.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataCombineLatest.kt index 296bfda89432..b68f2a7654f0 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaDataCombineLatest.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataCombineLatest.kt @@ -32,7 +32,7 @@ class MediaDataCombineLatest @Inject constructor() : MediaDataManager.Listener, oldKey: String?, data: MediaData, immediately: Boolean, - isSsReactivated: Boolean + receivedSmartspaceCardLatency: Int ) { if (oldKey != null && oldKey != key && entries.contains(oldKey)) { entries[key] = data to entries.remove(oldKey)?.second @@ -46,7 +46,8 @@ class MediaDataCombineLatest @Inject constructor() : MediaDataManager.Listener, override fun onSmartspaceMediaDataLoaded( key: String, data: SmartspaceMediaData, - shouldPrioritize: Boolean + shouldPrioritize: Boolean, + isSsReactivated: Boolean ) { listeners.toSet().forEach { it.onSmartspaceMediaDataLoaded(key, data) } } diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataFilter.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataFilter.kt index 79206e86da09..ae5c1f2b19a9 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaDataFilter.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataFilter.kt @@ -56,7 +56,6 @@ internal val SMARTSPACE_MAX_AGE = SystemProperties class MediaDataFilter @Inject constructor( private val context: Context, private val broadcastDispatcher: BroadcastDispatcher, - private val mediaResumeListener: MediaResumeListener, private val lockscreenUserManager: NotificationLockscreenUserManager, @Main private val executor: Executor, private val systemClock: SystemClock @@ -88,7 +87,7 @@ class MediaDataFilter @Inject constructor( oldKey: String?, data: MediaData, immediately: Boolean, - isSsReactivated: Boolean + receivedSmartspaceCardLatency: Int ) { if (oldKey != null && oldKey != key) { allEntries.remove(oldKey) @@ -106,14 +105,15 @@ class MediaDataFilter @Inject constructor( // Notify listeners listeners.forEach { - it.onMediaDataLoaded(key, oldKey, data, isSsReactivated = isSsReactivated) + it.onMediaDataLoaded(key, oldKey, data) } } override fun onSmartspaceMediaDataLoaded( key: String, data: SmartspaceMediaData, - shouldPrioritize: Boolean + shouldPrioritize: Boolean, + isSsReactivated: Boolean ) { if (!data.isActive) { Log.d(TAG, "Inactive recommendation data. Skip triggering.") @@ -123,8 +123,6 @@ class MediaDataFilter @Inject constructor( // Override the pass-in value here, as the order of Smartspace card is only determined here. var shouldPrioritizeMutable = false smartspaceMediaData = data - // Override the pass-in value here, as the Smartspace reactivation could only happen here. - var isSsReactivated = false // Before forwarding the smartspace target, first check if we have recently inactive media val sorted = userEntries.toSortedMap(compareBy { @@ -139,18 +137,25 @@ class MediaDataFilter @Inject constructor( smartspaceMaxAgeMillis = TimeUnit.SECONDS.toMillis(smartspaceMaxAgeSeconds) } } + + val activeMedia = userEntries.filter { (key, value) -> value.active } + var isSsReactivatedMutable = activeMedia.isEmpty() && userEntries.isNotEmpty() + if (timeSinceActive < smartspaceMaxAgeMillis) { - val lastActiveKey = sorted.lastKey() // most recently active - // Notify listeners to consider this media active - Log.d(TAG, "reactivating $lastActiveKey instead of smartspace") - reactivatedKey = lastActiveKey - if (MediaPlayerData.firstActiveMediaIndex() == -1) { - isSsReactivated = true - } - val mediaData = sorted.get(lastActiveKey)!!.copy(active = true) - listeners.forEach { - it.onMediaDataLoaded(lastActiveKey, lastActiveKey, mediaData, - isSsReactivated = isSsReactivated) + // It could happen there are existing active media resume cards, then we don't need to + // reactivate. + if (isSsReactivatedMutable) { + val lastActiveKey = sorted.lastKey() // most recently active + // Notify listeners to consider this media active + Log.d(TAG, "reactivating $lastActiveKey instead of smartspace") + reactivatedKey = lastActiveKey + val mediaData = sorted.get(lastActiveKey)!!.copy(active = true) + listeners.forEach { + it.onMediaDataLoaded(lastActiveKey, lastActiveKey, mediaData, + receivedSmartspaceCardLatency = + (systemClock.currentTimeMillis() - data.headphoneConnectionTimeMillis) + .toInt()) + } } } else { // Mark to prioritize Smartspace card if no recent media. @@ -161,7 +166,8 @@ class MediaDataFilter @Inject constructor( Log.d(TAG, "Invalid recommendation data. Skip showing the rec card") return } - listeners.forEach { it.onSmartspaceMediaDataLoaded(key, data, shouldPrioritizeMutable) } + listeners.forEach { it.onSmartspaceMediaDataLoaded(key, data, shouldPrioritizeMutable, + isSsReactivatedMutable) } } override fun onMediaDataRemoved(key: String) { diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt index 6e86bef40181..7c0f7fc2967e 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt @@ -84,7 +84,7 @@ private val LOADING = MediaData(-1, false, 0, null, null, null, null, null, emptyList(), emptyList(), "INVALID", null, null, null, true, null) @VisibleForTesting internal val EMPTY_SMARTSPACE_MEDIA_DATA = SmartspaceMediaData("INVALID", false, false, - "INVALID", null, emptyList(), null, 0) + "INVALID", null, emptyList(), null, 0, 0) fun isMediaNotification(sbn: StatusBarNotification): Boolean { return sbn.notification.isMediaNotification() @@ -852,15 +852,16 @@ class MediaDataManager( * until the next refresh-round before UI becomes visible. True by default to take in place * immediately. * - * @param isSsReactivated indicates transition from a state with no active media players to - * a state with active media players upon receiving Smartspace media data. + * @param receivedSmartspaceCardLatency is the latency between headphone connects and sysUI + * displays Smartspace media targets. Will be 0 if the data is not activated by Smartspace + * signal. */ fun onMediaDataLoaded( key: String, oldKey: String?, data: MediaData, immediately: Boolean = true, - isSsReactivated: Boolean = false + receivedSmartspaceCardLatency: Int = 0 ) {} /** @@ -869,11 +870,15 @@ class MediaDataManager( * @param shouldPrioritize indicates the sorting priority of the Smartspace card. If true, * it will be prioritized as the first card. Otherwise, it will show up as the last card as * default. + * + * @param isSsReactivated indicates resume media card is reactivated by Smartspace + * recommendation signal */ fun onSmartspaceMediaDataLoaded( key: String, data: SmartspaceMediaData, - shouldPrioritize: Boolean = false + shouldPrioritize: Boolean = false, + isSsReactivated: Boolean = false ) {} /** Called whenever a previously existing Media notification was removed. */ @@ -909,12 +914,13 @@ class MediaDataManager( packageName(target)?.let { return SmartspaceMediaData(target.smartspaceTargetId, isActive, true, it, target.baseAction, target.iconGrid, - dismissIntent, 0) + dismissIntent, 0, target.creationTimeMillis) } return EMPTY_SMARTSPACE_MEDIA_DATA .copy(targetId = target.smartspaceTargetId, - isActive = isActive, - dismissIntent = dismissIntent) + isActive = isActive, + dismissIntent = dismissIntent, + headphoneConnectionTimeMillis = target.creationTimeMillis) } private fun packageName(target: SmartspaceTarget): String? { diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt index fbfb919ede1e..bed254fe8249 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt @@ -68,7 +68,7 @@ class MediaDeviceManager @Inject constructor( oldKey: String?, data: MediaData, immediately: Boolean, - isSsReactivated: Boolean + receivedSmartspaceCardLatency: Int ) { if (oldKey != null && oldKey != key) { val oldEntry = entries.remove(oldKey) @@ -200,7 +200,7 @@ class MediaDeviceManager @Inject constructor( @WorkerThread private fun updateCurrent() { val device = localMediaManager.currentConnectedDevice - val route = controller?.let { mr2manager.getRoutingSessionForMediaController(it)} + val route = controller?.let { mr2manager.getRoutingSessionForMediaController(it) } // If we have a controller but get a null route, then don't trust the device val enabled = device != null && (controller == null || route != null) diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaHost.kt b/packages/SystemUI/src/com/android/systemui/media/MediaHost.kt index ff085c36ef9c..0a4b68b501f7 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaHost.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaHost.kt @@ -61,7 +61,7 @@ class MediaHost constructor( oldKey: String?, data: MediaData, immediately: Boolean, - isSsReactivated: Boolean + receivedSmartspaceCardLatency: Int ) { if (immediately) { updateViewVisibility() @@ -71,7 +71,8 @@ class MediaHost constructor( override fun onSmartspaceMediaDataLoaded( key: String, data: SmartspaceMediaData, - shouldPrioritize: Boolean + shouldPrioritize: Boolean, + isSsReactivated: Boolean ) { updateViewVisibility() } diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt b/packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt index d8095f3179b3..35f95dd27c1f 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt @@ -184,7 +184,7 @@ class MediaResumeListener @Inject constructor( oldKey: String?, data: MediaData, immediately: Boolean, - isSsReactivated: Boolean + receivedSmartspaceCardLatency: Int ) { if (useMediaResumption) { // If this had been started from a resume state, disconnect now that it's live diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaSessionBasedFilter.kt b/packages/SystemUI/src/com/android/systemui/media/MediaSessionBasedFilter.kt index 8bddde839817..1c448a2ff8c4 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaSessionBasedFilter.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaSessionBasedFilter.kt @@ -96,7 +96,7 @@ class MediaSessionBasedFilter @Inject constructor( oldKey: String?, data: MediaData, immediately: Boolean, - isSsReactivated: Boolean + receivedSmartspaceCardLatency: Int ) { backgroundExecutor.execute { data.token?.let { @@ -143,7 +143,8 @@ class MediaSessionBasedFilter @Inject constructor( override fun onSmartspaceMediaDataLoaded( key: String, data: SmartspaceMediaData, - shouldPrioritize: Boolean + shouldPrioritize: Boolean, + isSsReactivated: Boolean ) { backgroundExecutor.execute { dispatchSmartspaceMediaDataLoaded(key, data) diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaTimeoutListener.kt b/packages/SystemUI/src/com/android/systemui/media/MediaTimeoutListener.kt index 6f047712c954..9581a633a8c5 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaTimeoutListener.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaTimeoutListener.kt @@ -63,7 +63,7 @@ class MediaTimeoutListener @Inject constructor( oldKey: String?, data: MediaData, immediately: Boolean, - isSsReactivated: Boolean + receivedSmartspaceCardLatency: Int ) { var reusedListener: PlaybackStateListener? = null diff --git a/packages/SystemUI/src/com/android/systemui/media/SmartspaceMediaData.kt b/packages/SystemUI/src/com/android/systemui/media/SmartspaceMediaData.kt index 61fdefd4579f..066a6fbfa8be 100644 --- a/packages/SystemUI/src/com/android/systemui/media/SmartspaceMediaData.kt +++ b/packages/SystemUI/src/com/android/systemui/media/SmartspaceMediaData.kt @@ -52,5 +52,9 @@ data class SmartspaceMediaData( /** * View's background color. */ - val backgroundColor: Int + val backgroundColor: Int, + /** + * The timestamp in milliseconds that headphone is connected. + */ + val headphoneConnectionTimeMillis: Long ) diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java index 868193b44704..54e40f1429be 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java @@ -289,6 +289,9 @@ public abstract class MediaOutputBaseAdapter extends public void onAnimationEnd(Animator animation) { to.requireViewById(R.id.volume_indeterminate_progress).setVisibility( View.VISIBLE); + // Unset the listener, otherwise this may persist for another view + // property animation + toTitleText.animate().setListener(null); } }); // Animation for seek bar @@ -312,8 +315,14 @@ public abstract class MediaOutputBaseAdapter extends public void onAnimationEnd(Animator animation) { mIsAnimating = false; notifyDataSetChanged(); + // Unset the listener, otherwise this may persist for + // another view property animation + fromTitleText.animate().setListener(null); } }); + // Unset the listener, otherwise this may persist for another view + // property animation + fromSeekBar.animate().setListener(null); } }); } diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java index 26ce645eefc5..03a097746ba9 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java @@ -217,14 +217,6 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements dismiss(); } - @Override - public void onWindowFocusChanged(boolean hasFocus) { - super.onWindowFocusChanged(hasFocus); - if (!hasFocus && isShowing()) { - dismiss(); - } - } - void onHeaderIconClick() { } diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java index 52103d3bd739..42b7cc3952e7 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java @@ -24,12 +24,15 @@ import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A import android.content.ContentResolver; import android.content.Context; import android.database.ContentObserver; +import android.inputmethodservice.InputMethodService; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.UserHandle; import android.provider.Settings; +import android.view.View; +import android.view.WindowInsets; import android.view.accessibility.AccessibilityManager; import androidx.annotation.NonNull; @@ -42,12 +45,14 @@ import com.android.systemui.dump.DumpManager; import com.android.systemui.recents.OverviewProxyService; import com.android.systemui.settings.UserTracker; import com.android.systemui.shared.system.QuickStepContract; +import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; +import java.util.Optional; import javax.inject.Inject; @@ -69,10 +74,11 @@ public final class NavBarHelper implements Dumpable { private final AccessibilityManager mAccessibilityManager; private final Lazy<AssistManager> mAssistManagerLazy; + private final Lazy<Optional<StatusBar>> mStatusBarOptionalLazy; private final UserTracker mUserTracker; private final AccessibilityButtonModeObserver mAccessibilityButtonModeObserver; private final List<NavbarTaskbarStateUpdater> mA11yEventListeners = new ArrayList<>(); - private Context mContext; + private final Context mContext; private ContentResolver mContentResolver; private boolean mAssistantAvailable; private boolean mLongPressHomeEnabled; @@ -87,17 +93,26 @@ public final class NavBarHelper implements } }; + /** + * @param context This is not display specific, then again neither is any of the code in + * this class. Once there's display specific code, we may want to create an + * instance of this class per navbar vs having it be a singleton. + */ @Inject - public NavBarHelper(AccessibilityManager accessibilityManager, + public NavBarHelper(Context context, AccessibilityManager accessibilityManager, AccessibilityManagerWrapper accessibilityManagerWrapper, AccessibilityButtonModeObserver accessibilityButtonModeObserver, OverviewProxyService overviewProxyService, Lazy<AssistManager> assistManagerLazy, + Lazy<Optional<StatusBar>> statusBarOptionalLazy, NavigationModeController navigationModeController, UserTracker userTracker, DumpManager dumpManager) { + mContext = context; + mContentResolver = mContext.getContentResolver(); mAccessibilityManager = accessibilityManager; mAssistManagerLazy = assistManagerLazy; + mStatusBarOptionalLazy = statusBarOptionalLazy; mUserTracker = userTracker; accessibilityManagerWrapper.addCallback( accessibilityManager1 -> NavBarHelper.this.dispatchA11yEventUpdate()); @@ -109,9 +124,7 @@ public final class NavBarHelper implements dumpManager.registerDumpable(this); } - public void init(Context context) { - mContext = context; - mContentResolver = mContext.getContentResolver(); + public void init() { mContentResolver.registerContentObserver( Settings.Secure.getUriFor(Settings.Secure.ASSISTANT), false /* notifyForDescendants */, mAssistContentObserver, UserHandle.USER_ALL); @@ -227,6 +240,19 @@ public final class NavBarHelper implements } /** + * @return Whether the IME is shown on top of the screen given the {@code vis} flag of + * {@link InputMethodService} and the keyguard states. + */ + public boolean isImeShown(int vis) { + View shadeWindowView = mStatusBarOptionalLazy.get().get().getNotificationShadeWindowView(); + boolean isKeyguardShowing = mStatusBarOptionalLazy.get().get().isKeyguardShowing(); + boolean imeVisibleOnShade = shadeWindowView != null && shadeWindowView.isAttachedToWindow() + && shadeWindowView.getRootWindowInsets().isVisible(WindowInsets.Type.ime()); + return imeVisibleOnShade + || (!isKeyguardShowing && (vis & InputMethodService.IME_VISIBLE) != 0); + } + + /** * Callbacks will get fired once immediately after registering via * {@link #registerNavTaskStateUpdater(NavbarTaskbarStateUpdater)} */ diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java index 5141f25e4933..03bceacdfbdc 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java @@ -72,7 +72,6 @@ import android.graphics.Insets; import android.graphics.PixelFormat; import android.graphics.Rect; import android.graphics.RectF; -import android.inputmethodservice.InputMethodService; import android.os.Binder; import android.os.Bundle; import android.os.Handler; @@ -563,7 +562,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, mCommandQueue.addCallback(this); mLongPressHomeEnabled = mNavBarHelper.getLongPressHomeEnabled(); mContentResolver = mContext.getContentResolver(); - mNavBarHelper.init(mContext); + mNavBarHelper.init(); mAllowForceNavBarHandleOpaque = mContext.getResources().getBoolean( R.bool.allow_force_nav_bar_handle_opaque); mForceNavBarHandleOpaque = DeviceConfig.getBoolean( @@ -884,7 +883,8 @@ public class NavigationBar implements View.OnAttachStateChangeListener, if (displayId != mDisplayId) { return; } - boolean imeShown = (vis & InputMethodService.IME_VISIBLE) != 0; + boolean imeShown = mNavBarHelper.isImeShown(vis); + showImeSwitcher = imeShown && showImeSwitcher; int hints = Utilities.calculateBackDispositionHints(mNavigationIconHints, backDisposition, imeShown, showImeSwitcher); if (hints == mNavigationIconHints) return; @@ -1757,4 +1757,4 @@ public class NavigationBar implements View.OnAttachStateChangeListener, mInputMethodManager); } } -}
\ No newline at end of file +} diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java index 0429c022234d..bfabf716803b 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java @@ -395,6 +395,24 @@ public class NavigationBarController implements return (navBar == null) ? null : navBar.getView(); } + public void showPinningEnterExitToast(int displayId, boolean entering) { + final NavigationBarView navBarView = getNavigationBarView(displayId); + if (navBarView != null) { + navBarView.showPinningEnterExitToast(entering); + } else if (displayId == DEFAULT_DISPLAY && mTaskbarDelegate.isInitialized()) { + mTaskbarDelegate.showPinningEnterExitToast(entering); + } + } + + public void showPinningEscapeToast(int displayId) { + final NavigationBarView navBarView = getNavigationBarView(displayId); + if (navBarView != null) { + navBarView.showPinningEscapeToast(); + } else if (displayId == DEFAULT_DISPLAY && mTaskbarDelegate.isInitialized()) { + mTaskbarDelegate.showPinningEscapeToast(); + } + } + /** @return {@link NavigationBar} on the default display. */ @Nullable public NavigationBar getDefaultNavigationBar() { diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java index 680cc5cb5cba..7c8c3e0dce44 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java @@ -110,6 +110,7 @@ public class NavigationBarView extends FrameLayout implements private final int mNavColorSampleMargin; private final SysUiState mSysUiFlagContainer; + // The current view is one of mHorizontal or mVertical depending on the current configuration View mCurrentView = null; private View mVertical; private View mHorizontal; @@ -397,12 +398,6 @@ public class NavigationBarView extends FrameLayout implements } } - @Override - protected boolean onSetAlpha(int alpha) { - Log.e(TAG, "onSetAlpha", new Throwable()); - return super.onSetAlpha(alpha); - } - public void setAutoHideController(AutoHideController autoHideController) { mAutoHideController = autoHideController; } @@ -505,6 +500,18 @@ public class NavigationBarView extends FrameLayout implements return mCurrentView; } + /** + * Applies {@param consumer} to each of the nav bar views. + */ + public void forEachView(Consumer<View> consumer) { + if (mVertical != null) { + consumer.accept(mVertical); + } + if (mHorizontal != null) { + consumer.accept(mHorizontal); + } + } + public RotationButtonController getRotationButtonController() { return mRotationButtonController; } @@ -1205,7 +1212,9 @@ public class NavigationBarView extends FrameLayout implements protected void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); mTmpLastConfiguration.updateFrom(mConfiguration); - mConfiguration.updateFrom(newConfig); + final int changes = mConfiguration.updateFrom(newConfig); + mFloatingRotationButton.onConfigurationChanged(changes); + boolean uiCarModeChanged = updateCarMode(); updateIcons(mTmpLastConfiguration); updateRecentsIcon(); diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java index 3d58a5a81251..68f4aeaa7f17 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java @@ -61,6 +61,7 @@ import com.android.systemui.navigationbar.gestural.EdgeBackGestureHandler; import com.android.systemui.recents.OverviewProxyService; import com.android.systemui.shared.recents.utilities.Utilities; import com.android.systemui.shared.system.ActivityManagerWrapper; +import com.android.systemui.shared.system.QuickStepContract; import com.android.systemui.statusbar.AutoHideUiElement; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.phone.AutoHideController; @@ -110,6 +111,9 @@ public class TaskbarDelegate implements CommandQueue.Callbacks, private final Context mContext; private final DisplayManager mDisplayManager; private Context mWindowContext; + private ScreenPinningNotify mScreenPinningNotify; + private int mNavigationMode; + /** * Tracks the system calls for when taskbar should transiently show or hide so we can return * this value in {@link AutoHideUiElement#isVisible()} below. @@ -192,12 +196,13 @@ public class TaskbarDelegate implements CommandQueue.Callbacks, mEdgeBackGestureHandler.onNavigationModeChanged( mNavigationModeController.addListener(this)); mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater); - mNavBarHelper.init(mContext); + mNavBarHelper.init(); mEdgeBackGestureHandler.onNavBarAttached(); // Initialize component callback Display display = mDisplayManager.getDisplay(displayId); mWindowContext = mContext.createWindowContext(display, TYPE_APPLICATION, null); mWindowContext.registerComponentCallbacks(this); + mScreenPinningNotify = new ScreenPinningNotify(mWindowContext); // Set initial state for any listeners updateSysuiFlags(); mAutoHideController.setNavigationBar(mAutoHideUiElement); @@ -215,6 +220,7 @@ public class TaskbarDelegate implements CommandQueue.Callbacks, mNavBarHelper.removeNavTaskStateUpdater(mNavbarTaskbarStateUpdater); mNavBarHelper.destroy(); mEdgeBackGestureHandler.onNavBarDetached(); + mScreenPinningNotify = null; if (mWindowContext != null) { mWindowContext.unregisterComponentCallbacks(this); mWindowContext = null; @@ -225,6 +231,14 @@ public class TaskbarDelegate implements CommandQueue.Callbacks, mInitialized = false; } + /** + * Returns {@code true} if this taskBar is {@link #init(int)}. Returns {@code false} if this + * taskbar has not yet been {@link #init(int)} or has been {@link #destroy()}. + */ + public boolean isInitialized() { + return mInitialized; + } + private void updateSysuiFlags() { int a11yFlags = mNavBarHelper.getA11yButtonState(); boolean clickable = (a11yFlags & SYSUI_STATE_A11Y_BUTTON_CLICKABLE) != 0; @@ -265,7 +279,12 @@ public class TaskbarDelegate implements CommandQueue.Callbacks, @Override public void setImeWindowStatus(int displayId, IBinder token, int vis, int backDisposition, boolean showImeSwitcher) { - boolean imeShown = (vis & InputMethodService.IME_VISIBLE) != 0; + boolean imeShown = mNavBarHelper.isImeShown(vis); + if (!imeShown) { + // Count imperceptible changes as visible so we transition taskbar out quickly. + imeShown = (vis & InputMethodService.IME_VISIBLE_IMPERCEPTIBLE) != 0; + } + showImeSwitcher = imeShown && showImeSwitcher; int hints = Utilities.calculateBackDispositionHints(mNavigationIconHints, backDisposition, imeShown, showImeSwitcher); if (hints != mNavigationIconHints) { @@ -345,6 +364,7 @@ public class TaskbarDelegate implements CommandQueue.Callbacks, @Override public void onNavigationModeChanged(int mode) { + mNavigationMode = mode; mEdgeBackGestureHandler.onNavigationModeChanged(mode); } @@ -365,9 +385,33 @@ public class TaskbarDelegate implements CommandQueue.Callbacks, public void onLowMemory() {} @Override + public void showPinningEnterExitToast(boolean entering) { + updateSysuiFlags(); + if (mScreenPinningNotify == null) { + return; + } + if (entering) { + mScreenPinningNotify.showPinningStartToast(); + } else { + mScreenPinningNotify.showPinningExitToast(); + } + } + + @Override + public void showPinningEscapeToast() { + updateSysuiFlags(); + if (mScreenPinningNotify == null) { + return; + } + mScreenPinningNotify.showEscapeToast(QuickStepContract.isGesturalMode(mNavigationMode), + !QuickStepContract.isGesturalMode(mNavigationMode)); + } + + @Override public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) { pw.println("TaskbarDelegate (displayId=" + mDisplayId + "):"); pw.println(" mNavigationIconHints=" + mNavigationIconHints); + pw.println(" mNavigationMode=" + mNavigationMode); pw.println(" mDisabledFlags=" + mDisabledFlags); pw.println(" mTaskBarWindowState=" + mTaskBarWindowState); pw.println(" mBehavior=" + mBehavior); diff --git a/packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt b/packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt index 98b914672112..bc3a4fdfd7ff 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt @@ -116,7 +116,7 @@ class FooterActionsController @Inject constructor( } } else if (v === powerMenuLite) { uiEventLogger.log(GlobalActionsDialogLite.GlobalActionsEvent.GA_OPEN_QS) - globalActionsDialog.showOrHideDialog(false, true) + globalActionsDialog.showOrHideDialog(false, true, v) } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/HeaderPrivacyIconsController.kt b/packages/SystemUI/src/com/android/systemui/qs/HeaderPrivacyIconsController.kt new file mode 100644 index 000000000000..3b305bb01cbc --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qs/HeaderPrivacyIconsController.kt @@ -0,0 +1,146 @@ +package com.android.systemui.qs + +import android.view.View +import com.android.internal.R +import com.android.internal.logging.UiEventLogger +import com.android.systemui.privacy.OngoingPrivacyChip +import com.android.systemui.privacy.PrivacyChipEvent +import com.android.systemui.privacy.PrivacyDialogController +import com.android.systemui.privacy.PrivacyItem +import com.android.systemui.privacy.PrivacyItemController +import com.android.systemui.privacy.logging.PrivacyLogger +import com.android.systemui.statusbar.phone.StatusIconContainer +import javax.inject.Inject + +interface ChipVisibilityListener { + fun onChipVisibilityRefreshed(visible: Boolean) +} + +/** + * Controls privacy icons/chip residing in QS header which show up when app is using camera, + * microphone or location. + * Manages their visibility depending on privacy signals coming from [PrivacyItemController]. + * + * Unlike typical controller extending [com.android.systemui.util.ViewController] this view doesn't + * observe its attachment state because depending on where it is used, it might be never detached. + * Instead, parent controller should use [onParentVisible] and [onParentInvisible] to "activate" or + * "deactivate" this controller. + */ +class HeaderPrivacyIconsController @Inject constructor( + private val privacyItemController: PrivacyItemController, + private val uiEventLogger: UiEventLogger, + private val privacyChip: OngoingPrivacyChip, + private val privacyDialogController: PrivacyDialogController, + private val privacyLogger: PrivacyLogger, + private val iconContainer: StatusIconContainer +) { + + var chipVisibilityListener: ChipVisibilityListener? = null + private var listening = false + private var micCameraIndicatorsEnabled = false + private var locationIndicatorsEnabled = false + private var privacyChipLogged = false + private val cameraSlot = privacyChip.resources.getString(R.string.status_bar_camera) + private val micSlot = privacyChip.resources.getString(R.string.status_bar_microphone) + private val locationSlot = privacyChip.resources.getString(R.string.status_bar_location) + + private val picCallback: PrivacyItemController.Callback = + object : PrivacyItemController.Callback { + override fun onPrivacyItemsChanged(privacyItems: List<PrivacyItem>) { + privacyChip.privacyList = privacyItems + setChipVisibility(privacyItems.isNotEmpty()) + } + + override fun onFlagMicCameraChanged(flag: Boolean) { + if (micCameraIndicatorsEnabled != flag) { + micCameraIndicatorsEnabled = flag + update() + } + } + + override fun onFlagLocationChanged(flag: Boolean) { + if (locationIndicatorsEnabled != flag) { + locationIndicatorsEnabled = flag + update() + } + } + + private fun update() { + updatePrivacyIconSlots() + setChipVisibility(privacyChip.privacyList.isNotEmpty()) + } + } + + private fun getChipEnabled() = micCameraIndicatorsEnabled || locationIndicatorsEnabled + + fun onParentVisible() { + privacyChip.setOnClickListener { + // If the privacy chip is visible, it means there were some indicators + uiEventLogger.log(PrivacyChipEvent.ONGOING_INDICATORS_CHIP_CLICK) + privacyDialogController.showDialog(privacyChip.context) + } + setChipVisibility(privacyChip.visibility == View.VISIBLE) + micCameraIndicatorsEnabled = privacyItemController.micCameraAvailable + locationIndicatorsEnabled = privacyItemController.locationAvailable + + // Ignore privacy icons because they show in the space above QQS + updatePrivacyIconSlots() + } + + fun onParentInvisible() { + chipVisibilityListener = null + privacyChip.setOnClickListener(null) + } + + fun startListening() { + listening = true + // Get the most up to date info + micCameraIndicatorsEnabled = privacyItemController.micCameraAvailable + locationIndicatorsEnabled = privacyItemController.locationAvailable + privacyItemController.addCallback(picCallback) + } + + fun stopListening() { + listening = false + privacyItemController.removeCallback(picCallback) + privacyChipLogged = false + } + + private fun setChipVisibility(visible: Boolean) { + if (visible && getChipEnabled()) { + privacyLogger.logChipVisible(true) + // Makes sure that the chip is logged as viewed at most once each time QS is opened + // mListening makes sure that the callback didn't return after the user closed QS + if (!privacyChipLogged && listening) { + privacyChipLogged = true + uiEventLogger.log(PrivacyChipEvent.ONGOING_INDICATORS_CHIP_VIEW) + } + } else { + privacyLogger.logChipVisible(false) + } + + privacyChip.visibility = if (visible) View.VISIBLE else View.GONE + chipVisibilityListener?.onChipVisibilityRefreshed(visible) + } + + private fun updatePrivacyIconSlots() { + if (getChipEnabled()) { + if (micCameraIndicatorsEnabled) { + iconContainer.addIgnoredSlot(cameraSlot) + iconContainer.addIgnoredSlot(micSlot) + } else { + iconContainer.removeIgnoredSlot(cameraSlot) + iconContainer.removeIgnoredSlot(micSlot) + } + if (locationIndicatorsEnabled) { + iconContainer.addIgnoredSlot(locationSlot) + } else { + iconContainer.removeIgnoredSlot(locationSlot) + } + } else { + iconContainer.removeIgnoredSlot(cameraSlot) + iconContainer.removeIgnoredSlot(micSlot) + iconContainer.removeIgnoredSlot(locationSlot) + } + } +}
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java index e42c47b1d3be..ee59ae6ab6d7 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java @@ -770,6 +770,8 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca public void onAnimationEnd(Animator animation) { mHeaderAnimating = false; updateQsState(); + // Unset the listener, otherwise this may persist for another view property animation + getView().animate().setListener(null); } }; diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java index a923effea1e1..3bf8bee881d1 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java @@ -373,7 +373,6 @@ public class QuickStatusBarHeader extends FrameLayout { } void setChipVisibility(boolean visibility) { - mPrivacyChip.setVisibility(visibility ? View.VISIBLE : View.GONE); if (visibility) { // Animates the icons and battery indicator from alpha 0 to 1, when the chip is visible mIconsAlphaAnimator = mIconsAlphaAnimatorFixed; diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java index 3a80764d4c25..2dc4ee4e0064 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java @@ -17,26 +17,14 @@ package com.android.systemui.qs; import android.os.Bundle; -import android.view.View; -import android.view.View.OnClickListener; - -import androidx.annotation.NonNull; import com.android.internal.colorextraction.ColorExtractor; -import com.android.internal.logging.UiEventLogger; import com.android.systemui.R; import com.android.systemui.battery.BatteryMeterViewController; import com.android.systemui.colorextraction.SysuiColorExtractor; import com.android.systemui.demomode.DemoMode; import com.android.systemui.demomode.DemoModeController; import com.android.systemui.flags.FeatureFlags; -import com.android.systemui.plugins.ActivityStarter; -import com.android.systemui.privacy.OngoingPrivacyChip; -import com.android.systemui.privacy.PrivacyChipEvent; -import com.android.systemui.privacy.PrivacyDialogController; -import com.android.systemui.privacy.PrivacyItem; -import com.android.systemui.privacy.PrivacyItemController; -import com.android.systemui.privacy.logging.PrivacyLogger; import com.android.systemui.qs.carrier.QSCarrierGroupController; import com.android.systemui.qs.dagger.QSScope; import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider; @@ -54,23 +42,17 @@ import javax.inject.Inject; * Controller for {@link QuickStatusBarHeader}. */ @QSScope -class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader> { - private static final String TAG = "QuickStatusBarHeader"; +class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader> implements + ChipVisibilityListener { - private final PrivacyItemController mPrivacyItemController; - private final ActivityStarter mActivityStarter; - private final UiEventLogger mUiEventLogger; private final QSCarrierGroupController mQSCarrierGroupController; private final QuickQSPanelController mQuickQSPanelController; - private final OngoingPrivacyChip mPrivacyChip; private final Clock mClockView; private final StatusBarIconController mStatusBarIconController; private final DemoModeController mDemoModeController; private final StatusIconContainer mIconContainer; private final StatusBarIconController.TintedIconManager mIconManager; private final DemoMode mDemoModeReceiver; - private final PrivacyLogger mPrivacyLogger; - private final PrivacyDialogController mPrivacyDialogController; private final QSExpansionPathInterpolator mQSExpansionPathInterpolator; private final BatteryMeterViewController mBatteryMeterViewController; private final FeatureFlags mFeatureFlags; @@ -78,83 +60,31 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader private final VariableDateViewController mVariableDateViewControllerDateView; private final VariableDateViewController mVariableDateViewControllerClockDateView; + private final HeaderPrivacyIconsController mPrivacyIconsController; private boolean mListening; - private boolean mMicCameraIndicatorsEnabled; - private boolean mLocationIndicatorsEnabled; - private boolean mPrivacyChipLogged; - private final String mCameraSlot; - private final String mMicSlot; - private final String mLocationSlot; private SysuiColorExtractor mColorExtractor; private ColorExtractor.OnColorsChangedListener mOnColorsChangedListener; - private PrivacyItemController.Callback mPICCallback = new PrivacyItemController.Callback() { - @Override - public void onPrivacyItemsChanged(@NonNull List<PrivacyItem> privacyItems) { - mPrivacyChip.setPrivacyList(privacyItems); - setChipVisibility(!privacyItems.isEmpty()); - } - - @Override - public void onFlagMicCameraChanged(boolean flag) { - if (mMicCameraIndicatorsEnabled != flag) { - mMicCameraIndicatorsEnabled = flag; - update(); - } - } - - @Override - public void onFlagLocationChanged(boolean flag) { - if (mLocationIndicatorsEnabled != flag) { - mLocationIndicatorsEnabled = flag; - update(); - } - } - - private void update() { - updatePrivacyIconSlots(); - setChipVisibility(!mPrivacyChip.getPrivacyList().isEmpty()); - } - }; - - private View.OnClickListener mOnClickListener = new OnClickListener() { - @Override - public void onClick(View v) { - if (v == mPrivacyChip) { - // If the privacy chip is visible, it means there were some indicators - mUiEventLogger.log(PrivacyChipEvent.ONGOING_INDICATORS_CHIP_CLICK); - mPrivacyDialogController.showDialog(getContext()); - } - } - }; - @Inject QuickStatusBarHeaderController(QuickStatusBarHeader view, - PrivacyItemController privacyItemController, - ActivityStarter activityStarter, UiEventLogger uiEventLogger, + HeaderPrivacyIconsController headerPrivacyIconsController, StatusBarIconController statusBarIconController, DemoModeController demoModeController, QuickQSPanelController quickQSPanelController, QSCarrierGroupController.Builder qsCarrierGroupControllerBuilder, - PrivacyLogger privacyLogger, SysuiColorExtractor colorExtractor, - PrivacyDialogController privacyDialogController, QSExpansionPathInterpolator qsExpansionPathInterpolator, BatteryMeterViewController batteryMeterViewController, FeatureFlags featureFlags, VariableDateViewController.Factory variableDateViewControllerFactory, StatusBarContentInsetsProvider statusBarContentInsetsProvider) { super(view); - mPrivacyItemController = privacyItemController; - mActivityStarter = activityStarter; - mUiEventLogger = uiEventLogger; + mPrivacyIconsController = headerPrivacyIconsController; mStatusBarIconController = statusBarIconController; mDemoModeController = demoModeController; mQuickQSPanelController = quickQSPanelController; - mPrivacyLogger = privacyLogger; - mPrivacyDialogController = privacyDialogController; mQSExpansionPathInterpolator = qsExpansionPathInterpolator; mBatteryMeterViewController = batteryMeterViewController; mFeatureFlags = featureFlags; @@ -163,8 +93,6 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader mQSCarrierGroupController = qsCarrierGroupControllerBuilder .setQSCarrierGroup(mView.findViewById(R.id.carrier_group)) .build(); - - mPrivacyChip = mView.findViewById(R.id.privacy_chip); mClockView = mView.findViewById(R.id.clock); mIconContainer = mView.findViewById(R.id.statusIcons); mVariableDateViewControllerDateView = variableDateViewControllerFactory.create( @@ -183,10 +111,6 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader }; mColorExtractor.addOnColorsChangedListener(mOnColorsChangedListener); - mCameraSlot = getResources().getString(com.android.internal.R.string.status_bar_camera); - mMicSlot = getResources().getString(com.android.internal.R.string.status_bar_microphone); - mLocationSlot = getResources().getString(com.android.internal.R.string.status_bar_location); - // Don't need to worry about tuner settings for this icon mBatteryMeterViewController.ignoreTunerUpdates(); } @@ -198,20 +122,13 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader @Override protected void onViewAttached() { - mPrivacyChip.setOnClickListener(mOnClickListener); - - mMicCameraIndicatorsEnabled = mPrivacyItemController.getMicCameraAvailable(); - mLocationIndicatorsEnabled = mPrivacyItemController.getLocationAvailable(); - - // Ignore privacy icons because they show in the space above QQS - updatePrivacyIconSlots(); + mPrivacyIconsController.onParentVisible(); + mPrivacyIconsController.setChipVisibilityListener(this); mIconContainer.addIgnoredSlot( getResources().getString(com.android.internal.R.string.status_bar_managed_profile)); mIconContainer.setShouldRestrictIcons(false); mStatusBarIconController.addIconGroup(mIconManager); - setChipVisibility(mPrivacyChip.getVisibility() == View.VISIBLE); - mView.setIsSingleCarrier(mQSCarrierGroupController.isSingleCarrier()); mQSCarrierGroupController .setOnSingleCarrierChangedListener(mView::setIsSingleCarrier); @@ -241,7 +158,7 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader @Override protected void onViewDetached() { mColorExtractor.removeOnColorsChangedListener(mOnColorsChangedListener); - mPrivacyChip.setOnClickListener(null); + mPrivacyIconsController.onParentInvisible(); mStatusBarIconController.removeIconGroup(mIconManager); mQSCarrierGroupController.setOnSingleCarrierChangedListener(null); mDemoModeController.removeCallback(mDemoModeReceiver); @@ -266,54 +183,15 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader } if (listening) { - // Get the most up to date info - mMicCameraIndicatorsEnabled = mPrivacyItemController.getMicCameraAvailable(); - mLocationIndicatorsEnabled = mPrivacyItemController.getLocationAvailable(); - mPrivacyItemController.addCallback(mPICCallback); - } else { - mPrivacyItemController.removeCallback(mPICCallback); - mPrivacyChipLogged = false; - } - } - - private void setChipVisibility(boolean chipVisible) { - if (chipVisible && getChipEnabled()) { - mPrivacyLogger.logChipVisible(true); - // Makes sure that the chip is logged as viewed at most once each time QS is opened - // mListening makes sure that the callback didn't return after the user closed QS - if (!mPrivacyChipLogged && mListening) { - mPrivacyChipLogged = true; - mUiEventLogger.log(PrivacyChipEvent.ONGOING_INDICATORS_CHIP_VIEW); - } + mPrivacyIconsController.startListening(); } else { - mPrivacyLogger.logChipVisible(false); + mPrivacyIconsController.stopListening(); } - mView.setChipVisibility(chipVisible); } - private void updatePrivacyIconSlots() { - if (getChipEnabled()) { - if (mMicCameraIndicatorsEnabled) { - mIconContainer.addIgnoredSlot(mCameraSlot); - mIconContainer.addIgnoredSlot(mMicSlot); - } else { - mIconContainer.removeIgnoredSlot(mCameraSlot); - mIconContainer.removeIgnoredSlot(mMicSlot); - } - if (mLocationIndicatorsEnabled) { - mIconContainer.addIgnoredSlot(mLocationSlot); - } else { - mIconContainer.removeIgnoredSlot(mLocationSlot); - } - } else { - mIconContainer.removeIgnoredSlot(mCameraSlot); - mIconContainer.removeIgnoredSlot(mMicSlot); - mIconContainer.removeIgnoredSlot(mLocationSlot); - } - } - - private boolean getChipEnabled() { - return mMicCameraIndicatorsEnabled || mLocationIndicatorsEnabled; + @Override + public void onChipVisibilityRefreshed(boolean visible) { + mView.setChipVisibility(visible); } public void setContentMargins(int marginStart, int marginEnd) { diff --git a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java index b11420afa529..11e5b6e8934e 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java +++ b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java @@ -26,6 +26,7 @@ import com.android.systemui.R; import com.android.systemui.battery.BatteryMeterView; import com.android.systemui.dagger.qualifiers.RootView; import com.android.systemui.plugins.qs.QS; +import com.android.systemui.privacy.OngoingPrivacyChip; import com.android.systemui.qs.FooterActionsController; import com.android.systemui.qs.FooterActionsController.ExpansionState; import com.android.systemui.qs.FooterActionsControllerBuilder; @@ -39,6 +40,7 @@ import com.android.systemui.qs.QSPanel; import com.android.systemui.qs.QuickQSPanel; import com.android.systemui.qs.QuickStatusBarHeader; import com.android.systemui.qs.customize.QSCustomizer; +import com.android.systemui.statusbar.phone.StatusIconContainer; import javax.inject.Named; @@ -189,4 +191,18 @@ public interface QSFragmentModule { static boolean providesQSUsingMediaPlayer(Context context) { return useQsMediaPlayer(context); } + + /** */ + @Provides + @QSScope + static OngoingPrivacyChip providesPrivacyChip(QuickStatusBarHeader qsHeader) { + return qsHeader.findViewById(R.id.privacy_chip); + } + + /** */ + @Provides + @QSScope + static StatusIconContainer providesStatusIconContainer(QuickStatusBarHeader qsHeader) { + return qsHeader.findViewById(R.id.statusIcons); + } }
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java index 0427e38aa811..b83dc52240b3 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java @@ -31,7 +31,6 @@ import android.util.Log; import android.view.View; import android.view.View.OnAttachStateChangeListener; import android.view.ViewGroup; -import android.view.WindowManager.LayoutParams; import android.widget.Button; import androidx.annotation.Nullable; @@ -40,6 +39,7 @@ import com.android.internal.app.MediaRouteDialogPresenter; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.systemui.R; +import com.android.systemui.animation.DialogLaunchAnimator; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.plugins.ActivityStarter; @@ -76,6 +76,7 @@ public class CastTile extends QSTileImpl<BooleanState> { private final CastDetailAdapter mDetailAdapter; private final KeyguardStateController mKeyguard; private final NetworkController mNetworkController; + private final DialogLaunchAnimator mDialogLaunchAnimator; private final Callback mCallback = new Callback(); private Dialog mDialog; private boolean mWifiConnected; @@ -94,7 +95,8 @@ public class CastTile extends QSTileImpl<BooleanState> { CastController castController, KeyguardStateController keyguardStateController, NetworkController networkController, - HotspotController hotspotController + HotspotController hotspotController, + DialogLaunchAnimator dialogLaunchAnimator ) { super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger, statusBarStateController, activityStarter, qsLogger); @@ -102,6 +104,7 @@ public class CastTile extends QSTileImpl<BooleanState> { mDetailAdapter = new CastDetailAdapter(); mKeyguard = keyguardStateController; mNetworkController = networkController; + mDialogLaunchAnimator = dialogLaunchAnimator; mController.observe(this, mCallback); mKeyguard.observe(this, mCallback); mNetworkController.observe(this, mSignalCallback); @@ -153,9 +156,15 @@ public class CastTile extends QSTileImpl<BooleanState> { List<CastDevice> activeDevices = getActiveDevices(); if (willPopDetail()) { - mActivityStarter.postQSRunnableDismissingKeyguard(() -> { - showDetail(true); - }); + if (!mKeyguard.isShowing()) { + showDetail(view); + } else { + mActivityStarter.postQSRunnableDismissingKeyguard(() -> { + // Dismissing the keyguard will collapse the shade, so we don't animate from the + // view here as it would not look good. + showDetail(null /* view */); + }); + } } else { mController.stopCasting(activeDevices.get(0)); } @@ -184,19 +193,29 @@ public class CastTile extends QSTileImpl<BooleanState> { @Override public void showDetail(boolean show) { + showDetail(null /* view */); + } + + private void showDetail(@Nullable View view) { mUiHandler.post(() -> { mDialog = MediaRouteDialogPresenter.createDialog(mContext, ROUTE_TYPE_REMOTE_DISPLAY, v -> { + mDialogLaunchAnimator.disableAllCurrentDialogsExitAnimations(); mDialog.dismiss(); mActivityStarter .postStartActivityDismissingKeyguard(getLongClickIntent(), 0); }); - mDialog.getWindow().setType(LayoutParams.TYPE_KEYGUARD_DIALOG); SystemUIDialog.setShowForAllUsers(mDialog, true); SystemUIDialog.registerDismissListener(mDialog); SystemUIDialog.setWindowOnTop(mDialog); - mUiHandler.post(() -> mDialog.show()); - mHost.collapsePanels(); + + mUiHandler.post(() -> { + if (view != null) { + mDialogLaunchAnimator.showFromView(mDialog, view); + } else { + mDialog.show(); + } + }); }); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java index 3163c5f5a3c9..20805a141312 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java @@ -190,14 +190,10 @@ public class DndTile extends QSTileImpl<BooleanState> { case Settings.Secure.ZEN_DURATION_PROMPT: mUiHandler.post(() -> { Dialog dialog = makeZenModeDialog(); + SystemUIDialog.registerDismissListener(dialog); if (view != null) { - final Dialog hostDialog = - mDialogLaunchAnimator.showFromView(dialog, view, false); - setDialogListeners(dialog, hostDialog); + mDialogLaunchAnimator.showFromView(dialog, view, false); } else { - // If we are not launching with animator, register default - // dismiss listener - SystemUIDialog.registerDismissListener(dialog); dialog.show(); } }); @@ -222,12 +218,6 @@ public class DndTile extends QSTileImpl<BooleanState> { return dialog; } - private void setDialogListeners(Dialog zenModeDialog, Dialog hostDialog) { - // Zen mode dialog is never hidden. - SystemUIDialog.registerDismissListener(zenModeDialog, hostDialog::dismiss); - zenModeDialog.setOnCancelListener(dialog -> hostDialog.cancel()); - } - @Override protected void handleSecondaryClick(@Nullable View view) { if (mController.isVolumeRestricted()) { diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java index 883552a1f7c3..26c89ff83076 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java @@ -120,16 +120,19 @@ public class InternetDialog extends SystemUIDialog implements private ImageView mSignalIcon; private TextView mMobileTitleText; private TextView mMobileSummaryText; + private TextView mAirplaneModeSummaryText; private Switch mMobileDataToggle; private View mMobileToggleDivider; private Switch mWiFiToggle; private FrameLayout mDoneLayout; + private FrameLayout mAirplaneModeLayout; private Drawable mBackgroundOn; private Drawable mBackgroundOff = null; private int mDefaultDataSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; private boolean mCanConfigMobileData; // Wi-Fi entries + private int mWifiNetworkHeight; @VisibleForTesting protected WifiEntry mConnectedWifiEntry; @VisibleForTesting @@ -187,6 +190,9 @@ public class InternetDialog extends SystemUIDialog implements window.setWindowAnimations(R.style.Animation_InternetDialog); + mWifiNetworkHeight = mContext.getResources() + .getDimensionPixelSize(R.dimen.internet_dialog_wifi_network_height); + mInternetDialogLayout = mDialogView.requireViewById(R.id.internet_connectivity_dialog); mInternetDialogTitle = mDialogView.requireViewById(R.id.internet_dialog_title); mInternetDialogSubTitle = mDialogView.requireViewById(R.id.internet_dialog_subtitle); @@ -206,9 +212,11 @@ public class InternetDialog extends SystemUIDialog implements mWifiRecyclerView = mDialogView.requireViewById(R.id.wifi_list_layout); mSeeAllLayout = mDialogView.requireViewById(R.id.see_all_layout); mDoneLayout = mDialogView.requireViewById(R.id.done_layout); + mAirplaneModeLayout = mDialogView.requireViewById(R.id.apm_layout); mSignalIcon = mDialogView.requireViewById(R.id.signal_icon); mMobileTitleText = mDialogView.requireViewById(R.id.mobile_title); mMobileSummaryText = mDialogView.requireViewById(R.id.mobile_summary); + mAirplaneModeSummaryText = mDialogView.requireViewById(R.id.airplane_mode_summary); mMobileToggleDivider = mDialogView.requireViewById(R.id.mobile_toggle_divider); mMobileDataToggle = mDialogView.requireViewById(R.id.mobile_toggle); mWiFiToggle = mDialogView.requireViewById(R.id.wifi_toggle); @@ -226,6 +234,8 @@ public class InternetDialog extends SystemUIDialog implements setOnClickListener(); mTurnWifiOnLayout.setBackground(null); + mAirplaneModeLayout.setVisibility( + mInternetDialogController.isAirplaneModeEnabled() ? View.VISIBLE : View.GONE); mWifiRecyclerView.setLayoutManager(new LinearLayoutManager(mContext)); mWifiRecyclerView.setAdapter(mAdapter); } @@ -265,6 +275,7 @@ public class InternetDialog extends SystemUIDialog implements mSeeAllLayout.setOnClickListener(null); mWiFiToggle.setOnCheckedChangeListener(null); mDoneLayout.setOnClickListener(null); + mAirplaneModeLayout.setOnClickListener(null); mInternetDialogController.onStop(); mInternetDialogFactory.destroyDialog(); } @@ -290,13 +301,17 @@ public class InternetDialog extends SystemUIDialog implements } if (mInternetDialogController.isAirplaneModeEnabled()) { mInternetDialogSubTitle.setVisibility(View.GONE); + mAirplaneModeLayout.setVisibility(View.VISIBLE); } else { + mInternetDialogTitle.setText(getDialogTitleText()); + mInternetDialogSubTitle.setVisibility(View.VISIBLE); mInternetDialogSubTitle.setText(getSubtitleText()); + mAirplaneModeLayout.setVisibility(View.GONE); } updateEthernet(); if (shouldUpdateMobileNetwork) { - setMobileDataLayout(mInternetDialogController.activeNetworkIsCellular() - || mInternetDialogController.isCarrierNetworkActive()); + setMobileDataLayout(mInternetDialogController.activeNetworkIsCellular(), + mInternetDialogController.isCarrierNetworkActive()); } if (!mCanConfigWifi) { @@ -335,13 +350,13 @@ public class InternetDialog extends SystemUIDialog implements mSeeAllLayout.setOnClickListener(v -> onClickSeeMoreButton()); mWiFiToggle.setOnCheckedChangeListener( (buttonView, isChecked) -> { - if (isChecked) { - mWifiScanNotifyLayout.setVisibility(View.GONE); - } buttonView.setChecked(isChecked); mWifiManager.setWifiEnabled(isChecked); }); mDoneLayout.setOnClickListener(v -> dismiss()); + mAirplaneModeLayout.setOnClickListener(v -> { + mInternetDialogController.setAirplaneModeDisabled(); + }); } @MainThread @@ -350,46 +365,66 @@ public class InternetDialog extends SystemUIDialog implements mInternetDialogController.hasEthernet() ? View.VISIBLE : View.GONE); } - private void setMobileDataLayout(boolean isCarrierNetworkConnected) { - if (mInternetDialogController.isAirplaneModeEnabled() - || !mInternetDialogController.hasCarrier()) { + private void setMobileDataLayout(boolean activeNetworkIsCellular, + boolean isCarrierNetworkActive) { + boolean isNetworkConnected = activeNetworkIsCellular || isCarrierNetworkActive; + // 1. Mobile network should be gone if airplane mode ON or the list of active + // subscriptionId is null. + // 2. Carrier network should be gone if airplane mode ON and Wi-Fi is OFF. + if (DEBUG) { + Log.d(TAG, "setMobileDataLayout, isCarrierNetworkActive = " + isCarrierNetworkActive); + } + + if (!mInternetDialogController.hasActiveSubId() + && (!mWifiManager.isWifiEnabled() || !isCarrierNetworkActive)) { mMobileNetworkLayout.setVisibility(View.GONE); } else { - mMobileDataToggle.setChecked(mInternetDialogController.isMobileDataEnabled()); mMobileNetworkLayout.setVisibility(View.VISIBLE); + mMobileDataToggle.setChecked(mInternetDialogController.isMobileDataEnabled()); mMobileTitleText.setText(getMobileNetworkTitle()); - if (!TextUtils.isEmpty(getMobileNetworkSummary())) { + String summary = getMobileNetworkSummary(); + if (!TextUtils.isEmpty(summary)) { mMobileSummaryText.setText( - Html.fromHtml(getMobileNetworkSummary(), Html.FROM_HTML_MODE_LEGACY)); + Html.fromHtml(summary, Html.FROM_HTML_MODE_LEGACY)); mMobileSummaryText.setVisibility(View.VISIBLE); } else { mMobileSummaryText.setVisibility(View.GONE); } - mBackgroundExecutor.execute(() -> { Drawable drawable = getSignalStrengthDrawable(); mHandler.post(() -> { mSignalIcon.setImageDrawable(drawable); }); }); - mMobileTitleText.setTextAppearance(isCarrierNetworkConnected + mMobileTitleText.setTextAppearance(isNetworkConnected ? R.style.TextAppearance_InternetDialog_Active : R.style.TextAppearance_InternetDialog); - mMobileSummaryText.setTextAppearance(isCarrierNetworkConnected + int secondaryRes = isNetworkConnected ? R.style.TextAppearance_InternetDialog_Secondary_Active - : R.style.TextAppearance_InternetDialog_Secondary); + : R.style.TextAppearance_InternetDialog_Secondary; + mMobileSummaryText.setTextAppearance(secondaryRes); + // Set airplane mode to the summary for carrier network + if (mInternetDialogController.isAirplaneModeEnabled()) { + mAirplaneModeSummaryText.setVisibility(View.VISIBLE); + mAirplaneModeSummaryText.setText(mContext.getText(R.string.airplane_mode)); + mAirplaneModeSummaryText.setTextAppearance(secondaryRes); + } else { + mAirplaneModeSummaryText.setVisibility(View.GONE); + } mMobileNetworkLayout.setBackground( - isCarrierNetworkConnected ? mBackgroundOn : mBackgroundOff); + isNetworkConnected ? mBackgroundOn : mBackgroundOff); TypedArray array = mContext.obtainStyledAttributes( R.style.InternetDialog_Divider_Active, new int[]{android.R.attr.background}); int dividerColor = Utils.getColorAttrDefaultColor(mContext, android.R.attr.textColorSecondary); - mMobileToggleDivider.setBackgroundColor(isCarrierNetworkConnected + mMobileToggleDivider.setBackgroundColor(isNetworkConnected ? array.getColor(0, dividerColor) : dividerColor); array.recycle(); mMobileDataToggle.setVisibility(mCanConfigMobileData ? View.VISIBLE : View.INVISIBLE); + mMobileToggleDivider.setVisibility( + mCanConfigMobileData ? View.VISIBLE : View.INVISIBLE); } } @@ -427,9 +462,26 @@ public class InternetDialog extends SystemUIDialog implements mSeeAllLayout.setVisibility(View.GONE); return; } - mWifiRecyclerView.setVisibility(mWifiEntriesCount > 0 ? View.VISIBLE : View.GONE); - mSeeAllLayout.setVisibility( - (mConnectedWifiEntry != null || mWifiEntriesCount > 0) ? View.VISIBLE : View.GONE); + mWifiRecyclerView.setMinimumHeight(mWifiNetworkHeight * getWifiListMaxCount()); + mWifiRecyclerView.setVisibility(View.VISIBLE); + final boolean showSeeAll = mConnectedWifiEntry != null || mWifiEntriesCount > 0; + mSeeAllLayout.setVisibility(showSeeAll ? View.VISIBLE : View.INVISIBLE); + } + + @VisibleForTesting + @MainThread + int getWifiListMaxCount() { + int count = InternetDialogController.MAX_WIFI_ENTRY_COUNT; + if (mEthernetLayout.getVisibility() == View.VISIBLE) { + count -= 1; + } + if (mMobileNetworkLayout.getVisibility() == View.VISIBLE) { + count -= 1; + } + if (mConnectedWifListLayout.getVisibility() == View.VISIBLE) { + count -= 1; + } + return count; } @MainThread @@ -600,10 +652,13 @@ public class InternetDialog extends SystemUIDialog implements @WorkerThread public void onAccessPointsChanged(@Nullable List<WifiEntry> wifiEntries, @Nullable WifiEntry connectedEntry) { + // Should update the carrier network layout when it is connected under airplane mode ON. + boolean shouldUpdateCarrierNetwork = mMobileNetworkLayout.getVisibility() == View.VISIBLE + && mInternetDialogController.isAirplaneModeEnabled(); mHandler.post(() -> { mConnectedWifiEntry = connectedEntry; mWifiEntriesCount = wifiEntries == null ? 0 : wifiEntries.size(); - updateDialog(false /* shouldUpdateMobileNetwork */); + updateDialog(shouldUpdateCarrierNetwork /* shouldUpdateMobileNetwork */); mAdapter.setWifiEntries(wifiEntries, mWifiEntriesCount); mAdapter.notifyDataSetChanged(); }); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java index 2a7d2c35e82f..706f4230bf9f 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java @@ -281,6 +281,10 @@ public class InternetDialogController implements WifiEntry.DisconnectCallback, return mGlobalSettings.getInt(Settings.Global.AIRPLANE_MODE_ON, 0) != 0; } + void setAirplaneModeDisabled() { + mConnectivityManager.setAirplaneMode(false); + } + @VisibleForTesting protected int getDefaultDataSubscriptionId() { return mSubscriptionManager.getDefaultDataSubscriptionId(); @@ -352,7 +356,7 @@ public class InternetDialogController implements WifiEntry.DisconnectCallback, if (DEBUG) { Log.d(TAG, "No Wi-Fi item."); } - if (!hasCarrier() || (!isVoiceStateInService() && !isDataStateInService())) { + if (!hasActiveSubId() || (!isVoiceStateInService() && !isDataStateInService())) { if (DEBUG) { Log.d(TAG, "No carrier or service is out of service."); } @@ -403,15 +407,16 @@ public class InternetDialogController implements WifiEntry.DisconnectCallback, return drawable; } - if (isDataStateInService() || isVoiceStateInService()) { + boolean isCarrierNetworkActive = isCarrierNetworkActive(); + if (isDataStateInService() || isVoiceStateInService() || isCarrierNetworkActive) { AtomicReference<Drawable> shared = new AtomicReference<>(); - shared.set(getSignalStrengthDrawableWithLevel()); + shared.set(getSignalStrengthDrawableWithLevel(isCarrierNetworkActive)); drawable = shared.get(); } int tintColor = Utils.getColorAttrDefaultColor(mContext, android.R.attr.textColorTertiary); - if (activeNetworkIsCellular() || isCarrierNetworkActive()) { + if (activeNetworkIsCellular() || isCarrierNetworkActive) { tintColor = mContext.getColor(R.color.connected_network_primary_color); } drawable.setTint(tintColor); @@ -426,12 +431,15 @@ public class InternetDialogController implements WifiEntry.DisconnectCallback, * * @return The Drawable which is a signal bar icon with level. */ - Drawable getSignalStrengthDrawableWithLevel() { + Drawable getSignalStrengthDrawableWithLevel(boolean isCarrierNetworkActive) { final SignalStrength strength = mTelephonyManager.getSignalStrength(); int level = (strength == null) ? 0 : strength.getLevel(); int numLevels = SignalStrength.NUM_SIGNAL_STRENGTH_BINS; - if (mSubscriptionManager != null && shouldInflateSignalStrength(mDefaultDataSubId)) { - level += 1; + if ((mSubscriptionManager != null && shouldInflateSignalStrength(mDefaultDataSubId)) + || isCarrierNetworkActive) { + level = isCarrierNetworkActive + ? SignalStrength.NUM_SIGNAL_STRENGTH_BINS + : (level + 1); numLevels += 1; } return getSignalStrengthIcon(mContext, level, numLevels, NO_CELL_DATA_TYPE_ICON, @@ -586,15 +594,18 @@ public class InternetDialogController implements WifiEntry.DisconnectCallback, if (!isMobileDataEnabled()) { return context.getString(R.string.mobile_data_off_summary); } - if (!isDataStateInService()) { - return context.getString(R.string.mobile_data_no_connection); - } + String summary = networkTypeDescription; + // Set network description for the carrier network when connecting to the carrier network + // under the airplane mode ON. if (activeNetworkIsCellular() || isCarrierNetworkActive()) { summary = context.getString(R.string.preference_summary_default_combination, context.getString(R.string.mobile_data_connection_active), networkTypeDescription); + } else if (!isDataStateInService()) { + summary = context.getString(R.string.mobile_data_no_connection); } + return summary; } @@ -678,7 +689,7 @@ public class InternetDialogController implements WifiEntry.DisconnectCallback, /** * @return whether there is the carrier item in the slice. */ - boolean hasCarrier() { + boolean hasActiveSubId() { if (mSubscriptionManager == null) { if (DEBUG) { Log.d(TAG, "SubscriptionManager is null, can not check carrier."); @@ -888,7 +899,7 @@ public class InternetDialogController implements WifiEntry.DisconnectCallback, if (mHasEthernet) { count -= 1; } - if (hasCarrier()) { + if (hasActiveSubId()) { count -= 1; } if (hasConnectedWifi) { diff --git a/packages/SystemUI/src/com/android/systemui/qs/user/UserSwitchDialogController.kt b/packages/SystemUI/src/com/android/systemui/qs/user/UserSwitchDialogController.kt index 00e04540fd94..7c8f4b15d3a3 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/user/UserSwitchDialogController.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/user/UserSwitchDialogController.kt @@ -94,24 +94,24 @@ class UserSwitchDialogController @VisibleForTesting constructor( adapter.linkToViewGroup(gridFrame.findViewById(R.id.grid)) - val hostDialog = dialogLaunchAnimator.showFromView(this, view) - adapter.injectDialogShower(DialogShowerImpl(hostDialog, dialogLaunchAnimator)) + dialogLaunchAnimator.showFromView(this, view) + adapter.injectDialogShower(DialogShowerImpl(this, dialogLaunchAnimator)) } } private class DialogShowerImpl( - private val hostDialog: Dialog, + private val animateFrom: Dialog, private val dialogLaunchAnimator: DialogLaunchAnimator - ) : DialogInterface by hostDialog, DialogShower { - override fun showDialog(dialog: Dialog): Dialog { - return dialogLaunchAnimator.showFromDialog( + ) : DialogInterface by animateFrom, DialogShower { + override fun showDialog(dialog: Dialog) { + dialogLaunchAnimator.showFromDialog( dialog, - parentHostDialog = hostDialog + animateFrom = animateFrom ) } } interface DialogShower : DialogInterface { - fun showDialog(dialog: Dialog): Dialog + fun showDialog(dialog: Dialog) } }
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java b/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java index 5bb3413595ba..d64c05fadeb8 100644 --- a/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java +++ b/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java @@ -32,7 +32,6 @@ import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import android.os.UserHandle; -import android.provider.Settings; import android.util.Log; import android.widget.Toast; @@ -62,7 +61,6 @@ public class RecordingService extends Service implements MediaRecorder.OnInfoLis private static final String EXTRA_RESULT_CODE = "extra_resultCode"; private static final String EXTRA_PATH = "extra_path"; private static final String EXTRA_AUDIO_SOURCE = "extra_useAudio"; - private static final String EXTRA_SHOW_TAPS = "extra_showTaps"; private static final String ACTION_START = "com.android.systemui.screenrecord.START"; private static final String ACTION_STOP = "com.android.systemui.screenrecord.STOP"; @@ -74,8 +72,6 @@ public class RecordingService extends Service implements MediaRecorder.OnInfoLis private final RecordingController mController; private final KeyguardDismissUtil mKeyguardDismissUtil; private ScreenRecordingAudioSource mAudioSource; - private boolean mShowTaps; - private boolean mOriginalShowTaps; private ScreenMediaRecorder mRecorder; private final Executor mLongExecutor; private final UiEventLogger mUiEventLogger; @@ -102,15 +98,12 @@ public class RecordingService extends Service implements MediaRecorder.OnInfoLis * android.content.Intent)} * @param audioSource The ordinal value of the audio source * {@link com.android.systemui.screenrecord.ScreenRecordingAudioSource} - * @param showTaps True to make touches visible while recording */ - public static Intent getStartIntent(Context context, int resultCode, - int audioSource, boolean showTaps) { + public static Intent getStartIntent(Context context, int resultCode, int audioSource) { return new Intent(context, RecordingService.class) .setAction(ACTION_START) .putExtra(EXTRA_RESULT_CODE, resultCode) - .putExtra(EXTRA_AUDIO_SOURCE, audioSource) - .putExtra(EXTRA_SHOW_TAPS, showTaps); + .putExtra(EXTRA_AUDIO_SOURCE, audioSource); } @Override @@ -128,13 +121,6 @@ public class RecordingService extends Service implements MediaRecorder.OnInfoLis mAudioSource = ScreenRecordingAudioSource .values()[intent.getIntExtra(EXTRA_AUDIO_SOURCE, 0)]; Log.d(TAG, "recording with audio source" + mAudioSource); - mShowTaps = intent.getBooleanExtra(EXTRA_SHOW_TAPS, false); - - mOriginalShowTaps = Settings.System.getInt( - getApplicationContext().getContentResolver(), - Settings.System.SHOW_TOUCHES, 0) != 0; - - setTapsVisible(mShowTaps); mRecorder = new ScreenMediaRecorder( mUserContextTracker.getUserContext(), @@ -379,7 +365,6 @@ public class RecordingService extends Service implements MediaRecorder.OnInfoLis } private void stopRecording(int userId) { - setTapsVisible(mOriginalShowTaps); if (getRecorder() != null) { getRecorder().end(); saveRecording(userId); @@ -411,11 +396,6 @@ public class RecordingService extends Service implements MediaRecorder.OnInfoLis }); } - private void setTapsVisible(boolean turnOn) { - int value = turnOn ? 1 : 0; - Settings.System.putInt(getContentResolver(), Settings.System.SHOW_TOUCHES, value); - } - /** * Get an intent to stop the recording service. * @param context Context from the requesting activity diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordDialog.java b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordDialog.java index 1fb88dfe9b52..582cc762c1b7 100644 --- a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordDialog.java +++ b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordDialog.java @@ -55,7 +55,6 @@ public class ScreenRecordDialog extends SystemUIDialog { private final UserContextProvider mUserContextProvider; @Nullable private final Runnable mOnStartRecordingClicked; - private Switch mTapsSwitch; private Switch mAudioSwitch; private Spinner mOptions; @@ -96,7 +95,6 @@ public class ScreenRecordDialog extends SystemUIDialog { }); mAudioSwitch = findViewById(R.id.screenrecord_audio_switch); - mTapsSwitch = findViewById(R.id.screenrecord_taps_switch); mOptions = findViewById(R.id.screen_recording_options); ArrayAdapter a = new ScreenRecordingAdapter(getContext().getApplicationContext(), android.R.layout.simple_spinner_dropdown_item, @@ -110,7 +108,6 @@ public class ScreenRecordDialog extends SystemUIDialog { private void requestScreenCapture() { Context userContext = mUserContextProvider.getUserContext(); - boolean showTaps = mTapsSwitch.isChecked(); ScreenRecordingAudioSource audioMode = mAudioSwitch.isChecked() ? (ScreenRecordingAudioSource) mOptions.getSelectedItem() : NONE; @@ -118,7 +115,7 @@ public class ScreenRecordDialog extends SystemUIDialog { RecordingService.REQUEST_CODE, RecordingService.getStartIntent( userContext, Activity.RESULT_OK, - audioMode.ordinal(), showTaps), + audioMode.ordinal()), PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); PendingIntent stopIntent = PendingIntent.getService(userContext, RecordingService.REQUEST_CODE, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java index 190c773ef422..f43d9c350d62 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java @@ -21,8 +21,10 @@ import static android.view.View.GONE; import static android.view.View.VISIBLE; import static com.android.systemui.DejankUtils.whitelistIpcs; +import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.IMPORTANT_MSG_MIN_DURATION; import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_ALIGNMENT; import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_BATTERY; +import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_BIOMETRIC_MESSAGE; import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_DISCLOSURE; import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_LOGOUT; import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_OWNER_INFO; @@ -94,6 +96,15 @@ import javax.inject.Inject; /** * Controls the indications and error messages shown on the Keyguard + * + * On AoD, only one message shows with the following priorities: + * 1. Biometric + * 2. Transient + * 3. Charging alignment + * 4. Battery information + * + * On the lock screen, message rotate through different message types. + * See {@link KeyguardIndicationRotateTextViewController.IndicationType} for the list of types. */ @SysUISingleton public class KeyguardIndicationController { @@ -103,6 +114,7 @@ public class KeyguardIndicationController { private static final int MSG_HIDE_TRANSIENT = 1; private static final int MSG_SHOW_ACTION_TO_UNLOCK = 2; + private static final int MSG_HIDE_BIOMETRIC_MESSAGE = 3; private static final long TRANSIENT_BIOMETRIC_ERROR_TIMEOUT = 1300; private static final float BOUNCE_ANIMATION_FINAL_Y = 0f; @@ -132,9 +144,9 @@ public class KeyguardIndicationController { private String mRestingIndication; private String mAlignmentIndication; private CharSequence mTransientIndication; + private CharSequence mBiometricMessage; protected ColorStateList mInitialTextColorState; private boolean mVisible; - private boolean mHideTransientMessageOnScreenOff; private boolean mPowerPluggedIn; private boolean mPowerPluggedInWired; @@ -277,13 +289,15 @@ public class KeyguardIndicationController { } /** - * Doesn't include disclosure which gets triggered separately. + * Doesn't include disclosure (also a persistent indication) which gets triggered separately. + * + * This method also doesn't update transient messages like biometrics since those messages + * are also updated separately. */ - private void updateIndications(boolean animate, int userId) { + private void updatePersistentIndications(boolean animate, int userId) { updateOwnerInfo(); updateBattery(animate); updateUserLocked(userId); - updateTransient(); updateTrust(userId, getTrustGrantedIndication(), getTrustManagedIndication()); updateAlignment(); updateLogoutView(); @@ -383,12 +397,36 @@ public class KeyguardIndicationController { } } + private void updateBiometricMessage() { + if (!TextUtils.isEmpty(mBiometricMessage)) { + mRotateTextViewController.updateIndication( + INDICATION_TYPE_BIOMETRIC_MESSAGE, + new KeyguardIndication.Builder() + .setMessage(mBiometricMessage) + .setMinVisibilityMillis(IMPORTANT_MSG_MIN_DURATION) + .setTextColor(mInitialTextColorState) + .build(), + true + ); + } else { + mRotateTextViewController.hideIndication(INDICATION_TYPE_BIOMETRIC_MESSAGE); + } + + if (mDozing) { + updateIndication(false); + } + } + private void updateTransient() { if (!TextUtils.isEmpty(mTransientIndication)) { mRotateTextViewController.showTransient(mTransientIndication); } else { mRotateTextViewController.hideTransient(); } + + if (mDozing) { + updateIndication(false); + } } private void updateTrust(int userId, CharSequence trustGrantedIndication, @@ -577,32 +615,57 @@ public class KeyguardIndicationController { } /** - * Shows {@param transientIndication} until it is hidden by {@link #hideTransientIndication}. + * Hides biometric indication in {@param delayMs}. */ - public void showTransientIndication(int transientIndication) { - showTransientIndication(mContext.getResources().getString(transientIndication)); + public void hideBiometricMessageDelayed(long delayMs) { + mHandler.sendMessageDelayed( + mHandler.obtainMessage(MSG_HIDE_BIOMETRIC_MESSAGE), delayMs); } /** * Shows {@param transientIndication} until it is hidden by {@link #hideTransientIndication}. */ - public void showTransientIndication(CharSequence transientIndication) { - showTransientIndication(transientIndication, false /* isError */, - false /* hideOnScreenOff */); + public void showTransientIndication(int transientIndication) { + showTransientIndication(mContext.getResources().getString(transientIndication)); } /** * Shows {@param transientIndication} until it is hidden by {@link #hideTransientIndication}. */ - private void showTransientIndication(CharSequence transientIndication, - boolean isError, boolean hideOnScreenOff) { + private void showTransientIndication(CharSequence transientIndication) { mTransientIndication = transientIndication; - mHideTransientMessageOnScreenOff = hideOnScreenOff && transientIndication != null; mHandler.removeMessages(MSG_HIDE_TRANSIENT); - mHandler.removeMessages(MSG_SHOW_ACTION_TO_UNLOCK); hideTransientIndicationDelayed(BaseKeyguardCallback.HIDE_DELAY_MS); - updateIndication(false); + updateTransient(); + } + + /** + * Shows {@param biometricMessage} until it is hidden by {@link #hideBiometricMessage}. + */ + public void showBiometricMessage(int biometricMessage) { + showBiometricMessage(mContext.getResources().getString(biometricMessage)); + } + + /** + * Shows {@param biometricMessage} until it is hidden by {@link #hideBiometricMessage}. + */ + private void showBiometricMessage(CharSequence biometricMessage) { + mBiometricMessage = biometricMessage; + + mHandler.removeMessages(MSG_SHOW_ACTION_TO_UNLOCK); + mHandler.removeMessages(MSG_HIDE_BIOMETRIC_MESSAGE); + hideBiometricMessageDelayed(BaseKeyguardCallback.HIDE_DELAY_MS); + + updateBiometricMessage(); + } + + private void hideBiometricMessage() { + if (mBiometricMessage != null) { + mBiometricMessage = null; + mHandler.removeMessages(MSG_HIDE_BIOMETRIC_MESSAGE); + updateBiometricMessage(); + } } /** @@ -611,10 +674,8 @@ public class KeyguardIndicationController { public void hideTransientIndication() { if (mTransientIndication != null) { mTransientIndication = null; - mHideTransientMessageOnScreenOff = false; mHandler.removeMessages(MSG_HIDE_TRANSIENT); - mRotateTextViewController.hideTransient(); - updateIndication(false); + updateTransient(); } } @@ -635,7 +696,11 @@ public class KeyguardIndicationController { // When dozing we ignore any text color and use white instead, because // colors can be hard to read in low brightness. mTopIndicationView.setTextColor(Color.WHITE); - if (!TextUtils.isEmpty(mTransientIndication)) { + if (!TextUtils.isEmpty(mBiometricMessage)) { + mWakeLock.setAcquired(true); + mTopIndicationView.switchIndication(mBiometricMessage, null, + true, () -> mWakeLock.setAcquired(false)); + } else if (!TextUtils.isEmpty(mTransientIndication)) { mWakeLock.setAcquired(true); mTopIndicationView.switchIndication(mTransientIndication, null, true, () -> mWakeLock.setAcquired(false)); @@ -669,7 +734,7 @@ public class KeyguardIndicationController { mTopIndicationView.setVisibility(GONE); mTopIndicationView.setText(null); mLockScreenIndicationView.setVisibility(View.VISIBLE); - updateIndications(animate, KeyguardUpdateMonitor.getCurrentUser()); + updatePersistentIndications(animate, KeyguardUpdateMonitor.getCurrentUser()); } // animates textView - textView moves up and bounces down @@ -717,6 +782,9 @@ public class KeyguardIndicationController { textView.setTranslationY(BOUNCE_ANIMATION_FINAL_Y); ViewClippingUtil.setClippingDeactivated(textView, false, mClippingParams); + // Unset the listener, otherwise this may persist for + // another view property animation + textView.animate().setListener(null); } }); } @@ -795,6 +863,8 @@ public class KeyguardIndicationController { hideTransientIndication(); } else if (msg.what == MSG_SHOW_ACTION_TO_UNLOCK) { showActionToUnlock(); + } else if (msg.what == MSG_HIDE_BIOMETRIC_MESSAGE) { + hideBiometricMessage(); } } }; @@ -817,8 +887,7 @@ public class KeyguardIndicationController { mStatusBarKeyguardViewManager.showBouncerMessage(message, mInitialTextColorState); } } else { - showTransientIndication(mContext.getString(R.string.keyguard_unlock), - false /* isError */, true /* hideOnScreenOff */); + showBiometricMessage(mContext.getString(R.string.keyguard_unlock)); } } @@ -827,15 +896,15 @@ public class KeyguardIndicationController { // if udfps available, there will always be a tappable affordance to unlock // For example, the lock icon if (mKeyguardBypassController.getUserHasDeviceEntryIntent()) { - showTransientIndication(R.string.keyguard_unlock_press); + showBiometricMessage(R.string.keyguard_unlock_press); } else if (msgId == FaceManager.FACE_ERROR_LOCKOUT_PERMANENT) { // since face is locked out, simply show "try fingerprint" - showTransientIndication(R.string.keyguard_try_fingerprint); + showBiometricMessage(R.string.keyguard_try_fingerprint); } else { - showTransientIndication(R.string.keyguard_face_failed_use_fp); + showBiometricMessage(R.string.keyguard_face_failed_use_fp); } } else { - showTransientIndication(R.string.keyguard_try_fingerprint); + showBiometricMessage(R.string.keyguard_try_fingerprint); } // Although we suppress face auth errors visually, we still announce them for a11y @@ -854,6 +923,8 @@ public class KeyguardIndicationController { pw.println(" mChargingWattage: " + mChargingWattage); pw.println(" mMessageToShowOnScreenOn: " + mMessageToShowOnScreenOn); pw.println(" mDozing: " + mDozing); + pw.println(" mTransientIndication: " + mTransientIndication); + pw.println(" mBiometricMessage: " + mBiometricMessage); pw.println(" mBatteryLevel: " + mBatteryLevel); pw.println(" mBatteryPresent: " + mBatteryPresent); pw.println(" mTextView.getText(): " + ( @@ -868,7 +939,7 @@ public class KeyguardIndicationController { @Override public void onRefreshBatteryInfo(BatteryStatus status) { boolean isChargingOrFull = status.status == BatteryManager.BATTERY_STATUS_CHARGING - || status.status == BatteryManager.BATTERY_STATUS_FULL; + || status.isCharged(); boolean wasPluggedIn = mPowerPluggedIn; mPowerPluggedInWired = status.isPluggedInWired() && isChargingOrFull; mPowerPluggedInWireless = status.isPluggedInWireless() && isChargingOrFull; @@ -909,7 +980,6 @@ public class KeyguardIndicationController { .isUnlockingWithBiometricAllowed(true /* isStrongBiometric */)) { return; } - boolean showActionToUnlock = msgId == KeyguardUpdateMonitor.BIOMETRIC_HELP_FACE_NOT_RECOGNIZED; if (mStatusBarKeyguardViewManager.isBouncerShowing()) { @@ -918,14 +988,10 @@ public class KeyguardIndicationController { } else if (mKeyguardUpdateMonitor.isScreenOn()) { if (biometricSourceType == BiometricSourceType.FACE && shouldSuppressFaceMsgAndShowTryFingerprintMsg()) { - // don't show any help messages, b/c they can come in right before a success - // However, continue to announce help messages for a11y - if (!TextUtils.isEmpty(helpString)) { - mLockScreenIndicationView.announceForAccessibility(helpString); - } + showTryFingerprintMsg(msgId, helpString); return; } - showTransientIndication(helpString, false /* isError */, showActionToUnlock); + showBiometricMessage(helpString); } else if (showActionToUnlock) { mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_SHOW_ACTION_TO_UNLOCK), TRANSIENT_BIOMETRIC_ERROR_TIMEOUT); @@ -964,8 +1030,7 @@ public class KeyguardIndicationController { } else if (mStatusBarKeyguardViewManager.isBouncerShowing()) { mStatusBarKeyguardViewManager.showBouncerMessage(errString, mInitialTextColorState); } else if (mKeyguardUpdateMonitor.isScreenOn()) { - showTransientIndication(errString, /* isError */ true, - /* hideOnScreenOff */ true); + showBiometricMessage(errString); } else { mMessageToShowOnScreenOn = errString; } @@ -1011,16 +1076,15 @@ public class KeyguardIndicationController { @Override public void onTrustAgentErrorMessage(CharSequence message) { - showTransientIndication(message, true /* isError */, false /* hideOnScreenOff */); + showBiometricMessage(message); } @Override public void onScreenTurnedOn() { if (mMessageToShowOnScreenOn != null) { - showTransientIndication(mMessageToShowOnScreenOn, true /* isError */, - false /* hideOnScreenOff */); + showBiometricMessage(mMessageToShowOnScreenOn); // We want to keep this message around in case the screen was off - hideTransientIndicationDelayed(HIDE_DELAY_MS); + hideBiometricMessageDelayed(HIDE_DELAY_MS); mMessageToShowOnScreenOn = null; } } @@ -1031,7 +1095,7 @@ public class KeyguardIndicationController { if (running && biometricSourceType == BiometricSourceType.FACE) { // Let's hide any previous messages when authentication starts, otherwise // multiple auth attempts would overlap. - hideTransientIndication(); + hideBiometricMessage(); mMessageToShowOnScreenOn = null; } } @@ -1040,11 +1104,11 @@ public class KeyguardIndicationController { public void onBiometricAuthenticated(int userId, BiometricSourceType biometricSourceType, boolean isStrongBiometric) { super.onBiometricAuthenticated(userId, biometricSourceType, isStrongBiometric); - mHandler.sendEmptyMessage(MSG_HIDE_TRANSIENT); + hideBiometricMessage(); if (biometricSourceType == BiometricSourceType.FACE && !mKeyguardBypassController.canBypass()) { - mHandler.sendEmptyMessage(MSG_SHOW_ACTION_TO_UNLOCK); + showActionToUnlock(); } } @@ -1071,8 +1135,7 @@ public class KeyguardIndicationController { @Override public void onRequireUnlockForNfc() { - showTransientIndication(mContext.getString(R.string.require_unlock_for_nfc), - false /* isError */, false /* hideOnScreenOff */); + showTransientIndication(mContext.getString(R.string.require_unlock_for_nfc)); hideTransientIndicationDelayed(HIDE_DELAY_MS); } } @@ -1091,8 +1154,8 @@ public class KeyguardIndicationController { } mDozing = dozing; - if (mHideTransientMessageOnScreenOff && mDozing) { - hideTransientIndication(); + if (mDozing) { + hideBiometricMessage(); } updateIndication(false); } @@ -1109,7 +1172,7 @@ public class KeyguardIndicationController { public void onKeyguardShowingChanged() { if (!mKeyguardStateController.isShowing()) { mTopIndicationView.clearMessages(); - mLockScreenIndicationView.clearMessages(); + mRotateTextViewController.clearMessages(); } } }; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java index 50983704dd44..0e3b5b5c882b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java @@ -242,12 +242,13 @@ public class NotificationMediaManager implements Dumpable { @Override public void onMediaDataLoaded(@NonNull String key, @Nullable String oldKey, @NonNull MediaData data, boolean immediately, - boolean isSsReactivated) { + int receivedSmartspaceCardLatency) { } @Override public void onSmartspaceMediaDataLoaded(@NonNull String key, - @NonNull SmartspaceMediaData data, boolean shouldPrioritize) { + @NonNull SmartspaceMediaData data, boolean shouldPrioritize, + boolean isSsReactivated) { } @Override @@ -316,12 +317,13 @@ public class NotificationMediaManager implements Dumpable { @Override public void onMediaDataLoaded(@NonNull String key, @Nullable String oldKey, @NonNull MediaData data, boolean immediately, - boolean isSsReactivated) { + int receivedSmartspaceCardLatency) { } @Override public void onSmartspaceMediaDataLoaded(@NonNull String key, - @NonNull SmartspaceMediaData data, boolean shouldPrioritize) { + @NonNull SmartspaceMediaData data, boolean shouldPrioritize, + boolean isSsReactivated) { } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java index 74ea19f4ca22..1d921702e632 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java @@ -20,6 +20,7 @@ import android.app.IActivityManager; import android.app.NotificationManager; import android.content.Context; import android.os.Handler; +import android.service.dreams.IDreamManager; import com.android.internal.statusbar.IStatusBarService; import com.android.systemui.animation.ActivityLaunchAnimator; @@ -67,13 +68,10 @@ import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.phone.StatusBarIconController; import com.android.systemui.statusbar.phone.StatusBarIconControllerImpl; import com.android.systemui.statusbar.phone.StatusBarRemoteInputCallback; -import com.android.systemui.statusbar.phone.SystemUIHostDialogProvider; import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController; import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallLogger; import com.android.systemui.statusbar.policy.RemoteInputUriController; import com.android.systemui.statusbar.window.StatusBarWindowController; -import com.android.systemui.statusbar.window.StatusBarWindowModule; -import com.android.systemui.statusbar.window.StatusBarWindowView; import com.android.systemui.tracing.ProtoTracer; import com.android.systemui.util.concurrency.DelayableExecutor; import com.android.systemui.util.time.SystemClock; @@ -320,7 +318,7 @@ public interface StatusBarDependenciesModule { @Provides @SysUISingleton static DialogLaunchAnimator provideDialogLaunchAnimator(Context context, - LaunchAnimator launchAnimator) { - return new DialogLaunchAnimator(context, launchAnimator, new SystemUIHostDialogProvider()); + LaunchAnimator launchAnimator, IDreamManager dreamManager) { + return new DialogLaunchAnimator(context, launchAnimator, dreamManager); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFadeAware.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFadeAware.java new file mode 100644 index 000000000000..8d2e3c92c92a --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFadeAware.java @@ -0,0 +1,70 @@ +/* + * 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.statusbar.notification; + +import android.view.View; + +import androidx.annotation.Nullable; + +/** + * Used to let views that have an alpha not apply the HARDWARE layer type directly, and instead + * delegate that to specific children. This is useful if we want to fake not having overlapping + * rendering to avoid layer trashing, when fading out a view that is also changing. + */ +public interface NotificationFadeAware { + /** + * Calls {@link View#setLayerType} with {@link View#LAYER_TYPE_HARDWARE} if faded and + * {@link View#LAYER_TYPE_NONE} otherwise. + */ + static void setLayerTypeForFaded(@Nullable View view, boolean faded) { + if (view != null) { + int newLayerType = faded ? View.LAYER_TYPE_HARDWARE : View.LAYER_TYPE_NONE; + view.setLayerType(newLayerType, null); + } + } + + /** + * Used like {@link View#setLayerType} with {@link View#LAYER_TYPE_HARDWARE} or + * {@link View#LAYER_TYPE_NONE} except that instead of necessarily affecting this view + * specifically, this may delegate the call to child views. + * + * When set to <code>true</code>, the view has two possible paths: + * 1. If a hardware layer is required to ensure correct appearance of this view, then + * set that layer type. + * 2. Otherwise, delegate this call to children, who might make that call for themselves. + * + * When set to <code>false</code>, the view should undo the above, typically by calling + * {@link View#setLayerType} with {@link View#LAYER_TYPE_NONE} on itself and children, and + * delegating to this method on children where implemented. + * + * When this delegates to {@link View#setLayerType} on this view or a subview, `null` will be + * passed for the `paint` argument of that call. + */ + void setNotificationFaded(boolean faded); + + /** + * Interface for the top level notification view that fades and optimizes that through deep + * awareness of individual components. + */ + interface FadeOptimizedNotification extends NotificationFadeAware { + /** Top-level feature switch */ + boolean FADE_LAYER_OPTIMIZATION_ENABLED = true; + + /** Determine if the notification is currently faded. */ + boolean isNotificationFaded(); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java index a2d1040b8a4e..23a0a750561c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java @@ -87,6 +87,7 @@ import com.android.systemui.statusbar.RemoteInputController; import com.android.systemui.statusbar.StatusBarIconView; import com.android.systemui.statusbar.notification.AboveShelfChangedListener; import com.android.systemui.statusbar.notification.ExpandAnimationParameters; +import com.android.systemui.statusbar.notification.NotificationFadeAware; import com.android.systemui.statusbar.notification.NotificationLaunchAnimatorController; import com.android.systemui.statusbar.notification.NotificationUtils; import com.android.systemui.statusbar.notification.collection.NotificationEntry; @@ -125,7 +126,8 @@ import java.util.function.Consumer; * the group summary (which contains 1 or more child notifications). */ public class ExpandableNotificationRow extends ActivatableNotificationView - implements PluginListener<NotificationMenuRowPlugin>, SwipeableView { + implements PluginListener<NotificationMenuRowPlugin>, SwipeableView, + NotificationFadeAware.FadeOptimizedNotification { private static final boolean DEBUG = false; private static final int DEFAULT_DIVIDER_ALPHA = 0x29; @@ -138,6 +140,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView private boolean mUpdateBackgroundOnUpdate; private boolean mNotificationTranslationFinished = false; private boolean mIsSnoozed; + private boolean mIsFaded; /** * Listener for when {@link ExpandableNotificationRow} is laid out. @@ -2753,17 +2756,112 @@ public class ExpandableNotificationRow extends ActivatableNotificationView // alphas are reset if (mChildrenContainer != null) { mChildrenContainer.setAlpha(1.0f); - mChildrenContainer.setLayerType(LAYER_TYPE_NONE, null); } for (NotificationContentView l : mLayouts) { l.setAlpha(1.0f); - l.setLayerType(LAYER_TYPE_NONE, null); + } + if (FADE_LAYER_OPTIMIZATION_ENABLED) { + setNotificationFaded(false); + } else { + setNotificationFadedOnChildren(false); } } else { setHeadsUpAnimatingAway(false); } } + /** Gets the last value set with {@link #setNotificationFaded(boolean)} */ + @Override + public boolean isNotificationFaded() { + return mIsFaded; + } + + /** + * This class needs to delegate the faded state set on it by + * {@link com.android.systemui.statusbar.notification.stack.ViewState} to its children. + * Having each notification use layerType of HARDWARE anytime it fades in/out can result in + * extremely large layers (in the case of groups, it can even exceed the device height). + * Because these large renders can cause serious jank when rendering, we instead have + * notifications return false from {@link #hasOverlappingRendering()} and delegate the + * layerType to child views which really need it in order to render correctly, such as icon + * views or the conversation face pile. + * + * Another compounding factor for notifications is that we change clipping on each frame of the + * animation, so the hardware layer isn't able to do any caching at the top level, but the + * individual elements we render with hardware layers (e.g. icons) cache wonderfully because we + * never invalidate them. + */ + @Override + public void setNotificationFaded(boolean faded) { + mIsFaded = faded; + if (childrenRequireOverlappingRendering()) { + // == Simple Scenario == + // If a child (like remote input) needs this to have overlapping rendering, then set + // the layerType of this view and reset the children to render as if the notification is + // not fading. + NotificationFadeAware.setLayerTypeForFaded(this, faded); + setNotificationFadedOnChildren(false); + } else { + // == Delegating Scenario == + // This is the new normal for alpha: Explicitly reset this view's layer type to NONE, + // and require that all children use their own hardware layer if they have bad + // overlapping rendering. + NotificationFadeAware.setLayerTypeForFaded(this, false); + setNotificationFadedOnChildren(faded); + } + } + + /** Private helper for iterating over the layouts and children containers to set faded state */ + private void setNotificationFadedOnChildren(boolean faded) { + delegateNotificationFaded(mChildrenContainer, faded); + for (NotificationContentView layout : mLayouts) { + delegateNotificationFaded(layout, faded); + } + } + + private static void delegateNotificationFaded(@Nullable View view, boolean faded) { + if (FADE_LAYER_OPTIMIZATION_ENABLED && view instanceof NotificationFadeAware) { + ((NotificationFadeAware) view).setNotificationFaded(faded); + } else { + NotificationFadeAware.setLayerTypeForFaded(view, faded); + } + } + + /** + * Only declare overlapping rendering if independent children of the view require it. + */ + @Override + public boolean hasOverlappingRendering() { + return super.hasOverlappingRendering() && childrenRequireOverlappingRendering(); + } + + /** + * Because RemoteInputView is designed to be an opaque view that overlaps the Actions row, the + * row should require overlapping rendering to ensure that the overlapped view doesn't bleed + * through when alpha fading. + * + * Note that this currently works for top-level notifications which squish their height down + * while collapsing the shade, but does not work for children inside groups, because the + * accordion affect does not apply to those views, so super.hasOverlappingRendering() will + * always return false to avoid the clipping caused when the view's measured height is less than + * the 'actual height'. + */ + private boolean childrenRequireOverlappingRendering() { + if (!FADE_LAYER_OPTIMIZATION_ENABLED) { + return true; + } + // The colorized background is another layer with which all other elements overlap + if (getEntry().getSbn().getNotification().isColorized()) { + return true; + } + // Check if the showing layout has a need for overlapping rendering. + // NOTE: We could check both public and private layouts here, but becuause these states + // don't animate well, there are bigger visual artifacts if we start changing the shown + // layout during shade expansion. + NotificationContentView showingLayout = getShowingLayout(); + return showingLayout != null && showingLayout.requireRowToHaveOverlappingRendering(); + } + @Override public int getExtraBottomPadding() { if (mIsSummaryWithChildren && isGroupExpanded()) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridConversationNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridConversationNotificationView.java index caba3ac7e17b..c66140822d92 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridConversationNotificationView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridConversationNotificationView.java @@ -28,6 +28,7 @@ import android.widget.TextView; import com.android.internal.widget.ConversationLayout; import com.android.systemui.R; +import com.android.systemui.statusbar.notification.NotificationFadeAware; /** * A hybrid view which may contain information about one ore more conversations. @@ -138,4 +139,14 @@ public class HybridConversationNotificationView extends HybridNotificationView { lp.height = size; view.setLayoutParams(lp); } + + /** + * Apply the faded state as a layer type change to the face pile view which needs to have + * overlapping contents render precisely. + */ + @Override + public void setNotificationFaded(boolean faded) { + super.setNotificationFaded(faded); + NotificationFadeAware.setLayerTypeForFaded(mConversationFacePile, faded); + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridNotificationView.java index bc2adac31d07..c0d85a6a16ef 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridNotificationView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridNotificationView.java @@ -28,13 +28,14 @@ import com.android.systemui.R; import com.android.systemui.statusbar.CrossFadeHelper; import com.android.systemui.statusbar.TransformableView; import com.android.systemui.statusbar.ViewTransformationHelper; +import com.android.systemui.statusbar.notification.NotificationFadeAware; import com.android.systemui.statusbar.notification.TransformState; /** * A hybrid view which may contain information about one ore more notifications. */ public class HybridNotificationView extends AlphaOptimizedLinearLayout - implements TransformableView { + implements TransformableView, NotificationFadeAware { protected final ViewTransformationHelper mTransformationHelper = new ViewTransformationHelper(); protected TextView mTitleView; @@ -148,4 +149,7 @@ public class HybridNotificationView extends AlphaOptimizedLinearLayout setVisibility(visible ? View.VISIBLE : View.INVISIBLE); mTransformationHelper.setVisible(visible); } + + @Override + public void setNotificationFaded(boolean faded) {} } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java index 0ffca30ed409..9cc484c02802 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java @@ -46,6 +46,7 @@ import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin; import com.android.systemui.statusbar.RemoteInputController; import com.android.systemui.statusbar.SmartReplyController; import com.android.systemui.statusbar.TransformableView; +import com.android.systemui.statusbar.notification.NotificationFadeAware; import com.android.systemui.statusbar.notification.NotificationUtils; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager; @@ -71,7 +72,7 @@ import java.util.List; * expanded and heads up layout. This class is responsible for clipping the content and and * switching between the expanded, contracted and the heads up view depending on its clipped size. */ -public class NotificationContentView extends FrameLayout { +public class NotificationContentView extends FrameLayout implements NotificationFadeAware { private static final String TAG = "NotificationContentView"; private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); @@ -1994,4 +1995,39 @@ public class NotificationContentView extends FrameLayout { } return Notification.COLOR_INVALID; } + + /** + * Delegate the faded state to the notification content views which actually + * need to have overlapping contents render precisely. + */ + @Override + public void setNotificationFaded(boolean faded) { + if (mContractedWrapper != null) { + mContractedWrapper.setNotificationFaded(faded); + } + if (mHeadsUpWrapper != null) { + mHeadsUpWrapper.setNotificationFaded(faded); + } + if (mExpandedWrapper != null) { + mExpandedWrapper.setNotificationFaded(faded); + } + if (mSingleLineView != null) { + mSingleLineView.setNotificationFaded(faded); + } + } + + /** + * @return true if a visible view has a remote input active, as this requires that the entire + * row report that it has overlapping rendering. + */ + public boolean requireRowToHaveOverlappingRendering() { + // This inexpensive check is done on both states to avoid state invalidating the result. + if (mHeadsUpRemoteInput != null && mHeadsUpRemoteInput.isActive()) { + return true; + } + if (mExpandedRemoteInput != null && mExpandedRemoteInput.isActive()) { + return true; + } + return false; + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCallTemplateViewWrapper.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCallTemplateViewWrapper.kt index 12e94cbc1ab9..bb43b95357db 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCallTemplateViewWrapper.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCallTemplateViewWrapper.kt @@ -21,6 +21,7 @@ import android.view.View import com.android.internal.widget.CachingIconView import com.android.internal.widget.CallLayout import com.android.systemui.R +import com.android.systemui.statusbar.notification.NotificationFadeAware import com.android.systemui.statusbar.notification.NotificationUtils import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow @@ -37,6 +38,7 @@ class NotificationCallTemplateViewWrapper constructor( NotificationUtils.getFontScaledHeight(ctx, R.dimen.notification_max_height) private val callLayout: CallLayout = view as CallLayout + private lateinit var conversationIconContainer: View private lateinit var conversationIconView: CachingIconView private lateinit var conversationBadgeBg: View private lateinit var expandBtn: View @@ -45,6 +47,8 @@ class NotificationCallTemplateViewWrapper constructor( private fun resolveViews() { with(callLayout) { + conversationIconContainer = + requireViewById(com.android.internal.R.id.conversation_icon_container) conversationIconView = requireViewById(com.android.internal.R.id.conversation_icon) conversationBadgeBg = requireViewById(com.android.internal.R.id.conversation_icon_badge_bg) @@ -82,4 +86,14 @@ class NotificationCallTemplateViewWrapper constructor( } override fun getMinLayoutHeight(): Int = minHeightWithActions + + /** + * Apply the faded state as a layer type change to the face pile view which needs to have + * overlapping contents render precisely. + */ + override fun setNotificationFaded(faded: Boolean) { + // Do not call super + NotificationFadeAware.setLayerTypeForFaded(expandBtn, faded) + NotificationFadeAware.setLayerTypeForFaded(conversationIconContainer, faded) + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationConversationTemplateViewWrapper.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationConversationTemplateViewWrapper.kt index 3ef5b665d778..e136055b80b3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationConversationTemplateViewWrapper.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationConversationTemplateViewWrapper.kt @@ -23,6 +23,7 @@ import com.android.internal.widget.CachingIconView import com.android.internal.widget.ConversationLayout import com.android.internal.widget.MessagingLinearLayout import com.android.systemui.R +import com.android.systemui.statusbar.notification.NotificationFadeAware import com.android.systemui.statusbar.notification.NotificationUtils import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow import com.android.systemui.statusbar.notification.row.wrapper.NotificationMessagingTemplateViewWrapper.setCustomImageMessageTransform @@ -42,6 +43,7 @@ class NotificationConversationTemplateViewWrapper constructor( ) private val conversationLayout: ConversationLayout = view as ConversationLayout + private lateinit var conversationIconContainer: View private lateinit var conversationIconView: CachingIconView private lateinit var conversationBadgeBg: View private lateinit var expandBtn: View @@ -59,6 +61,8 @@ class NotificationConversationTemplateViewWrapper constructor( messagingLinearLayout = conversationLayout.messagingLinearLayout imageMessageContainer = conversationLayout.imageMessageContainer with(conversationLayout) { + conversationIconContainer = + requireViewById(com.android.internal.R.id.conversation_icon_container) conversationIconView = requireViewById(com.android.internal.R.id.conversation_icon) conversationBadgeBg = requireViewById(com.android.internal.R.id.conversation_icon_badge_bg) @@ -136,4 +140,10 @@ class NotificationConversationTemplateViewWrapper constructor( minHeightWithActions else super.getMinLayoutHeight() + + override fun setNotificationFaded(faded: Boolean) { + // Do not call super + NotificationFadeAware.setLayerTypeForFaded(expandBtn, faded) + NotificationFadeAware.setLayerTypeForFaded(conversationIconContainer, faded) + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapper.java index 4c9c2f95b35c..fdff12d22354 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapper.java @@ -22,6 +22,7 @@ import android.view.View; import com.android.internal.graphics.ColorUtils; import com.android.systemui.R; +import com.android.systemui.statusbar.notification.NotificationFadeAware; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; /** @@ -86,4 +87,14 @@ public class NotificationCustomViewWrapper extends NotificationViewWrapper { public boolean shouldClipToRounding(boolean topRounded, boolean bottomRounded) { return true; } + + /** + * Apply the faded state as a layer type change to the custom view which needs to have + * overlapping contents render precisely. + */ + @Override + public void setNotificationFaded(boolean faded) { + super.setNotificationFaded(faded); + NotificationFadeAware.setLayerTypeForFaded(mView, faded); + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationDecoratedCustomViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationDecoratedCustomViewWrapper.java index 8c6fa023d92b..31595397b9b0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationDecoratedCustomViewWrapper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationDecoratedCustomViewWrapper.java @@ -20,6 +20,7 @@ import android.content.Context; import android.view.View; import android.view.ViewGroup; +import com.android.systemui.statusbar.notification.NotificationFadeAware; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; /** @@ -67,4 +68,14 @@ public class NotificationDecoratedCustomViewWrapper extends NotificationTemplate } super.onContentUpdated(row); } + + /** + * Apply the faded state as a layer type change to the custom view which needs to have + * overlapping contents render precisely. + */ + @Override + public void setNotificationFaded(boolean faded) { + super.setNotificationFaded(faded); + NotificationFadeAware.setLayerTypeForFaded(mWrappedView, faded); + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java index 76301917b458..6c3e0d2f798b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java @@ -42,6 +42,7 @@ import com.android.internal.widget.CachingIconView; import com.android.settingslib.Utils; import com.android.systemui.statusbar.CrossFadeHelper; import com.android.systemui.statusbar.TransformableView; +import com.android.systemui.statusbar.notification.NotificationFadeAware; import com.android.systemui.statusbar.notification.TransformState; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; @@ -395,4 +396,13 @@ public abstract class NotificationViewWrapper implements TransformableView { */ public void setRecentlyAudiblyAlerted(boolean audiblyAlerted) { } + + /** + * Apply the faded state as a layer type change to the views which need to have overlapping + * contents render precisely. + */ + public void setNotificationFaded(boolean faded) { + NotificationFadeAware.setLayerTypeForFaded(getIcon(), faded); + NotificationFadeAware.setLayerTypeForFaded(getExpandButton(), faded); + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java index c2716b949b71..7ece3d89ce6e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java @@ -38,6 +38,7 @@ import com.android.internal.widget.NotificationExpandButton; import com.android.systemui.R; import com.android.systemui.statusbar.CrossFadeHelper; import com.android.systemui.statusbar.NotificationGroupingUtil; +import com.android.systemui.statusbar.notification.NotificationFadeAware; import com.android.systemui.statusbar.notification.NotificationUtils; import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; @@ -51,7 +52,8 @@ import java.util.List; /** * A container containing child notifications */ -public class NotificationChildrenContainer extends ViewGroup { +public class NotificationChildrenContainer extends ViewGroup + implements NotificationFadeAware { @VisibleForTesting static final int NUMBER_OF_CHILDREN_WHEN_COLLAPSED = 2; @@ -111,6 +113,7 @@ public class NotificationChildrenContainer extends ViewGroup { private int mCurrentHeaderTranslation = 0; private float mHeaderVisibleAmount = 1.0f; private int mUntruncatedChildCount; + private boolean mContainingNotificationIsFaded = false; public NotificationChildrenContainer(Context context) { this(context, null); @@ -277,6 +280,7 @@ public class NotificationChildrenContainer extends ViewGroup { mDividers.add(newIndex, divider); row.setContentTransformationAmount(0, false /* isLastChild */); + row.setNotificationFaded(mContainingNotificationIsFaded); // It doesn't make sense to keep old animations around, lets cancel them! ExpandableViewState viewState = row.getViewState(); if (viewState != null) { @@ -301,6 +305,7 @@ public class NotificationChildrenContainer extends ViewGroup { }); row.setSystemChildExpanded(false); + row.setNotificationFaded(false); row.setUserLocked(false); if (!row.isRemoved()) { mGroupingUtil.restoreChildNotification(row); @@ -1308,4 +1313,18 @@ public class NotificationChildrenContainer extends ViewGroup { mNotificationHeaderWrapperLowPriority.setRecentlyAudiblyAlerted(audiblyAlertedRecently); } } + + @Override + public void setNotificationFaded(boolean faded) { + mContainingNotificationIsFaded = faded; + if (mNotificationHeaderWrapper != null) { + mNotificationHeaderWrapper.setNotificationFaded(faded); + } + if (mNotificationHeaderWrapperLowPriority != null) { + mNotificationHeaderWrapperLowPriority.setNotificationFaded(faded); + } + for (ExpandableNotificationRow child : mAttachedChildren) { + child.setNotificationFaded(faded); + } + } } 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 6a127102b726..ab08865c8bef 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 @@ -6092,6 +6092,14 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable return mExpandHelperCallback; } + float getAppearFraction() { + return mLastSentAppear; + } + + float getExpandedHeight() { + return mLastSentExpandedHeight; + } + /** Enum for selecting some or all notification rows (does not included non-notif views). */ @Retention(SOURCE) @IntDef({ROWS_ALL, ROWS_HIGH_PRIORITY, ROWS_GENTLE}) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java index 03fc76760133..f14cc93c2046 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java @@ -858,6 +858,14 @@ public class NotificationStackScrollLayoutController { mView.setHeadsUpAppearanceController(controller); } + public float getAppearFraction() { + return mView.getAppearFraction(); + } + + public float getExpandedHeight() { + return mView.getExpandedHeight(); + } + public void requestLayout() { mView.requestLayout(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java index 6d82a45313d1..83bea84c8d33 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java @@ -29,6 +29,7 @@ import com.android.systemui.Dumpable; import com.android.systemui.R; import com.android.systemui.animation.Interpolators; import com.android.systemui.statusbar.notification.AnimatableProperty; +import com.android.systemui.statusbar.notification.NotificationFadeAware.FadeOptimizedNotification; import com.android.systemui.statusbar.notification.PropertyAnimator; import com.android.systemui.statusbar.notification.row.ExpandableView; import com.android.systemui.statusbar.policy.HeadsUpUtil; @@ -206,14 +207,26 @@ public class ViewState implements Dumpable { } else if (view.getAlpha() != this.alpha) { // apply layer type boolean becomesFullyVisible = this.alpha == 1.0f; - boolean newLayerTypeIsHardware = !becomesInvisible && !becomesFullyVisible - && view.hasOverlappingRendering(); - int layerType = view.getLayerType(); - int newLayerType = newLayerTypeIsHardware - ? View.LAYER_TYPE_HARDWARE - : View.LAYER_TYPE_NONE; - if (layerType != newLayerType) { - view.setLayerType(newLayerType, null); + boolean becomesFaded = !becomesInvisible && !becomesFullyVisible; + if (FadeOptimizedNotification.FADE_LAYER_OPTIMIZATION_ENABLED + && view instanceof FadeOptimizedNotification) { + // NOTE: A view that's going to utilize this interface to avoid having a hardware + // layer will have to return false from hasOverlappingRendering(), so we + // intentionally do not check that value in this if, even though we do in the else. + FadeOptimizedNotification fadeOptimizedView = (FadeOptimizedNotification) view; + boolean isFaded = fadeOptimizedView.isNotificationFaded(); + if (isFaded != becomesFaded) { + fadeOptimizedView.setNotificationFaded(becomesFaded); + } + } else { + boolean newLayerTypeIsHardware = becomesFaded && view.hasOverlappingRendering(); + int layerType = view.getLayerType(); + int newLayerType = newLayerTypeIsHardware + ? View.LAYER_TYPE_HARDWARE + : View.LAYER_TYPE_NONE; + if (layerType != newLayerType) { + view.setLayerType(newLayerType, null); + } } // apply alpha diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java index 927b4c8cc919..8a7cf360a254 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java @@ -24,6 +24,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.widget.ViewClippingUtil; import com.android.systemui.Dependency; import com.android.systemui.R; +import com.android.systemui.dagger.qualifiers.RootView; import com.android.systemui.plugins.DarkIconDispatcher; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.CommandQueue; @@ -35,23 +36,29 @@ import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController; +import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentScope; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener; +import com.android.systemui.util.ViewController; import java.util.function.BiConsumer; import java.util.function.Consumer; +import javax.inject.Inject; + /** * Controls the appearance of heads up notifications in the icon area and the header itself. */ -public class HeadsUpAppearanceController implements OnHeadsUpChangedListener, - DarkIconDispatcher.DarkReceiver, NotificationWakeUpCoordinator.WakeUpListener { +@StatusBarFragmentScope +public class HeadsUpAppearanceController extends ViewController<HeadsUpStatusBarView> + implements OnHeadsUpChangedListener, + DarkIconDispatcher.DarkReceiver, + NotificationWakeUpCoordinator.WakeUpListener { public static final int CONTENT_FADE_DURATION = 110; public static final int CONTENT_FADE_DELAY = 100; private final NotificationIconAreaController mNotificationIconAreaController; private final HeadsUpManagerPhone mHeadsUpManager; private final NotificationStackScrollLayoutController mStackScrollerController; - private final HeadsUpStatusBarView mHeadsUpStatusBarView; private final View mCenteredIconView; private final View mClockView; private final View mOperatorNameView; @@ -67,8 +74,6 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener, @VisibleForTesting float mExpandedHeight; @VisibleForTesting - boolean mIsExpanded; - @VisibleForTesting float mAppearFraction; private ExpandableNotificationRow mTrackedChild; private boolean mShown; @@ -83,7 +88,7 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener, Point mPoint; private KeyguardStateController mKeyguardStateController; - + @Inject public HeadsUpAppearanceController( NotificationIconAreaController notificationIconAreaController, HeadsUpManagerPhone headsUpManager, @@ -92,11 +97,15 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener, KeyguardBypassController keyguardBypassController, KeyguardStateController keyguardStateController, NotificationWakeUpCoordinator wakeUpCoordinator, CommandQueue commandQueue, - NotificationPanelViewController notificationPanelViewController, View statusBarView) { + NotificationPanelViewController notificationPanelViewController, + @RootView PhoneStatusBarView statusBarView) { this(notificationIconAreaController, headsUpManager, statusBarStateController, keyguardBypassController, wakeUpCoordinator, keyguardStateController, commandQueue, notificationStackScrollLayoutController, notificationPanelViewController, + // TODO(b/205609837): We should have the StatusBarFragmentComponent provide these + // four views, and then we can delete this constructor and just use the one below + // (which also removes the undesirable @VisibleForTesting). statusBarView.findViewById(R.id.heads_up_status_bar_view), statusBarView.findViewById(R.id.clock), statusBarView.findViewById(R.id.operator_name_frame), @@ -118,25 +127,27 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener, View clockView, View operatorNameView, View centeredIconView) { + super(headsUpStatusBarView); mNotificationIconAreaController = notificationIconAreaController; mHeadsUpManager = headsUpManager; - mHeadsUpManager.addListener(this); - mHeadsUpStatusBarView = headsUpStatusBarView; mCenteredIconView = centeredIconView; - headsUpStatusBarView.setOnDrawingRectChangedListener( - () -> updateIsolatedIconLocation(true /* requireUpdate */)); + + // We may be mid-HUN-expansion when this controller is re-created (for example, if the user + // has started pulling down the notification shade from the HUN and then the font size + // changes). We need to re-fetch these values since they're used to correctly display the + // HUN during this shade expansion. + mTrackedChild = notificationPanelViewController.getTrackedHeadsUpNotification(); + mAppearFraction = stackScrollerController.getAppearFraction(); + mExpandedHeight = stackScrollerController.getExpandedHeight(); + mStackScrollerController = stackScrollerController; mNotificationPanelViewController = notificationPanelViewController; - notificationPanelViewController.addTrackingHeadsUpListener(mSetTrackingHeadsUp); - notificationPanelViewController.setHeadsUpAppearanceController(this); - mStackScrollerController.addOnExpandedHeightChangedListener(mSetExpandedHeight); mStackScrollerController.setHeadsUpAppearanceController(this); mClockView = clockView; mOperatorNameView = operatorNameView; mDarkIconDispatcher = Dependency.get(DarkIconDispatcher.class); - mDarkIconDispatcher.addDarkReceiver(this); - mHeadsUpStatusBarView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() { + mView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() { @Override public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { @@ -146,21 +157,32 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener, // trigger scroller to notify the latest panel translation mStackScrollerController.requestLayout(); } - mHeadsUpStatusBarView.removeOnLayoutChangeListener(this); + mView.removeOnLayoutChangeListener(this); } }); mBypassController = bypassController; mStatusBarStateController = stateController; mWakeUpCoordinator = wakeUpCoordinator; - wakeUpCoordinator.addListener(this); mCommandQueue = commandQueue; mKeyguardStateController = keyguardStateController; } + @Override + protected void onViewAttached() { + mHeadsUpManager.addListener(this); + mView.setOnDrawingRectChangedListener( + () -> updateIsolatedIconLocation(true /* requireUpdate */)); + mWakeUpCoordinator.addListener(this); + mNotificationPanelViewController.addTrackingHeadsUpListener(mSetTrackingHeadsUp); + mNotificationPanelViewController.setHeadsUpAppearanceController(this); + mStackScrollerController.addOnExpandedHeightChangedListener(mSetExpandedHeight); + mDarkIconDispatcher.addDarkReceiver(this); + } - public void destroy() { + @Override + protected void onViewDetached() { mHeadsUpManager.removeListener(this); - mHeadsUpStatusBarView.setOnDrawingRectChangedListener(null); + mView.setOnDrawingRectChangedListener(null); mWakeUpCoordinator.removeListener(this); mNotificationPanelViewController.removeTrackingHeadsUpListener(mSetTrackingHeadsUp); mNotificationPanelViewController.setHeadsUpAppearanceController(null); @@ -170,7 +192,7 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener, private void updateIsolatedIconLocation(boolean requireStateUpdate) { mNotificationIconAreaController.setIsolatedIconLocation( - mHeadsUpStatusBarView.getIconDrawingRect(), requireStateUpdate); + mView.getIconDrawingRect(), requireStateUpdate); } @Override @@ -184,20 +206,20 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener, if (shouldBeVisible()) { newEntry = mHeadsUpManager.getTopEntry(); } - NotificationEntry previousEntry = mHeadsUpStatusBarView.getShowingEntry(); - mHeadsUpStatusBarView.setEntry(newEntry); + NotificationEntry previousEntry = mView.getShowingEntry(); + mView.setEntry(newEntry); if (newEntry != previousEntry) { boolean animateIsolation = false; if (newEntry == null) { // no heads up anymore, lets start the disappear animation setShown(false); - animateIsolation = !mIsExpanded; + animateIsolation = !isExpanded(); } else if (previousEntry == null) { // We now have a headsUp and didn't have one before. Let's start the disappear // animation setShown(true); - animateIsolation = !mIsExpanded; + animateIsolation = !isExpanded(); } updateIsolatedIconLocation(false /* requireUpdate */); mNotificationIconAreaController.showIconIsolated(newEntry == null ? null @@ -210,8 +232,8 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener, mShown = isShown; if (isShown) { updateParentClipping(false /* shouldClip */); - mHeadsUpStatusBarView.setVisibility(View.VISIBLE); - show(mHeadsUpStatusBarView); + mView.setVisibility(View.VISIBLE); + show(mView); hide(mClockView, View.INVISIBLE); if (mCenteredIconView.getVisibility() != View.GONE) { hide(mCenteredIconView, View.INVISIBLE); @@ -227,21 +249,21 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener, if (mOperatorNameView != null) { show(mOperatorNameView); } - hide(mHeadsUpStatusBarView, View.GONE, () -> { + hide(mView, View.GONE, () -> { updateParentClipping(true /* shouldClip */); }); } // Show the status bar icons when the view gets shown / hidden if (mStatusBarStateController.getState() != StatusBarState.SHADE) { mCommandQueue.recomputeDisableFlags( - mHeadsUpStatusBarView.getContext().getDisplayId(), false); + mView.getContext().getDisplayId(), false); } } } private void updateParentClipping(boolean shouldClip) { ViewClippingUtil.setClippingDeactivated( - mHeadsUpStatusBarView, !shouldClip, mParentClippingParams); + mView, !shouldClip, mParentClippingParams); } /** @@ -310,7 +332,7 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener, */ public boolean shouldBeVisible() { boolean notificationsShown = !mWakeUpCoordinator.getNotificationsFullyHidden(); - boolean canShow = !mIsExpanded && notificationsShown; + boolean canShow = !isExpanded() && notificationsShown; if (mBypassController.getBypassEnabled() && (mStatusBarStateController.getState() == StatusBarState.KEYGUARD || mKeyguardStateController.isKeyguardGoingAway()) @@ -328,17 +350,17 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener, public void setAppearFraction(float expandedHeight, float appearFraction) { boolean changed = expandedHeight != mExpandedHeight; + boolean oldIsExpanded = isExpanded(); + mExpandedHeight = expandedHeight; mAppearFraction = appearFraction; - boolean isExpanded = expandedHeight > 0; // We only notify if the expandedHeight changed and not on the appearFraction, since // otherwise we may run into an infinite loop where the panel and this are constantly // updating themselves over just a small fraction if (changed) { updateHeadsUpHeaders(); } - if (isExpanded != mIsExpanded) { - mIsExpanded = isExpanded; + if (isExpanded() != oldIsExpanded) { updateTopEntry(); } } @@ -358,6 +380,10 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener, } } + private boolean isExpanded() { + return mExpandedHeight > 0; + } + private void updateHeadsUpHeaders() { mHeadsUpManager.getAllEntries().forEach(entry -> { updateHeader(entry); @@ -376,22 +402,13 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener, @Override public void onDarkChanged(Rect area, float darkIntensity, int tint) { - mHeadsUpStatusBarView.onDarkChanged(area, darkIntensity, tint); + mView.onDarkChanged(area, darkIntensity, tint); } public void onStateChanged() { updateTopEntry(); } - void readFrom(HeadsUpAppearanceController oldController) { - if (oldController != null) { - mTrackedChild = oldController.mTrackedChild; - mExpandedHeight = oldController.mExpandedHeight; - mIsExpanded = oldController.mIsExpanded; - mAppearFraction = oldController.mAppearFraction; - } - } - @Override public void onFullyHiddenChanged(boolean isFullyHidden) { updateTopEntry(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java index e26f75f7ce40..aeef8cd433ab 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java @@ -71,6 +71,7 @@ import android.widget.ImageView; import android.widget.TextView; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.widget.LockPatternUtils; @@ -150,6 +151,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL private ControlsComponent mControlsComponent; private boolean mControlServicesAvailable = false; + @Nullable private View mAmbientIndicationArea; private ViewGroup mIndicationArea; private TextView mIndicationText; private TextView mIndicationTextBottom; @@ -270,6 +272,29 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL public void initFrom(KeyguardBottomAreaView oldBottomArea) { setStatusBar(oldBottomArea.mStatusBar); + + // if it exists, continue to use the original ambient indication container + // instead of the newly inflated one + if (mAmbientIndicationArea != null) { + // remove old ambient indication from its parent + View originalAmbientIndicationView = + oldBottomArea.findViewById(R.id.ambient_indication_container); + ((ViewGroup) originalAmbientIndicationView.getParent()) + .removeView(originalAmbientIndicationView); + + // remove current ambient indication from its parent (discard) + ViewGroup ambientIndicationParent = (ViewGroup) mAmbientIndicationArea.getParent(); + int ambientIndicationIndex = + ambientIndicationParent.indexOfChild(mAmbientIndicationArea); + ambientIndicationParent.removeView(mAmbientIndicationArea); + + // add the old ambient indication to this view + ambientIndicationParent.addView(originalAmbientIndicationView, ambientIndicationIndex); + mAmbientIndicationArea = originalAmbientIndicationView; + + // update burn-in offsets + dozeTimeTick(); + } } @Override @@ -283,6 +308,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL mWalletButton = findViewById(R.id.wallet_button); mControlsButton = findViewById(R.id.controls_button); mIndicationArea = findViewById(R.id.keyguard_indication_area); + mAmbientIndicationArea = findViewById(R.id.ambient_indication_container); mIndicationText = findViewById(R.id.keyguard_indication_text); mIndicationTextBottom = findViewById(R.id.keyguard_indication_text_bottom); mIndicationBottomMargin = getResources().getDimensionPixelSize( @@ -901,6 +927,9 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL int burnInYOffset = getBurnInOffset(mBurnInYOffset * 2, false /* xAxis */) - mBurnInYOffset; mIndicationArea.setTranslationY(burnInYOffset * mDarkAmount); + if (mAmbientIndicationArea != null) { + mAmbientIndicationArea.setTranslationY(burnInYOffset * mDarkAmount); + } } public void setAntiBurnInOffsetX(int burnInXOffset) { @@ -909,6 +938,9 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL } mBurnInXOffset = burnInXOffset; mIndicationArea.setTranslationX(burnInXOffset); + if (mAmbientIndicationArea != null) { + mAmbientIndicationArea.setTranslationX(burnInXOffset); + } } /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java index 3a68b9c3d1b3..339f371c0d12 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java @@ -35,23 +35,20 @@ import com.android.systemui.R; import com.android.systemui.animation.Interpolators; import com.android.systemui.keyguard.KeyguardIndication; -import java.util.LinkedList; - /** * A view to show hints on Keyguard ("Swipe up to unlock", "Tap again to open"). */ public class KeyguardIndicationTextView extends TextView { - private static final long MSG_MIN_DURATION_MILLIS_DEFAULT = 1500; - @StyleRes private static int sStyleId = R.style.TextAppearance_Keyguard_BottomArea; @StyleRes private static int sButtonStyleId = R.style.TextAppearance_Keyguard_BottomArea_Button; - private long mNextAnimationTime = 0; private boolean mAnimationsEnabled = true; - private LinkedList<CharSequence> mMessages = new LinkedList<>(); - private LinkedList<KeyguardIndication> mKeyguardIndicationInfo = new LinkedList<>(); + private CharSequence mMessage; + private KeyguardIndication mKeyguardIndicationInfo; + + private Animator mLastAnimator; public KeyguardIndicationTextView(Context context) { super(context); @@ -71,22 +68,24 @@ public class KeyguardIndicationTextView extends TextView { } /** - * Clears message queue. + * Clears message queue and currently shown message. */ public void clearMessages() { - mMessages.clear(); - mKeyguardIndicationInfo.clear(); + if (mLastAnimator != null) { + mLastAnimator.cancel(); + } + setText(""); } /** - * Changes the text with an animation and makes sure a single indication is shown long enough. + * Changes the text with an animation. */ public void switchIndication(int textResId) { switchIndication(getResources().getText(textResId), null); } /** - * Changes the text with an animation and makes sure a single indication is shown long enough. + * Changes the text with an animation. * * @param indication The text to show. */ @@ -95,15 +94,14 @@ public class KeyguardIndicationTextView extends TextView { } /** - * Changes the text with an animation. Makes sure a single indication is shown long enough. + * Changes the text with an animation. */ public void switchIndication(CharSequence text, KeyguardIndication indication) { switchIndication(text, indication, true, null); } /** - * Changes the text with an optional animation. For animating text, makes sure a single - * indication is shown long enough. + * Updates the text with an optional animation. * * @param text The text to show. * @param indication optional display information for the text @@ -112,33 +110,15 @@ public class KeyguardIndicationTextView extends TextView { */ public void switchIndication(CharSequence text, KeyguardIndication indication, boolean animate, Runnable onAnimationEndCallback) { - if (text == null) text = ""; - - CharSequence lastPendingMessage = mMessages.peekLast(); - if (TextUtils.equals(lastPendingMessage, text) - || (lastPendingMessage == null && TextUtils.equals(text, getText()))) { - if (onAnimationEndCallback != null) { - onAnimationEndCallback.run(); - } - return; - } - mMessages.add(text); - mKeyguardIndicationInfo.add(indication); + mMessage = text; + mKeyguardIndicationInfo = indication; if (animate) { final boolean hasIcon = indication != null && indication.getIcon() != null; - final AnimatorSet animator = new AnimatorSet(); + AnimatorSet animator = new AnimatorSet(); // Make sure each animation is visible for a minimum amount of time, while not worrying // about fading in blank text - long timeInMillis = System.currentTimeMillis(); - long delay = Math.max(0, mNextAnimationTime - timeInMillis); - setNextAnimationTime(timeInMillis + delay + getFadeOutDuration()); - final long minDurationMillis = - (indication != null && indication.getMinVisibilityMillis() != null) - ? indication.getMinVisibilityMillis() - : MSG_MIN_DURATION_MILLIS_DEFAULT; - if (!text.equals("") || hasIcon) { - setNextAnimationTime(mNextAnimationTime + minDurationMillis); + if (!TextUtils.isEmpty(mMessage) || hasIcon) { Animator inAnimator = getInAnimator(); inAnimator.addListener(new AnimatorListenerAdapter() { @Override @@ -164,7 +144,10 @@ public class KeyguardIndicationTextView extends TextView { animator.play(outAnimator); } - animator.setStartDelay(delay); + if (mLastAnimator != null) { + mLastAnimator.cancel(); + } + mLastAnimator = animator; animator.start(); } else { setAlpha(1f); @@ -173,6 +156,10 @@ public class KeyguardIndicationTextView extends TextView { if (onAnimationEndCallback != null) { onAnimationEndCallback.run(); } + if (mLastAnimator != null) { + mLastAnimator.cancel(); + mLastAnimator = null; + } } } @@ -182,10 +169,20 @@ public class KeyguardIndicationTextView extends TextView { fadeOut.setDuration(getFadeOutDuration()); fadeOut.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN); fadeOut.addListener(new AnimatorListenerAdapter() { + private boolean mCancelled = false; @Override public void onAnimationEnd(Animator animator) { super.onAnimationEnd(animator); - setNextIndication(); + if (!mCancelled) { + setNextIndication(); + } + } + + @Override + public void onAnimationCancel(Animator animator) { + super.onAnimationCancel(animator); + mCancelled = true; + setAlpha(0); } }); @@ -198,20 +195,19 @@ public class KeyguardIndicationTextView extends TextView { } private void setNextIndication() { - KeyguardIndication info = mKeyguardIndicationInfo.poll(); - if (info != null) { + if (mKeyguardIndicationInfo != null) { // First, update the style. // If a background is set on the text, we don't want shadow on the text - if (info.getBackground() != null) { + if (mKeyguardIndicationInfo.getBackground() != null) { setTextAppearance(sButtonStyleId); } else { setTextAppearance(sStyleId); } - setBackground(info.getBackground()); - setTextColor(info.getTextColor()); - setOnClickListener(info.getClickListener()); - setClickable(info.getClickListener() != null); - final Drawable icon = info.getIcon(); + setBackground(mKeyguardIndicationInfo.getBackground()); + setTextColor(mKeyguardIndicationInfo.getTextColor()); + setOnClickListener(mKeyguardIndicationInfo.getClickListener()); + setClickable(mKeyguardIndicationInfo.getClickListener() != null); + final Drawable icon = mKeyguardIndicationInfo.getIcon(); if (icon != null) { icon.setTint(getCurrentTextColor()); if (icon instanceof AnimatedVectorDrawable) { @@ -220,7 +216,7 @@ public class KeyguardIndicationTextView extends TextView { } setCompoundDrawablesRelativeWithIntrinsicBounds(icon, null, null, null); } - setText(mMessages.poll()); + setText(mMessage); } private AnimatorSet getInAnimator() { @@ -238,6 +234,7 @@ public class KeyguardIndicationTextView extends TextView { public void onAnimationCancel(Animator animation) { super.onAnimationCancel(animation); setTranslationY(0); + setAlpha(1f); } }); animatorSet.playTogether(yTranslate, fadeIn); @@ -270,14 +267,6 @@ public class KeyguardIndicationTextView extends TextView { return 167L; } - private void setNextAnimationTime(long time) { - if (mAnimationsEnabled) { - mNextAnimationTime = time; - } else { - mNextAnimationTime = 0L; - } - } - private int getYTranslationPixels() { return mContext.getResources().getDimensionPixelSize( com.android.systemui.R.dimen.keyguard_indication_y_translation); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightsOutNotifController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightsOutNotifController.java index 3f3328172e12..68ab07798520 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightsOutNotifController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightsOutNotifController.java @@ -124,6 +124,9 @@ public class LightsOutNotifController { public void onAnimationEnd(Animator a) { mLightsOutNotifView.setAlpha(showDot ? 1 : 0); mLightsOutNotifView.setVisibility(showDot ? View.VISIBLE : View.GONE); + // Unset the listener, otherwise this may persist for + // another view property animation + mLightsOutNotifView.animate().setListener(null); } }) .start(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java index 9b5fa2a49ff1..0312c30c73ec 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java @@ -88,6 +88,7 @@ import android.view.accessibility.AccessibilityManager; import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; +import androidx.annotation.Nullable; import androidx.constraintlayout.widget.ConstraintSet; import com.android.internal.annotations.VisibleForTesting; @@ -451,9 +452,13 @@ public class NotificationPanelViewController extends PanelViewController { private boolean mUserSetupComplete; private boolean mHideIconsDuringLaunchAnimation = true; private int mStackScrollerMeasuringPass; - private ArrayList<Consumer<ExpandableNotificationRow>> - mTrackingHeadsUpListeners = - new ArrayList<>(); + /** + * Non-null if there's a heads-up notification that we're currently tracking the position of. + */ + @Nullable + private ExpandableNotificationRow mTrackedHeadsUpNotification; + private final ArrayList<Consumer<ExpandableNotificationRow>> + mTrackingHeadsUpListeners = new ArrayList<>(); private HeadsUpAppearanceController mHeadsUpAppearanceController; private int mPanelAlpha; @@ -3050,18 +3055,24 @@ public class NotificationPanelViewController extends PanelViewController { mQsExpandImmediate = false; mNotificationStackScrollLayoutController.setShouldShowShelfOnly(false); mTwoFingerQsExpandPossible = false; - notifyListenersTrackingHeadsUp(null); + updateTrackingHeadsUp(null); mExpandingFromHeadsUp = false; setPanelScrimMinFraction(0.0f); } - private void notifyListenersTrackingHeadsUp(ExpandableNotificationRow pickedChild) { + private void updateTrackingHeadsUp(@Nullable ExpandableNotificationRow pickedChild) { + mTrackedHeadsUpNotification = pickedChild; for (int i = 0; i < mTrackingHeadsUpListeners.size(); i++) { Consumer<ExpandableNotificationRow> listener = mTrackingHeadsUpListeners.get(i); listener.accept(pickedChild); } } + @Nullable + public ExpandableNotificationRow getTrackedHeadsUpNotification() { + return mTrackedHeadsUpNotification; + } + private void setListening(boolean listening) { mKeyguardStatusBarViewController.setBatteryListening(listening); if (mQs == null) return; @@ -3298,7 +3309,7 @@ public class NotificationPanelViewController extends PanelViewController { public void setTrackedHeadsUp(ExpandableNotificationRow pickedChild) { if (pickedChild != null) { - notifyListenersTrackingHeadsUp(pickedChild); + updateTrackingHeadsUp(pickedChild); mExpandingFromHeadsUp = true; } // otherwise we update the state when the expansion is finished diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java index 01587f7fe98c..55f14500f8fc 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java @@ -338,6 +338,11 @@ public class NotificationShadeWindowViewController { return true; } + if (mLockIconViewController.onInterceptTouchEvent(ev)) { + // immediately return true; don't send the touch to the drag down helper + return true; + } + boolean intercept = false; if (mNotificationPanelViewController.isFullyExpanded() && mDragDownHelper.isDragDownEnabled() diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsButton.java index 9cefded72365..bf5467716910 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsButton.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsButton.java @@ -120,6 +120,9 @@ public class SettingsButton extends AlphaOptimizedImageButton { setAlpha(1f); setTranslationX(0); cancelLongClick(); + // Unset the listener, otherwise this may persist for + // another view property animation + animate().setListener(null); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SplitShadeHeaderController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SplitShadeHeaderController.kt index a4feeab48e6e..bceffb3de208 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SplitShadeHeaderController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SplitShadeHeaderController.kt @@ -23,6 +23,7 @@ import com.android.systemui.animation.ShadeInterpolation import com.android.systemui.battery.BatteryMeterView import com.android.systemui.battery.BatteryMeterViewController import com.android.systemui.flags.FeatureFlags +import com.android.systemui.qs.HeaderPrivacyIconsController import com.android.systemui.qs.carrier.QSCarrierGroupController import com.android.systemui.statusbar.phone.dagger.StatusBarComponent.StatusBarScope import com.android.systemui.statusbar.phone.dagger.StatusBarViewModule.SPLIT_SHADE_BATTERY_CONTROLLER @@ -34,6 +35,7 @@ import javax.inject.Named class SplitShadeHeaderController @Inject constructor( @Named(SPLIT_SHADE_HEADER) private val statusBar: View, private val statusBarIconController: StatusBarIconController, + private val privacyIconsController: HeaderPrivacyIconsController, qsCarrierGroupControllerBuilder: QSCarrierGroupController.Builder, featureFlags: FeatureFlags, @Named(SPLIT_SHADE_BATTERY_CONTROLLER) batteryMeterViewController: BatteryMeterViewController @@ -63,8 +65,7 @@ class SplitShadeHeaderController @Inject constructor( return } field = value - updateVisibility() - updatePosition() + onShadeExpandedChanged() } var splitShadeMode = false @@ -73,8 +74,7 @@ class SplitShadeHeaderController @Inject constructor( return } field = value - updateVisibility() - updateConstraints() + onSplitShadeModeChanged() } var shadeExpandedFraction = -1f @@ -124,6 +124,26 @@ class SplitShadeHeaderController @Inject constructor( updateConstraints() } + private fun onShadeExpandedChanged() { + if (shadeExpanded) { + privacyIconsController.startListening() + } else { + privacyIconsController.stopListening() + } + updateVisibility() + updatePosition() + } + + private fun onSplitShadeModeChanged() { + if (splitShadeMode) { + privacyIconsController.onParentVisible() + } else { + privacyIconsController.onParentInvisible() + } + updateVisibility() + updateConstraints() + } + private fun updateVisibility() { val visibility = if (!splitShadeMode && !combinedHeaders) { View.GONE @@ -166,4 +186,4 @@ class SplitShadeHeaderController @Inject constructor( statusBarIconController.removeIconGroup(iconManager) } } -}
\ No newline at end of file +} 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 7b6cdbecc640..b2be9948fea9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -133,6 +133,7 @@ import com.android.systemui.InitController; import com.android.systemui.Prefs; import com.android.systemui.R; import com.android.systemui.SystemUI; +import com.android.systemui.accessibility.floatingmenu.AccessibilityFloatingMenuController; import com.android.systemui.animation.ActivityLaunchAnimator; import com.android.systemui.animation.DelegateLaunchAnimatorController; import com.android.systemui.assist.AssistManager; @@ -519,7 +520,6 @@ public class StatusBar extends SystemUI implements private QSPanelController mQSPanelController; private final OperatorNameViewController.Factory mOperatorNameViewControllerFactory; - private final PhoneStatusBarViewController.Factory mPhoneStatusBarViewControllerFactory; KeyguardIndicationController mKeyguardIndicationController; private View mReportRejectedTouch; @@ -664,7 +664,6 @@ public class StatusBar extends SystemUI implements private boolean mNoAnimationOnNextBarModeChange; private final SysuiStatusBarStateController mStatusBarStateController; - private HeadsUpAppearanceController mHeadsUpAppearanceController; private final ActivityLaunchAnimator mActivityLaunchAnimator; private NotificationLaunchAnimatorControllerProvider mNotificationAnimationProvider; protected StatusBarNotificationPresenter mPresenter; @@ -734,6 +733,7 @@ public class StatusBar extends SystemUI implements VisualStabilityManager visualStabilityManager, DeviceProvisionedController deviceProvisionedController, NavigationBarController navigationBarController, + AccessibilityFloatingMenuController accessibilityFloatingMenuController, Lazy<AssistManager> assistManagerLazy, ConfigurationController configurationController, NotificationShadeWindowController notificationShadeWindowController, @@ -765,7 +765,6 @@ public class StatusBar extends SystemUI implements ExtensionController extensionController, UserInfoControllerImpl userInfoControllerImpl, OperatorNameViewController.Factory operatorNameViewControllerFactory, - PhoneStatusBarViewController.Factory phoneStatusBarViewControllerFactory, PhoneStatusBarPolicy phoneStatusBarPolicy, KeyguardIndicationController keyguardIndicationController, DemoModeController demoModeController, @@ -804,7 +803,6 @@ public class StatusBar extends SystemUI implements mKeyguardStateController = keyguardStateController; mHeadsUpManager = headsUpManagerPhone; mOperatorNameViewControllerFactory = operatorNameViewControllerFactory; - mPhoneStatusBarViewControllerFactory = phoneStatusBarViewControllerFactory; mKeyguardIndicationController = keyguardIndicationController; mStatusBarTouchableRegionManager = statusBarTouchableRegionManager; mDynamicPrivacyController = dynamicPrivacyController; @@ -838,6 +836,7 @@ public class StatusBar extends SystemUI implements mVisualStabilityManager = visualStabilityManager; mDeviceProvisionedController = deviceProvisionedController; mNavigationBarController = navigationBarController; + mAccessibilityFloatingMenuController = accessibilityFloatingMenuController; mAssistManagerLazy = assistManagerLazy; mConfigurationController = configurationController; mNotificationShadeWindowController = notificationShadeWindowController; @@ -1052,6 +1051,8 @@ public class StatusBar extends SystemUI implements mBatteryController.observe(mLifecycle, mBatteryStateChangeCallback); mLifecycle.setCurrentState(RESUMED); + mAccessibilityFloatingMenuController.init(); + // set the initial view visibility int disabledFlags1 = result.mDisabledFlags1; int disabledFlags2 = result.mDisabledFlags2; @@ -1149,12 +1150,8 @@ public class StatusBar extends SystemUI implements } mStatusBarView = statusBarFragmentComponent.getPhoneStatusBarView(); - - // TODO(b/205609837): Migrate this to StatusBarFragmentComponent. - mPhoneStatusBarViewController = mPhoneStatusBarViewControllerFactory - .create(mStatusBarView, mNotificationPanelViewController - .getStatusBarTouchEventHandler()); - mPhoneStatusBarViewController.init(); + mPhoneStatusBarViewController = + statusBarFragmentComponent.getPhoneStatusBarViewController(); // Ensure we re-propagate panel expansion values to the panel controller and // any listeners it may have, such as PanelBar. This will also ensure we @@ -1164,21 +1161,6 @@ public class StatusBar extends SystemUI implements mNotificationPanelViewController.updatePanelExpansionAndVisibility(); setBouncerShowingForStatusBarComponents(mBouncerShowing); - HeadsUpAppearanceController oldController = mHeadsUpAppearanceController; - if (mHeadsUpAppearanceController != null) { - // This view is being recreated, let's destroy the old one - mHeadsUpAppearanceController.destroy(); - } - // TODO (b/136993073) Separate notification shade and status bar - // TODO(b/205609837): Migrate this to StatusBarFragmentComponent. - mHeadsUpAppearanceController = new HeadsUpAppearanceController( - mNotificationIconAreaController, mHeadsUpManager, - mStackScrollerController, - mStatusBarStateController, mKeyguardBypassController, - mKeyguardStateController, mWakeUpCoordinator, mCommandQueue, - mNotificationPanelViewController, mStatusBarView); - mHeadsUpAppearanceController.readFrom(oldController); - mLightsOutNotifController.setLightsOutNotifView( mStatusBarView.findViewById(R.id.notification_lights_out)); mNotificationShadeWindowViewController.setStatusBarView(mStatusBarView); @@ -1879,10 +1861,6 @@ public class StatusBar extends SystemUI implements return mDozeServiceHost.isPulsing(); } - public boolean hideStatusBarIconsWhenExpanded() { - return mNotificationPanelViewController.hideStatusBarIconsWhenExpanded(); - } - @Nullable public View getAmbientIndicationContainer() { return mAmbientIndicationContainer; @@ -1904,10 +1882,6 @@ public class StatusBar extends SystemUI implements mScrimController.setKeyguardOccluded(occluded); } - public boolean headsUpShouldBeVisible() { - return mHeadsUpAppearanceController.shouldBeVisible(); - } - /** A launch animation was cancelled. */ //TODO: These can / should probably be moved to NotificationPresenter or ShadeController public void onLaunchAnimationCancelled(boolean isLaunchForActivity) { @@ -1987,7 +1961,7 @@ public class StatusBar extends SystemUI implements } } - public void maybeEscalateHeadsUp() { + private void maybeEscalateHeadsUp() { mHeadsUpManager.getAllEntries().forEach(entry -> { final StatusBarNotification sbn = entry.getSbn(); final Notification notification = sbn.getNotification(); @@ -1998,6 +1972,7 @@ public class StatusBar extends SystemUI implements try { EventLog.writeEvent(EventLogTags.SYSUI_HEADS_UP_ESCALATION, sbn.getKey()); + wakeUpForFullScreenIntent(); notification.fullScreenIntent.send(); entry.notifyFullScreenIntentLaunched(); } catch (PendingIntent.CanceledException e) { @@ -2007,6 +1982,17 @@ public class StatusBar extends SystemUI implements mHeadsUpManager.releaseAllImmediately(); } + void wakeUpForFullScreenIntent() { + if (isGoingToSleep() || mDozing) { + mPowerManager.wakeUp( + SystemClock.uptimeMillis(), + PowerManager.WAKE_REASON_APPLICATION, + "com.android.systemui:full_screen_intent"); + mWakeUpComingFromTouch = false; + mWakeUpTouchLocation = null; + } + } + void makeExpandedVisible(boolean force) { if (SPEW) Log.d(TAG, "Make expanded visible: expanded visible=" + mExpandedVisible); if (!force && (mExpandedVisible || !mCommandQueue.panelsEnabled())) { @@ -2096,7 +2082,7 @@ public class StatusBar extends SystemUI implements mShadeController.runPostCollapseRunnables(); setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false); if (!mNotificationActivityStarter.isCollapsingToShowActivityOverLockscreen()) { - showBouncerIfKeyguard(); + showBouncerOrLockScreenIfKeyguard(); } else if (DEBUG) { Log.d(TAG, "Not showing bouncer due to activity showing over lockscreen"); } @@ -3302,13 +3288,17 @@ public class StatusBar extends SystemUI implements return false; } - private void showBouncerIfKeyguard() { + private void showBouncerOrLockScreenIfKeyguard() { if (!mKeyguardViewMediator.isHiding()) { - if (mState == StatusBarState.KEYGUARD - && !mStatusBarKeyguardViewManager.bouncerIsOrWillBeShowing()) { + if (mState == StatusBarState.SHADE_LOCKED + && mKeyguardUpdateMonitor.isUdfpsEnrolled()) { + // shade is showing while locked on the keyguard, so go back to showing the + // lock screen where users can use the UDFPS affordance to enter the device + mStatusBarKeyguardViewManager.reset(true); + } else if ((mState == StatusBarState.KEYGUARD + && !mStatusBarKeyguardViewManager.bouncerIsOrWillBeShowing()) + || mState == StatusBarState.SHADE_LOCKED) { mStatusBarKeyguardViewManager.showGenericBouncer(true /* scrimmed */); - } else if (mState == StatusBarState.SHADE_LOCKED) { - mStatusBarKeyguardViewManager.showBouncer(true /* scrimmed */); } } } @@ -3443,6 +3433,14 @@ public class StatusBar extends SystemUI implements return mNavigationBarController.getNavigationBarView(mDisplayId); } + public void showPinningEnterExitToast(boolean entering) { + mNavigationBarController.showPinningEnterExitToast(mDisplayId, entering); + } + + public void showPinningEscapeToast() { + mNavigationBarController.showPinningEscapeToast(mDisplayId); + } + /** * TODO: Remove this method. Views should not be passed forward. Will cause theme issues. * @return bottom area view @@ -3536,7 +3534,7 @@ public class StatusBar extends SystemUI implements DejankUtils.startDetectingBlockingIpcs(tag); updateRevealEffect(false /* wakingUp */); updateNotificationPanelTouchState(); - notifyHeadsUpGoingToSleep(); + maybeEscalateHeadsUp(); dismissVolumeDialog(); mWakeUpCoordinator.setFullyAwake(false); mBypassHeadsUpNotifier.setFullyAwake(false); @@ -3822,6 +3820,7 @@ public class StatusBar extends SystemUI implements private final DeviceProvisionedController mDeviceProvisionedController; private final NavigationBarController mNavigationBarController; + private final AccessibilityFloatingMenuController mAccessibilityFloatingMenuController; // UI-specific methods @@ -4081,10 +4080,6 @@ public class StatusBar extends SystemUI implements } } - protected void notifyHeadsUpGoingToSleep() { - maybeEscalateHeadsUp(); - } - /** * @return Whether the security bouncer from Keyguard is showing. */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarCommandQueueCallbacks.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarCommandQueueCallbacks.java index a77a097f0453..3ce4472014c8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarCommandQueueCallbacks.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarCommandQueueCallbacks.java @@ -549,16 +549,12 @@ public class StatusBarCommandQueueCallbacks implements CommandQueue.Callbacks { @Override public void showPinningEnterExitToast(boolean entering) { - if (mStatusBar.getNavigationBarView() != null) { - mStatusBar.getNavigationBarView().showPinningEnterExitToast(entering); - } + mStatusBar.showPinningEnterExitToast(entering); } @Override public void showPinningEscapeToast() { - if (mStatusBar.getNavigationBarView() != null) { - mStatusBar.getNavigationBarView().showPinningEscapeToast(); - } + mStatusBar.showPinningEscapeToast(); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java index 0d23d663c51c..b84e6e6f37cc 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java @@ -60,6 +60,7 @@ import com.android.systemui.shared.system.SysUiStatsLog; import com.android.systemui.statusbar.NotificationMediaManager; import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.RemoteInputController; +import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.statusbar.notification.ViewGroupFadeHelper; import com.android.systemui.statusbar.phone.KeyguardBouncer.BouncerExpansionCallback; @@ -337,6 +338,12 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb // • Full-screen user switcher is displayed. if (mNotificationPanelViewController.isUnlockHintRunning()) { mBouncer.setExpansion(KeyguardBouncer.EXPANSION_HIDDEN); + } else if (mStatusBarStateController.getState() == StatusBarState.SHADE_LOCKED + && mKeyguardUpdateManager.isUdfpsEnrolled()) { + // Don't expand to the bouncer. Instead transition back to the lock screen (see + // StatusBar#showBouncerOrLockScreenIfKeyguard) where the user can use the UDFPS + // affordance to enter the device (or swipe up to the input bouncer) + return; } else if (bouncerNeedsScrimming()) { mBouncer.setExpansion(KeyguardBouncer.EXPANSION_VISIBLE); } else if (mShowing) { @@ -555,12 +562,13 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb public void onStartedWakingUp() { mStatusBar.getNotificationShadeWindowView().getWindowInsetsController() .setAnimationsDisabled(false); - View currentView = getCurrentNavBarView(); - if (currentView != null) { - currentView.animate() - .alpha(1f) - .setDuration(NAV_BAR_CONTENT_FADE_DURATION) - .start(); + NavigationBarView navBarView = mStatusBar.getNavigationBarView(); + if (navBarView != null) { + navBarView.forEachView(view -> + view.animate() + .alpha(1f) + .setDuration(NAV_BAR_CONTENT_FADE_DURATION) + .start()); } } @@ -568,12 +576,13 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb public void onStartedGoingToSleep() { mStatusBar.getNotificationShadeWindowView().getWindowInsetsController() .setAnimationsDisabled(true); - View currentView = getCurrentNavBarView(); - if (currentView != null) { - currentView.animate() - .alpha(0f) - .setDuration(NAV_BAR_CONTENT_FADE_DURATION) - .start(); + NavigationBarView navBarView = mStatusBar.getNavigationBarView(); + if (navBarView != null) { + navBarView.forEachView(view -> + view.animate() + .alpha(0f) + .setDuration(NAV_BAR_CONTENT_FADE_DURATION) + .start()); } } @@ -1015,17 +1024,6 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb mStatusBar.onKeyguardViewManagerStatesUpdated(); } - /** - * Updates the visibility of the nav bar content views. - */ - private void updateNavigationBarContentVisibility(boolean navBarContentVisible) { - final NavigationBarView navBarView = mStatusBar.getNavigationBarView(); - if (navBarView != null && navBarView.getCurrentView() != null) { - final View currentView = navBarView.getCurrentView(); - currentView.setVisibility(navBarContentVisible ? View.VISIBLE : View.INVISIBLE); - } - } - private View getCurrentNavBarView() { final NavigationBarView navBarView = mStatusBar.getNavigationBarView(); return navBarView != null ? navBarView.getCurrentView() : null; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java index dba3b2418790..ce3811113912 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java @@ -41,6 +41,8 @@ import android.text.TextUtils; import android.util.EventLog; import android.view.View; +import androidx.annotation.VisibleForTesting; + import com.android.internal.jank.InteractionJankMonitor; import com.android.internal.logging.MetricsLogger; import com.android.internal.statusbar.NotificationVisibility; @@ -593,7 +595,8 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit } } - private void handleFullScreenIntent(NotificationEntry entry) { + @VisibleForTesting + void handleFullScreenIntent(NotificationEntry entry) { if (mNotificationInterruptStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry)) { if (shouldSuppressFullScreenIntent(entry)) { mLogger.logFullScreenIntentSuppressedByDnD(entry.getKey()); @@ -617,6 +620,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit try { EventLog.writeEvent(EventLogTags.SYSUI_FULLSCREEN_NOTIFICATION, entry.getKey()); + mStatusBar.wakeUpForFullScreenIntent(); fullscreenIntent.send(); entry.notifyFullScreenIntentLaunched(); mMetricsLogger.count("note_fullscreen", 1); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java index ed52a81751dd..43264b600a0e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java @@ -40,30 +40,21 @@ import androidx.annotation.Nullable; import com.android.systemui.Dependency; import com.android.systemui.R; -import com.android.systemui.animation.DialogListener; -import com.android.systemui.animation.DialogListener.DismissReason; -import com.android.systemui.animation.ListenableDialog; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.statusbar.policy.KeyguardStateController; -import java.util.LinkedHashSet; -import java.util.Set; - - /** * Base class for dialogs that should appear over panels and keyguard. * The SystemUIDialog registers a listener for the screen off / close system dialogs broadcast, * and dismisses itself when it receives the broadcast. */ -public class SystemUIDialog extends AlertDialog implements ListenableDialog, - ViewRootImpl.ConfigChangedCallback { +public class SystemUIDialog extends AlertDialog implements ViewRootImpl.ConfigChangedCallback { // TODO(b/203389579): Remove this once the dialog width on large screens has been agreed on. private static final String FLAG_TABLET_DIALOG_WIDTH = "persist.systemui.flag_tablet_dialog_width"; private final Context mContext; private final DismissReceiver mDismissReceiver; - private final Set<DialogListener> mDialogListeners = new LinkedHashSet<>(); private final Handler mHandler = new Handler(); private int mLastWidth = Integer.MIN_VALUE; @@ -117,10 +108,6 @@ public class SystemUIDialog extends AlertDialog implements ListenableDialog, mLastWidth = width; mLastHeight = height; getWindow().setLayout(width, height); - - for (DialogListener listener : new LinkedHashSet<>(mDialogListeners)) { - listener.onSizeChanged(); - } } @Override @@ -197,60 +184,6 @@ public class SystemUIDialog extends AlertDialog implements ListenableDialog, ViewRootImpl.removeConfigCallback(this); } - @Override - public void addListener(DialogListener listener) { - mDialogListeners.add(listener); - } - - @Override - public void removeListener(DialogListener listener) { - mDialogListeners.remove(listener); - } - - @Override - public void dismiss() { - dismiss(DismissReason.UNKNOWN); - } - - private void dismiss(DismissReason reason) { - super.dismiss(); - - for (DialogListener listener : new LinkedHashSet<>(mDialogListeners)) { - listener.onDismiss(reason); - } - } - - /** - * Dismiss this dialog. If it was launched from another dialog using - * {@link com.android.systemui.animation.DialogLaunchAnimator#showFromView} with a - * non-{@code null} {@code parentHostDialog} parameter, also dismisses the stack of dialogs, - * animating back to the original touchSurface. - */ - public void dismissStack() { - for (DialogListener listener : new LinkedHashSet<>(mDialogListeners)) { - listener.prepareForStackDismiss(); - } - dismiss(); - } - - @Override - public void hide() { - super.hide(); - - for (DialogListener listener : new LinkedHashSet<>(mDialogListeners)) { - listener.onHide(); - } - } - - @Override - public void show() { - super.show(); - - for (DialogListener listener : new LinkedHashSet<>(mDialogListeners)) { - listener.onShow(); - } - } - public void setShowForAllUsers(boolean show) { setShowForAllUsers(this, show); } @@ -364,11 +297,7 @@ public class SystemUIDialog extends AlertDialog implements ListenableDialog, @Override public void onReceive(Context context, Intent intent) { - if (mDialog instanceof SystemUIDialog) { - ((SystemUIDialog) mDialog).dismiss(DismissReason.DEVICE_LOCKED); - } else { - mDialog.dismiss(); - } + mDialog.dismiss(); } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIHostDialogProvider.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIHostDialogProvider.kt deleted file mode 100644 index 4f18f8c597b2..000000000000 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIHostDialogProvider.kt +++ /dev/null @@ -1,51 +0,0 @@ -package com.android.systemui.statusbar.phone - -import android.app.Dialog -import android.content.Context -import android.os.Bundle -import android.view.ViewGroup -import com.android.systemui.animation.HostDialogProvider - -/** An implementation of [HostDialogProvider] to be used when animating SysUI dialogs. */ -class SystemUIHostDialogProvider : HostDialogProvider { - override fun createHostDialog( - context: Context, - theme: Int, - onCreateCallback: () -> Unit, - dismissOverride: (() -> Unit) -> Unit - ): Dialog { - return SystemUIHostDialog(context, theme, onCreateCallback, dismissOverride) - } - - /** - * This host dialog is a SystemUIDialog so that it's displayed above all SystemUI windows. Note - * that it is not automatically dismissed when the device is locked, but only when the hosted - * (original) dialog is dismissed. That way, the behavior of the dialog (dismissed when locking - * or not) is consistent with when the dialog is shown with or without the dialog animator. - */ - private class SystemUIHostDialog( - context: Context, - theme: Int, - private val onCreateCallback: () -> Unit, - private val dismissOverride: (() -> Unit) -> Unit - ) : SystemUIDialog(context, theme, false /* dismissOnDeviceLock */) { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - onCreateCallback() - } - - override fun dismiss() { - dismissOverride { - super.dismiss() - } - } - - override fun getWidth(): Int { - return ViewGroup.LayoutParams.MATCH_PARENT - } - - override fun getHeight(): Int { - return ViewGroup.LayoutParams.MATCH_PARENT - } - } -}
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java index 50e6151bd3a3..fcb98fa8e972 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java @@ -28,6 +28,7 @@ import com.android.internal.logging.MetricsLogger; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.ViewMediatorCallback; import com.android.systemui.InitController; +import com.android.systemui.accessibility.floatingmenu.AccessibilityFloatingMenuController; import com.android.systemui.animation.ActivityLaunchAnimator; import com.android.systemui.assist.AssistManager; import com.android.systemui.broadcast.BroadcastDispatcher; @@ -88,7 +89,6 @@ import com.android.systemui.statusbar.phone.LockscreenGestureLogger; import com.android.systemui.statusbar.phone.LockscreenWallpaper; import com.android.systemui.statusbar.phone.NotificationIconAreaController; import com.android.systemui.statusbar.phone.PhoneStatusBarPolicy; -import com.android.systemui.statusbar.phone.PhoneStatusBarViewController; import com.android.systemui.statusbar.phone.ScrimController; import com.android.systemui.statusbar.phone.ShadeController; import com.android.systemui.statusbar.phone.StatusBar; @@ -185,6 +185,7 @@ public interface StatusBarPhoneModule { VisualStabilityManager visualStabilityManager, DeviceProvisionedController deviceProvisionedController, NavigationBarController navigationBarController, + AccessibilityFloatingMenuController accessibilityFloatingMenuController, Lazy<AssistManager> assistManagerLazy, ConfigurationController configurationController, NotificationShadeWindowController notificationShadeWindowController, @@ -216,7 +217,6 @@ public interface StatusBarPhoneModule { ExtensionController extensionController, UserInfoControllerImpl userInfoControllerImpl, OperatorNameViewController.Factory operatorNameViewControllerFactory, - PhoneStatusBarViewController.Factory phoneStatusBarViewControllerFactory, PhoneStatusBarPolicy phoneStatusBarPolicy, KeyguardIndicationController keyguardIndicationController, DemoModeController demoModeController, @@ -287,6 +287,7 @@ public interface StatusBarPhoneModule { visualStabilityManager, deviceProvisionedController, navigationBarController, + accessibilityFloatingMenuController, assistManagerLazy, configurationController, notificationShadeWindowController, @@ -317,7 +318,6 @@ public interface StatusBarPhoneModule { extensionController, userInfoControllerImpl, operatorNameViewControllerFactory, - phoneStatusBarViewControllerFactory, phoneStatusBarPolicy, keyguardIndicationController, demoModeController, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java index 76176df136b5..14cca13b396b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java @@ -32,6 +32,7 @@ import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.flags.FeatureFlags; import com.android.systemui.plugins.statusbar.StatusBarStateController; +import com.android.systemui.privacy.OngoingPrivacyChip; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.NotificationShelf; import com.android.systemui.statusbar.NotificationShelfController; @@ -45,10 +46,10 @@ import com.android.systemui.statusbar.phone.NotificationPanelView; import com.android.systemui.statusbar.phone.NotificationPanelViewController; import com.android.systemui.statusbar.phone.NotificationShadeWindowView; import com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer; -import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.phone.StatusBarHideIconsForBouncerManager; import com.android.systemui.statusbar.phone.StatusBarIconController; import com.android.systemui.statusbar.phone.StatusBarLocationPublisher; +import com.android.systemui.statusbar.phone.StatusIconContainer; import com.android.systemui.statusbar.phone.TapAgainView; import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment; import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragmentLogger; @@ -60,15 +61,12 @@ import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.tuner.TunerService; -import java.util.Optional; - import javax.inject.Named; -import dagger.Lazy; import dagger.Module; import dagger.Provides; -@Module +@Module(subcomponents = StatusBarFragmentComponent.class) public abstract class StatusBarViewModule { public static final String SPLIT_SHADE_HEADER = "split_shade_header"; @@ -173,6 +171,21 @@ public abstract class StatusBarViewModule { /** */ @Provides @StatusBarComponent.StatusBarScope + public static OngoingPrivacyChip getSplitShadeOngoingPrivacyChip( + @Named(SPLIT_SHADE_HEADER) View header) { + return header.findViewById(R.id.privacy_chip); + } + + /** */ + @Provides + @StatusBarComponent.StatusBarScope + static StatusIconContainer providesStatusIconContainer(@Named(SPLIT_SHADE_HEADER) View header) { + return header.findViewById(R.id.statusIcons); + } + + /** */ + @Provides + @StatusBarComponent.StatusBarScope @Named(SPLIT_SHADE_BATTERY_VIEW) static BatteryMeterView getBatteryMeterView(@Named(SPLIT_SHADE_HEADER) View view) { return view.findViewById(R.id.batteryRemainingIcon); @@ -236,7 +249,6 @@ public abstract class StatusBarViewModule { NotificationIconAreaController notificationIconAreaController, PanelExpansionStateManager panelExpansionStateManager, FeatureFlags featureFlags, - Lazy<Optional<StatusBar>> statusBarOptionalLazy, StatusBarIconController statusBarIconController, StatusBarHideIconsForBouncerManager statusBarHideIconsForBouncerManager, KeyguardStateController keyguardStateController, @@ -254,7 +266,6 @@ public abstract class StatusBarViewModule { notificationIconAreaController, panelExpansionStateManager, featureFlags, - statusBarOptionalLazy, statusBarIconController, statusBarHideIconsForBouncerManager, keyguardStateController, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java index b32acce51e84..d6ba6f3ff97a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java @@ -55,7 +55,6 @@ import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler; import com.android.systemui.statusbar.phone.NotificationIconAreaController; import com.android.systemui.statusbar.phone.NotificationPanelViewController; import com.android.systemui.statusbar.phone.PhoneStatusBarView; -import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.phone.StatusBarHideIconsForBouncerManager; import com.android.systemui.statusbar.phone.StatusBarIconController; import com.android.systemui.statusbar.phone.StatusBarIconController.DarkIconManager; @@ -71,12 +70,9 @@ import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; -import java.util.Optional; import javax.inject.Inject; -import dagger.Lazy; - /** * Contains the collapsed status bar and handles hiding/showing based on disable flags * and keyguard state. Also manages lifecycle to make sure the views it contains are being @@ -104,7 +100,6 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue private View mCenteredIconArea; private int mDisabled1; private int mDisabled2; - private Lazy<Optional<StatusBar>> mStatusBarOptionalLazy; private DarkIconManager mDarkIconManager; private final StatusBarFragmentComponent.Factory mStatusBarFragmentComponentFactory; private final CommandQueue mCommandQueue; @@ -145,7 +140,6 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue NotificationIconAreaController notificationIconAreaController, PanelExpansionStateManager panelExpansionStateManager, FeatureFlags featureFlags, - Lazy<Optional<StatusBar>> statusBarOptionalLazy, StatusBarIconController statusBarIconController, StatusBarHideIconsForBouncerManager statusBarHideIconsForBouncerManager, KeyguardStateController keyguardStateController, @@ -163,7 +157,6 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue mNotificationIconAreaController = notificationIconAreaController; mPanelExpansionStateManager = panelExpansionStateManager; mFeatureFlags = featureFlags; - mStatusBarOptionalLazy = statusBarOptionalLazy; mStatusBarIconController = statusBarIconController; mStatusBarHideIconsForBouncerManager = statusBarHideIconsForBouncerManager; mKeyguardStateController = keyguardStateController; @@ -329,8 +322,8 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue } protected int adjustDisableFlags(int state) { - boolean headsUpVisible = mStatusBarOptionalLazy.get() - .map(StatusBar::headsUpShouldBeVisible).orElse(false); + boolean headsUpVisible = + mStatusBarFragmentComponent.getHeadsUpAppearanceController().shouldBeVisible(); if (headsUpVisible) { state |= DISABLE_CLOCK; } @@ -399,10 +392,8 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue } private boolean shouldHideNotificationIcons() { - final Optional<StatusBar> statusBarOptional = mStatusBarOptionalLazy.get(); if (!mPanelExpansionStateManager.isClosed() - && statusBarOptional.map( - StatusBar::hideStatusBarIconsWhenExpanded).orElse(false)) { + && mNotificationPanelViewController.hideStatusBarIconsWhenExpanded()) { return true; } return mStatusBarHideIconsForBouncerManager.getShouldHideStatusBarIconsForBouncer(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentComponent.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentComponent.java index 47c187540740..3656ed116b32 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentComponent.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentComponent.java @@ -18,7 +18,9 @@ package com.android.systemui.statusbar.phone.fragment.dagger; import com.android.systemui.battery.BatteryMeterViewController; import com.android.systemui.dagger.qualifiers.RootView; +import com.android.systemui.statusbar.phone.HeadsUpAppearanceController; import com.android.systemui.statusbar.phone.PhoneStatusBarView; +import com.android.systemui.statusbar.phone.PhoneStatusBarViewController; import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment; import dagger.BindsInstance; @@ -56,6 +58,8 @@ public interface StatusBarFragmentComponent { // No one accesses this controller, so we need to make sure we reference it here so it does // get initialized. getBatteryMeterViewController().init(); + getHeadsUpAppearanceController().init(); + getPhoneStatusBarViewController().init(); } /** */ @@ -66,4 +70,12 @@ public interface StatusBarFragmentComponent { @StatusBarFragmentScope @RootView PhoneStatusBarView getPhoneStatusBarView(); + + /** */ + @StatusBarFragmentScope + PhoneStatusBarViewController getPhoneStatusBarViewController(); + + /** */ + @StatusBarFragmentScope + HeadsUpAppearanceController getHeadsUpAppearanceController(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentModule.java index 969361bb6100..d2445580d56b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentModule.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentModule.java @@ -19,7 +19,9 @@ package com.android.systemui.statusbar.phone.fragment.dagger; import com.android.systemui.R; import com.android.systemui.battery.BatteryMeterView; import com.android.systemui.dagger.qualifiers.RootView; +import com.android.systemui.statusbar.phone.NotificationPanelViewController; import com.android.systemui.statusbar.phone.PhoneStatusBarView; +import com.android.systemui.statusbar.phone.PhoneStatusBarViewController; import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment; import dagger.Module; @@ -43,4 +45,16 @@ public interface StatusBarFragmentModule { static BatteryMeterView provideBatteryMeterView(@RootView PhoneStatusBarView view) { return view.findViewById(R.id.battery); } + + /** */ + @Provides + @StatusBarFragmentScope + static PhoneStatusBarViewController providePhoneStatusBarViewController( + PhoneStatusBarViewController.Factory phoneStatusBarViewControllerFactory, + @RootView PhoneStatusBarView phoneStatusBarView, + NotificationPanelViewController notificationPanelViewController) { + return phoneStatusBarViewControllerFactory.create( + phoneStatusBarView, + notificationPanelViewController.getStatusBarTouchEventHandler()); + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java index 85add6c21b72..aec9db5c2de2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java @@ -219,6 +219,7 @@ public class SmartReplyView extends ViewGroup { private void clearLayoutLineCount(View view) { if (view instanceof TextView) { ((TextView) view).nullLayouts(); + view.forceLayout(); } } @@ -270,6 +271,9 @@ public class SmartReplyView extends ViewGroup { clearLayoutLineCount(child); child.measure(MEASURE_SPEC_ANY_LENGTH, heightMeasureSpec); + if (((Button) child).getLayout() == null) { + Log.wtf(TAG, "Button layout is null after measure."); + } coveredSuggestions.add(child); @@ -590,6 +594,9 @@ public class SmartReplyView extends ViewGroup { button.getPaddingLeft() + button.getPaddingRight() + textWidth + getLeftCompoundDrawableWidthWithPadding(button), MeasureSpec.AT_MOST); button.measure(widthMeasureSpec, heightMeasureSpec); + if (button.getLayout() == null) { + Log.wtf(TAG, "Button layout is null after measure."); + } final int newWidth = button.getMeasuredWidth(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java index fd387ae0a82e..36e56f967424 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java @@ -69,6 +69,7 @@ import com.android.systemui.Prefs; import com.android.systemui.Prefs.Key; import com.android.systemui.R; import com.android.systemui.SystemUISecondaryUserService; +import com.android.systemui.animation.DialogLaunchAnimator; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Background; @@ -133,6 +134,7 @@ public class UserSwitcherController implements Dumpable { private final IActivityTaskManager mActivityTaskManager; private final InteractionJankMonitor mInteractionJankMonitor; private final LatencyTracker mLatencyTracker; + private final DialogLaunchAnimator mDialogLaunchAnimator; private ArrayList<UserRecord> mUsers = new ArrayList<>(); @VisibleForTesting @@ -180,7 +182,8 @@ public class UserSwitcherController implements Dumpable { @Background Executor bgExecutor, InteractionJankMonitor interactionJankMonitor, LatencyTracker latencyTracker, - DumpManager dumpManager) { + DumpManager dumpManager, + DialogLaunchAnimator dialogLaunchAnimator) { mContext = context; mActivityManager = activityManager; mUserTracker = userTracker; @@ -208,6 +211,8 @@ public class UserSwitcherController implements Dumpable { mHandler = handler; mActivityStarter = activityStarter; mUserManager = userManager; + mDialogLaunchAnimator = dialogLaunchAnimator; + IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_USER_ADDED); filter.addAction(Intent.ACTION_USER_REMOVED); @@ -1179,7 +1184,7 @@ public class UserSwitcherController implements Dumpable { cancel(); } else { mUiEventLogger.log(QSUserSwitcherEvent.QS_USER_GUEST_REMOVE); - dismissStack(); + mDialogLaunchAnimator.dismissStack(this); removeGuestUser(mGuestId, mTargetId); } } @@ -1210,7 +1215,7 @@ public class UserSwitcherController implements Dumpable { if (which == BUTTON_NEGATIVE) { cancel(); } else { - dismissStack(); + mDialogLaunchAnimator.dismissStack(this); if (ActivityManager.isUserAMonkey()) { return; } diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java index a56c177ef9ae..b546edf428b8 100644 --- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java +++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java @@ -56,6 +56,7 @@ import com.android.systemui.statusbar.policy.UserInfoController; import com.android.systemui.tracing.ProtoTracer; import com.android.systemui.tracing.nano.SystemUiTraceProto; import com.android.wm.shell.ShellCommandHandler; +import com.android.wm.shell.draganddrop.DragAndDrop; import com.android.wm.shell.hidedisplaycutout.HideDisplayCutout; import com.android.wm.shell.legacysplitscreen.LegacySplitScreen; import com.android.wm.shell.nano.WmShellTraceProto; @@ -114,6 +115,7 @@ public final class WMShell extends SystemUI private final Optional<HideDisplayCutout> mHideDisplayCutoutOptional; private final Optional<ShellCommandHandler> mShellCommandHandler; private final Optional<SizeCompatUI> mSizeCompatUIOptional; + private final Optional<DragAndDrop> mDragAndDropOptional; private final CommandQueue mCommandQueue; private final ConfigurationController mConfigurationController; @@ -142,6 +144,7 @@ public final class WMShell extends SystemUI Optional<HideDisplayCutout> hideDisplayCutoutOptional, Optional<ShellCommandHandler> shellCommandHandler, Optional<SizeCompatUI> sizeCompatUIOptional, + Optional<DragAndDrop> dragAndDropOptional, CommandQueue commandQueue, ConfigurationController configurationController, KeyguardUpdateMonitor keyguardUpdateMonitor, @@ -167,6 +170,7 @@ public final class WMShell extends SystemUI mProtoTracer = protoTracer; mShellCommandHandler = shellCommandHandler; mSizeCompatUIOptional = sizeCompatUIOptional; + mDragAndDropOptional = dragAndDropOptional; mSysUiMainExecutor = sysUiMainExecutor; } @@ -182,6 +186,7 @@ public final class WMShell extends SystemUI mOneHandedOptional.ifPresent(this::initOneHanded); mHideDisplayCutoutOptional.ifPresent(this::initHideDisplayCutout); mSizeCompatUIOptional.ifPresent(this::initSizeCompatUi); + mDragAndDropOptional.ifPresent(this::initDragAndDrop); } @VisibleForTesting @@ -396,6 +401,20 @@ public final class WMShell extends SystemUI mKeyguardUpdateMonitor.registerCallback(mSizeCompatUIKeyguardCallback); } + void initDragAndDrop(DragAndDrop dragAndDrop) { + mConfigurationController.addCallback(new ConfigurationController.ConfigurationListener() { + @Override + public void onConfigChanged(Configuration newConfig) { + dragAndDrop.onConfigChanged(newConfig); + } + + @Override + public void onThemeChanged() { + dragAndDrop.onThemeChanged(); + } + }); + } + @Override public void writeToProto(SystemUiTraceProto proto) { if (proto.wmShell == null) { diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java index de8cc8992da0..ef9b850c99c2 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java @@ -1056,6 +1056,16 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { verify(callback, atLeastOnce()).onRequireUnlockForNfc(); } + @Test + public void testFaceDoesNotAuth_afterPinAttempt() { + mTestableLooper.processAllMessages(); + mKeyguardUpdateMonitor.setCredentialAttempted(); + verify(mFingerprintManager, never()).authenticate(any(), any(), any(), + any(), anyInt()); + verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(), + anyBoolean()); + } + private void setKeyguardBouncerVisibility(boolean isVisible) { mKeyguardUpdateMonitor.sendKeyguardBouncerChanged(isVisible); mTestableLooper.processAllMessages(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuControllerTest.java index 62370313e5ae..f56bf69f9101 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuControllerTest.java @@ -282,9 +282,12 @@ public class AccessibilityFloatingMenuControllerTest extends SysuiTestCase { mTargetsObserver = spy(Dependency.get(AccessibilityButtonTargetsObserver.class)); mModeObserver = spy(Dependency.get(AccessibilityButtonModeObserver.class)); mKeyguardUpdateMonitor = Dependency.get(KeyguardUpdateMonitor.class); + final AccessibilityFloatingMenuController controller = + new AccessibilityFloatingMenuController(mContextWrapper, mTargetsObserver, + mModeObserver, mKeyguardUpdateMonitor); + controller.init(); - return new AccessibilityFloatingMenuController(mContextWrapper, mTargetsObserver, - mModeObserver, mKeyguardUpdateMonitor); + return controller; } private void enableAccessibilityFloatingMenuConfig() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/DialogLaunchAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/animation/DialogLaunchAnimatorTest.kt index 9bd33eb8db6b..f9ad740f86df 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/animation/DialogLaunchAnimatorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/animation/DialogLaunchAnimatorTest.kt @@ -2,35 +2,49 @@ package com.android.systemui.animation import android.app.Dialog import android.content.Context +import android.graphics.Color +import android.graphics.drawable.ColorDrawable import android.os.Bundle +import android.service.dreams.IDreamManager import android.testing.AndroidTestingRunner import android.testing.TestableLooper import android.testing.ViewUtils import android.view.View import android.view.ViewGroup +import android.view.ViewGroup.LayoutParams.MATCH_PARENT import android.view.WindowManager import android.widget.LinearLayout import androidx.test.filters.SmallTest +import com.android.internal.policy.DecorView import com.android.systemui.SysuiTestCase -import com.android.systemui.animation.DialogListener.DismissReason import junit.framework.Assert.assertEquals import junit.framework.Assert.assertFalse +import junit.framework.Assert.assertNotNull import junit.framework.Assert.assertTrue import org.junit.After +import org.junit.Before +import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith +import org.mockito.Mock +import org.mockito.junit.MockitoJUnit @SmallTest @RunWith(AndroidTestingRunner::class) @TestableLooper.RunWithLooper class DialogLaunchAnimatorTest : SysuiTestCase() { private val launchAnimator = LaunchAnimator(context, isForTesting = true) - private val hostDialogprovider = TestHostDialogProvider() - private val dialogLaunchAnimator = - DialogLaunchAnimator(context, launchAnimator, hostDialogprovider) - + private lateinit var dialogLaunchAnimator: DialogLaunchAnimator private val attachedViews = mutableSetOf<View>() + @Mock lateinit var dreamManager: IDreamManager + @get:Rule val rule = MockitoJUnit.rule() + + @Before + fun setUp() { + dialogLaunchAnimator = DialogLaunchAnimator(context, launchAnimator, dreamManager) + } + @After fun tearDown() { runOnMainThreadAndWaitForIdleSync { @@ -44,76 +58,66 @@ class DialogLaunchAnimatorTest : SysuiTestCase() { fun testShowDialogFromView() { // Show the dialog. showFromView() must be called on the main thread with a dialog created // on the main thread too. - val (dialog, hostDialog) = createDialogAndHostDialog() - - // Only the host dialog is actually showing. - assertTrue(hostDialog.isShowing) - assertFalse(dialog.isShowing) - - // The dialog onStart() method was called but not onStop(). - assertTrue(dialog.onStartCalled) - assertFalse(dialog.onStopCalled) - - // The dialog content has been stolen and is shown inside the host dialog. - val hostDialogContent = hostDialog.findViewById<ViewGroup>(android.R.id.content) - assertEquals(0, dialog.findViewById<ViewGroup>(android.R.id.content).childCount) - assertEquals(1, hostDialogContent.childCount) - - // The original dialog content is added to another view that is the same size as the - // original dialog window. - val hostDialogRoot = hostDialogContent.getChildAt(0) as ViewGroup - assertEquals(1, hostDialogRoot.childCount) - - val dialogContentParent = hostDialogRoot.getChildAt(0) as ViewGroup - assertEquals(1, dialogContentParent.childCount) - assertEquals(TestDialog.DIALOG_WIDTH, dialogContentParent.layoutParams.width) - assertEquals(TestDialog.DIALOG_HEIGHT, dialogContentParent.layoutParams.height) - - val dialogContent = dialogContentParent.getChildAt(0) - assertEquals(dialog.contentView, dialogContent) - assertEquals(ViewGroup.LayoutParams.MATCH_PARENT, dialogContent.layoutParams.width) - assertEquals(ViewGroup.LayoutParams.MATCH_PARENT, dialogContent.layoutParams.height) - - // Hiding/showing/dismissing the dialog should hide/show/dismiss the host dialog given that - // it's a ListenableDialog. - runOnMainThreadAndWaitForIdleSync { dialog.hide() } - assertFalse(hostDialog.isShowing) - assertFalse(dialog.isShowing) - - runOnMainThreadAndWaitForIdleSync { dialog.show() } - assertTrue(hostDialog.isShowing) - assertFalse(dialog.isShowing) - - assertFalse(dialog.onStopCalled) + val dialog = createAndShowDialog() + + assertTrue(dialog.isShowing) + + // The dialog is now fullscreen. + val window = dialog.window + val decorView = window.decorView as DecorView + assertEquals(MATCH_PARENT, window.attributes.width) + assertEquals(MATCH_PARENT, window.attributes.height) + assertEquals(MATCH_PARENT, decorView.layoutParams.width) + assertEquals(MATCH_PARENT, decorView.layoutParams.height) + + // The single DecorView child is a transparent fullscreen view that will dismiss the dialog + // when clicked. + assertEquals(1, decorView.childCount) + val transparentBackground = decorView.getChildAt(0) as ViewGroup + assertEquals(MATCH_PARENT, transparentBackground.layoutParams.width) + assertEquals(MATCH_PARENT, transparentBackground.layoutParams.height) + + // The single transparent background child is a fake window with the same size and + // background as the dialog initially had. + assertEquals(1, transparentBackground.childCount) + val dialogContentWithBackground = transparentBackground.getChildAt(0) as ViewGroup + assertEquals(TestDialog.DIALOG_WIDTH, dialogContentWithBackground.layoutParams.width) + assertEquals(TestDialog.DIALOG_HEIGHT, dialogContentWithBackground.layoutParams.height) + assertEquals(dialog.windowBackground, dialogContentWithBackground.background) + + // The dialog content is inside this fake window view. + assertNotNull( + dialogContentWithBackground.findViewByPredicate { it === dialog.contentView }) + + // Clicking the transparent background should dismiss the dialog. runOnMainThreadAndWaitForIdleSync { // TODO(b/204561691): Remove this call to disableAllCurrentDialogsExitAnimations() and // make sure that the test still pass on git_master/cf_x86_64_phone-userdebug in // Forrest. dialogLaunchAnimator.disableAllCurrentDialogsExitAnimations() - dialog.dismiss() + transparentBackground.performClick() } - assertFalse(hostDialog.isShowing) assertFalse(dialog.isShowing) - assertTrue(hostDialog.wasDismissed) - assertTrue(dialog.onStopCalled) } @Test fun testStackedDialogsDismissesAll() { - val (_, hostDialogFirst) = createDialogAndHostDialog() - val (dialogSecond, hostDialogSecond) = createDialogAndHostDialogFromDialog(hostDialogFirst) + val firstDialog = createAndShowDialog() + val secondDialog = createDialogAndShowFromDialog(firstDialog) + assertTrue(firstDialog.isShowing) + assertTrue(secondDialog.isShowing) runOnMainThreadAndWaitForIdleSync { dialogLaunchAnimator.disableAllCurrentDialogsExitAnimations() - dialogSecond.dismissStack() + dialogLaunchAnimator.dismissStack(secondDialog) } - assertTrue(hostDialogSecond.wasDismissed) - assertTrue(hostDialogFirst.wasDismissed) + assertFalse(firstDialog.isShowing) + assertFalse(secondDialog.isShowing) } - private fun createDialogAndHostDialog(): Pair<TestDialog, TestHostDialog> { + private fun createAndShowDialog(): TestDialog { return runOnMainThreadAndWaitForIdleSync { val touchSurfaceRoot = LinearLayout(context) val touchSurface = View(context) @@ -125,22 +129,16 @@ class DialogLaunchAnimatorTest : SysuiTestCase() { attachedViews.add(touchSurfaceRoot) val dialog = TestDialog(context) - val hostDialog = - dialogLaunchAnimator.showFromView(dialog, touchSurface) as TestHostDialog - dialog to hostDialog + dialogLaunchAnimator.showFromView(dialog, touchSurface) + dialog } } - private fun createDialogAndHostDialogFromDialog( - hostParent: Dialog - ): Pair<TestDialog, TestHostDialog> { + private fun createDialogAndShowFromDialog(animateFrom: Dialog): TestDialog { return runOnMainThreadAndWaitForIdleSync { val dialog = TestDialog(context) - val hostDialog = dialogLaunchAnimator.showFromDialog( - dialog, - hostParent - ) as TestHostDialog - dialog to hostDialog + dialogLaunchAnimator.showFromDialog(dialog, animateFrom) + dialog } } @@ -153,50 +151,14 @@ class DialogLaunchAnimatorTest : SysuiTestCase() { return result } - private class TestHostDialogProvider : HostDialogProvider { - override fun createHostDialog( - context: Context, - theme: Int, - onCreateCallback: () -> Unit, - dismissOverride: (() -> Unit) -> Unit - ): Dialog = TestHostDialog(context, onCreateCallback, dismissOverride) - } - - private class TestHostDialog( - context: Context, - private val onCreateCallback: () -> Unit, - private val dismissOverride: (() -> Unit) -> Unit - ) : Dialog(context) { - var wasDismissed = false - - init { - // We need to set the window type for dialogs shown by SysUI, otherwise WM will throw. - window.setType(WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL) - } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - onCreateCallback() - } - - override fun dismiss() { - dismissOverride { - super.dismiss() - wasDismissed = true - } - } - } - - private class TestDialog(context: Context) : Dialog(context), ListenableDialog { + private class TestDialog(context: Context) : Dialog(context) { companion object { const val DIALOG_WIDTH = 100 const val DIALOG_HEIGHT = 200 } - private val listeners = hashSetOf<DialogListener>() val contentView = View(context) - var onStartCalled = false - var onStopCalled = false + val windowBackground = ColorDrawable(Color.RED) init { // We need to set the window type for dialogs shown by SysUI, otherwise WM will throw. @@ -205,52 +167,10 @@ class DialogLaunchAnimatorTest : SysuiTestCase() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - window.setLayout(DIALOG_WIDTH, DIALOG_HEIGHT) setContentView(contentView) - } - - override fun onStart() { - super.onStart() - onStartCalled = true - } - - override fun onStop() { - super.onStart() - onStopCalled = true - } - - override fun addListener(listener: DialogListener) { - listeners.add(listener) - } - - override fun removeListener(listener: DialogListener) { - listeners.remove(listener) - } - - override fun dismiss() { - super.dismiss() - notifyListeners { onDismiss(DismissReason.UNKNOWN) } - } - - override fun hide() { - super.hide() - notifyListeners { onHide() } - } - override fun show() { - super.show() - notifyListeners { onShow() } - } - - fun dismissStack() { - notifyListeners { prepareForStackDismiss() } - dismiss() - } - - private fun notifyListeners(notify: DialogListener.() -> Unit) { - for (listener in HashSet(listeners)) { - listener.notify() - } + window.setLayout(DIALOG_WIDTH, DIALOG_HEIGHT) + window.setBackgroundDrawable(windowBackground) } } }
\ No newline at end of file diff --git a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogLiteTest.java b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogLiteTest.java index 3b1c5f32a772..bf5522c50a78 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogLiteTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogLiteTest.java @@ -54,6 +54,7 @@ import com.android.internal.statusbar.IStatusBarService; import com.android.internal.widget.LockPatternUtils; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.systemui.SysuiTestCase; +import com.android.systemui.animation.DialogLaunchAnimator; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.colorextraction.SysuiColorExtractor; import com.android.systemui.model.SysUiState; @@ -115,6 +116,7 @@ public class GlobalActionsDialogLiteTest extends SysuiTestCase { @Mock private UserContextProvider mUserContextProvider; @Mock private StatusBar mStatusBar; @Mock private KeyguardUpdateMonitor mKeyguardUpdateMonitor; + @Mock private DialogLaunchAnimator mDialogLaunchAnimator; private TestableLooper mTestableLooper; @@ -159,8 +161,8 @@ public class GlobalActionsDialogLiteTest extends SysuiTestCase { mHandler, mPackageManager, Optional.of(mStatusBar), - mKeyguardUpdateMonitor - ); + mKeyguardUpdateMonitor, + mDialogLaunchAnimator); mGlobalActionsDialogLite.setZeroDialogPressDelayForTesting(); ColorExtractor.GradientColors backdropColors = new ColorExtractor.GradientColors(); @@ -218,7 +220,7 @@ public class GlobalActionsDialogLiteTest extends SysuiTestCase { GlobalActionsDialogLite.ActionsDialogLite dialog = mGlobalActionsDialogLite.createDialog(); GestureDetector.SimpleOnGestureListener gestureListener = spy(dialog.mGestureListener); - gestureListener.onSingleTapConfirmed(null); + gestureListener.onSingleTapUp(null); verifyLogPosted(GlobalActionsDialogLite.GlobalActionsEvent.GA_CLOSE_TAP_OUTSIDE); } @@ -444,12 +446,12 @@ public class GlobalActionsDialogLiteTest extends SysuiTestCase { // When entering power menu from lockscreen, with smart lock enabled when(mKeyguardUpdateMonitor.getUserHasTrust(anyInt())).thenReturn(true); - mGlobalActionsDialogLite.showOrHideDialog(true, true); + mGlobalActionsDialogLite.showOrHideDialog(true, true, null /* view */); // Then smart lock will be disabled verify(mLockPatternUtils).requireCredentialEntry(eq(user)); // hide dialog again - mGlobalActionsDialogLite.showOrHideDialog(true, true); + mGlobalActionsDialogLite.showOrHideDialog(true, true, null /* view */); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewControllerTest.java index 61b404107519..22906761ac32 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewControllerTest.java @@ -18,6 +18,7 @@ package com.android.systemui.keyguard; import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_BATTERY; +import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_BIOMETRIC_MESSAGE; import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_DISCLOSURE; import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_OWNER_INFO; @@ -56,7 +57,8 @@ import org.mockito.MockitoAnnotations; public class KeyguardIndicationRotateTextViewControllerTest extends SysuiTestCase { private static final String TEST_MESSAGE = "test message"; - private static final String TEST_MESSAGE_2 = "test message 2"; + private static final String TEST_MESSAGE_2 = "test message two"; + private int mMsgId = 0; @Mock private DelayableExecutor mExecutor; @@ -201,6 +203,24 @@ public class KeyguardIndicationRotateTextViewControllerTest extends SysuiTestCas } @Test + public void testSameMessage_noIndicationUpdate() { + // GIVEN we are showing and indication with a test message + mController.updateIndication( + INDICATION_TYPE_OWNER_INFO, createIndication(TEST_MESSAGE), true); + reset(mView); + reset(mExecutor); + + // WHEN the same type tries to show the same exact message + final KeyguardIndication sameIndication = createIndication(TEST_MESSAGE); + mController.updateIndication( + INDICATION_TYPE_OWNER_INFO, sameIndication, true); + + // THEN + // - we don't update the indication b/c there's no reason the animate the same text + verify(mView, never()).switchIndication(sameIndication); + } + + @Test public void testTransientIndication() { // GIVEN we already have two indication messages mController.updateIndication( @@ -223,8 +243,11 @@ public class KeyguardIndicationRotateTextViewControllerTest extends SysuiTestCas @Test public void testHideIndicationOneMessage() { // GIVEN we have one indication message + KeyguardIndication indication = createIndication(); mController.updateIndication( - INDICATION_TYPE_OWNER_INFO, createIndication(), false); + INDICATION_TYPE_OWNER_INFO, indication, false); + verify(mView).switchIndication(indication); + reset(mView); // WHEN we hide the current indication type mController.hideIndication(INDICATION_TYPE_OWNER_INFO); @@ -254,6 +277,10 @@ public class KeyguardIndicationRotateTextViewControllerTest extends SysuiTestCas @Test public void testStartDozing() { + // GIVEN a biometric message is showing + mController.updateIndication(INDICATION_TYPE_BIOMETRIC_MESSAGE, + createIndication(), true); + // WHEN the device is dozing mStatusBarStateListener.onDozingChanged(true); @@ -293,9 +320,19 @@ public class KeyguardIndicationRotateTextViewControllerTest extends SysuiTestCas verify(mView, never()).switchIndication(any()); } + /** + * Create an indication with a unique message. + */ private KeyguardIndication createIndication() { + return createIndication(TEST_MESSAGE + " " + mMsgId++); + } + + /** + * Create an indication with the given message. + */ + private KeyguardIndication createIndication(String msg) { return new KeyguardIndication.Builder() - .setMessage(TEST_MESSAGE) + .setMessage(msg) .setTextColor(ColorStateList.valueOf(Color.WHITE)) .build(); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt index bbeadf62ae0f..41ce9417c78f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt @@ -123,6 +123,7 @@ public class MediaControlPanelTest : SysuiTestCase() { private lateinit var session: MediaSession private val device = MediaDeviceData(true, null, DEVICE_NAME) private val disabledDevice = MediaDeviceData(false, null, "Disabled Device") + private val clock = FakeSystemClock() @JvmField @Rule val mockito = MockitoJUnit.rule() @@ -134,7 +135,7 @@ public class MediaControlPanelTest : SysuiTestCase() { player = MediaControlPanel(context, bgExecutor, activityStarter, mediaViewController, seekBarViewModel, Lazy { mediaDataManager }, keyguardDismissUtil, - mediaOutputDialogFactory, mediaCarouselController, falsingManager) + mediaOutputDialogFactory, mediaCarouselController, falsingManager, clock) whenever(seekBarViewModel.progress).thenReturn(seekBarData) // Mock out a view holder for the player to attach to. diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataCombineLatestTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataCombineLatestTest.java index f870da3e68d9..09c83e566ee8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataCombineLatestTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataCombineLatestTest.java @@ -18,6 +18,7 @@ package com.android.systemui.media; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyBoolean; import static org.mockito.Mockito.eq; @@ -83,10 +84,10 @@ public class MediaDataCombineLatestTest extends SysuiTestCase { public void eventNotEmittedWithoutDevice() { // WHEN data source emits an event without device data mManager.onMediaDataLoaded(KEY, null, mMediaData, true /* immediately */, - false /* isSsReactivated */); + 0 /* receivedSmartspaceCardLatency */); // THEN an event isn't emitted verify(mListener, never()).onMediaDataLoaded(eq(KEY), any(), any(), anyBoolean(), - anyBoolean()); + anyInt()); } @Test @@ -95,7 +96,7 @@ public class MediaDataCombineLatestTest extends SysuiTestCase { mManager.onMediaDeviceChanged(KEY, null, mDeviceData); // THEN an event isn't emitted verify(mListener, never()).onMediaDataLoaded(eq(KEY), any(), any(), anyBoolean(), - anyBoolean()); + anyInt()); } @Test @@ -104,11 +105,11 @@ public class MediaDataCombineLatestTest extends SysuiTestCase { mManager.onMediaDeviceChanged(KEY, null, mDeviceData); // WHEN media event is received mManager.onMediaDataLoaded(KEY, null, mMediaData, true /* immediately */, - false /* isSsReactivated */); + 0 /* receivedSmartspaceCardLatency */); // THEN the listener receives a combined event ArgumentCaptor<MediaData> captor = ArgumentCaptor.forClass(MediaData.class); verify(mListener).onMediaDataLoaded(eq(KEY), any(), captor.capture(), anyBoolean(), - anyBoolean()); + anyInt()); assertThat(captor.getValue().getDevice()).isNotNull(); } @@ -116,13 +117,13 @@ public class MediaDataCombineLatestTest extends SysuiTestCase { public void emitEventAfterMediaFirst() { // GIVEN that media event has already been received mManager.onMediaDataLoaded(KEY, null, mMediaData, true /* immediately */, - false /* isSsReactivated */); + 0 /* receivedSmartspaceCardLatency */); // WHEN device event is received mManager.onMediaDeviceChanged(KEY, null, mDeviceData); // THEN the listener receives a combined event ArgumentCaptor<MediaData> captor = ArgumentCaptor.forClass(MediaData.class); verify(mListener).onMediaDataLoaded(eq(KEY), any(), captor.capture(), anyBoolean(), - anyBoolean()); + anyInt()); assertThat(captor.getValue().getDevice()).isNotNull(); } @@ -130,16 +131,16 @@ public class MediaDataCombineLatestTest extends SysuiTestCase { public void migrateKeyMediaFirst() { // GIVEN that media and device info has already been received mManager.onMediaDataLoaded(OLD_KEY, null, mMediaData, true /* immediately */, - false /* isSsReactivated */); + 0 /* receivedSmartspaceCardLatency */); mManager.onMediaDeviceChanged(OLD_KEY, null, mDeviceData); reset(mListener); // WHEN a key migration event is received mManager.onMediaDataLoaded(KEY, OLD_KEY, mMediaData, true /* immediately */, - false /* isSsReactivated */); + 0 /* receivedSmartspaceCardLatency */); // THEN the listener receives a combined event ArgumentCaptor<MediaData> captor = ArgumentCaptor.forClass(MediaData.class); verify(mListener).onMediaDataLoaded(eq(KEY), eq(OLD_KEY), captor.capture(), anyBoolean(), - anyBoolean()); + anyInt()); assertThat(captor.getValue().getDevice()).isNotNull(); } @@ -147,7 +148,7 @@ public class MediaDataCombineLatestTest extends SysuiTestCase { public void migrateKeyDeviceFirst() { // GIVEN that media and device info has already been received mManager.onMediaDataLoaded(OLD_KEY, null, mMediaData, true /* immediately */, - false /* isSsReactivated */); + 0 /* receivedSmartspaceCardLatency */); mManager.onMediaDeviceChanged(OLD_KEY, null, mDeviceData); reset(mListener); // WHEN a key migration event is received @@ -155,7 +156,7 @@ public class MediaDataCombineLatestTest extends SysuiTestCase { // THEN the listener receives a combined event ArgumentCaptor<MediaData> captor = ArgumentCaptor.forClass(MediaData.class); verify(mListener).onMediaDataLoaded(eq(KEY), eq(OLD_KEY), captor.capture(), anyBoolean(), - anyBoolean()); + anyInt()); assertThat(captor.getValue().getDevice()).isNotNull(); } @@ -163,17 +164,17 @@ public class MediaDataCombineLatestTest extends SysuiTestCase { public void migrateKeyMediaAfter() { // GIVEN that media and device info has already been received mManager.onMediaDataLoaded(OLD_KEY, null, mMediaData, true /* immediately */, - false /* isSsReactivated */); + 0 /* receivedSmartspaceCardLatency */); mManager.onMediaDeviceChanged(OLD_KEY, null, mDeviceData); mManager.onMediaDeviceChanged(KEY, OLD_KEY, mDeviceData); reset(mListener); // WHEN a second key migration event is received for media mManager.onMediaDataLoaded(KEY, OLD_KEY, mMediaData, true /* immediately */, - false /* isSsReactivated */); + 0 /* receivedSmartspaceCardLatency */); // THEN the key has already been migrated ArgumentCaptor<MediaData> captor = ArgumentCaptor.forClass(MediaData.class); verify(mListener).onMediaDataLoaded(eq(KEY), eq(KEY), captor.capture(), anyBoolean(), - anyBoolean()); + anyInt()); assertThat(captor.getValue().getDevice()).isNotNull(); } @@ -181,17 +182,17 @@ public class MediaDataCombineLatestTest extends SysuiTestCase { public void migrateKeyDeviceAfter() { // GIVEN that media and device info has already been received mManager.onMediaDataLoaded(OLD_KEY, null, mMediaData, true /* immediately */, - false /* isSsReactivated */); + 0 /* receivedSmartspaceCardLatency */); mManager.onMediaDeviceChanged(OLD_KEY, null, mDeviceData); mManager.onMediaDataLoaded(KEY, OLD_KEY, mMediaData, true /* immediately */, - false /* isSsReactivated */); + 0 /* receivedSmartspaceCardLatency */); reset(mListener); // WHEN a second key migration event is received for the device mManager.onMediaDeviceChanged(KEY, OLD_KEY, mDeviceData); // THEN the key has already be migrated ArgumentCaptor<MediaData> captor = ArgumentCaptor.forClass(MediaData.class); verify(mListener).onMediaDataLoaded(eq(KEY), eq(KEY), captor.capture(), anyBoolean(), - anyBoolean()); + anyInt()); assertThat(captor.getValue().getDevice()).isNotNull(); } @@ -206,7 +207,7 @@ public class MediaDataCombineLatestTest extends SysuiTestCase { @Test public void mediaDataRemovedAfterMediaEvent() { mManager.onMediaDataLoaded(KEY, null, mMediaData, true /* immediately */, - false /* isSsReactivated */); + 0 /* receivedSmartspaceCardLatency */); mManager.onMediaDataRemoved(KEY); verify(mListener).onMediaDataRemoved(eq(KEY)); } @@ -222,14 +223,14 @@ public class MediaDataCombineLatestTest extends SysuiTestCase { public void mediaDataKeyUpdated() { // GIVEN that device and media events have already been received mManager.onMediaDataLoaded(KEY, null, mMediaData, true /* immediately */, - false /* isSsReactivated */); + 0 /* receivedSmartspaceCardLatency */); mManager.onMediaDeviceChanged(KEY, null, mDeviceData); // WHEN the key is changed mManager.onMediaDataLoaded("NEW_KEY", KEY, mMediaData, true /* immediately */, - false /* isSsReactivated */); + 0 /* receivedSmartspaceCardLatency */); // THEN the listener gets a load event with the correct keys ArgumentCaptor<MediaData> captor = ArgumentCaptor.forClass(MediaData.class); verify(mListener).onMediaDataLoaded( - eq("NEW_KEY"), any(), captor.capture(), anyBoolean(), anyBoolean()); + eq("NEW_KEY"), any(), captor.capture(), anyBoolean(), anyInt()); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataFilterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataFilterTest.kt index a435e7961b35..5a3c43c6cc15 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataFilterTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataFilterTest.kt @@ -87,7 +87,7 @@ class MediaDataFilterTest : SysuiTestCase() { fun setup() { MockitoAnnotations.initMocks(this) MediaPlayerData.clear() - mediaDataFilter = MediaDataFilter(context, broadcastDispatcher, mediaResumeListener, + mediaDataFilter = MediaDataFilter(context, broadcastDispatcher, lockscreenUserManager, executor, clock) mediaDataFilter.mediaDataManager = mediaDataManager mediaDataFilter.addListener(listener) @@ -107,6 +107,8 @@ class MediaDataFilterTest : SysuiTestCase() { `when`(smartspaceData.isValid).thenReturn(true) `when`(smartspaceData.packageName).thenReturn(PACKAGE) `when`(smartspaceData.recommendations).thenReturn(listOf(smartspaceMediaRecommendationItem)) + `when`(smartspaceData.headphoneConnectionTimeMillis).thenReturn( + clock.currentTimeMillis() - 100) } private fun setUser(id: Int) { @@ -122,7 +124,7 @@ class MediaDataFilterTest : SysuiTestCase() { // THEN we should tell the listener verify(listener).onMediaDataLoaded(eq(KEY), eq(null), eq(dataMain), eq(true), - eq(false)) + eq(0)) } @Test @@ -131,7 +133,7 @@ class MediaDataFilterTest : SysuiTestCase() { mediaDataFilter.onMediaDataLoaded(KEY, null, dataGuest) // THEN we should NOT tell the listener - verify(listener, never()).onMediaDataLoaded(any(), any(), any(), anyBoolean(), anyBoolean()) + verify(listener, never()).onMediaDataLoaded(any(), any(), any(), anyBoolean(), anyInt()) } @Test @@ -178,11 +180,11 @@ class MediaDataFilterTest : SysuiTestCase() { // THEN we should add back the guest user media verify(listener).onMediaDataLoaded(eq(KEY_ALT), eq(null), eq(dataGuest), eq(true), - eq(false)) + eq(0)) // but not the main user's verify(listener, never()).onMediaDataLoaded(eq(KEY), any(), eq(dataMain), anyBoolean(), - anyBoolean()) + anyInt()) } @Test @@ -239,7 +241,8 @@ class MediaDataFilterTest : SysuiTestCase() { mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData) verify(listener) - .onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), eq(true)) + .onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), eq(true), + eq(false)) assertThat(mediaDataFilter.hasActiveMedia()).isTrue() } @@ -249,8 +252,9 @@ class MediaDataFilterTest : SysuiTestCase() { mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData) - verify(listener, never()).onMediaDataLoaded(any(), any(), any(), anyBoolean(), anyBoolean()) - verify(listener, never()).onSmartspaceMediaDataLoaded(any(), any(), anyBoolean()) + verify(listener, never()).onMediaDataLoaded(any(), any(), any(), anyBoolean(), anyInt()) + verify(listener, never()).onSmartspaceMediaDataLoaded(any(), any(), anyBoolean(), + anyBoolean()) assertThat(mediaDataFilter.hasActiveMedia()).isFalse() } @@ -262,7 +266,8 @@ class MediaDataFilterTest : SysuiTestCase() { mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData) verify(listener) - .onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), eq(true)) + .onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), eq(true), + eq(true)) assertThat(mediaDataFilter.hasActiveMedia()).isTrue() } @@ -275,7 +280,8 @@ class MediaDataFilterTest : SysuiTestCase() { clock.advanceTime(SMARTSPACE_MAX_AGE + 100) mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData) - verify(listener, never()).onSmartspaceMediaDataLoaded(any(), any(), anyBoolean()) + verify(listener, never()).onSmartspaceMediaDataLoaded(any(), any(), anyBoolean(), + anyBoolean()) assertThat(mediaDataFilter.hasActiveMedia()).isFalse() } @@ -287,15 +293,16 @@ class MediaDataFilterTest : SysuiTestCase() { val dataCurrent = dataMain.copy(active = false, lastActive = clock.elapsedRealtime()) mediaDataFilter.onMediaDataLoaded(KEY, null, dataCurrent) verify(listener).onMediaDataLoaded(eq(KEY), eq(null), eq(dataCurrent), eq(true), - eq(false)) + eq(0)) // AND we get a smartspace signal mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData) // THEN we should tell listeners to treat the media as not active instead verify(listener, never()).onMediaDataLoaded(eq(KEY), eq(KEY), any(), anyBoolean(), + anyInt()) + verify(listener, never()).onSmartspaceMediaDataLoaded(any(), any(), anyBoolean(), anyBoolean()) - verify(listener, never()).onSmartspaceMediaDataLoaded(any(), any(), anyBoolean()) assertThat(mediaDataFilter.hasActiveMedia()).isFalse() } @@ -307,7 +314,7 @@ class MediaDataFilterTest : SysuiTestCase() { val dataCurrent = dataMain.copy(active = false, lastActive = clock.elapsedRealtime()) mediaDataFilter.onMediaDataLoaded(KEY, null, dataCurrent) verify(listener).onMediaDataLoaded(eq(KEY), eq(null), eq(dataCurrent), eq(true), - eq(false)) + eq(0)) // AND we get a smartspace signal mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData) @@ -315,10 +322,11 @@ class MediaDataFilterTest : SysuiTestCase() { // THEN we should tell listeners to treat the media as active instead val dataCurrentAndActive = dataCurrent.copy(active = true) verify(listener).onMediaDataLoaded(eq(KEY), eq(KEY), eq(dataCurrentAndActive), eq(true), - eq(true)) + eq(100)) assertThat(mediaDataFilter.hasActiveMedia()).isTrue() // Smartspace update shouldn't be propagated for the empty rec list. - verify(listener, never()).onSmartspaceMediaDataLoaded(any(), any(), anyBoolean()) + verify(listener, never()).onSmartspaceMediaDataLoaded(any(), any(), anyBoolean(), + anyBoolean()) } @Test @@ -327,7 +335,7 @@ class MediaDataFilterTest : SysuiTestCase() { val dataCurrent = dataMain.copy(active = false, lastActive = clock.elapsedRealtime()) mediaDataFilter.onMediaDataLoaded(KEY, null, dataCurrent) verify(listener).onMediaDataLoaded(eq(KEY), eq(null), eq(dataCurrent), eq(true), - eq(false)) + eq(0)) // AND we get a smartspace signal mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData) @@ -335,11 +343,12 @@ class MediaDataFilterTest : SysuiTestCase() { // THEN we should tell listeners to treat the media as active instead val dataCurrentAndActive = dataCurrent.copy(active = true) verify(listener).onMediaDataLoaded(eq(KEY), eq(KEY), eq(dataCurrentAndActive), eq(true), - eq(true)) + eq(100)) assertThat(mediaDataFilter.hasActiveMedia()).isTrue() // Smartspace update should also be propagated but not prioritized. verify(listener) - .onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), eq(false)) + .onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), eq(false), + eq(true)) } @Test @@ -356,13 +365,13 @@ class MediaDataFilterTest : SysuiTestCase() { val dataCurrent = dataMain.copy(active = false, lastActive = clock.elapsedRealtime()) mediaDataFilter.onMediaDataLoaded(KEY, null, dataCurrent) verify(listener).onMediaDataLoaded(eq(KEY), eq(null), eq(dataCurrent), eq(true), - eq(false)) + eq(0)) mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData) val dataCurrentAndActive = dataCurrent.copy(active = true) verify(listener).onMediaDataLoaded(eq(KEY), eq(KEY), eq(dataCurrentAndActive), eq(true), - eq(true)) + eq(100)) mediaDataFilter.onSmartspaceMediaDataRemoved(SMARTSPACE_KEY) diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt index f44cc38c78c0..e2019e089329 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt @@ -160,6 +160,7 @@ class MediaDataManagerTest : SysuiTestCase() { whenever(mediaSmartspaceTarget.smartspaceTargetId).thenReturn(KEY_MEDIA_SMARTSPACE) whenever(mediaSmartspaceTarget.featureType).thenReturn(SmartspaceTarget.FEATURE_MEDIA) whenever(mediaSmartspaceTarget.iconGrid).thenReturn(listOf(mediaRecommendationItem)) + whenever(mediaSmartspaceTarget.creationTimeMillis).thenReturn(1234L) } @After @@ -213,7 +214,7 @@ class MediaDataManagerTest : SysuiTestCase() { mediaDataManager.onNotificationAdded(KEY, mediaNotification) mediaDataManager.onMediaDataLoaded(KEY, oldKey = null, data = mock(MediaData::class.java)) verify(listener).onMediaDataLoaded(eq(KEY), eq(null), anyObject(), eq(true), - eq(false)) + eq(0)) } @Test @@ -225,7 +226,7 @@ class MediaDataManagerTest : SysuiTestCase() { assertThat(backgroundExecutor.runAllReady()).isEqualTo(1) assertThat(foregroundExecutor.runAllReady()).isEqualTo(1) verify(listener).onMediaDataLoaded(eq(KEY), eq(null), capture(mediaDataCaptor), eq(true), - eq(false)) + eq(0)) assertThat(mediaDataCaptor.value!!.active).isTrue() } @@ -248,7 +249,7 @@ class MediaDataManagerTest : SysuiTestCase() { assertThat(backgroundExecutor.runAllReady()).isEqualTo(1) assertThat(foregroundExecutor.runAllReady()).isEqualTo(1) verify(listener).onMediaDataLoaded(eq(KEY), eq(null), capture(mediaDataCaptor), eq(true), - eq(false)) + eq(0)) assertThat(mediaDataCaptor.value!!.playbackLocation).isEqualTo( MediaData.PLAYBACK_CAST_REMOTE) } @@ -269,7 +270,7 @@ class MediaDataManagerTest : SysuiTestCase() { assertThat(backgroundExecutor.runAllReady()).isEqualTo(1) assertThat(foregroundExecutor.runAllReady()).isEqualTo(1) verify(listener).onMediaDataLoaded(eq(KEY), eq(null), capture(mediaDataCaptor), eq(true), - eq(false)) + eq(0)) val data = mediaDataCaptor.value assertThat(data.resumption).isFalse() mediaDataManager.onMediaDataLoaded(KEY, null, data.copy(resumeAction = Runnable {})) @@ -278,7 +279,7 @@ class MediaDataManagerTest : SysuiTestCase() { // THEN the media data indicates that it is for resumption verify(listener) .onMediaDataLoaded(eq(PACKAGE_NAME), eq(KEY), capture(mediaDataCaptor), eq(true), - eq(false)) + eq(0)) assertThat(mediaDataCaptor.value.resumption).isTrue() assertThat(mediaDataCaptor.value.isPlaying).isFalse() } @@ -293,7 +294,7 @@ class MediaDataManagerTest : SysuiTestCase() { assertThat(foregroundExecutor.runAllReady()).isEqualTo(2) verify(listener) .onMediaDataLoaded(eq(KEY), eq(null), capture(mediaDataCaptor), eq(true), - eq(false)) + eq(0)) val data = mediaDataCaptor.value assertThat(data.resumption).isFalse() val resumableData = data.copy(resumeAction = Runnable {}) @@ -305,7 +306,7 @@ class MediaDataManagerTest : SysuiTestCase() { // THEN the data is for resumption and the key is migrated to the package name verify(listener) .onMediaDataLoaded(eq(PACKAGE_NAME), eq(KEY), capture(mediaDataCaptor), eq(true), - eq(false)) + eq(0)) assertThat(mediaDataCaptor.value.resumption).isTrue() verify(listener, never()).onMediaDataRemoved(eq(KEY)) // WHEN the second is removed @@ -314,7 +315,7 @@ class MediaDataManagerTest : SysuiTestCase() { verify(listener) .onMediaDataLoaded( eq(PACKAGE_NAME), eq(PACKAGE_NAME), capture(mediaDataCaptor), eq(true), - eq(false)) + eq(0)) assertThat(mediaDataCaptor.value.resumption).isTrue() verify(listener).onMediaDataRemoved(eq(KEY_2)) } @@ -329,7 +330,7 @@ class MediaDataManagerTest : SysuiTestCase() { assertThat(backgroundExecutor.runAllReady()).isEqualTo(1) assertThat(foregroundExecutor.runAllReady()).isEqualTo(1) verify(listener).onMediaDataLoaded(eq(KEY), eq(null), capture(mediaDataCaptor), eq(true), - eq(false)) + eq(0)) val data = mediaDataCaptor.value val dataRemoteWithResume = data.copy(resumeAction = Runnable {}, playbackLocation = MediaData.PLAYBACK_CAST_LOCAL) @@ -357,7 +358,7 @@ class MediaDataManagerTest : SysuiTestCase() { // THEN the media data indicates that it is for resumption verify(listener) .onMediaDataLoaded(eq(PACKAGE_NAME), eq(null), capture(mediaDataCaptor), eq(true), - eq(false)) + eq(0)) val data = mediaDataCaptor.value assertThat(data.resumption).isTrue() assertThat(data.song).isEqualTo(SESSION_TITLE) @@ -405,7 +406,7 @@ class MediaDataManagerTest : SysuiTestCase() { assertThat(foregroundExecutor.runAllReady()).isEqualTo(1) verify(listener) .onMediaDataLoaded(eq(KEY), eq(null), capture(mediaDataCaptor), eq(true), - eq(false)) + eq(0)) } @Test @@ -415,8 +416,8 @@ class MediaDataManagerTest : SysuiTestCase() { eq(KEY_MEDIA_SMARTSPACE), eq(SmartspaceMediaData(KEY_MEDIA_SMARTSPACE, true /* isActive */, true /*isValid */, PACKAGE_NAME, mediaSmartspaceBaseAction, listOf(mediaRecommendationItem), - DISMISS_INTENT, 0)), - eq(false)) + DISMISS_INTENT, 0, 1234L)), + eq(false), eq(false)) } @Test @@ -427,8 +428,9 @@ class MediaDataManagerTest : SysuiTestCase() { eq(KEY_MEDIA_SMARTSPACE), eq(EMPTY_SMARTSPACE_MEDIA_DATA .copy(targetId = KEY_MEDIA_SMARTSPACE, isActive = true, - isValid = false, dismissIntent = DISMISS_INTENT)), - eq(false)) + isValid = false, dismissIntent = DISMISS_INTENT, + headphoneConnectionTimeMillis = 1234L)), + eq(false), eq(false)) } @Test @@ -447,15 +449,15 @@ class MediaDataManagerTest : SysuiTestCase() { eq(KEY_MEDIA_SMARTSPACE), eq(EMPTY_SMARTSPACE_MEDIA_DATA .copy(targetId = KEY_MEDIA_SMARTSPACE, isActive = true, - isValid = false, dismissIntent = null)), - eq(false)) + isValid = false, dismissIntent = null, headphoneConnectionTimeMillis = 1234L)), + eq(false), eq(false)) } @Test fun testOnSmartspaceMediaDataLoaded_hasNoneMediaTarget_notCallsListener() { smartspaceMediaDataProvider.onTargetsAvailable(listOf()) verify(listener, never()) - .onSmartspaceMediaDataLoaded(anyObject(), anyObject(), anyBoolean()) + .onSmartspaceMediaDataLoaded(anyObject(), anyObject(), anyBoolean(), anyBoolean()) } @Test @@ -479,7 +481,7 @@ class MediaDataManagerTest : SysuiTestCase() { // THEN smartspace signal is ignored verify(listener, never()) - .onSmartspaceMediaDataLoaded(anyObject(), anyObject(), anyBoolean()) + .onSmartspaceMediaDataLoaded(anyObject(), anyObject(), anyBoolean(), anyBoolean()) } @Test @@ -487,7 +489,7 @@ class MediaDataManagerTest : SysuiTestCase() { // GIVEN a media recommendation card is present smartspaceMediaDataProvider.onTargetsAvailable(listOf(mediaSmartspaceTarget)) verify(listener).onSmartspaceMediaDataLoaded(eq(KEY_MEDIA_SMARTSPACE), anyObject(), - anyBoolean()) + anyBoolean(), anyBoolean()) // WHEN the media recommendation setting is turned off Settings.Secure.putInt(context.contentResolver, @@ -507,7 +509,7 @@ class MediaDataManagerTest : SysuiTestCase() { assertThat(backgroundExecutor.runAllReady()).isEqualTo(1) assertThat(foregroundExecutor.runAllReady()).isEqualTo(1) verify(listener).onMediaDataLoaded(eq(KEY), eq(null), capture(mediaDataCaptor), eq(true), - eq(false)) + eq(0)) assertThat(mediaDataCaptor.value!!.lastActive).isAtLeast(currentTime) } @@ -525,7 +527,7 @@ class MediaDataManagerTest : SysuiTestCase() { // THEN the last active time is not changed verify(listener).onMediaDataLoaded(eq(KEY), eq(KEY), capture(mediaDataCaptor), eq(true), - eq(false)) + eq(0)) assertThat(mediaDataCaptor.value.lastActive).isLessThan(currentTime) } @@ -537,7 +539,7 @@ class MediaDataManagerTest : SysuiTestCase() { assertThat(backgroundExecutor.runAllReady()).isEqualTo(1) assertThat(foregroundExecutor.runAllReady()).isEqualTo(1) verify(listener).onMediaDataLoaded(eq(KEY), eq(null), capture(mediaDataCaptor), eq(true), - eq(false)) + eq(0)) val data = mediaDataCaptor.value assertThat(data.resumption).isFalse() mediaDataManager.onMediaDataLoaded(KEY, null, data.copy(resumeAction = Runnable {})) @@ -550,7 +552,7 @@ class MediaDataManagerTest : SysuiTestCase() { // THEN the last active time is not changed verify(listener) .onMediaDataLoaded(eq(PACKAGE_NAME), eq(KEY), capture(mediaDataCaptor), eq(true), - eq(false)) + eq(0)) assertThat(mediaDataCaptor.value.resumption).isTrue() assertThat(mediaDataCaptor.value.lastActive).isLessThan(currentTime) } @@ -577,7 +579,7 @@ class MediaDataManagerTest : SysuiTestCase() { // THEN only the first MAX_COMPACT_ACTIONS are actually set verify(listener).onMediaDataLoaded(eq(KEY), eq(null), capture(mediaDataCaptor), eq(true), - eq(false)) + eq(0)) assertThat(mediaDataCaptor.value.actionsToShowInCompact.size).isEqualTo( MediaDataManager.MAX_COMPACT_ACTIONS) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaSessionBasedFilterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaSessionBasedFilterTest.kt index b9caab277c4c..5d53181c8345 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaSessionBasedFilterTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaSessionBasedFilterTest.kt @@ -37,6 +37,7 @@ import org.junit.Test import org.junit.runner.RunWith import org.mockito.ArgumentCaptor import org.mockito.ArgumentMatchers.anyBoolean +import org.mockito.ArgumentMatchers.anyInt import org.mockito.Mock import org.mockito.Mockito import org.mockito.Mockito.any @@ -186,7 +187,7 @@ public class MediaSessionBasedFilterTest : SysuiTestCase() { bgExecutor.runAllReady() fgExecutor.runAllReady() verify(mediaListener).onMediaDataLoaded(eq(KEY), eq(null), eq(mediaData1), eq(true), - eq(false)) + eq(0)) } @Test @@ -209,7 +210,7 @@ public class MediaSessionBasedFilterTest : SysuiTestCase() { fgExecutor.runAllReady() // THEN the event is not filtered verify(mediaListener).onMediaDataLoaded(eq(KEY), eq(null), eq(mediaData1), eq(true), - eq(false)) + eq(0)) } @Test @@ -239,7 +240,7 @@ public class MediaSessionBasedFilterTest : SysuiTestCase() { fgExecutor.runAllReady() // THEN the event is not filtered verify(mediaListener).onMediaDataLoaded(eq(KEY), eq(null), eq(mediaData1), eq(true), - eq(false)) + eq(0)) } @Test @@ -255,14 +256,14 @@ public class MediaSessionBasedFilterTest : SysuiTestCase() { fgExecutor.runAllReady() // THEN the event is not filtered verify(mediaListener).onMediaDataLoaded(eq(KEY), eq(null), eq(mediaData1), eq(true), - eq(false)) + eq(0)) // WHEN a loaded event is received that matches the local session filter.onMediaDataLoaded(KEY, null, mediaData2) bgExecutor.runAllReady() fgExecutor.runAllReady() // THEN the event is filtered verify(mediaListener, never()).onMediaDataLoaded( - eq(KEY), eq(null), eq(mediaData2), anyBoolean(), anyBoolean()) + eq(KEY), eq(null), eq(mediaData2), anyBoolean(), anyInt()) } @Test @@ -279,7 +280,7 @@ public class MediaSessionBasedFilterTest : SysuiTestCase() { // THEN the event is not filtered because there isn't a notification for the remote // session. verify(mediaListener).onMediaDataLoaded(eq(KEY), eq(null), eq(mediaData1), eq(true), - eq(false)) + eq(0)) } @Test @@ -297,14 +298,14 @@ public class MediaSessionBasedFilterTest : SysuiTestCase() { fgExecutor.runAllReady() // THEN the event is not filtered verify(mediaListener).onMediaDataLoaded(eq(key1), eq(null), eq(mediaData1), eq(true), - eq(false)) + eq(0)) // WHEN a loaded event is received that matches the local session filter.onMediaDataLoaded(key2, null, mediaData2) bgExecutor.runAllReady() fgExecutor.runAllReady() // THEN the event is filtered verify(mediaListener, never()) - .onMediaDataLoaded(eq(key2), eq(null), eq(mediaData2), anyBoolean(), anyBoolean()) + .onMediaDataLoaded(eq(key2), eq(null), eq(mediaData2), anyBoolean(), anyInt()) // AND there should be a removed event for key2 verify(mediaListener).onMediaDataRemoved(eq(key2)) } @@ -324,14 +325,14 @@ public class MediaSessionBasedFilterTest : SysuiTestCase() { fgExecutor.runAllReady() // THEN the event is not filtered verify(mediaListener).onMediaDataLoaded(eq(key1), eq(null), eq(mediaData1), eq(true), - eq(false)) + eq(0)) // WHEN a loaded event is received that matches the remote session filter.onMediaDataLoaded(key2, null, mediaData2) bgExecutor.runAllReady() fgExecutor.runAllReady() // THEN the event is not filtered verify(mediaListener).onMediaDataLoaded(eq(key2), eq(null), eq(mediaData2), eq(true), - eq(false)) + eq(0)) } @Test @@ -348,14 +349,14 @@ public class MediaSessionBasedFilterTest : SysuiTestCase() { fgExecutor.runAllReady() // THEN the event is not filtered verify(mediaListener).onMediaDataLoaded(eq(KEY), eq(null), eq(mediaData1), eq(true), - eq(false)) + eq(0)) // WHEN a loaded event is received that matches the local session filter.onMediaDataLoaded(KEY, null, mediaData2) bgExecutor.runAllReady() fgExecutor.runAllReady() // THEN the event is not filtered verify(mediaListener).onMediaDataLoaded(eq(KEY), eq(null), eq(mediaData2), eq(true), - eq(false)) + eq(0)) } @Test @@ -374,7 +375,7 @@ public class MediaSessionBasedFilterTest : SysuiTestCase() { fgExecutor.runAllReady() // THEN the event is not filtered verify(mediaListener).onMediaDataLoaded(eq(KEY), eq(null), eq(mediaData1), eq(true), - eq(false)) + eq(0)) } @Test @@ -397,7 +398,7 @@ public class MediaSessionBasedFilterTest : SysuiTestCase() { fgExecutor.runAllReady() // THEN the key migration event is fired verify(mediaListener).onMediaDataLoaded(eq(key2), eq(key1), eq(mediaData2), eq(true), - eq(false)) + eq(0)) } @Test @@ -427,13 +428,13 @@ public class MediaSessionBasedFilterTest : SysuiTestCase() { fgExecutor.runAllReady() // THEN the key migration event is filtered verify(mediaListener, never()) - .onMediaDataLoaded(eq(key2), eq(null), eq(mediaData2), anyBoolean(), anyBoolean()) + .onMediaDataLoaded(eq(key2), eq(null), eq(mediaData2), anyBoolean(), anyInt()) // WHEN a loaded event is received that matches the remote session filter.onMediaDataLoaded(key2, null, mediaData1) bgExecutor.runAllReady() fgExecutor.runAllReady() // THEN the key migration event is fired verify(mediaListener).onMediaDataLoaded(eq(key2), eq(null), eq(mediaData1), eq(true), - eq(false)) + eq(0)) } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavBarHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavBarHelperTest.java index 734faec4ec74..a445d6f4e5c5 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavBarHelperTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavBarHelperTest.java @@ -18,6 +18,7 @@ package com.android.systemui.navigationbar; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -34,6 +35,7 @@ import com.android.systemui.assist.AssistManager; import com.android.systemui.dump.DumpManager; import com.android.systemui.recents.OverviewProxyService; import com.android.systemui.settings.UserTracker; +import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper; import org.junit.Before; @@ -42,6 +44,8 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import java.util.Optional; + import dagger.Lazy; @RunWith(AndroidJUnit4.class) @@ -80,10 +84,10 @@ public class NavBarHelperTest extends SysuiTestCase { when(mAssistManager.getAssistInfoForUser(anyInt())).thenReturn(mAssistantComponent); when(mUserTracker.getUserId()).thenReturn(1); - mNavBarHelper = new NavBarHelper(mAccessibilityManager, + mNavBarHelper = new NavBarHelper(mContext, mAccessibilityManager, mAccessibilityManagerWrapper, mAccessibilityButtonModeObserver, - mOverviewProxyService, mAssistManagerLazy, mNavigationModeController, - mUserTracker, mDumpManager); + mOverviewProxyService, mAssistManagerLazy, () -> Optional.of(mock(StatusBar.class)), + mNavigationModeController, mUserTracker, mDumpManager); } @@ -96,13 +100,13 @@ public class NavBarHelperTest extends SysuiTestCase { @Test public void registerAssistantContentObserver() { - mNavBarHelper.init(mContext); + mNavBarHelper.init(); verify(mAssistManager, times(1)).getAssistInfoForUser(anyInt()); } @Test public void callbacksFiredWhenRegistering() { - mNavBarHelper.init(mContext); + mNavBarHelper.init(); mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater); verify(mNavbarTaskbarStateUpdater, times(1)) .updateAccessibilityServicesState(); @@ -112,7 +116,7 @@ public class NavBarHelperTest extends SysuiTestCase { @Test public void assistantCallbacksFiredAfterConnecting() { - mNavBarHelper.init(mContext); + mNavBarHelper.init(); // 1st set of callbacks get called when registering mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater); @@ -133,7 +137,7 @@ public class NavBarHelperTest extends SysuiTestCase { @Test public void a11yCallbacksFiredAfterModeChange() { - mNavBarHelper.init(mContext); + mNavBarHelper.init(); // 1st set of callbacks get called when registering mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater); @@ -146,7 +150,7 @@ public class NavBarHelperTest extends SysuiTestCase { @Test public void assistantCallbacksFiredAfterNavModeChange() { - mNavBarHelper.init(mContext); + mNavBarHelper.init(); // 1st set of callbacks get called when registering mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater); @@ -159,7 +163,7 @@ public class NavBarHelperTest extends SysuiTestCase { @Test public void removeListenerNoCallbacksFired() { - mNavBarHelper.init(mContext); + mNavBarHelper.init(); // 1st set of callbacks get called when registering mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater); diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java index 776b6aa2ef38..5003013358be 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java @@ -23,17 +23,20 @@ import static android.inputmethodservice.InputMethodService.IME_INVISIBLE; import static android.inputmethodservice.InputMethodService.IME_VISIBLE; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS; +import static android.view.WindowInsets.Type.ime; import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.HOME_BUTTON_LONG_PRESS_DURATION_MS; import static com.android.systemui.navigationbar.NavigationBar.NavBarActionEvent.NAVBAR_ASSIST_LONGPRESS; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; @@ -57,6 +60,7 @@ import android.view.Display; import android.view.DisplayInfo; import android.view.MotionEvent; import android.view.View; +import android.view.WindowInsets; import android.view.WindowManager; import android.view.WindowMetrics; import android.view.accessibility.AccessibilityManager; @@ -72,6 +76,7 @@ import com.android.systemui.accessibility.AccessibilityButtonModeObserver; import com.android.systemui.accessibility.SystemActions; import com.android.systemui.assist.AssistManager; import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.dump.DumpManager; import com.android.systemui.model.SysUiState; import com.android.systemui.navigationbar.gestural.EdgeBackGestureHandler; import com.android.systemui.plugins.statusbar.StatusBarStateController; @@ -83,8 +88,10 @@ import com.android.systemui.statusbar.NotificationRemoteInputManager; import com.android.systemui.statusbar.NotificationShadeDepthController; import com.android.systemui.statusbar.phone.AutoHideController; import com.android.systemui.statusbar.phone.LightBarController; +import com.android.systemui.statusbar.phone.NotificationShadeWindowView; import com.android.systemui.statusbar.phone.ShadeController; import com.android.systemui.statusbar.phone.StatusBar; +import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper; import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.utils.leaks.LeakCheckedTest; @@ -98,6 +105,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import org.mockito.Spy; import java.util.Optional; @@ -130,7 +138,6 @@ public class NavigationBarTest extends SysuiTestCase { EdgeBackGestureHandler.Factory mEdgeBackGestureHandlerFactory; @Mock EdgeBackGestureHandler mEdgeBackGestureHandler; - @Mock NavBarHelper mNavBarHelper; @Mock private LightBarController mLightBarController; @@ -148,6 +155,8 @@ public class NavigationBarTest extends SysuiTestCase { private InputMethodManager mInputMethodManager; @Mock private AssistManager mAssistManager; + @Mock + private StatusBar mStatusBar; @Rule public final LeakCheckedTest.SysuiLeakCheck mLeakCheck = new LeakCheckedTest.SysuiLeakCheck(); @@ -172,6 +181,12 @@ public class NavigationBarTest extends SysuiTestCase { mDependency.injectTestDependency(OverviewProxyService.class, mOverviewProxyService); mDependency.injectTestDependency(NavigationModeController.class, mNavigationModeController); TestableLooper.get(this).runWithLooper(() -> { + mNavBarHelper = spy(new NavBarHelper(mContext, mock(AccessibilityManager.class), + mock(AccessibilityManagerWrapper.class), + mock(AccessibilityButtonModeObserver.class), mOverviewProxyService, + () -> mock(AssistManager.class), () -> Optional.of(mStatusBar), + mock(NavigationModeController.class), mock(UserTracker.class), + mock(DumpManager.class))); mNavigationBar = createNavBar(mContext); mExternalDisplayNavigationBar = createNavBar(mSysuiTestableContextExternal); }); @@ -256,6 +271,11 @@ public class NavigationBarTest extends SysuiTestCase { // Create default & external NavBar fragment. NavigationBar defaultNavBar = mNavigationBar; NavigationBar externalNavBar = mExternalDisplayNavigationBar; + NotificationShadeWindowView mockShadeWindowView = mock(NotificationShadeWindowView.class); + WindowInsets windowInsets = new WindowInsets.Builder().setVisible(ime(), false).build(); + doReturn(windowInsets).when(mockShadeWindowView).getRootWindowInsets(); + doReturn(mockShadeWindowView).when(mStatusBar).getNotificationShadeWindowView(); + doReturn(true).when(mockShadeWindowView).isAttachedToWindow(); doNothing().when(defaultNavBar).checkNavBarModes(); doNothing().when(externalNavBar).checkNavBarModes(); defaultNavBar.createView(null); @@ -282,6 +302,40 @@ public class NavigationBarTest extends SysuiTestCase { } @Test + public void testSetImeWindowStatusWhenKeyguardLockingAndImeInsetsChange() { + NotificationShadeWindowView mockShadeWindowView = mock(NotificationShadeWindowView.class); + doReturn(mockShadeWindowView).when(mStatusBar).getNotificationShadeWindowView(); + doReturn(true).when(mockShadeWindowView).isAttachedToWindow(); + doNothing().when(mNavigationBar).checkNavBarModes(); + mNavigationBar.createView(null); + WindowInsets windowInsets = new WindowInsets.Builder().setVisible(ime(), false).build(); + doReturn(windowInsets).when(mockShadeWindowView).getRootWindowInsets(); + + // Verify navbar altered back icon when an app is showing IME + mNavigationBar.setImeWindowStatus(DEFAULT_DISPLAY, null, IME_VISIBLE, + BACK_DISPOSITION_DEFAULT, true); + assertTrue((mNavigationBar.getNavigationIconHints() & NAVIGATION_HINT_BACK_ALT) != 0); + assertTrue((mNavigationBar.getNavigationIconHints() & NAVIGATION_HINT_IME_SHOWN) != 0); + + // Verify navbar didn't alter and showing back icon when the keyguard is showing without + // requesting IME insets visible. + doReturn(true).when(mStatusBar).isKeyguardShowing(); + mNavigationBar.setImeWindowStatus(DEFAULT_DISPLAY, null, IME_VISIBLE, + BACK_DISPOSITION_DEFAULT, true); + assertFalse((mNavigationBar.getNavigationIconHints() & NAVIGATION_HINT_BACK_ALT) != 0); + assertFalse((mNavigationBar.getNavigationIconHints() & NAVIGATION_HINT_IME_SHOWN) != 0); + + // Verify navbar altered and showing back icon when the keyguard is showing and + // requesting IME insets visible. + windowInsets = new WindowInsets.Builder().setVisible(ime(), true).build(); + doReturn(windowInsets).when(mockShadeWindowView).getRootWindowInsets(); + mNavigationBar.setImeWindowStatus(DEFAULT_DISPLAY, null, IME_VISIBLE, + BACK_DISPOSITION_DEFAULT, true); + assertTrue((mNavigationBar.getNavigationIconHints() & NAVIGATION_HINT_BACK_ALT) != 0); + assertTrue((mNavigationBar.getNavigationIconHints() & NAVIGATION_HINT_IME_SHOWN) != 0); + } + + @Test public void testA11yEventAfterDetach() { View v = mNavigationBar.createView(null); mNavigationBar.onViewAttachedToWindow(v); @@ -314,7 +368,7 @@ public class NavigationBarTest extends SysuiTestCase { Optional.of(mock(Pip.class)), Optional.of(mock(LegacySplitScreen.class)), Optional.of(mock(Recents.class)), - () -> Optional.of(mock(StatusBar.class)), + () -> Optional.of(mStatusBar), mock(ShadeController.class), mock(NotificationRemoteInputManager.class), mock(NotificationShadeDepthController.class), diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/HeaderPrivacyIconsControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/HeaderPrivacyIconsControllerTest.kt new file mode 100644 index 000000000000..92743ae51c95 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/HeaderPrivacyIconsControllerTest.kt @@ -0,0 +1,128 @@ +package com.android.systemui.qs + +import android.content.Context +import android.testing.AndroidTestingRunner +import android.view.View +import androidx.test.filters.SmallTest +import com.android.internal.logging.UiEventLogger +import com.android.systemui.SysuiTestCase +import com.android.systemui.privacy.OngoingPrivacyChip +import com.android.systemui.privacy.PrivacyDialogController +import com.android.systemui.privacy.PrivacyItemController +import com.android.systemui.privacy.logging.PrivacyLogger +import com.android.systemui.statusbar.phone.StatusIconContainer +import com.android.systemui.util.mockito.any +import com.android.systemui.util.mockito.argumentCaptor +import com.android.systemui.util.mockito.capture +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mock +import org.mockito.Mockito.verify +import org.mockito.MockitoAnnotations +import org.mockito.Mockito.`when` as whenever + +@SmallTest +@RunWith(AndroidTestingRunner::class) +class HeaderPrivacyIconsControllerTest : SysuiTestCase() { + + @Mock + private lateinit var privacyItemController: PrivacyItemController + @Mock + private lateinit var uiEventLogger: UiEventLogger + @Mock + private lateinit var privacyChip: OngoingPrivacyChip + @Mock + private lateinit var privacyDialogController: PrivacyDialogController + @Mock + private lateinit var privacyLogger: PrivacyLogger + @Mock + private lateinit var iconContainer: StatusIconContainer + + private lateinit var cameraSlotName: String + private lateinit var microphoneSlotName: String + private lateinit var locationSlotName: String + + private lateinit var controller: HeaderPrivacyIconsController + + @Before + fun setUp() { + MockitoAnnotations.initMocks(this) + whenever(privacyChip.context).thenReturn(context) + whenever(privacyChip.resources).thenReturn(context.resources) + + cameraSlotName = context.getString(com.android.internal.R.string.status_bar_camera) + microphoneSlotName = context.getString(com.android.internal.R.string.status_bar_microphone) + locationSlotName = context.getString(com.android.internal.R.string.status_bar_location) + + controller = HeaderPrivacyIconsController( + privacyItemController, + uiEventLogger, + privacyChip, + privacyDialogController, + privacyLogger, + iconContainer + ) + } + + @Test + fun testIgnoredSlotsOnParentVisible_noIndicators() { + setPrivacyController(micCamera = false, location = false) + + controller.onParentVisible() + + verify(iconContainer).removeIgnoredSlot(cameraSlotName) + verify(iconContainer).removeIgnoredSlot(microphoneSlotName) + verify(iconContainer).removeIgnoredSlot(locationSlotName) + } + + @Test + fun testIgnoredSlotsOnParentVisible_onlyMicCamera() { + setPrivacyController(micCamera = true, location = false) + + controller.onParentVisible() + + verify(iconContainer).addIgnoredSlot(cameraSlotName) + verify(iconContainer).addIgnoredSlot(microphoneSlotName) + verify(iconContainer).removeIgnoredSlot(locationSlotName) + } + + @Test + fun testIgnoredSlotsOnParentVisible_onlyLocation() { + setPrivacyController(micCamera = false, location = true) + + controller.onParentVisible() + + verify(iconContainer).removeIgnoredSlot(cameraSlotName) + verify(iconContainer).removeIgnoredSlot(microphoneSlotName) + verify(iconContainer).addIgnoredSlot(locationSlotName) + } + + @Test + fun testIgnoredSlotsOnParentVisible_locationMicCamera() { + setPrivacyController(micCamera = true, location = true) + + controller.onParentVisible() + + verify(iconContainer).addIgnoredSlot(cameraSlotName) + verify(iconContainer).addIgnoredSlot(microphoneSlotName) + verify(iconContainer).addIgnoredSlot(locationSlotName) + } + + @Test + fun testPrivacyChipClicked() { + controller.onParentVisible() + + val captor = argumentCaptor<View.OnClickListener>() + verify(privacyChip).setOnClickListener(capture(captor)) + + captor.value.onClick(privacyChip) + + verify(privacyDialogController).showDialog(any(Context::class.java)) + } + + private fun setPrivacyController(micCamera: Boolean, location: Boolean) { + whenever(privacyItemController.micCameraAvailable).thenReturn(micCamera) + whenever(privacyItemController.locationAvailable).thenReturn(location) + } +}
\ No newline at end of file diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt index f85167e6aa63..62b6725cab38 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt @@ -20,18 +20,12 @@ import android.content.Context import android.testing.AndroidTestingRunner import android.view.View import androidx.test.filters.SmallTest -import com.android.internal.logging.UiEventLogger import com.android.systemui.R import com.android.systemui.SysuiTestCase import com.android.systemui.battery.BatteryMeterViewController import com.android.systemui.colorextraction.SysuiColorExtractor import com.android.systemui.demomode.DemoModeController import com.android.systemui.flags.FeatureFlags -import com.android.systemui.plugins.ActivityStarter -import com.android.systemui.privacy.OngoingPrivacyChip -import com.android.systemui.privacy.PrivacyDialogController -import com.android.systemui.privacy.PrivacyItemController -import com.android.systemui.privacy.logging.PrivacyLogger import com.android.systemui.qs.carrier.QSCarrierGroup import com.android.systemui.qs.carrier.QSCarrierGroupController import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider @@ -51,10 +45,10 @@ import org.junit.runner.RunWith import org.mockito.Answers import org.mockito.ArgumentMatchers.anyInt import org.mockito.Mock +import org.mockito.Mockito.`when` import org.mockito.Mockito.anyBoolean import org.mockito.Mockito.reset import org.mockito.Mockito.verify -import org.mockito.Mockito.`when` import org.mockito.MockitoAnnotations @SmallTest @@ -64,11 +58,7 @@ class QuickStatusBarHeaderControllerTest : SysuiTestCase() { @Mock private lateinit var view: QuickStatusBarHeader @Mock - private lateinit var privacyItemController: PrivacyItemController - @Mock - private lateinit var activityStarter: ActivityStarter - @Mock - private lateinit var uiEventLogger: UiEventLogger + private lateinit var privacyIconsController: HeaderPrivacyIconsController @Mock private lateinit var statusBarIconController: StatusBarIconController @Mock @@ -80,18 +70,12 @@ class QuickStatusBarHeaderControllerTest : SysuiTestCase() { @Mock private lateinit var qsCarrierGroupController: QSCarrierGroupController @Mock - private lateinit var privacyLogger: PrivacyLogger - @Mock private lateinit var colorExtractor: SysuiColorExtractor @Mock private lateinit var iconContainer: StatusIconContainer @Mock private lateinit var qsCarrierGroup: QSCarrierGroup @Mock - private lateinit var privacyChip: OngoingPrivacyChip - @Mock - private lateinit var privacyDialogController: PrivacyDialogController - @Mock private lateinit var variableDateViewControllerFactory: VariableDateViewController.Factory @Mock private lateinit var variableDateViewController: VariableDateViewController @@ -114,10 +98,6 @@ class QuickStatusBarHeaderControllerTest : SysuiTestCase() { private lateinit var controller: QuickStatusBarHeaderController - private lateinit var cameraSlotName: String - private lateinit var microphoneSlotName: String - private lateinit var locationSlotName: String - @Before fun setUp() { MockitoAnnotations.initMocks(this) @@ -130,25 +110,14 @@ class QuickStatusBarHeaderControllerTest : SysuiTestCase() { `when`(view.isAttachedToWindow).thenReturn(true) `when`(view.context).thenReturn(context) - cameraSlotName = mContext.resources.getString( - com.android.internal.R.string.status_bar_camera) - microphoneSlotName = mContext.resources.getString( - com.android.internal.R.string.status_bar_microphone) - locationSlotName = mContext.resources.getString( - com.android.internal.R.string.status_bar_location) - controller = QuickStatusBarHeaderController( view, - privacyItemController, - activityStarter, - uiEventLogger, + privacyIconsController, statusBarIconController, demoModeController, quickQSPanelController, qsCarrierGroupControllerBuilder, - privacyLogger, colorExtractor, - privacyDialogController, qsExpansionPathInterpolator, batteryMeterViewController, featureFlags, @@ -168,62 +137,6 @@ class QuickStatusBarHeaderControllerTest : SysuiTestCase() { } @Test - fun testIgnoredSlotsOnAttached_noIndicators() { - setPrivacyController(micCamera = false, location = false) - - controller.init() - - verify(iconContainer).removeIgnoredSlot(cameraSlotName) - verify(iconContainer).removeIgnoredSlot(microphoneSlotName) - verify(iconContainer).removeIgnoredSlot(locationSlotName) - } - - @Test - fun testIgnoredSlotsOnAttached_onlyMicCamera() { - setPrivacyController(micCamera = true, location = false) - - controller.init() - - verify(iconContainer).addIgnoredSlot(cameraSlotName) - verify(iconContainer).addIgnoredSlot(microphoneSlotName) - verify(iconContainer).removeIgnoredSlot(locationSlotName) - } - - @Test - fun testIgnoredSlotsOnAttached_onlyLocation() { - setPrivacyController(micCamera = false, location = true) - - controller.init() - - verify(iconContainer).removeIgnoredSlot(cameraSlotName) - verify(iconContainer).removeIgnoredSlot(microphoneSlotName) - verify(iconContainer).addIgnoredSlot(locationSlotName) - } - - @Test - fun testIgnoredSlotsOnAttached_locationMicCamera() { - setPrivacyController(micCamera = true, location = true) - - controller.init() - - verify(iconContainer).addIgnoredSlot(cameraSlotName) - verify(iconContainer).addIgnoredSlot(microphoneSlotName) - verify(iconContainer).addIgnoredSlot(locationSlotName) - } - - @Test - fun testPrivacyChipClicked() { - controller.init() - - val captor = argumentCaptor<View.OnClickListener>() - verify(privacyChip).setOnClickListener(capture(captor)) - - captor.value.onClick(privacyChip) - - verify(privacyDialogController).showDialog(any(Context::class.java)) - } - - @Test fun testSingleCarrierListenerAttachedOnInit() { controller.init() @@ -292,14 +205,8 @@ class QuickStatusBarHeaderControllerTest : SysuiTestCase() { `when`(view.findViewById<View>(anyInt())).thenReturn(mockView) `when`(view.findViewById<QSCarrierGroup>(R.id.carrier_group)).thenReturn(qsCarrierGroup) `when`(view.findViewById<StatusIconContainer>(R.id.statusIcons)).thenReturn(iconContainer) - `when`(view.findViewById<OngoingPrivacyChip>(R.id.privacy_chip)).thenReturn(privacyChip) `when`(view.findViewById<Clock>(R.id.clock)).thenReturn(clock) `when`(view.requireViewById<VariableDateView>(R.id.date)).thenReturn(variableDateView) `when`(view.requireViewById<VariableDateView>(R.id.date_clock)).thenReturn(variableDateView) } - - private fun setPrivacyController(micCamera: Boolean, location: Boolean) { - `when`(privacyItemController.micCameraAvailable).thenReturn(micCamera) - `when`(privacyItemController.locationAvailable).thenReturn(location) - } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java index 5a49337fe640..b40a20c27820 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java @@ -38,6 +38,7 @@ import androidx.test.filters.SmallTest; import com.android.internal.logging.MetricsLogger; import com.android.systemui.SysuiTestCase; +import com.android.systemui.animation.DialogLaunchAnimator; import com.android.systemui.classifier.FalsingManagerFake; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.statusbar.StatusBarStateController; @@ -90,6 +91,8 @@ public class CastTileTest extends SysuiTestCase { private HotspotController.Callback mHotspotCallback; @Mock private QSLogger mQSLogger; + @Mock + private DialogLaunchAnimator mDialogLaunchAnimator; private TestableLooper mTestableLooper; private CastTile mCastTile; @@ -113,7 +116,8 @@ public class CastTileTest extends SysuiTestCase { mController, mKeyguard, mNetworkController, - mHotspotController + mHotspotController, + mDialogLaunchAnimator ); mCastTile.initialize(); @@ -241,6 +245,7 @@ public class CastTileTest extends SysuiTestCase { List<CastDevice> devices = new ArrayList<>(); devices.add(device); when(mController.getCastDevices()).thenReturn(devices); + when(mKeyguard.isShowing()).thenReturn(true); enableWifiAndProcessMessages(); mCastTile.handleClick(null /* view */); diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt index 13df04ccef6f..9936d4951d00 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt @@ -96,8 +96,6 @@ class DndTileTest : SysuiTestCase() { whenever(qsHost.userId).thenReturn(DEFAULT_USER) whenever(qsHost.uiEventLogger).thenReturn(uiEventLogger) - whenever(dialogLaunchAnimator.showFromView(any(), any(), anyBoolean())) - .thenReturn(hostDialog) val wrappedContext = object : ContextWrapper(context) { override fun getSharedPreferences(file: File?, mode: Int): SharedPreferences { diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java index b32b4d4f3810..0cf063f5db39 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java @@ -1,5 +1,7 @@ package com.android.systemui.qs.tiles.dialog; +import static com.android.systemui.qs.tiles.dialog.InternetDialogController.MAX_WIFI_ENTRY_COUNT; + import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; @@ -78,6 +80,7 @@ public class InternetDialogTest extends SysuiTestCase { private RecyclerView mWifiList; private LinearLayout mSeeAll; private LinearLayout mWifiScanNotify; + private TextView mAirplaneModeSummaryText; @Before public void setUp() { @@ -112,6 +115,7 @@ public class InternetDialogTest extends SysuiTestCase { mWifiList = mDialogView.requireViewById(R.id.wifi_list_layout); mSeeAll = mDialogView.requireViewById(R.id.see_all_layout); mWifiScanNotify = mDialogView.requireViewById(R.id.wifi_scan_notify_layout); + mAirplaneModeSummaryText = mDialogView.requireViewById(R.id.airplane_mode_summary); } @After @@ -189,12 +193,91 @@ public class InternetDialogTest extends SysuiTestCase { } @Test - public void updateDialog_withApmOn_mobileDataLayoutGone() { + public void updateDialog_apmOffAndNotCarrierNetwork_mobileDataLayoutGone() { + // Mobile network should be gone if the list of active subscriptionId is null. + when(mInternetDialogController.isCarrierNetworkActive()).thenReturn(false); + when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(false); + when(mInternetDialogController.hasActiveSubId()).thenReturn(false); + + mInternetDialog.updateDialog(true); + + assertThat(mMobileDataToggle.getVisibility()).isEqualTo(View.GONE); + } + + @Test + public void updateDialog_apmOnWithCarrierNetworkAndWifiStatus_mobileDataLayout() { + // Carrier network should be gone if airplane mode ON and Wi-Fi is off. + when(mInternetDialogController.isCarrierNetworkActive()).thenReturn(true); when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(true); + when(mWifiManager.isWifiEnabled()).thenReturn(false); mInternetDialog.updateDialog(true); assertThat(mMobileDataToggle.getVisibility()).isEqualTo(View.GONE); + + // Carrier network should be visible if airplane mode ON and Wi-Fi is ON. + when(mInternetDialogController.isCarrierNetworkActive()).thenReturn(true); + when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(true); + when(mWifiManager.isWifiEnabled()).thenReturn(true); + + mInternetDialog.updateDialog(true); + + assertThat(mMobileDataToggle.getVisibility()).isEqualTo(View.VISIBLE); + } + + @Test + public void updateDialog_apmOnAndNoCarrierNetwork_mobileDataLayoutGone() { + when(mInternetDialogController.isCarrierNetworkActive()).thenReturn(false); + when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(true); + + mInternetDialog.updateDialog(true); + + assertThat(mMobileDataToggle.getVisibility()).isEqualTo(View.GONE); + } + + @Test + public void updateDialog_apmOnAndWifiOnHasCarrierNetwork_showAirplaneSummary() { + when(mInternetDialogController.isCarrierNetworkActive()).thenReturn(true); + when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(true); + mInternetDialog.mConnectedWifiEntry = null; + doReturn(false).when(mInternetDialogController).activeNetworkIsCellular(); + + mInternetDialog.updateDialog(true); + + assertThat(mMobileDataToggle.getVisibility()).isEqualTo(View.VISIBLE); + assertThat(mAirplaneModeSummaryText.getVisibility()).isEqualTo(View.VISIBLE); + } + + @Test + public void updateDialog_apmOffAndWifiOnHasCarrierNetwork_notShowApmSummary() { + when(mInternetDialogController.isCarrierNetworkActive()).thenReturn(true); + when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(false); + mInternetDialog.mConnectedWifiEntry = null; + doReturn(false).when(mInternetDialogController).activeNetworkIsCellular(); + + mInternetDialog.updateDialog(true); + + assertThat(mAirplaneModeSummaryText.getVisibility()).isEqualTo(View.GONE); + } + + @Test + public void updateDialog_apmOffAndHasCarrierNetwork_notShowApmSummary() { + when(mInternetDialogController.isCarrierNetworkActive()).thenReturn(true); + when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(false); + + mInternetDialog.updateDialog(true); + + assertThat(mAirplaneModeSummaryText.getVisibility()).isEqualTo(View.GONE); + } + + @Test + public void updateDialog_apmOnAndNoCarrierNetwork_notShowApmSummary() { + when(mInternetDialogController.isCarrierNetworkActive()).thenReturn(false); + when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(true); + + mInternetDialog.updateDialog(true); + + assertThat(mAirplaneModeSummaryText.getVisibility()).isEqualTo(View.GONE); } @Test @@ -219,7 +302,7 @@ public class InternetDialogTest extends SysuiTestCase { } @Test - public void updateDialog_wifiOnAndNoWifiEntry_hideWifiEntryAndSeeAll() { + public void updateDialog_wifiOnAndNoWifiEntry_showWifiListAndSeeAllArea() { // The precondition WiFi ON is already in setUp() mInternetDialog.mConnectedWifiEntry = null; mInternetDialog.mWifiEntriesCount = 0; @@ -227,19 +310,21 @@ public class InternetDialogTest extends SysuiTestCase { mInternetDialog.updateDialog(false); assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.GONE); - assertThat(mWifiList.getVisibility()).isEqualTo(View.GONE); - assertThat(mSeeAll.getVisibility()).isEqualTo(View.GONE); + // Show a blank block to fix the dialog height even if there is no WiFi list + assertThat(mWifiList.getVisibility()).isEqualTo(View.VISIBLE); + assertThat(mSeeAll.getVisibility()).isEqualTo(View.INVISIBLE); } @Test - public void updateDialog_wifiOnAndHasConnectedWifi_showConnectedWifiAndSeeAll() { + public void updateDialog_wifiOnAndHasConnectedWifi_showAllWifiAndSeeAllArea() { // The preconditions WiFi ON and WiFi entries are already in setUp() mInternetDialog.mWifiEntriesCount = 0; mInternetDialog.updateDialog(false); assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.VISIBLE); - assertThat(mWifiList.getVisibility()).isEqualTo(View.GONE); + // Show a blank block to fix the dialog height even if there is no WiFi list + assertThat(mWifiList.getVisibility()).isEqualTo(View.VISIBLE); assertThat(mSeeAll.getVisibility()).isEqualTo(View.VISIBLE); } @@ -412,4 +497,54 @@ public class InternetDialogTest extends SysuiTestCase { assertThat(mInternetDialog.mIsProgressBarVisible).isTrue(); assertThat(mInternetDialog.mIsSearchingHidden).isTrue(); } + + @Test + public void getWifiListMaxCount_returnCountCorrectly() { + // Ethernet, MobileData, ConnectedWiFi are all hidden. + // Then the maximum count is equal to MAX_WIFI_ENTRY_COUNT. + setNetworkVisible(false, false, false); + + assertThat(mInternetDialog.getWifiListMaxCount()).isEqualTo(MAX_WIFI_ENTRY_COUNT); + + // Only one of Ethernet, MobileData, ConnectedWiFi is displayed. + // Then the maximum count is equal to MAX_WIFI_ENTRY_COUNT - 1. + setNetworkVisible(true, false, false); + + assertThat(mInternetDialog.getWifiListMaxCount()).isEqualTo(MAX_WIFI_ENTRY_COUNT - 1); + + setNetworkVisible(false, true, false); + + assertThat(mInternetDialog.getWifiListMaxCount()).isEqualTo(MAX_WIFI_ENTRY_COUNT - 1); + + setNetworkVisible(false, false, true); + + assertThat(mInternetDialog.getWifiListMaxCount()).isEqualTo(MAX_WIFI_ENTRY_COUNT - 1); + + // Only one of Ethernet, MobileData, ConnectedWiFi is hidden. + // Then the maximum count is equal to MAX_WIFI_ENTRY_COUNT - 2. + setNetworkVisible(true, true, false); + + assertThat(mInternetDialog.getWifiListMaxCount()).isEqualTo(MAX_WIFI_ENTRY_COUNT - 2); + + setNetworkVisible(true, false, true); + + assertThat(mInternetDialog.getWifiListMaxCount()).isEqualTo(MAX_WIFI_ENTRY_COUNT - 2); + + setNetworkVisible(false, true, true); + + assertThat(mInternetDialog.getWifiListMaxCount()).isEqualTo(MAX_WIFI_ENTRY_COUNT - 2); + + // Ethernet, MobileData, ConnectedWiFi are all displayed. + // Then the maximum count is equal to MAX_WIFI_ENTRY_COUNT - 3. + setNetworkVisible(true, true, true); + + assertThat(mInternetDialog.getWifiListMaxCount()).isEqualTo(MAX_WIFI_ENTRY_COUNT - 3); + } + + private void setNetworkVisible(boolean ethernetVisible, boolean mobileDataVisible, + boolean connectedWifiVisible) { + mEthernet.setVisibility(ethernetVisible ? View.VISIBLE : View.GONE); + mMobileDataToggle.setVisibility(mobileDataVisible ? View.VISIBLE : View.GONE); + mConnectedWifi.setVisibility(connectedWifiVisible ? View.VISIBLE : View.GONE); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/user/UserSwitchDialogControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/user/UserSwitchDialogControllerTest.kt index 3c4a557eac10..b7fdc1a6cb0d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/user/UserSwitchDialogControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/user/UserSwitchDialogControllerTest.kt @@ -16,7 +16,6 @@ package com.android.systemui.qs.user -import android.app.Dialog import android.content.DialogInterface import android.content.Intent import android.provider.Settings @@ -31,7 +30,6 @@ import com.android.systemui.qs.PseudoGridView import com.android.systemui.qs.tiles.UserDetailView import com.android.systemui.statusbar.phone.SystemUIDialog import com.android.systemui.util.mockito.any -import com.android.systemui.util.mockito.argumentCaptor import com.android.systemui.util.mockito.capture import com.android.systemui.util.mockito.eq import org.junit.Before @@ -42,7 +40,6 @@ import org.mockito.ArgumentMatcher import org.mockito.Captor import org.mockito.Mock import org.mockito.Mockito.`when` -import org.mockito.Mockito.anyBoolean import org.mockito.Mockito.anyInt import org.mockito.Mockito.argThat import org.mockito.Mockito.never @@ -65,8 +62,6 @@ class UserSwitchDialogControllerTest : SysuiTestCase() { private lateinit var launchView: View @Mock private lateinit var dialogLaunchAnimator: DialogLaunchAnimator - @Mock - private lateinit var hostDialog: Dialog @Captor private lateinit var clickCaptor: ArgumentCaptor<DialogInterface.OnClickListener> @@ -78,8 +73,6 @@ class UserSwitchDialogControllerTest : SysuiTestCase() { `when`(launchView.context).thenReturn(mContext) `when`(dialog.context).thenReturn(mContext) - `when`(dialogLaunchAnimator.showFromView(any(), any(), anyBoolean())) - .thenReturn(hostDialog) controller = UserSwitchDialogController( { userDetailViewAdapter }, @@ -151,18 +144,6 @@ class UserSwitchDialogControllerTest : SysuiTestCase() { verify(activityStarter, never()).postStartActivityDismissingKeyguard(any(), anyInt()) } - @Test - fun callbackFromDialogShower_dismissesDialog() { - val captor = argumentCaptor<UserSwitchDialogController.DialogShower>() - - controller.showDialog(launchView) - verify(userDetailViewAdapter).injectDialogShower(capture(captor)) - - captor.value.dismiss() - - verify(hostDialog).dismiss() - } - private class IntentMatcher(private val action: String) : ArgumentMatcher<Intent> { override fun matches(argument: Intent?): Boolean { return argument?.action == action diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenrecord/RecordingServiceTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenrecord/RecordingServiceTest.java index 91cafead596c..4073bb336283 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/screenrecord/RecordingServiceTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/screenrecord/RecordingServiceTest.java @@ -104,7 +104,7 @@ public class RecordingServiceTest extends SysuiTestCase { @Test public void testLogStartRecording() { - Intent startIntent = RecordingService.getStartIntent(mContext, 0, 0, false); + Intent startIntent = RecordingService.getStartIntent(mContext, 0, 0); mRecordingService.onStartCommand(startIntent, 0, 0); verify(mUiEventLogger, times(1)).log(Events.ScreenRecordEvent.SCREEN_RECORD_START); @@ -137,7 +137,7 @@ public class RecordingServiceTest extends SysuiTestCase { // When the screen recording does not start properly doThrow(new RuntimeException("fail")).when(mScreenMediaRecorder).start(); - Intent startIntent = RecordingService.getStartIntent(mContext, 0, 0, false); + Intent startIntent = RecordingService.getStartIntent(mContext, 0, 0); mRecordingService.onStartCommand(startIntent, 0, 0); // Then the state is set to not recording diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java index 8afefde86632..e427d53306ea 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java @@ -22,6 +22,7 @@ import static android.content.pm.UserInfo.FLAG_MANAGED_PROFILE; import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_ALIGNMENT; import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_BATTERY; +import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_BIOMETRIC_MESSAGE; import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_DISCLOSURE; import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_OWNER_INFO; import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_RESTING; @@ -112,6 +113,8 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase { private static final ComponentName DEVICE_OWNER_COMPONENT = new ComponentName("com.android.foo", "bar"); + private static final int TEST_STRING_RES = R.string.keyguard_indication_trust_unlocked; + private String mKeyguardTryFingerprintMsg; private String mDisclosureWithOrganization; private String mDisclosureGeneric; @@ -419,7 +422,7 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase { // WHEN transient text is shown mStatusBarStateListener.onDozingChanged(true); - mController.showTransientIndication("Test"); + mController.showTransientIndication(TEST_STRING_RES); // THEN wake lock is held while the animation is running assertTrue("WakeLock expected: HELD, was: RELEASED", mWakeLock.isHeld()); @@ -434,7 +437,7 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase { // WHEN we show the transient indication mStatusBarStateListener.onDozingChanged(true); - mController.showTransientIndication("Test"); + mController.showTransientIndication(TEST_STRING_RES); // THEN wake lock is RELEASED, not held assertFalse("WakeLock expected: RELEASED, was: HELD", mWakeLock.isHeld()); @@ -445,10 +448,11 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase { createController(); mController.setVisible(true); - mController.showTransientIndication("Test"); + mController.showTransientIndication(TEST_STRING_RES); mStatusBarStateListener.onDozingChanged(true); - assertThat(mTextView.getText()).isEqualTo("Test"); + assertThat(mTextView.getText()).isEqualTo( + mContext.getResources().getString(TEST_STRING_RES)); assertThat(mTextView.getCurrentTextColor()).isEqualTo(Color.WHITE); assertThat(mTextView.getAlpha()).isEqualTo(1f); } @@ -462,11 +466,11 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase { mController.getKeyguardCallback().onBiometricHelp( KeyguardUpdateMonitor.BIOMETRIC_HELP_FACE_NOT_RECOGNIZED, message, BiometricSourceType.FACE); - verifyTransientMessage(message); + verifyIndicationMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE, message); reset(mRotateTextViewController); mStatusBarStateListener.onDozingChanged(true); - verifyHideIndication(INDICATION_TYPE_TRANSIENT); + verifyHideIndication(INDICATION_TYPE_BIOMETRIC_MESSAGE); } @Test @@ -478,7 +482,7 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase { mController.getKeyguardCallback().onBiometricError(FaceManager.FACE_ERROR_TIMEOUT, "A message", BiometricSourceType.FACE); - verifyTransientMessage(message); + verifyIndicationMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE, message); mStatusBarStateListener.onDozingChanged(true); assertThat(mTextView.getText()).isNotEqualTo(message); @@ -497,7 +501,8 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase { FingerprintManager.FINGERPRINT_ERROR_CANCELED, "bar", BiometricSourceType.FINGERPRINT); - verifyNoTransientMessage(); + verifyNoMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE); + verifyNoMessage(INDICATION_TYPE_TRANSIENT); } @Test @@ -757,7 +762,12 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase { verify(mRotateTextViewController).showTransient(eq(message)); } - private void verifyNoTransientMessage() { - verify(mRotateTextViewController, never()).showTransient(any()); + private void verifyNoMessage(int type) { + if (type == INDICATION_TYPE_TRANSIENT) { + verify(mRotateTextViewController, never()).showTransient(anyString()); + } else { + verify(mRotateTextViewController, never()).updateIndication(eq(type), + anyObject(), anyBoolean()); + } } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java index bafbccdb87d2..db5fd262a1d1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java @@ -162,8 +162,11 @@ public class HeadsUpAppearanceControllerTest extends SysuiTestCase { } @Test - public void testHeaderReadFromOldController() { - mHeadsUpAppearanceController.setAppearFraction(1.0f, 1.0f); + public void constructor_animationValuesUpdated() { + float appearFraction = .75f; + float expandedHeight = 400f; + when(mStackScrollerController.getAppearFraction()).thenReturn(appearFraction); + when(mStackScrollerController.getExpandedHeight()).thenReturn(expandedHeight); HeadsUpAppearanceController newController = new HeadsUpAppearanceController( mock(NotificationIconAreaController.class), @@ -179,14 +182,9 @@ public class HeadsUpAppearanceControllerTest extends SysuiTestCase { new View(mContext), new View(mContext), new View(mContext)); - newController.readFrom(mHeadsUpAppearanceController); - - Assert.assertEquals(mHeadsUpAppearanceController.mExpandedHeight, - newController.mExpandedHeight, 0.0f); - Assert.assertEquals(mHeadsUpAppearanceController.mAppearFraction, - newController.mAppearFraction, 0.0f); - Assert.assertEquals(mHeadsUpAppearanceController.mIsExpanded, - newController.mIsExpanded); + + Assert.assertEquals(expandedHeight, newController.mExpandedHeight, 0.0f); + Assert.assertEquals(appearFraction, newController.mAppearFraction, 0.0f); } @Test @@ -195,7 +193,9 @@ public class HeadsUpAppearanceControllerTest extends SysuiTestCase { reset(mDarkIconDispatcher); reset(mPanelView); reset(mStackScrollerController); - mHeadsUpAppearanceController.destroy(); + + mHeadsUpAppearanceController.onViewDetached(); + verify(mHeadsUpManager).removeListener(any()); verify(mDarkIconDispatcher).removeDarkReceiver((DarkIconDispatcher.DarkReceiver) any()); verify(mPanelView).removeTrackingHeadsUpListener(any()); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaTest.kt index 210744eb30cf..3257a84f14d6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaTest.kt @@ -47,8 +47,8 @@ class KeyguardBottomAreaTest : SysuiTestCase() { @Test fun initFrom_doesntCrash() { - val other = LayoutInflater.from(mContext).inflate( - R.layout.keyguard_bottom_area, null, false) as KeyguardBottomAreaView + val other = LayoutInflater.from(mContext).inflate(R.layout.keyguard_bottom_area, + null, false) as KeyguardBottomAreaView other.initFrom(mKeyguardBottomArea) other.launchVoiceAssist() diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/SplitShadeHeaderControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/SplitShadeHeaderControllerTest.kt index 0cf0bd300419..2e7f8a2897f2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/SplitShadeHeaderControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/SplitShadeHeaderControllerTest.kt @@ -9,6 +9,7 @@ import com.android.systemui.animation.ShadeInterpolation import com.android.systemui.battery.BatteryMeterView import com.android.systemui.battery.BatteryMeterViewController import com.android.systemui.flags.FeatureFlags +import com.android.systemui.qs.HeaderPrivacyIconsController import com.android.systemui.qs.carrier.QSCarrierGroupController import com.google.common.truth.Truth.assertThat import org.junit.Before @@ -34,6 +35,7 @@ class SplitShadeHeaderControllerTest : SysuiTestCase() { @Mock private lateinit var featureFlags: FeatureFlags @Mock private lateinit var batteryMeterView: BatteryMeterView @Mock private lateinit var batteryMeterViewController: BatteryMeterViewController + @Mock private lateinit var privacyIconsController: HeaderPrivacyIconsController @JvmField @Rule val mockitoRule = MockitoJUnit.rule() var viewVisibility = View.GONE @@ -56,8 +58,14 @@ class SplitShadeHeaderControllerTest : SysuiTestCase() { } whenever(view.visibility).thenAnswer { _ -> viewVisibility } whenever(featureFlags.useCombinedQSHeaders()).thenReturn(false) - splitShadeHeaderController = SplitShadeHeaderController(view, statusBarIconController, - qsCarrierGroupControllerBuilder, featureFlags, batteryMeterViewController) + splitShadeHeaderController = SplitShadeHeaderController( + view, + statusBarIconController, + privacyIconsController, + qsCarrierGroupControllerBuilder, + featureFlags, + batteryMeterViewController + ) } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java index 72a3d664a6ce..cec5877e324a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java @@ -34,6 +34,7 @@ import static org.mockito.Mockito.when; import android.app.KeyguardManager; import android.app.Notification; +import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Intent; import android.os.Handler; @@ -62,7 +63,6 @@ import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.NotificationPresenter; import com.android.systemui.statusbar.NotificationRemoteInputManager; import com.android.systemui.statusbar.StatusBarState; -import com.android.systemui.statusbar.notification.NotificationActivityStarter; import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.NotificationLaunchAnimatorControllerProvider; import com.android.systemui.statusbar.notification.collection.NotifPipeline; @@ -114,6 +114,8 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase { @Mock private KeyguardStateController mKeyguardStateController; @Mock + private NotificationInterruptStateProvider mNotificationInterruptStateProvider; + @Mock private Handler mHandler; @Mock private BubblesManager mBubblesManager; @@ -133,7 +135,7 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase { @Mock private OnUserInteractionCallback mOnUserInteractionCallback; @Mock - private NotificationActivityStarter mNotificationActivityStarter; + private StatusBarNotificationActivityStarter mNotificationActivityStarter; @Mock private ActivityLaunchAnimator mActivityLaunchAnimator; private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock()); @@ -209,7 +211,7 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase { mock(NotificationLockscreenUserManager.class), mShadeController, mKeyguardStateController, - mock(NotificationInterruptStateProvider.class), + mNotificationInterruptStateProvider, mock(LockPatternUtils.class), mock(StatusBarRemoteInputCallback.class), mActivityIntentHelper, @@ -365,4 +367,27 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase { // Notification should not be cancelled. verify(mEntryManager, never()).performRemoveNotification(eq(sbn), any(), anyInt()); } + + @Test + public void testOnFullScreenIntentWhenDozing_wakeUpDevice() { + // GIVEN entry that can has a full screen intent that can show + Notification.Builder nb = new Notification.Builder(mContext, "a") + .setContentTitle("foo") + .setSmallIcon(android.R.drawable.sym_def_app_icon) + .setFullScreenIntent(mock(PendingIntent.class), true); + StatusBarNotification sbn = new StatusBarNotification("pkg", "pkg", 0, + "tag" + System.currentTimeMillis(), 0, 0, + nb.build(), new UserHandle(0), null, 0); + NotificationEntry entry = mock(NotificationEntry.class); + when(entry.getImportance()).thenReturn(NotificationManager.IMPORTANCE_HIGH); + when(entry.getSbn()).thenReturn(sbn); + when(mNotificationInterruptStateProvider.shouldLaunchFullScreenIntentWhenAdded(eq(entry))) + .thenReturn(true); + + // WHEN + mNotificationActivityStarter.handleFullScreenIntent(entry); + + // THEN display should try wake up for the full screen intent + verify(mStatusBar).wakeUpForFullScreenIntent(); + } } 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 d58e13cd8a64..20575ae504ad 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 @@ -77,6 +77,7 @@ import com.android.keyguard.ViewMediatorCallback; import com.android.systemui.InitController; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; +import com.android.systemui.accessibility.floatingmenu.AccessibilityFloatingMenuController; import com.android.systemui.animation.ActivityLaunchAnimator; import com.android.systemui.assist.AssistManager; import com.android.systemui.broadcast.BroadcastDispatcher; @@ -216,6 +217,7 @@ public class StatusBarTest extends SysuiTestCase { @Mock private NotificationGutsManager mNotificationGutsManager; @Mock private NotificationMediaManager mNotificationMediaManager; @Mock private NavigationBarController mNavigationBarController; + @Mock private AccessibilityFloatingMenuController mAccessibilityFloatingMenuController; @Mock private BypassHeadsUpNotifier mBypassHeadsUpNotifier; @Mock private SysuiColorExtractor mColorExtractor; @Mock private ColorExtractor.GradientColors mGradientColors; @@ -275,7 +277,6 @@ public class StatusBarTest extends SysuiTestCase { @Mock private StartingSurface mStartingSurface; @Mock private OperatorNameViewController mOperatorNameViewController; @Mock private OperatorNameViewController.Factory mOperatorNameViewControllerFactory; - @Mock private PhoneStatusBarViewController.Factory mPhoneStatusBarViewControllerFactory; @Mock private ActivityLaunchAnimator mActivityLaunchAnimator; private ShadeController mShadeController; private final FakeSystemClock mFakeSystemClock = new FakeSystemClock(); @@ -404,6 +405,7 @@ public class StatusBarTest extends SysuiTestCase { mVisualStabilityManager, mDeviceProvisionedController, mNavigationBarController, + mAccessibilityFloatingMenuController, () -> mAssistManager, configurationController, mNotificationShadeWindowController, @@ -433,7 +435,6 @@ public class StatusBarTest extends SysuiTestCase { mExtensionController, mUserInfoControllerImpl, mOperatorNameViewControllerFactory, - mPhoneStatusBarViewControllerFactory, mPhoneStatusBarPolicy, mKeyguardIndicationController, mDemoModeController, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java index 8b5989ff61a3..b97f053b24b5 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java @@ -21,7 +21,6 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.atLeast; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.reset; import static org.mockito.Mockito.when; import android.app.Fragment; @@ -48,9 +47,9 @@ import com.android.systemui.statusbar.DisableFlagsLogger; import com.android.systemui.statusbar.OperatorNameViewController; import com.android.systemui.statusbar.connectivity.NetworkController; import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler; +import com.android.systemui.statusbar.phone.HeadsUpAppearanceController; import com.android.systemui.statusbar.phone.NotificationIconAreaController; import com.android.systemui.statusbar.phone.NotificationPanelViewController; -import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.phone.StatusBarHideIconsForBouncerManager; import com.android.systemui.statusbar.phone.StatusBarIconController; import com.android.systemui.statusbar.phone.StatusBarLocationPublisher; @@ -62,12 +61,11 @@ import com.android.systemui.util.concurrency.FakeExecutor; import com.android.systemui.util.time.FakeSystemClock; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mock; import org.mockito.Mockito; - -import java.util.Optional; +import org.mockito.MockitoAnnotations; @RunWith(AndroidTestingRunner.class) @RunWithLooper(setAsMainLooper = true) @@ -82,16 +80,22 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest { // Set in instantiate() private StatusBarIconController mStatusBarIconController; private NetworkController mNetworkController; - private StatusBarStateController mStatusBarStateController; private KeyguardStateController mKeyguardStateController; - private final StatusBar mStatusBar = mock(StatusBar.class); private final CommandQueue mCommandQueue = mock(CommandQueue.class); private OperatorNameViewController.Factory mOperatorNameViewControllerFactory; private OperatorNameViewController mOperatorNameViewController; + @Mock private StatusBarFragmentComponent.Factory mStatusBarFragmentComponentFactory; + @Mock private StatusBarFragmentComponent mStatusBarFragmentComponent; + @Mock + private StatusBarStateController mStatusBarStateController; + @Mock + private HeadsUpAppearanceController mHeadsUpAppearanceController; + @Mock + private NotificationPanelViewController mNotificationPanelViewController; public CollapsedStatusBarFragmentTest() { super(CollapsedStatusBarFragment.class); @@ -99,49 +103,35 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest { @Before public void setup() { - mStatusBarStateController = mDependency - .injectMockDependency(StatusBarStateController.class); injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES); - when(mStatusBar.getPanelController()).thenReturn( - mock(NotificationPanelViewController.class)); } @Test - public void testDisableNone() throws Exception { - mFragments.dispatchResume(); - processAllMessages(); - CollapsedStatusBarFragment fragment = (CollapsedStatusBarFragment) mFragment; + public void testDisableNone() { + CollapsedStatusBarFragment fragment = resumeAndGetFragment(); fragment.disable(DEFAULT_DISPLAY, 0, 0, false); - assertEquals(View.VISIBLE, mFragment.getView().findViewById(R.id.system_icon_area) - .getVisibility()); - assertEquals(View.VISIBLE, mFragment.getView().findViewById(R.id.clock) - .getVisibility()); + assertEquals(View.VISIBLE, getSystemIconAreaView().getVisibility()); + assertEquals(View.VISIBLE, getClockView().getVisibility()); } @Test - public void testDisableSystemInfo() throws Exception { - mFragments.dispatchResume(); - processAllMessages(); - CollapsedStatusBarFragment fragment = (CollapsedStatusBarFragment) mFragment; + public void testDisableSystemInfo() { + CollapsedStatusBarFragment fragment = resumeAndGetFragment(); fragment.disable(DEFAULT_DISPLAY, StatusBarManager.DISABLE_SYSTEM_INFO, 0, false); - assertEquals(View.INVISIBLE, mFragment.getView().findViewById(R.id.system_icon_area) - .getVisibility()); + assertEquals(View.INVISIBLE, getSystemIconAreaView().getVisibility()); fragment.disable(DEFAULT_DISPLAY, 0, 0, false); - assertEquals(View.VISIBLE, mFragment.getView().findViewById(R.id.system_icon_area) - .getVisibility()); + assertEquals(View.VISIBLE, getSystemIconAreaView().getVisibility()); } @Test - public void testDisableNotifications() throws Exception { - mFragments.dispatchResume(); - processAllMessages(); - CollapsedStatusBarFragment fragment = (CollapsedStatusBarFragment) mFragment; + public void testDisableNotifications() { + CollapsedStatusBarFragment fragment = resumeAndGetFragment(); fragment.disable(DEFAULT_DISPLAY, StatusBarManager.DISABLE_NOTIFICATION_ICONS, 0, false); @@ -153,25 +143,21 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest { } @Test - public void testDisableClock() throws Exception { - mFragments.dispatchResume(); - processAllMessages(); - CollapsedStatusBarFragment fragment = (CollapsedStatusBarFragment) mFragment; + public void testDisableClock() { + CollapsedStatusBarFragment fragment = resumeAndGetFragment(); fragment.disable(DEFAULT_DISPLAY, StatusBarManager.DISABLE_CLOCK, 0, false); - assertEquals(View.GONE, mFragment.getView().findViewById(R.id.clock).getVisibility()); + assertEquals(View.GONE, getClockView().getVisibility()); fragment.disable(DEFAULT_DISPLAY, 0, 0, false); - assertEquals(View.VISIBLE, mFragment.getView().findViewById(R.id.clock).getVisibility()); + assertEquals(View.VISIBLE, getClockView().getVisibility()); } @Test public void disable_noOngoingCall_chipHidden() { - mFragments.dispatchResume(); - processAllMessages(); - CollapsedStatusBarFragment fragment = (CollapsedStatusBarFragment) mFragment; + CollapsedStatusBarFragment fragment = resumeAndGetFragment(); when(mOngoingCallController.hasOngoingCall()).thenReturn(false); @@ -183,9 +169,7 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest { @Test public void disable_hasOngoingCall_chipDisplayedAndNotificationIconsHidden() { - mFragments.dispatchResume(); - processAllMessages(); - CollapsedStatusBarFragment fragment = (CollapsedStatusBarFragment) mFragment; + CollapsedStatusBarFragment fragment = resumeAndGetFragment(); when(mOngoingCallController.hasOngoingCall()).thenReturn(true); @@ -199,9 +183,7 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest { @Test public void disable_hasOngoingCallButNotificationIconsDisabled_chipHidden() { - mFragments.dispatchResume(); - processAllMessages(); - CollapsedStatusBarFragment fragment = (CollapsedStatusBarFragment) mFragment; + CollapsedStatusBarFragment fragment = resumeAndGetFragment(); when(mOngoingCallController.hasOngoingCall()).thenReturn(true); @@ -214,9 +196,7 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest { @Test public void disable_ongoingCallEnded_chipHidden() { - mFragments.dispatchResume(); - processAllMessages(); - CollapsedStatusBarFragment fragment = (CollapsedStatusBarFragment) mFragment; + CollapsedStatusBarFragment fragment = resumeAndGetFragment(); when(mOngoingCallController.hasOngoingCall()).thenReturn(true); @@ -234,41 +214,95 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest { mFragment.getView().findViewById(R.id.ongoing_call_chip).getVisibility()); } - @Ignore("b/192618546") @Test - public void testOnDozingChanged() throws Exception { - mFragments.dispatchResume(); - processAllMessages(); - CollapsedStatusBarFragment fragment = (CollapsedStatusBarFragment) mFragment; + public void disable_isDozingButNoCustomClock_clockAndSystemInfoVisible() { + CollapsedStatusBarFragment fragment = resumeAndGetFragment(); + when(mStatusBarStateController.isDozing()).thenReturn(true); + when(mNotificationPanelViewController.hasCustomClock()).thenReturn(false); - fragment.disable(DEFAULT_DISPLAY, StatusBarManager.DISABLE_NOTIFICATION_ICONS, 0, false); + fragment.disable(DEFAULT_DISPLAY, 0, 0, false); - Mockito.verify(mNotificationAreaInner, atLeast(1)).setVisibility(eq(View.INVISIBLE)); + assertEquals(View.VISIBLE, getSystemIconAreaView().getVisibility()); + assertEquals(View.VISIBLE, getClockView().getVisibility()); + } + + @Test + public void disable_customClockButNotDozing_clockAndSystemInfoVisible() { + CollapsedStatusBarFragment fragment = resumeAndGetFragment(); + when(mStatusBarStateController.isDozing()).thenReturn(false); + when(mNotificationPanelViewController.hasCustomClock()).thenReturn(true); + + fragment.disable(DEFAULT_DISPLAY, 0, 0, false); + + assertEquals(View.VISIBLE, getSystemIconAreaView().getVisibility()); + assertEquals(View.VISIBLE, getClockView().getVisibility()); + } + + @Test + public void disable_dozingAndCustomClock_clockAndSystemInfoHidden() { + CollapsedStatusBarFragment fragment = resumeAndGetFragment(); + when(mStatusBarStateController.isDozing()).thenReturn(true); + when(mNotificationPanelViewController.hasCustomClock()).thenReturn(true); + + // Make sure they start out as visible + assertEquals(View.VISIBLE, getSystemIconAreaView().getVisibility()); + assertEquals(View.VISIBLE, getClockView().getVisibility()); - reset(mStatusBarStateController); + fragment.disable(DEFAULT_DISPLAY, 0, 0, false); + + assertEquals(View.INVISIBLE, getSystemIconAreaView().getVisibility()); + assertEquals(View.GONE, getClockView().getVisibility()); + } + + @Test + public void onDozingChanged_clockAndSystemInfoVisibilitiesUpdated() { + CollapsedStatusBarFragment fragment = resumeAndGetFragment(); when(mStatusBarStateController.isDozing()).thenReturn(true); + when(mNotificationPanelViewController.hasCustomClock()).thenReturn(true); + + // Make sure they start out as visible + assertEquals(View.VISIBLE, getSystemIconAreaView().getVisibility()); + assertEquals(View.VISIBLE, getClockView().getVisibility()); + fragment.onDozingChanged(true); - Mockito.verify(mStatusBarStateController).isDozing(); - Mockito.verify(mNotificationAreaInner, atLeast(1)).setVisibility(eq(View.VISIBLE)); + // When this callback is triggered, we want to make sure the clock and system info + // visibilities are recalculated. Since dozing=true, they shouldn't be visible. + assertEquals(View.INVISIBLE, getSystemIconAreaView().getVisibility()); + assertEquals(View.GONE, getClockView().getVisibility()); + } + + @Test + public void disable_headsUpShouldBeVisibleTrue_clockDisabled() { + CollapsedStatusBarFragment fragment = resumeAndGetFragment(); + when(mHeadsUpAppearanceController.shouldBeVisible()).thenReturn(true); + + fragment.disable(DEFAULT_DISPLAY, 0, 0, false); + + assertEquals(View.GONE, getClockView().getVisibility()); + } + + @Test + public void disable_headsUpShouldBeVisibleFalse_clockNotDisabled() { + CollapsedStatusBarFragment fragment = resumeAndGetFragment(); + when(mHeadsUpAppearanceController.shouldBeVisible()).thenReturn(false); + + fragment.disable(DEFAULT_DISPLAY, 0, 0, false); + + assertEquals(View.VISIBLE, getClockView().getVisibility()); } @Test public void setUp_fragmentCreatesDaggerComponent() { - mFragments.dispatchResume(); - processAllMessages(); - CollapsedStatusBarFragment fragment = (CollapsedStatusBarFragment) mFragment; + CollapsedStatusBarFragment fragment = resumeAndGetFragment(); assertEquals(mStatusBarFragmentComponent, fragment.getStatusBarFragmentComponent()); } @Override protected Fragment instantiate(Context context, String className, Bundle arguments) { - mStatusBarFragmentComponentFactory = - mock(StatusBarFragmentComponent.Factory.class); - mStatusBarFragmentComponent = mock(StatusBarFragmentComponent.class); - when(mStatusBarFragmentComponentFactory.create(any())) - .thenReturn(mStatusBarFragmentComponent); + MockitoAnnotations.initMocks(this); + setUpDaggerComponent(); mOngoingCallController = mock(OngoingCallController.class); mAnimationScheduler = mock(SystemStatusAnimationScheduler.class); mLocationPublisher = mock(StatusBarLocationPublisher.class); @@ -290,12 +324,11 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest { mMockNotificationAreaController, new PanelExpansionStateManager(), mock(FeatureFlags.class), - () -> Optional.of(mStatusBar), mStatusBarIconController, new StatusBarHideIconsForBouncerManager( mCommandQueue, new FakeExecutor(new FakeSystemClock()), new DumpManager()), mKeyguardStateController, - mock(NotificationPanelViewController.class), + mNotificationPanelViewController, mNetworkController, mStatusBarStateController, mCommandQueue, @@ -306,6 +339,13 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest { mOperatorNameViewControllerFactory); } + private void setUpDaggerComponent() { + when(mStatusBarFragmentComponentFactory.create(any())) + .thenReturn(mStatusBarFragmentComponent); + when(mStatusBarFragmentComponent.getHeadsUpAppearanceController()) + .thenReturn(mHeadsUpAppearanceController); + } + private void setUpNotificationIconAreaController() { mMockNotificationAreaController = mock(NotificationIconAreaController.class); @@ -324,4 +364,18 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest { when(mMockNotificationAreaController.getNotificationInnerAreaView()).thenReturn( mNotificationAreaInner); } + + private CollapsedStatusBarFragment resumeAndGetFragment() { + mFragments.dispatchResume(); + processAllMessages(); + return (CollapsedStatusBarFragment) mFragment; + } + + private View getClockView() { + return mFragment.getView().findViewById(R.id.clock); + } + + private View getSystemIconAreaView() { + return mFragment.getView().findViewById(R.id.system_icon_area); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt index 724f841922ff..a4bf14254e2c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt @@ -40,6 +40,7 @@ import com.android.internal.util.UserIcons import com.android.systemui.GuestResumeSessionReceiver import com.android.systemui.R import com.android.systemui.SysuiTestCase +import com.android.systemui.animation.DialogLaunchAnimator import com.android.systemui.broadcast.BroadcastDispatcher import com.android.systemui.dump.DumpManager import com.android.systemui.plugins.ActivityStarter @@ -94,6 +95,7 @@ class UserSwitcherControllerTest : SysuiTestCase() { @Mock private lateinit var dialogShower: UserSwitchDialogController.DialogShower @Mock private lateinit var notificationShadeWindowView: NotificationShadeWindowView @Mock private lateinit var threadedRenderer: ThreadedRenderer + @Mock private lateinit var dialogLaunchAnimator: DialogLaunchAnimator private lateinit var testableLooper: TestableLooper private lateinit var uiBgExecutor: FakeExecutor private lateinit var uiEventLogger: UiEventLoggerFake @@ -147,7 +149,8 @@ class UserSwitcherControllerTest : SysuiTestCase() { uiBgExecutor, interactionJankMonitor, latencyTracker, - dumpManager) + dumpManager, + dialogLaunchAnimator) userSwitcherController.mPauseRefreshUsers = true // Since userSwitcherController involves InteractionJankMonitor. diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java index ae7afcef57a6..1e15d2ae0bdb 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java @@ -35,6 +35,7 @@ import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.tracing.ProtoTracer; import com.android.wm.shell.ShellCommandHandler; import com.android.wm.shell.common.ShellExecutor; +import com.android.wm.shell.draganddrop.DragAndDrop; import com.android.wm.shell.hidedisplaycutout.HideDisplayCutout; import com.android.wm.shell.legacysplitscreen.LegacySplitScreen; import com.android.wm.shell.onehanded.OneHanded; @@ -79,6 +80,7 @@ public class WMShellTest extends SysuiTestCase { @Mock ShellCommandHandler mShellCommandHandler; @Mock SizeCompatUI mSizeCompatUI; @Mock ShellExecutor mSysUiMainExecutor; + @Mock DragAndDrop mDragAndDrop; @Before public void setUp() { @@ -87,6 +89,7 @@ public class WMShellTest extends SysuiTestCase { mWMShell = new WMShell(mContext, Optional.of(mPip), Optional.of(mLegacySplitScreen), Optional.of(mSplitScreen), Optional.of(mOneHanded), Optional.of(mHideDisplayCutout), Optional.of(mShellCommandHandler), Optional.of(mSizeCompatUI), + Optional.of(mDragAndDrop), mCommandQueue, mConfigurationController, mKeyguardUpdateMonitor, mNavigationModeController, mScreenLifecycle, mSysUiState, mProtoTracer, mWakefulnessLifecycle, mSysUiMainExecutor); diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index df2ae987f8cb..9a371f3b0b31 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -157,6 +157,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.procstats.ServiceState; import com.android.internal.messages.nano.SystemMessageProto; import com.android.internal.notification.SystemNotificationChannels; +import com.android.internal.os.SomeArgs; import com.android.internal.os.TransferPipe; import com.android.internal.util.DumpUtils; import com.android.internal.util.FastPrintWriter; @@ -4209,9 +4210,12 @@ public final class ActiveServices { if (r.app != null) { Message msg = mAm.mHandler.obtainMessage( ActivityManagerService.SERVICE_FOREGROUND_CRASH_MSG); - msg.obj = r.app; - msg.getData().putCharSequence( - ActivityManagerService.SERVICE_RECORD_KEY, r.toString()); + SomeArgs args = SomeArgs.obtain(); + args.arg1 = r.app; + args.arg2 = r.toString(); + args.arg3 = r.getComponentName(); + + msg.obj = args; mAm.mHandler.sendMessage(msg); } } @@ -5272,11 +5276,14 @@ public final class ActiveServices { } } - void serviceForegroundCrash(ProcessRecord app, CharSequence serviceRecord) { - mAm.crashApplicationWithType(app.uid, app.getPid(), app.info.packageName, app.userId, + void serviceForegroundCrash(ProcessRecord app, String serviceRecord, + ComponentName service) { + mAm.crashApplicationWithTypeWithExtras( + app.uid, app.getPid(), app.info.packageName, app.userId, "Context.startForegroundService() did not then call Service.startForeground(): " + serviceRecord, false /*force*/, - ForegroundServiceDidNotStartInTimeException.TYPE_ID); + ForegroundServiceDidNotStartInTimeException.TYPE_ID, + ForegroundServiceDidNotStartInTimeException.createExtrasForService(service)); } void scheduleServiceTimeoutLocked(ProcessRecord proc) { diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index dde1ed9cdca9..53b1608841b4 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -338,6 +338,7 @@ import com.android.internal.os.BinderTransactionNameResolver; import com.android.internal.os.ByteTransferPipe; import com.android.internal.os.IResultReceiver; import com.android.internal.os.ProcessCpuTracker; +import com.android.internal.os.SomeArgs; import com.android.internal.os.TransferPipe; import com.android.internal.os.Zygote; import com.android.internal.policy.AttributeCache; @@ -1472,8 +1473,6 @@ public class ActivityManagerService extends IActivityManager.Stub static final int FIRST_BROADCAST_QUEUE_MSG = 200; - static final String SERVICE_RECORD_KEY = "servicerecord"; - /** * Flag whether the current user is a "monkey", i.e. whether * the UI is driven by a UI automation tool. @@ -1652,8 +1651,12 @@ public class ActivityManagerService extends IActivityManager.Stub mServices.serviceForegroundTimeout((ServiceRecord) msg.obj); } break; case SERVICE_FOREGROUND_CRASH_MSG: { - mServices.serviceForegroundCrash((ProcessRecord) msg.obj, - msg.getData().getCharSequence(SERVICE_RECORD_KEY)); + SomeArgs args = (SomeArgs) msg.obj; + mServices.serviceForegroundCrash( + (ProcessRecord) args.arg1, + (String) args.arg2, + (ComponentName) args.arg3); + args.recycle(); } break; case UPDATE_TIME_ZONE: { synchronized (mProcLock) { @@ -3001,6 +3004,14 @@ public class ActivityManagerService extends IActivityManager.Stub @Override public void crashApplicationWithType(int uid, int initialPid, String packageName, int userId, String message, boolean force, int exceptionTypeId) { + crashApplicationWithTypeWithExtras(uid, initialPid, packageName, userId, message, + force, exceptionTypeId, null); + } + + @Override + public void crashApplicationWithTypeWithExtras(int uid, int initialPid, String packageName, + int userId, String message, boolean force, int exceptionTypeId, + @Nullable Bundle extras) { if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES) != PackageManager.PERMISSION_GRANTED) { String msg = "Permission Denial: crashApplication() from pid=" @@ -3013,7 +3024,7 @@ public class ActivityManagerService extends IActivityManager.Stub synchronized(this) { mAppErrors.scheduleAppCrashLocked(uid, initialPid, packageName, userId, - message, force, exceptionTypeId); + message, force, exceptionTypeId, extras); } } diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java index bcb42bb38495..0bf0fe2be246 100644 --- a/services/core/java/com/android/server/am/AppErrors.java +++ b/services/core/java/com/android/server/am/AppErrors.java @@ -27,6 +27,7 @@ import static com.android.server.am.ActivityManagerService.MY_PID; import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_FREE_RESIZE; import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_NONE; +import android.annotation.Nullable; import android.app.ActivityManager; import android.app.ActivityOptions; import android.app.AnrController; @@ -40,6 +41,7 @@ import android.content.pm.VersionedPackage; import android.net.Uri; import android.os.Binder; import android.os.Build; +import android.os.Bundle; import android.os.Message; import android.os.Process; import android.os.SystemClock; @@ -489,7 +491,7 @@ class AppErrors { * @param message */ void scheduleAppCrashLocked(int uid, int initialPid, String packageName, int userId, - String message, boolean force, int exceptionTypeId) { + String message, boolean force, int exceptionTypeId, @Nullable Bundle extras) { ProcessRecord proc = null; // Figure out which process to kill. We don't trust that initialPid @@ -521,7 +523,7 @@ class AppErrors { return; } - proc.scheduleCrashLocked(message, exceptionTypeId); + proc.scheduleCrashLocked(message, exceptionTypeId, extras); if (force) { // If the app is responsive, the scheduled crash will happen as expected // and then the delayed summary kill will be a no-op. diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java index 487101b7eac4..2da41070a6f4 100644 --- a/services/core/java/com/android/server/am/BroadcastQueue.java +++ b/services/core/java/com/android/server/am/BroadcastQueue.java @@ -611,7 +611,7 @@ public final class BroadcastQueue { Slog.w(TAG, "Can't deliver broadcast to " + app.processName + " (pid " + app.getPid() + "). Crashing it."); app.scheduleCrashLocked("can't deliver broadcast", - CannotDeliverBroadcastException.TYPE_ID); + CannotDeliverBroadcastException.TYPE_ID, /* extras=*/ null); } throw ex; } diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java index 14ba7167f529..b9d7917ed38d 100644 --- a/services/core/java/com/android/server/am/ProcessRecord.java +++ b/services/core/java/com/android/server/am/ProcessRecord.java @@ -31,6 +31,7 @@ import android.content.pm.ProcessInfo; import android.content.pm.VersionedPackage; import android.content.res.CompatibilityInfo; import android.os.Binder; +import android.os.Bundle; import android.os.IBinder; import android.os.Process; import android.os.RemoteException; @@ -958,7 +959,7 @@ class ProcessRecord implements WindowProcessListener { * of its subclasses. */ @GuardedBy("mService") - void scheduleCrashLocked(String message, int exceptionTypeId) { + void scheduleCrashLocked(String message, int exceptionTypeId, @Nullable Bundle extras) { // Checking killedbyAm should keep it from showing the crash dialog if the process // was already dead for a good / normal reason. if (!mKilledByAm) { @@ -969,7 +970,7 @@ class ProcessRecord implements WindowProcessListener { } final long ident = Binder.clearCallingIdentity(); try { - mThread.scheduleCrash(message, exceptionTypeId); + mThread.scheduleCrash(message, exceptionTypeId, extras); } catch (RemoteException e) { // If it's already dead our work is done. If it's wedged just kill it. // We won't get the crash dialog or the error reporting. diff --git a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java index 61b8ded60db7..7341e744dea3 100644 --- a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java @@ -251,7 +251,7 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T> "Successful background authentication!"); } - mAlreadyDone = true; + markAlreadyDone(); if (mTaskStackListener != null) { mActivityTaskManager.unregisterTaskStackListener(mTaskStackListener); @@ -327,7 +327,7 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T> final @LockoutTracker.LockoutMode int lockoutMode = handleFailedAttempt(getTargetUserId()); if (lockoutMode != LockoutTracker.LOCKOUT_NONE) { - mAlreadyDone = true; + markAlreadyDone(); } final CoexCoordinator coordinator = CoexCoordinator.getInstance(); diff --git a/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java b/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java index 9764a167fbbf..b73e91173a43 100644 --- a/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java +++ b/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java @@ -114,7 +114,7 @@ public abstract class BaseClientMonitor extends LoggableMonitor // Currently only used for authentication client. The cookie generated by BiometricService // is never 0. private final int mCookie; - boolean mAlreadyDone; + private boolean mAlreadyDone = false; // Use an empty callback by default since delayed operations can receive events // before they are started and cause NPE in subclasses that access this field directly. @@ -202,11 +202,9 @@ public abstract class BaseClientMonitor extends LoggableMonitor return callback; } - public boolean isAlreadyDone() { - return mAlreadyDone; - } - - public void destroy() { + /** Signals this operation has completed its lifecycle and should no longer be used. */ + void destroy() { + mAlreadyDone = true; if (mToken != null) { try { mToken.unlinkToDeath(this, 0); @@ -218,6 +216,20 @@ public abstract class BaseClientMonitor extends LoggableMonitor } } + /** + * Call while the operation is still active, but nearly done, to prevent any action + * upon client death (only needed for authentication clients). + */ + void markAlreadyDone() { + Slog.d(TAG, "marking operation as done: " + this); + mAlreadyDone = true; + } + + /** If this operation has been marked as completely done (or cancelled). */ + public boolean isAlreadyDone() { + return mAlreadyDone; + } + @Override public void binderDied() { binderDiedInternal(true /* clearListener */); @@ -225,10 +237,9 @@ public abstract class BaseClientMonitor extends LoggableMonitor // TODO(b/157790417): Move this to the scheduler void binderDiedInternal(boolean clearListener) { - Slog.e(TAG, "Binder died, owner: " + getOwnerString() - + ", operation: " + this.getClass().getName()); + Slog.e(TAG, "Binder died, operation: " + this); - if (isAlreadyDone()) { + if (mAlreadyDone) { Slog.w(TAG, "Binder died but client is finished, ignoring"); return; } @@ -299,7 +310,7 @@ public abstract class BaseClientMonitor extends LoggableMonitor @Override public String toString() { return "{[" + mSequentialId + "] " - + this.getClass().getSimpleName() + + this.getClass().getName() + ", proto=" + getProtoEnum() + ", owner=" + getOwnerString() + ", cookie=" + getCookie() diff --git a/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java b/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java index 361ec40f2877..a358bc2bad55 100644 --- a/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java +++ b/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java @@ -605,6 +605,9 @@ public class BiometricScheduler { if (operation.mState == Operation.STATE_WAITING_FOR_COOKIE) { Slog.w(getTag(), "Skipping cancellation for non-started operation: " + operation); // We can set it to null immediately, since the HAL was never notified to start. + if (mCurrentOperation != null) { + mCurrentOperation.mClientMonitor.destroy(); + } mCurrentOperation = null; startNextOperationIfIdle(); return; diff --git a/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java b/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java index 792feea01e27..806a5dd65a13 100644 --- a/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java +++ b/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java @@ -31,7 +31,6 @@ import android.annotation.Nullable; import android.content.Context; import android.hardware.devicestate.DeviceStateInfo; import android.hardware.devicestate.DeviceStateManager; -import android.hardware.devicestate.DeviceStateManagerInternal; import android.hardware.devicestate.IDeviceStateManager; import android.hardware.devicestate.IDeviceStateManagerCallback; import android.os.Binder; @@ -162,7 +161,6 @@ public final class DeviceStateManagerService extends SystemService { @Override public void onStart() { publishBinderService(Context.DEVICE_STATE_SERVICE, mBinderService); - publishLocalService(DeviceStateManagerInternal.class, new LocalService()); } @VisibleForTesting @@ -242,6 +240,13 @@ public final class DeviceStateManagerService extends SystemService { } /** Returns the list of currently supported device state identifiers. */ + private int[] getSupportedStateIdentifiers() { + synchronized (mLock) { + return getSupportedStateIdentifiersLocked(); + } + } + + /** Returns the list of currently supported device state identifiers. */ private int[] getSupportedStateIdentifiersLocked() { int[] supportedStates = new int[mDeviceStates.size()]; for (int i = 0; i < supportedStates.length; i++) { @@ -843,14 +848,4 @@ public final class DeviceStateManagerService extends SystemService { } } } - - /** Implementation of {@link DeviceStateManagerInternal} published as a local service. */ - private final class LocalService extends DeviceStateManagerInternal { - @Override - public int[] getSupportedStateIdentifiers() { - synchronized (mLock) { - return getSupportedStateIdentifiersLocked(); - } - } - } } diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java index fadaf1082e46..b394d6b49d65 100644 --- a/services/core/java/com/android/server/display/DisplayManagerService.java +++ b/services/core/java/com/android/server/display/DisplayManagerService.java @@ -53,7 +53,6 @@ import android.graphics.Point; import android.hardware.Sensor; import android.hardware.SensorManager; import android.hardware.devicestate.DeviceStateManager; -import android.hardware.devicestate.DeviceStateManagerInternal; import android.hardware.display.AmbientBrightnessDayStats; import android.hardware.display.BrightnessChangeEvent; import android.hardware.display.BrightnessConfiguration; @@ -64,6 +63,8 @@ import android.hardware.display.DisplayManagerGlobal; import android.hardware.display.DisplayManagerInternal; import android.hardware.display.DisplayManagerInternal.DisplayGroupListener; import android.hardware.display.DisplayManagerInternal.DisplayTransactionListener; +import android.hardware.display.DisplayManagerInternal.RefreshRateLimitation; +import android.hardware.display.DisplayManagerInternal.RefreshRateRange; import android.hardware.display.DisplayViewport; import android.hardware.display.DisplayedContentSample; import android.hardware.display.DisplayedContentSamplingAttributes; @@ -132,7 +133,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Optional; -import java.util.Set; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.atomic.AtomicLong; import java.util.function.Consumer; @@ -212,7 +212,6 @@ public final class DisplayManagerService extends SystemService { private WindowManagerInternal mWindowManagerInternal; private InputManagerInternal mInputManagerInternal; private IMediaProjectionManager mProjectionService; - private DeviceStateManagerInternal mDeviceStateManager; private int[] mUserDisabledHdrTypes = {}; private boolean mAreUserDisabledHdrTypesAllowed = true; @@ -560,9 +559,10 @@ public final class DisplayManagerService extends SystemService { mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class); mInputManagerInternal = LocalServices.getService(InputManagerInternal.class); - mDeviceStateManager = LocalServices.getService(DeviceStateManagerInternal.class); - mContext.getSystemService(DeviceStateManager.class).registerCallback( - new HandlerExecutor(mHandler), new DeviceStateListener()); + DeviceStateManager deviceStateManager = + mContext.getSystemService(DeviceStateManager.class); + deviceStateManager.registerCallback(new HandlerExecutor(mHandler), + new DeviceStateListener()); scheduleTraversalLocked(false); } @@ -651,9 +651,6 @@ public final class DisplayManagerService extends SystemService { synchronized (mSyncRoot) { final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId); if (display != null) { - // Do not let constrain be overwritten by override from WindowManager. - info.shouldConstrainMetricsForLauncher = - display.getDisplayInfoLocked().shouldConstrainMetricsForLauncher; if (display.setDisplayInfoOverrideFromWindowManagerLocked(info)) { handleLogicalDisplayChangedLocked(display); scheduleTraversalLocked(false); @@ -1783,21 +1780,6 @@ public final class DisplayManagerService extends SystemService { } } - void setShouldConstrainMetricsForLauncher(boolean constrain) { - // Apply constrain for every display. - synchronized (mSyncRoot) { - int[] displayIds = mLogicalDisplayMapper.getDisplayIdsLocked(Process.myUid()); - for (int i : displayIds) { - final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(i); - if (display == null) { - return; - } - display.getDisplayInfoLocked().shouldConstrainMetricsForLauncher = constrain; - setDisplayInfoOverrideFromWindowManagerInternal(i, display.getDisplayInfoLocked()); - } - } - } - private void clearViewportsLocked() { mViewports.clear(); } @@ -3292,53 +3274,6 @@ public final class DisplayManagerService extends SystemService { } @Override - public Set<DisplayInfo> getPossibleDisplayInfo(int displayId) { - synchronized (mSyncRoot) { - // Retrieve the group associated with this display id. - final int displayGroupId = - mLogicalDisplayMapper.getDisplayGroupIdFromDisplayIdLocked(displayId); - if (displayGroupId == Display.INVALID_DISPLAY_GROUP) { - Slog.w(TAG, - "Can't get possible display info since display group for " + displayId - + " does not exist"); - return new ArraySet<>(); - } - - // Assume any display in this group can be swapped out for the given display id. - Set<DisplayInfo> possibleInfo = new ArraySet<>(); - final DisplayGroup group = mLogicalDisplayMapper.getDisplayGroupLocked( - displayGroupId); - for (int i = 0; i < group.getSizeLocked(); i++) { - final int id = group.getIdLocked(i); - final LogicalDisplay logical = mLogicalDisplayMapper.getDisplayLocked(id); - if (logical == null) { - Slog.w(TAG, - "Can't get possible display info since logical display for " - + "display id " + id + " does not exist, as part of group " - + displayGroupId); - } else { - possibleInfo.add(logical.getDisplayInfoLocked()); - } - } - - // For the supported device states, retrieve the DisplayInfos for the logical - // display layout. - if (mDeviceStateManager == null) { - Slog.w(TAG, "Can't get supported states since DeviceStateManager not ready"); - } else { - final int[] supportedStates = - mDeviceStateManager.getSupportedStateIdentifiers(); - for (int state : supportedStates) { - possibleInfo.addAll( - mLogicalDisplayMapper.getDisplayInfoForStateLocked(state, displayId, - displayGroupId)); - } - } - return possibleInfo; - } - } - - @Override public Point getDisplayPosition(int displayId) { synchronized (mSyncRoot) { final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId); diff --git a/services/core/java/com/android/server/display/DisplayManagerShellCommand.java b/services/core/java/com/android/server/display/DisplayManagerShellCommand.java index 9412c938f934..158c8f06d13e 100644 --- a/services/core/java/com/android/server/display/DisplayManagerShellCommand.java +++ b/services/core/java/com/android/server/display/DisplayManagerShellCommand.java @@ -58,8 +58,6 @@ class DisplayManagerShellCommand extends ShellCommand { return setDisplayModeDirectorLoggingEnabled(false); case "dwb-set-cct": return setAmbientColorTemperatureOverride(); - case "constrain-launcher-metrics": - return setConstrainLauncherMetrics(); default: return handleDefaultCommands(cmd); } @@ -90,9 +88,6 @@ class DisplayManagerShellCommand extends ShellCommand { pw.println(" Disable display mode director logging."); pw.println(" dwb-set-cct CCT"); pw.println(" Sets the ambient color temperature override to CCT (use -1 to disable)."); - pw.println(" constrain-launcher-metrics [true|false]"); - pw.println(" Sets if Display#getRealSize and getRealMetrics should be constrained for "); - pw.println(" Launcher."); pw.println(); Intent.printIntentArgsHelp(pw , ""); } @@ -155,15 +150,4 @@ class DisplayManagerShellCommand extends ShellCommand { mService.setAmbientColorTemperatureOverride(cct); return 0; } - - private int setConstrainLauncherMetrics() { - String constrainText = getNextArg(); - if (constrainText == null) { - getErrPrintWriter().println("Error: no value specified"); - return 1; - } - boolean constrain = Boolean.parseBoolean(constrainText); - mService.setShouldConstrainMetricsForLauncher(constrain); - return 0; - } } diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java index 86c9ca937482..5186744d5c27 100644 --- a/services/core/java/com/android/server/display/LogicalDisplay.java +++ b/services/core/java/com/android/server/display/LogicalDisplay.java @@ -233,8 +233,6 @@ final class LogicalDisplay { info.physicalXDpi = mOverrideDisplayInfo.physicalXDpi; info.physicalYDpi = mOverrideDisplayInfo.physicalYDpi; info.roundedCorners = mOverrideDisplayInfo.roundedCorners; - info.shouldConstrainMetricsForLauncher = - mOverrideDisplayInfo.shouldConstrainMetricsForLauncher; } mInfo.set(info); } diff --git a/services/core/java/com/android/server/display/LogicalDisplayMapper.java b/services/core/java/com/android/server/display/LogicalDisplayMapper.java index 0fbc3e8fb89a..f0093bd07752 100644 --- a/services/core/java/com/android/server/display/LogicalDisplayMapper.java +++ b/services/core/java/com/android/server/display/LogicalDisplayMapper.java @@ -26,7 +26,6 @@ import android.os.PowerManager; import android.os.SystemClock; import android.os.SystemProperties; import android.text.TextUtils; -import android.util.ArraySet; import android.util.IndentingPrintWriter; import android.util.Slog; import android.util.SparseArray; @@ -41,7 +40,6 @@ import com.android.server.display.layout.Layout; import java.io.PrintWriter; import java.util.Arrays; -import java.util.Set; import java.util.function.Consumer; /** @@ -267,61 +265,6 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener { return mDisplayGroups.get(groupId); } - /** - * Returns the set of {@link DisplayInfo} for this device state, only fetching the info that is - * part of the same display group as the provided display id. The DisplayInfo represent the - * logical display layouts possible for the given device state. - * - * @param deviceState the state to query possible layouts for - * @param displayId the display id to apply to all displays within the group - * @param groupId the display group to filter display info for. Must be the same group as - * the display with the provided display id. - */ - public Set<DisplayInfo> getDisplayInfoForStateLocked(int deviceState, int displayId, - int groupId) { - Set<DisplayInfo> displayInfos = new ArraySet<>(); - final Layout layout = mDeviceStateToLayoutMap.get(deviceState); - final int layoutSize = layout.size(); - for (int i = 0; i < layoutSize; i++) { - Layout.Display displayLayout = layout.getAt(i); - if (displayLayout == null) { - continue; - } - - // If the underlying display-device we want to use for this display - // doesn't exist, then skip it. This can happen at startup as display-devices - // trickle in one at a time. When the new display finally shows up, the layout is - // recalculated so that the display is properly added to the current layout. - final DisplayAddress address = displayLayout.getAddress(); - final DisplayDevice device = mDisplayDeviceRepo.getByAddressLocked(address); - if (device == null) { - Slog.w(TAG, "The display device (" + address + "), is not available" - + " for the display state " + deviceState); - continue; - } - - // Find or create the LogicalDisplay to map the DisplayDevice to. - final int logicalDisplayId = displayLayout.getLogicalDisplayId(); - final LogicalDisplay logicalDisplay = getDisplayLocked(logicalDisplayId); - if (logicalDisplay == null) { - Slog.w(TAG, "The logical display (" + address + "), is not available" - + " for the display state " + deviceState); - continue; - } - final DisplayInfo temp = logicalDisplay.getDisplayInfoLocked(); - DisplayInfo displayInfo = new DisplayInfo(temp); - if (displayInfo.displayGroupId != groupId) { - // Ignore any displays not in the provided group. - continue; - } - // A display in the same group can be swapped out at any point, so set the display id - // for all results to the provided display id. - displayInfo.displayId = displayId; - displayInfos.add(displayInfo); - } - return displayInfos; - } - public void dumpLocked(PrintWriter pw) { pw.println("LogicalDisplayMapper:"); IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java index 9d6678053533..3fb5f02b756a 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java @@ -542,9 +542,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub */ private InputMethodSubtype mCurrentSubtype; - // Was the keyguard locked when this client became current? - private boolean mCurClientInKeyguard; - /** * {@code true} if the IME has not been mostly hidden via {@link android.view.InsetsController} */ @@ -2363,14 +2360,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub mImeHiddenByDisplayPolicy = false; if (mCurClient != cs) { - // Was the keyguard locked when switching over to the new client? - mCurClientInKeyguard = isKeyguardLocked(); // If the client is changing, we need to switch over to the new // one. unbindCurrentClientLocked(UnbindReason.SWITCH_CLIENT); - if (DEBUG) Slog.v(TAG, "switching to client: client=" - + cs.client.asBinder() + " keyguard=" + mCurClientInKeyguard); - // If the screen is on, inform the new client it is active if (mIsInteractive) { scheduleSetActiveToClient(cs, true /* active */, false /* fullscreen */, @@ -2875,12 +2867,13 @@ public class InputMethodManagerService extends IInputMethodManager.Stub // all updateSystemUi happens on system previlege. final long ident = Binder.clearCallingIdentity(); try { - // apply policy for binder calls - if (vis != 0 && isKeyguardLocked() && !mCurClientInKeyguard) { - vis = 0; - } if (!mCurPerceptible) { - vis &= ~InputMethodService.IME_VISIBLE; + if ((vis & InputMethodService.IME_VISIBLE) != 0) { + vis &= ~InputMethodService.IME_VISIBLE; + vis |= InputMethodService.IME_VISIBLE_IMPERCEPTIBLE; + } + } else { + vis &= ~InputMethodService.IME_VISIBLE_IMPERCEPTIBLE; } // mImeWindowVis should be updated before calling shouldShowImeSwitcherLocked(). final boolean needsToShowImeSwitcher = shouldShowImeSwitcherLocked(vis); diff --git a/services/core/java/com/android/server/location/gnss/GnssMeasurementsProvider.java b/services/core/java/com/android/server/location/gnss/GnssMeasurementsProvider.java index 8460d6797543..1781588b0ba2 100644 --- a/services/core/java/com/android/server/location/gnss/GnssMeasurementsProvider.java +++ b/services/core/java/com/android/server/location/gnss/GnssMeasurementsProvider.java @@ -52,8 +52,6 @@ public final class GnssMeasurementsProvider extends private class GnssMeasurementListenerRegistration extends GnssListenerRegistration { - private static final String GNSS_MEASUREMENTS_BUCKET = "gnss_measurement"; - protected GnssMeasurementListenerRegistration( @Nullable GnssMeasurementRequest request, CallerIdentity callerIdentity, @@ -70,15 +68,13 @@ public final class GnssMeasurementsProvider extends @Nullable @Override protected void onActive() { - mLocationAttributionHelper.reportHighPowerLocationStart( - getIdentity(), GNSS_MEASUREMENTS_BUCKET, getKey()); + mLocationAttributionHelper.reportHighPowerLocationStart(getIdentity()); } @Nullable @Override protected void onInactive() { - mLocationAttributionHelper.reportHighPowerLocationStop( - getIdentity(), GNSS_MEASUREMENTS_BUCKET, getKey()); + mLocationAttributionHelper.reportHighPowerLocationStop(getIdentity()); } } diff --git a/services/core/java/com/android/server/location/injector/LocationAttributionHelper.java b/services/core/java/com/android/server/location/injector/LocationAttributionHelper.java index 5cb360be819a..483875230ac4 100644 --- a/services/core/java/com/android/server/location/injector/LocationAttributionHelper.java +++ b/services/core/java/com/android/server/location/injector/LocationAttributionHelper.java @@ -24,55 +24,23 @@ import static com.android.server.location.LocationManagerService.TAG; import android.location.util.identity.CallerIdentity; import android.util.ArrayMap; -import android.util.ArraySet; import android.util.Log; import com.android.internal.annotations.GuardedBy; import java.util.Map; -import java.util.Objects; -import java.util.Set; /** * Helps manage appop monitoring for multiple location clients. */ public class LocationAttributionHelper { - private static class BucketKey { - private final String mBucket; - private final Object mKey; - - private BucketKey(String bucket, Object key) { - mBucket = Objects.requireNonNull(bucket); - mKey = Objects.requireNonNull(key); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - BucketKey that = (BucketKey) o; - return mBucket.equals(that.mBucket) - && mKey.equals(that.mKey); - } - - @Override - public int hashCode() { - return Objects.hash(mBucket, mKey); - } - } - private final AppOpsHelper mAppOpsHelper; @GuardedBy("this") - private final Map<CallerIdentity, Set<BucketKey>> mAttributions; + private final Map<CallerIdentity, Integer> mAttributions; @GuardedBy("this") - private final Map<CallerIdentity, Set<BucketKey>> mHighPowerAttributions; + private final Map<CallerIdentity, Integer> mHighPowerAttributions; public LocationAttributionHelper(AppOpsHelper appOpsHelper) { mAppOpsHelper = appOpsHelper; @@ -84,15 +52,16 @@ public class LocationAttributionHelper { /** * Report normal location usage for the given caller in the given bucket, with a unique key. */ - public synchronized void reportLocationStart(CallerIdentity identity, String bucket, - Object key) { - Set<BucketKey> keySet = mAttributions.computeIfAbsent(identity, - i -> new ArraySet<>()); - boolean empty = keySet.isEmpty(); - if (keySet.add(new BucketKey(bucket, key)) && empty) { - if (!mAppOpsHelper.startOpNoThrow(OP_MONITOR_LOCATION, identity)) { - mAttributions.remove(identity); + public synchronized void reportLocationStart(CallerIdentity identity) { + identity = CallerIdentity.forAggregation(identity); + + int count = mAttributions.getOrDefault(identity, 0); + if (count == 0) { + if (mAppOpsHelper.startOpNoThrow(OP_MONITOR_LOCATION, identity)) { + mAttributions.put(identity, 1); } + } else { + mAttributions.put(identity, count + 1); } } @@ -100,13 +69,15 @@ public class LocationAttributionHelper { * Report normal location usage has stopped for the given caller in the given bucket, with a * unique key. */ - public synchronized void reportLocationStop(CallerIdentity identity, String bucket, - Object key) { - Set<BucketKey> keySet = mAttributions.get(identity); - if (keySet != null && keySet.remove(new BucketKey(bucket, key)) - && keySet.isEmpty()) { + public synchronized void reportLocationStop(CallerIdentity identity) { + identity = CallerIdentity.forAggregation(identity); + + int count = mAttributions.getOrDefault(identity, 0); + if (count == 1) { mAttributions.remove(identity); mAppOpsHelper.finishOp(OP_MONITOR_LOCATION, identity); + } else if (count > 1) { + mAttributions.put(identity, count - 1); } } @@ -114,19 +85,19 @@ public class LocationAttributionHelper { * Report high power location usage for the given caller in the given bucket, with a unique * key. */ - public synchronized void reportHighPowerLocationStart(CallerIdentity identity, String bucket, - Object key) { - Set<BucketKey> keySet = mHighPowerAttributions.computeIfAbsent(identity, - i -> new ArraySet<>()); - boolean empty = keySet.isEmpty(); - if (keySet.add(new BucketKey(bucket, key)) && empty) { + public synchronized void reportHighPowerLocationStart(CallerIdentity identity) { + identity = CallerIdentity.forAggregation(identity); + + int count = mHighPowerAttributions.getOrDefault(identity, 0); + if (count == 0) { + if (D) { + Log.v(TAG, "starting high power location attribution for " + identity); + } if (mAppOpsHelper.startOpNoThrow(OP_MONITOR_HIGH_POWER_LOCATION, identity)) { - if (D) { - Log.v(TAG, "starting high power location attribution for " + identity); - } - } else { - mHighPowerAttributions.remove(identity); + mHighPowerAttributions.put(identity, 1); } + } else { + mHighPowerAttributions.put(identity, count + 1); } } @@ -134,16 +105,18 @@ public class LocationAttributionHelper { * Report high power location usage has stopped for the given caller in the given bucket, * with a unique key. */ - public synchronized void reportHighPowerLocationStop(CallerIdentity identity, String bucket, - Object key) { - Set<BucketKey> keySet = mHighPowerAttributions.get(identity); - if (keySet != null && keySet.remove(new BucketKey(bucket, key)) - && keySet.isEmpty()) { + public synchronized void reportHighPowerLocationStop(CallerIdentity identity) { + identity = CallerIdentity.forAggregation(identity); + + int count = mHighPowerAttributions.getOrDefault(identity, 0); + if (count == 1) { if (D) { Log.v(TAG, "stopping high power location attribution for " + identity); } mHighPowerAttributions.remove(identity); mAppOpsHelper.finishOp(OP_MONITOR_HIGH_POWER_LOCATION, identity); + } else if (count > 1) { + mHighPowerAttributions.put(identity, count - 1); } } } diff --git a/services/core/java/com/android/server/location/provider/LocationProviderManager.java b/services/core/java/com/android/server/location/provider/LocationProviderManager.java index f7c4d03bfdf3..155b61891d12 100644 --- a/services/core/java/com/android/server/location/provider/LocationProviderManager.java +++ b/services/core/java/com/android/server/location/provider/LocationProviderManager.java @@ -398,7 +398,7 @@ public class LocationProviderManager extends EVENT_LOG.logProviderClientActive(mName, getIdentity()); if (!getRequest().isHiddenFromAppOps()) { - mLocationAttributionHelper.reportLocationStart(getIdentity(), getName(), getKey()); + mLocationAttributionHelper.reportLocationStart(getIdentity()); } onHighPowerUsageChanged(); @@ -413,7 +413,7 @@ public class LocationProviderManager extends onHighPowerUsageChanged(); if (!getRequest().isHiddenFromAppOps()) { - mLocationAttributionHelper.reportLocationStop(getIdentity(), getName(), getKey()); + mLocationAttributionHelper.reportLocationStop(getIdentity()); } onProviderListenerInactive(); @@ -488,10 +488,10 @@ public class LocationProviderManager extends if (!getRequest().isHiddenFromAppOps()) { if (mIsUsingHighPower) { mLocationAttributionHelper.reportHighPowerLocationStart( - getIdentity(), getName(), getKey()); + getIdentity()); } else { mLocationAttributionHelper.reportHighPowerLocationStop( - getIdentity(), getName(), getKey()); + getIdentity()); } } } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 979b77f050b4..ba11e9c26dfe 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -15355,7 +15355,8 @@ public class PackageManagerService extends IPackageManager.Stub mResolveActivity.processName = "system:ui"; mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE; mResolveActivity.documentLaunchMode = ActivityInfo.DOCUMENT_LAUNCH_NEVER; - mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS; + mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS + | ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY; mResolveActivity.theme = R.style.Theme_Material_Dialog_Alert; mResolveActivity.exported = true; mResolveActivity.enabled = true; @@ -28824,8 +28825,12 @@ public class PackageManagerService extends IPackageManager.Stub @Override public void setSplashScreenTheme(@NonNull String packageName, @Nullable String themeId, int userId) { - int callingUid = Binder.getCallingUid(); - PackageSetting packageSetting = getPackageSettingForUser(packageName, callingUid, userId); + final int callingUid = Binder.getCallingUid(); + enforceCrossUserPermission(callingUid, userId, false /* requireFullPermission */, + false /* checkShell */, "setSplashScreenTheme"); + enforceOwnerRights(packageName, callingUid); + final PackageSetting packageSetting = getPackageSettingForUser(packageName, callingUid, + userId); if (packageSetting != null) { packageSetting.setSplashScreenTheme(userId, themeId); } diff --git a/services/core/java/com/android/server/wallpaper/LocalColorRepository.java b/services/core/java/com/android/server/wallpaper/LocalColorRepository.java new file mode 100644 index 000000000000..e6265f4dbd39 --- /dev/null +++ b/services/core/java/com/android/server/wallpaper/LocalColorRepository.java @@ -0,0 +1,166 @@ +/* + * 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.server.wallpaper; + +import android.app.ILocalWallpaperColorConsumer; +import android.graphics.RectF; +import android.os.IBinder; +import android.os.RemoteCallbackList; +import android.os.RemoteException; +import android.util.ArrayMap; +import android.util.ArraySet; +import android.util.SparseArray; + +import com.android.internal.annotations.VisibleForTesting; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; + +/** + * Manages the lifecycle of local wallpaper color callbacks and their interested wallpaper regions. + */ +public class LocalColorRepository { + /** + * Maps local wallpaper color callbacks' binders to their interested wallpaper regions, which + * are stored in a map of display Ids to wallpaper regions. + * binder callback -> [display id: int] -> areas + */ + ArrayMap<IBinder, SparseArray<ArraySet<RectF>>> mLocalColorAreas = new ArrayMap(); + RemoteCallbackList<ILocalWallpaperColorConsumer> mCallbacks = new RemoteCallbackList(); + + /** + * Add areas to a consumer + * @param consumer + * @param areas + * @param displayId + */ + public void addAreas(ILocalWallpaperColorConsumer consumer, List<RectF> areas, int displayId) { + IBinder binder = consumer.asBinder(); + SparseArray<ArraySet<RectF>> displays = mLocalColorAreas.get(binder); + ArraySet<RectF> displayAreas = null; + if (displays == null) { + try { + consumer.asBinder().linkToDeath(() -> + mLocalColorAreas.remove(consumer.asBinder()), 0); + } catch (RemoteException e) { + e.printStackTrace(); + } + displays = new SparseArray<>(); + mLocalColorAreas.put(binder, displays); + } else { + displayAreas = displays.get(displayId); + } + if (displayAreas == null) { + displayAreas = new ArraySet(areas); + displays.put(displayId, displayAreas); + } + + for (int i = 0; i < areas.size(); i++) { + displayAreas.add(areas.get(i)); + } + mCallbacks.register(consumer); + } + + /** + * remove an area for a consumer + * @param consumer + * @param areas + * @param displayId + * @return the areas that are removed from all callbacks + */ + public List<RectF> removeAreas(ILocalWallpaperColorConsumer consumer, List<RectF> areas, + int displayId) { + IBinder binder = consumer.asBinder(); + SparseArray<ArraySet<RectF>> displays = mLocalColorAreas.get(binder); + ArraySet<RectF> registeredAreas = null; + if (displays != null) { + registeredAreas = displays.get(displayId); + if (registeredAreas == null) { + mCallbacks.unregister(consumer); + } else { + for (int i = 0; i < areas.size(); i++) { + registeredAreas.remove(areas.get(i)); + } + if (registeredAreas.size() == 0) { + displays.remove(displayId); + } + } + if (displays.size() == 0) { + mLocalColorAreas.remove(binder); + mCallbacks.unregister(consumer); + } + } else { + mCallbacks.unregister(consumer); + } + ArraySet<RectF> purged = new ArraySet<>(areas); + for (int i = 0; i < mLocalColorAreas.size(); i++) { + for (int j = 0; j < mLocalColorAreas.valueAt(i).size(); j++) { + for (int k = 0; k < mLocalColorAreas.valueAt(i).valueAt(j).size(); k++) { + purged.remove(mLocalColorAreas.valueAt(i).valueAt(j).valueAt(k)); + } + } + } + return new ArrayList(purged); + } + + /** + * Return the local areas by display id + * @param displayId + * @return + */ + public List<RectF> getAreasByDisplayId(int displayId) { + ArrayList<RectF> areas = new ArrayList(); + for (int i = 0; i < mLocalColorAreas.size(); i++) { + SparseArray<ArraySet<RectF>> displays = mLocalColorAreas.valueAt(i); + if (displays == null) continue; + ArraySet<RectF> displayAreas = displays.get(displayId); + if (displayAreas == null) continue; + for (int j = 0; j < displayAreas.size(); j++) { + areas.add(displayAreas.valueAt(j)); + } + } + return areas; + } + + /** + * invoke a callback for each area of interest + * @param callback + * @param area + * @param displayId + */ + public void forEachCallback(Consumer<ILocalWallpaperColorConsumer> callback, + RectF area, int displayId) { + mCallbacks.broadcast(cb -> { + IBinder binder = cb.asBinder(); + SparseArray<ArraySet<RectF>> displays = mLocalColorAreas.get(binder); + if (displays == null) return; + ArraySet<RectF> displayAreas = displays.get(displayId); + if (displayAreas != null && displayAreas.contains(area)) callback.accept(cb); + }); + } + + /** + * For testing + * @param callback + * @return if the callback is registered + */ + @VisibleForTesting + protected boolean isCallbackAvailable(ILocalWallpaperColorConsumer callback) { + return mLocalColorAreas.get(callback.asBinder()) != null; + } +} diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java index 2f353d19b5df..a7924e61cd3e 100644 --- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java +++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java @@ -89,8 +89,6 @@ import android.service.wallpaper.IWallpaperService; import android.service.wallpaper.WallpaperService; import android.system.ErrnoException; import android.system.Os; -import android.util.ArrayMap; -import android.util.ArraySet; import android.util.EventLog; import android.util.Slog; import android.util.SparseArray; @@ -881,12 +879,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub private final SparseBooleanArray mUserRestorecon = new SparseBooleanArray(); private int mCurrentUserId = UserHandle.USER_NULL; private boolean mInAmbientMode; - private ArrayMap<IBinder, ArraySet<RectF>> mLocalColorCallbackAreas = - new ArrayMap<>(); - private ArrayMap<RectF, RemoteCallbackList<ILocalWallpaperColorConsumer>> - mLocalColorAreaCallbacks = new ArrayMap<>(); - private ArrayMap<Integer, ArraySet<RectF>> mLocalColorDisplayIdAreas = new ArrayMap<>(); - private ArrayMap<IBinder, Integer> mLocalColorCallbackDisplayId = new ArrayMap<>(); + private LocalColorRepository mLocalColorRepo = new LocalColorRepository(); static class WallpaperData { @@ -1305,24 +1298,16 @@ public class WallpaperManagerService extends IWallpaperManager.Stub public void onLocalWallpaperColorsChanged(RectF area, WallpaperColors colors, int displayId) { forEachDisplayConnector(displayConnector -> { - if (displayConnector.mDisplayId == displayId) { - RemoteCallbackList<ILocalWallpaperColorConsumer> callbacks; - ArrayMap<IBinder, Integer> callbackDisplayIds; - synchronized (mLock) { - callbacks = mLocalColorAreaCallbacks.get(area); - callbackDisplayIds = new ArrayMap<>(mLocalColorCallbackDisplayId); + Consumer<ILocalWallpaperColorConsumer> callback = cb -> { + try { + cb.onColorsChanged(area, colors); + } catch (RemoteException e) { + e.printStackTrace(); } - if (callbacks == null) return; - callbacks.broadcast(c -> { - try { - Integer targetDisplayId = - callbackDisplayIds.get(c.asBinder()); - if (targetDisplayId == null) return; - if (targetDisplayId == displayId) c.onColorsChanged(area, colors); - } catch (RemoteException e) { - e.printStackTrace(); - } - }); + }; + synchronized (mLock) { + // it is safe to make an IPC call since it is one way (returns immediately) + mLocalColorRepo.forEachCallback(callback, area, displayId); } }); } @@ -1491,10 +1476,10 @@ public class WallpaperManagerService extends IWallpaperManager.Stub Slog.w(TAG, "Failed to request wallpaper colors", e); } - ArraySet<RectF> areas = mLocalColorDisplayIdAreas.get(displayId); + List<RectF> areas = mLocalColorRepo.getAreasByDisplayId(displayId); if (areas != null && areas.size() != 0) { try { - connector.mEngine.addLocalColorsAreas(new ArrayList<>(areas)); + connector.mEngine.addLocalColorsAreas(areas); } catch (RemoteException e) { Slog.w(TAG, "Failed to register local colors areas", e); } @@ -2494,37 +2479,10 @@ public class WallpaperManagerService extends IWallpaperManager.Stub } IWallpaperEngine engine = getEngine(which, userId, displayId); if (engine == null) return; - ArrayList<RectF> validAreas = new ArrayList<>(regions.size()); synchronized (mLock) { - ArraySet<RectF> areas = mLocalColorCallbackAreas.get(callback); - if (areas == null) areas = new ArraySet<>(regions.size()); - areas.addAll(regions); - mLocalColorCallbackAreas.put(callback.asBinder(), areas); + mLocalColorRepo.addAreas(callback, regions, displayId); } - for (int i = 0; i < regions.size(); i++) { - if (!LOCAL_COLOR_BOUNDS.contains(regions.get(i))) { - continue; - } - RemoteCallbackList callbacks; - synchronized (mLock) { - callbacks = mLocalColorAreaCallbacks.get( - regions.get(i)); - if (callbacks == null) { - callbacks = new RemoteCallbackList(); - mLocalColorAreaCallbacks.put(regions.get(i), callbacks); - } - mLocalColorCallbackDisplayId.put(callback.asBinder(), displayId); - ArraySet<RectF> displayAreas = mLocalColorDisplayIdAreas.get(displayId); - if (displayAreas == null) { - displayAreas = new ArraySet<>(1); - mLocalColorDisplayIdAreas.put(displayId, displayAreas); - } - displayAreas.add(regions.get(i)); - } - validAreas.add(regions.get(i)); - callbacks.register(callback); - } - engine.addLocalColorsAreas(validAreas); + engine.addLocalColorsAreas(regions); } @Override @@ -2539,45 +2497,19 @@ public class WallpaperManagerService extends IWallpaperManager.Stub throw new SecurityException("calling user id does not match"); } final long identity = Binder.clearCallingIdentity(); - ArrayList<RectF> purgeAreas = new ArrayList<>(); - IBinder binder = callback.asBinder(); + List<RectF> purgeAreas = null; try { synchronized (mLock) { - ArraySet<RectF> currentAreas = mLocalColorCallbackAreas.get(binder); - if (currentAreas == null) return; - currentAreas.removeAll(removeAreas); - if (currentAreas.size() == 0) { - mLocalColorCallbackDisplayId.remove(binder); - for (RectF removeArea : removeAreas) { - RemoteCallbackList<ILocalWallpaperColorConsumer> remotes = - mLocalColorAreaCallbacks.get(removeArea); - if (remotes == null) continue; - remotes.unregister(callback); - if (remotes.getRegisteredCallbackCount() == 0) { - mLocalColorAreaCallbacks.remove(removeArea); - purgeAreas.add(removeArea); - ArraySet<RectF> displayAreas = mLocalColorDisplayIdAreas.get(displayId); - if (displayAreas != null) { - displayAreas.remove(removeArea); - if (displayAreas.size() == 0) { - mLocalColorDisplayIdAreas.remove(displayId); - } - } - } - } - } + purgeAreas = mLocalColorRepo.removeAreas(callback, removeAreas, displayId); } - } catch (Exception e) { // ignore any exception } finally { Binder.restoreCallingIdentity(identity); } - - if (purgeAreas.size() == 0) return; IWallpaperEngine engine = getEngine(which, userId, displayId); - if (engine == null) return; - engine.removeLocalColorsAreas(purgeAreas); + if (engine == null || purgeAreas == null) return; + if (purgeAreas.size() > 0) engine.removeLocalColorsAreas(purgeAreas); } @Override diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 95a286cf9047..acb155bac5bc 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -1387,9 +1387,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A /** Whether we should prepare a transition for this {@link ActivityRecord} parent change. */ private boolean shouldStartChangeTransition( @Nullable TaskFragment newParent, @Nullable TaskFragment oldParent) { - if (mWmService.mDisableTransitionAnimation - || mDisplayContent == null || newParent == null || oldParent == null - || getSurfaceControl() == null || !isVisible() || !isVisibleRequested()) { + if (newParent == null || oldParent == null || !canStartChangeTransition()) { return false; } @@ -7924,9 +7922,17 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // Above coordinates are in "@" space, now place "*" and "#" to screen space. final boolean fillContainer = resolvedBounds.equals(containingBounds); final int screenPosX = fillContainer ? containerBounds.left : containerAppBounds.left; - final int screenPosY = mSizeCompatBounds == null + // If the activity is not in size compat mode, calculate vertical centering + // from the container and resolved bounds. + // If the activity is in size compat mode, calculate vertical centering + // from the container and size compat bounds. + // The container bounds contain the parent bounds offset in the display, for + // example when an activity is in the lower split of split screen. + final int screenPosY = (mSizeCompatBounds == null ? (containerBounds.height() - resolvedBounds.height()) / 2 - : (containerBounds.height() - mSizeCompatBounds.height()) / 2; + : (containerBounds.height() - mSizeCompatBounds.height()) / 2) + + containerBounds.top; + if (screenPosX != 0 || screenPosY != 0) { if (mSizeCompatBounds != null) { mSizeCompatBounds.offset(screenPosX, screenPosY); diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java index dc5126dbf916..2cf23c5e6f7f 100644 --- a/services/core/java/com/android/server/wm/ActivityStarter.java +++ b/services/core/java/com/android/server/wm/ActivityStarter.java @@ -2741,8 +2741,8 @@ class ActivityStarter { // If it exist, we need to reparent target root task from TDA to launch root task. final TaskDisplayArea tda = mTargetRootTask.getDisplayArea(); final Task launchRootTask = tda.getLaunchRootTask(mTargetRootTask.getWindowingMode(), - mTargetRootTask.getActivityType(), null /** options */, - mSourceRootTask, 0 /** launchFlags */); + mTargetRootTask.getActivityType(), null /** options */, mSourceRootTask, + mLaunchFlags); // If target root task is created by organizer, let organizer handle reparent itself. if (!mTargetRootTask.mCreatedByOrganizer && launchRootTask != null && launchRootTask != mTargetRootTask) { diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java index 878822522d08..721907c21904 100644 --- a/services/core/java/com/android/server/wm/AppTransitionController.java +++ b/services/core/java/com/android/server/wm/AppTransitionController.java @@ -176,6 +176,9 @@ public class AppTransitionController { Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "AppTransitionReady"); ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "**** GOOD TO GO"); + // TODO(b/205335975): Remove window which stuck in animatingExit status. Find actual cause. + mDisplayContent.forAllWindows(WindowState::cleanupAnimatingExitWindow, + true /* traverseTopToBottom */); // TODO(new-app-transition): Remove code using appTransition.getAppTransition() final AppTransition appTransition = mDisplayContent.mAppTransition; diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 36579d96d6c5..b7c992e073f3 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -44,6 +44,8 @@ import static android.view.Display.FLAG_PRIVATE; import static android.view.Display.FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS; import static android.view.Display.INVALID_DISPLAY; import static android.view.Display.REMOVE_MODE_DESTROY_CONTENT; +import static android.view.Display.STATE_UNKNOWN; +import static android.view.Display.isSuspendedState; import static android.view.InsetsState.ITYPE_IME; import static android.view.InsetsState.ITYPE_LEFT_GESTURES; import static android.view.InsetsState.ITYPE_NAVIGATION_BAR; @@ -322,11 +324,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp */ private Rect mLastMirroredDisplayAreaBounds = null; - /** - * The last state of the display. - */ - private int mLastDisplayState; - // Contains all IME window containers. Note that the z-ordering of the IME windows will depend // on the IME target. We mainly have this container grouping so we can keep track of all the IME // window containers together and move them in-sync if/when needed. We use a subclass of @@ -594,7 +591,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp /** Caches the value whether told display manager that we have content. */ private boolean mLastHasContent; - private static DisplayRotationUtil sRotationUtil = new DisplayRotationUtil(); + private DisplayRotationUtil mRotationUtil = new DisplayRotationUtil(); /** * The input method window for this display. @@ -1658,11 +1655,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp // to cover the activity configuration change. return false; } - if (r.attachedToProcess() && mayImeShowOnLaunchingActivity(r)) { - // Currently it is unknown that when will IME window be ready. Reject the case to - // avoid flickering by showing IME in inconsistent orientation. - return false; - } if (checkOpening) { if (!mAppTransition.isTransitionSet() || !mOpeningApps.contains(r)) { // Apply normal rotation animation in case of the activity set different requested @@ -2098,35 +2090,29 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp return mDisplayCutoutCache.getOrCompute(mInitialDisplayCutout, rotation); } - static WmDisplayCutout calculateDisplayCutoutForRotationAndDisplaySizeUncached( - DisplayCutout cutout, int rotation, int displayWidth, int displayHeight) { + private WmDisplayCutout calculateDisplayCutoutForRotationUncached( + DisplayCutout cutout, int rotation) { if (cutout == null || cutout == DisplayCutout.NO_CUTOUT) { return WmDisplayCutout.NO_CUTOUT; } if (rotation == ROTATION_0) { return WmDisplayCutout.computeSafeInsets( - cutout, displayWidth, displayHeight); + cutout, mInitialDisplayWidth, mInitialDisplayHeight); } final Insets waterfallInsets = RotationUtils.rotateInsets(cutout.getWaterfallInsets(), rotation); final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270); - final Rect[] newBounds = sRotationUtil.getRotatedBounds( + final Rect[] newBounds = mRotationUtil.getRotatedBounds( cutout.getBoundingRectsAll(), - rotation, displayWidth, displayHeight); + rotation, mInitialDisplayWidth, mInitialDisplayHeight); final CutoutPathParserInfo info = cutout.getCutoutPathParserInfo(); final CutoutPathParserInfo newInfo = new CutoutPathParserInfo( info.getDisplayWidth(), info.getDisplayHeight(), info.getDensity(), info.getCutoutSpec(), rotation, info.getScale()); return WmDisplayCutout.computeSafeInsets( DisplayCutout.constructDisplayCutout(newBounds, waterfallInsets, newInfo), - rotated ? displayHeight : displayWidth, - rotated ? displayWidth : displayHeight); - } - - private WmDisplayCutout calculateDisplayCutoutForRotationUncached( - DisplayCutout cutout, int rotation) { - return calculateDisplayCutoutForRotationAndDisplaySizeUncached(cutout, rotation, - mInitialDisplayWidth, mInitialDisplayHeight); + rotated ? mInitialDisplayHeight : mInitialDisplayWidth, + rotated ? mInitialDisplayWidth : mInitialDisplayHeight); } RoundedCorners calculateRoundedCornersForRotation(int rotation) { @@ -4723,12 +4709,9 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp mWmService.requestTraversal(); } + @Override boolean okToDisplay() { - return okToDisplay(false); - } - - boolean okToDisplay(boolean ignoreFrozen) { - return okToDisplay(ignoreFrozen, false /* ignoreScreenOn */); + return okToDisplay(false /* ignoreFrozen */, false /* ignoreScreenOn */); } boolean okToDisplay(boolean ignoreFrozen, boolean ignoreScreenOn) { @@ -4740,18 +4723,12 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp return mDisplayInfo.state == Display.STATE_ON; } - boolean okToAnimate() { - return okToAnimate(false); - } - - boolean okToAnimate(boolean ignoreFrozen) { - return okToAnimate(ignoreFrozen, false /* ignoreScreenOn */); - } - + @Override boolean okToAnimate(boolean ignoreFrozen, boolean ignoreScreenOn) { return okToDisplay(ignoreFrozen, ignoreScreenOn) && (mDisplayId != DEFAULT_DISPLAY - || mWmService.mPolicy.okToAnimate(ignoreScreenOn)); + || mWmService.mPolicy.okToAnimate(ignoreScreenOn)) + && getDisplayPolicy().isScreenOnFully(); } static final class TaskForResizePointSearchResult { @@ -4884,7 +4861,10 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp // WindowState#applyImeWindowsIfNeeded} in case of any state mismatch. return dc.mImeLayeringTarget != null && (!dc.getDefaultTaskDisplayArea().isSplitScreenModeActivated() - || dc.mImeLayeringTarget.getTask() == null); + || dc.mImeLayeringTarget.getTask() == null) + // Make sure that the IME window won't be skipped to report that it has + // completed the orientation change. + && !dc.mWmService.mDisplayFrozen; } /** Like {@link #forAllWindows}, but ignores {@link #skipImeWindowsDuringTraversal} */ @@ -5623,12 +5603,13 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp void onDisplayChanged() { mDisplay.getRealSize(mTmpDisplaySize); setBounds(0, 0, mTmpDisplaySize.x, mTmpDisplaySize.y); + final int lastDisplayState = mDisplayInfo.state; updateDisplayInfo(); // The window policy is responsible for stopping activities on the default display. final int displayId = mDisplay.getDisplayId(); + final int displayState = mDisplayInfo.state; if (displayId != DEFAULT_DISPLAY) { - final int displayState = mDisplay.getState(); if (displayState == Display.STATE_OFF) { mOffTokenAcquirer.acquire(mDisplayId); } else if (displayState == Display.STATE_ON) { @@ -5637,12 +5618,18 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp ProtoLog.v(WM_DEBUG_LAYER_MIRRORING, "Display %d state is now (%d), so update layer mirroring?", mDisplayId, displayState); - if (mLastDisplayState != displayState) { + if (lastDisplayState != displayState) { // If state is on due to surface being added, then start layer mirroring. // If state is off due to surface being removed, then stop layer mirroring. updateMirroring(); } - mLastDisplayState = displayState; + } + // Dispatch pending Configuration to WindowContext if the associated display changes to + // un-suspended state from suspended. + if (isSuspendedState(lastDisplayState) + && !isSuspendedState(displayState) && displayState != STATE_UNKNOWN) { + mWmService.mWindowContextListenerController + .dispatchPendingConfigurationIfNeeded(mDisplayId); } mWmService.requestTraversal(); } diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java index 1e7b676fbfe4..6afd3355b0a1 100644 --- a/services/core/java/com/android/server/wm/InputMonitor.java +++ b/services/core/java/com/android/server/wm/InputMonitor.java @@ -51,7 +51,6 @@ import static com.android.server.wm.WindowManagerService.LOGTAG_INPUT_FOCUS; import static java.lang.Integer.MAX_VALUE; import android.annotation.Nullable; -import android.graphics.Rect; import android.graphics.Region; import android.os.Handler; import android.os.IBinder; @@ -303,9 +302,6 @@ final class InputMonitor { && !mDisableWallpaperTouchEvents; inputWindowHandle.setHasWallpaper(hasWallpaper); - final Rect frame = w.getFrame(); - inputWindowHandle.setFrame(frame.left, frame.top, frame.right, frame.bottom); - // Surface insets are hardcoded to be the same in all directions // and we could probably deprecate the "left/right/top/bottom" concept. // we avoid reintroducing this concept by just choosing one of them here. @@ -315,11 +311,19 @@ final class InputMonitor { // what is on screen to what is actually being touched in the UI. inputWindowHandle.setScaleFactor(w.mGlobalScale != 1f ? (1f / w.mGlobalScale) : 1f); - final int flags = w.getSurfaceTouchableRegion(mTmpRegion, w.mAttrs.flags); - inputWindowHandle.setTouchableRegion(mTmpRegion); + // Update layout params flags to force the window to be not touch modal. We do this to + // restrict the window's touchable region to the task even if it request touches outside its + // window bounds. An example is a dialog in primary split should get touches outside its + // window within the primary task but should not get any touches going to the secondary + // task. + int flags = w.mAttrs.flags; + if (w.mAttrs.isModal()) { + flags = flags | FLAG_NOT_TOUCH_MODAL; + } inputWindowHandle.setLayoutParamsFlags(flags); - boolean useSurfaceCrop = false; + boolean useSurfaceBoundsAsTouchRegion = false; + SurfaceControl touchableRegionCrop = null; final Task task = w.getTask(); if (task != null) { // TODO(b/165794636): Remove the special case for freeform window once drag resizing is @@ -331,20 +335,22 @@ final class InputMonitor { // we need to make sure that these changes in crop are reflected in the input // windows, and so ensure this flag is set so that the input crop always reflects // the surface hierarchy. - // TODO(b/168252846): we have some issues with modal-windows, so we need to cross - // that bridge now that we organize full-screen Tasks. - inputWindowHandle.setTouchableRegionCrop(null /* Use this surfaces crop */); - inputWindowHandle.setReplaceTouchableRegionWithCrop(true); - useSurfaceCrop = true; + useSurfaceBoundsAsTouchRegion = true; + + if (w.mAttrs.isModal()) { + TaskFragment parent = w.getTaskFragment(); + touchableRegionCrop = parent != null ? parent.getSurfaceControl() : null; + } } else if (task.cropWindowsToRootTaskBounds() && !w.inFreeformWindowingMode()) { - inputWindowHandle.setTouchableRegionCrop(task.getRootTask().getSurfaceControl()); - inputWindowHandle.setReplaceTouchableRegionWithCrop(false); - useSurfaceCrop = true; + touchableRegionCrop = task.getRootTask().getSurfaceControl(); } } - if (!useSurfaceCrop) { - inputWindowHandle.setReplaceTouchableRegionWithCrop(false); - inputWindowHandle.setTouchableRegionCrop(null); + inputWindowHandle.setReplaceTouchableRegionWithCrop(useSurfaceBoundsAsTouchRegion); + inputWindowHandle.setTouchableRegionCrop(touchableRegionCrop); + + if (!useSurfaceBoundsAsTouchRegion) { + w.getSurfaceTouchableRegion(mTmpRegion, w.mAttrs); + inputWindowHandle.setTouchableRegion(mTmpRegion); } } diff --git a/services/core/java/com/android/server/wm/PossibleDisplayInfoMapper.java b/services/core/java/com/android/server/wm/PossibleDisplayInfoMapper.java deleted file mode 100644 index 11a27c593d9e..000000000000 --- a/services/core/java/com/android/server/wm/PossibleDisplayInfoMapper.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * 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.server.wm; - -import static android.view.Surface.ROTATION_0; -import static android.view.Surface.ROTATION_270; - -import android.hardware.display.DisplayManagerInternal; -import android.util.ArraySet; -import android.util.Slog; -import android.util.SparseArray; -import android.view.DisplayInfo; -import android.view.Surface; - -import java.util.Set; - -/** - * Maintains a map of possible {@link DisplayInfo} for displays and states that may be encountered - * on a device. This is not guaranteed to include all possible device states for all displays. - * - * By 'possible', this class only handles device states for displays and display groups it is - * currently aware of. It can not handle all eventual states the system may enter, for example, if - * an external display is added, or a new display is added to the group. - */ -public class PossibleDisplayInfoMapper { - private static final String TAG = "PossibleDisplayInfoMapper"; - private static final boolean DEBUG = false; - - private final DisplayManagerInternal mDisplayManagerInternal; - - /** - * Map of all logical displays, indexed by logical display id. - * Each logical display has multiple entries, one for each possible rotation and device - * state. - * - * Emptied and re-calculated when a display is added, removed, or changed. - */ - private final SparseArray<Set<DisplayInfo>> mDisplayInfos = new SparseArray<>(); - - PossibleDisplayInfoMapper(DisplayManagerInternal displayManagerInternal) { - mDisplayManagerInternal = displayManagerInternal; - } - - - /** - * Returns, for the given displayId, a set of display infos. Set contains the possible rotations - * for each supported device state. - */ - public Set<DisplayInfo> getPossibleDisplayInfos(int displayId) { - // Update display infos before returning, since any cached values would have been removed - // in response to any display event. This model avoids re-computing the cache for every - // display change event (which occurs extremely frequently in the normal usage of the - // device). - updatePossibleDisplayInfos(displayId); - if (!mDisplayInfos.contains(displayId)) { - return new ArraySet<>(); - } - return Set.copyOf(mDisplayInfos.get(displayId)); - } - - /** - * Updates the possible {@link DisplayInfo}s for the given display, by calculating the - * DisplayInfo for each rotation across supported device states. - */ - public void updatePossibleDisplayInfos(int displayId) { - Set<DisplayInfo> displayInfos = mDisplayManagerInternal.getPossibleDisplayInfo(displayId); - if (DEBUG) { - Slog.v(TAG, "updatePossibleDisplayInfos, calculate rotations for given DisplayInfo " - + displayInfos.size() + " on display " + displayId); - } - updateDisplayInfos(displayInfos); - } - - /** - * For the given displayId, removes all possible {@link DisplayInfo}. - */ - public void removePossibleDisplayInfos(int displayId) { - if (DEBUG && mDisplayInfos.get(displayId) != null) { - Slog.v(TAG, "onDisplayRemoved, remove all DisplayInfo (" + mDisplayInfos.get( - displayId).size() + ") with id " + displayId); - } - mDisplayInfos.remove(displayId); - } - - private void updateDisplayInfos(Set<DisplayInfo> displayInfos) { - // Empty out cache before re-computing. - mDisplayInfos.clear(); - DisplayInfo[] originalDisplayInfos = new DisplayInfo[displayInfos.size()]; - displayInfos.toArray(originalDisplayInfos); - // Iterate over each logical display layout for the current state. - Set<DisplayInfo> rotatedDisplayInfos; - for (DisplayInfo di : originalDisplayInfos) { - rotatedDisplayInfos = new ArraySet<>(); - // Calculate all possible rotations for each logical display. - for (int rotation = ROTATION_0; rotation <= ROTATION_270; rotation++) { - rotatedDisplayInfos.add(applyRotation(di, rotation)); - } - // Combine all results under the logical display id. - Set<DisplayInfo> priorDisplayInfos = mDisplayInfos.get(di.displayId, new ArraySet<>()); - priorDisplayInfos.addAll(rotatedDisplayInfos); - mDisplayInfos.put(di.displayId, priorDisplayInfos); - } - } - - private static DisplayInfo applyRotation(DisplayInfo displayInfo, - @Surface.Rotation int rotation) { - DisplayInfo updatedDisplayInfo = new DisplayInfo(); - updatedDisplayInfo.copyFrom(displayInfo); - // Apply rotations before updating width and height - updatedDisplayInfo.roundedCorners = updatedDisplayInfo.roundedCorners.rotate(rotation, - updatedDisplayInfo.logicalWidth, updatedDisplayInfo.logicalHeight); - updatedDisplayInfo.displayCutout = - DisplayContent.calculateDisplayCutoutForRotationAndDisplaySizeUncached( - updatedDisplayInfo.displayCutout, rotation, updatedDisplayInfo.logicalWidth, - updatedDisplayInfo.logicalHeight).getDisplayCutout(); - - updatedDisplayInfo.rotation = rotation; - final int naturalWidth = updatedDisplayInfo.getNaturalWidth(); - final int naturalHeight = updatedDisplayInfo.getNaturalHeight(); - updatedDisplayInfo.logicalWidth = naturalWidth; - updatedDisplayInfo.logicalHeight = naturalHeight; - return updatedDisplayInfo; - } -} diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index 3ffa62dbbe7e..fbc8f73b53b0 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -2587,9 +2587,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent> if (mService.isBooted() || mService.isBooting()) { startSystemDecorations(display); } - // Drop any cached DisplayInfos associated with this display id - the values are now - // out of date given this display added event. - mWmService.mPossibleDisplayInfoMapper.removePossibleDisplayInfos(displayId); } } @@ -2610,8 +2607,8 @@ class RootWindowContainer extends WindowContainer<DisplayContent> if (displayContent == null) { return; } + displayContent.remove(); - mWmService.mPossibleDisplayInfoMapper.removePossibleDisplayInfos(displayId); } } @@ -2623,9 +2620,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent> if (displayContent != null) { displayContent.onDisplayChanged(); } - // Drop any cached DisplayInfos associated with this display id - the values are now - // out of date given this display changed event. - mWmService.mPossibleDisplayInfoMapper.removePossibleDisplayInfos(displayId); } } diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 1b7a012094f6..a53a8cdea0a7 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -2163,10 +2163,7 @@ class Task extends TaskFragment { } private boolean shouldStartChangeTransition(int prevWinMode, int newWinMode) { - if (mWmService.mDisableTransitionAnimation - || !isVisible() - || getSurfaceControl() == null - || !isLeafTask()) { + if (!isLeafTask() || !canStartChangeTransition()) { return false; } // Only do an animation into and out-of freeform mode for now. Other mode @@ -4650,23 +4647,14 @@ class Task extends TaskFragment { moveToFront(reason, null); } - /** - * @param reason The reason for moving the root task to the front. - * @param task If non-null, the task will be moved to the top of the root task. - */ void moveToFront(String reason, Task task) { - if (!isAttached()) { - return; - } - - final TaskDisplayArea taskDisplayArea = getDisplayArea(); - if (inSplitScreenSecondaryWindowingMode()) { // If the root task is in split-screen secondary mode, we need to make sure we move the // primary split-screen root task forward in the case it is currently behind a // fullscreen root task so both halves of the split-screen appear on-top and the // fullscreen root task isn't cutting between them. // TODO(b/70677280): This is a workaround until we can fix as part of b/70677280. + final TaskDisplayArea taskDisplayArea = getDisplayArea(); final Task topFullScreenRootTask = taskDisplayArea.getTopRootTaskInWindowingMode(WINDOWING_MODE_FULLSCREEN); if (topFullScreenRootTask != null) { @@ -4674,10 +4662,30 @@ class Task extends TaskFragment { taskDisplayArea.getRootSplitScreenPrimaryTask(); if (primarySplitScreenRootTask != null && topFullScreenRootTask.compareTo(primarySplitScreenRootTask) > 0) { - primarySplitScreenRootTask.moveToFront(reason + " splitScreenToTop"); + primarySplitScreenRootTask.moveToFrontInner(reason + " splitScreenToTop", + null /* task */); } } + } else if (mMoveAdjacentTogether && getAdjacentTaskFragment() != null) { + final Task adjacentTask = getAdjacentTaskFragment().asTask(); + if (adjacentTask != null) { + adjacentTask.moveToFrontInner(reason + " adjacentTaskToTop", null /* task */); + } } + moveToFrontInner(reason, task); + } + + /** + * @param reason The reason for moving the root task to the front. + * @param task If non-null, the task will be moved to the top of the root task. + */ + @VisibleForTesting + void moveToFrontInner(String reason, Task task) { + if (!isAttached()) { + return; + } + + final TaskDisplayArea taskDisplayArea = getDisplayArea(); if (!isActivityTypeHome() && returnsToHomeRootTask()) { // Make sure the root home task is behind this root task since that is where we diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java index 1e367dc78198..ec3554a4f0f6 100644 --- a/services/core/java/com/android/server/wm/TaskDisplayArea.java +++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java @@ -867,6 +867,10 @@ final class TaskDisplayArea extends DisplayArea<WindowContainer> { // Place root home tasks to the bottom. layer = adjustRootTaskLayer(t, mTmpHomeChildren, layer); layer = adjustRootTaskLayer(t, mTmpNormalChildren, layer); + // TODO(b/207185041): Remove this divider workaround after we full remove leagacy split and + // make app pair split only have single root then we can just attach the + // divider to the single root task in shell. + layer = Math.max(layer, SPLIT_DIVIDER_LAYER + 1); adjustRootTaskLayer(t, mTmpAlwaysOnTopChildren, layer); t.setLayer(mSplitScreenDividerAnchor, SPLIT_DIVIDER_LAYER); } diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java index 51cede0c051d..985128aaec35 100644 --- a/services/core/java/com/android/server/wm/TaskFragment.java +++ b/services/core/java/com/android/server/wm/TaskFragment.java @@ -169,6 +169,14 @@ class TaskFragment extends WindowContainer<WindowContainer> { private TaskFragment mAdjacentTaskFragment; /** + * Whether to move adjacent task fragment together when re-positioning. + * + * @see #mAdjacentTaskFragment + */ + // TODO(b/207185041): Remove this once having a single-top root for split screen. + boolean mMoveAdjacentTogether; + + /** * Prevents duplicate calls to onTaskAppeared. */ boolean mTaskFragmentAppearedSent; @@ -313,14 +321,15 @@ class TaskFragment extends WindowContainer<WindowContainer> { return service.mWindowOrganizerController.getTaskFragment(token); } - void setAdjacentTaskFragment(@Nullable TaskFragment taskFragment) { + void setAdjacentTaskFragment(@Nullable TaskFragment taskFragment, boolean moveTogether) { if (mAdjacentTaskFragment == taskFragment) { return; } resetAdjacentTaskFragment(); if (taskFragment != null) { mAdjacentTaskFragment = taskFragment; - taskFragment.setAdjacentTaskFragment(this); + mMoveAdjacentTogether = moveTogether; + taskFragment.setAdjacentTaskFragment(this, moveTogether); } } @@ -329,9 +338,11 @@ class TaskFragment extends WindowContainer<WindowContainer> { if (mAdjacentTaskFragment != null && mAdjacentTaskFragment.mAdjacentTaskFragment == this) { mAdjacentTaskFragment.mAdjacentTaskFragment = null; mAdjacentTaskFragment.mDelayLastActivityRemoval = false; + mAdjacentTaskFragment.mMoveAdjacentTogether = false; } mAdjacentTaskFragment = null; mDelayLastActivityRemoval = false; + mMoveAdjacentTogether = false; } void setTaskFragmentOrganizer(@NonNull TaskFragmentOrganizerToken organizer, int uid, @@ -2125,13 +2136,7 @@ class TaskFragment extends WindowContainer<WindowContainer> { /** Whether we should prepare a transition for this {@link TaskFragment} bounds change. */ private boolean shouldStartChangeTransition(Rect startBounds) { - if (mWmService.mDisableTransitionAnimation - || mDisplayContent == null - || mTaskFragmentOrganizer == null - || getSurfaceControl() == null - // The change transition will be covered by display. - || mDisplayContent.inTransition() - || !isVisible()) { + if (mTaskFragmentOrganizer == null || !canStartChangeTransition()) { return false; } diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java index 58bc244e9250..5af9147cd56f 100644 --- a/services/core/java/com/android/server/wm/WindowContainer.java +++ b/services/core/java/com/android/server/wm/WindowContainer.java @@ -2600,6 +2600,13 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< mSurfaceFreezer.unfreeze(getPendingTransaction()); } + /** Whether we can start change transition with this window and current display status. */ + boolean canStartChangeTransition() { + return !mWmService.mDisableTransitionAnimation && mDisplayContent != null + && getSurfaceControl() != null && !mDisplayContent.inTransition() + && isVisible() && isVisibleRequested() && okToAnimate(); + } + /** * Initializes a change transition. See {@link SurfaceFreezer} for more information. * @@ -2948,12 +2955,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< } boolean okToAnimate() { - return okToAnimate(false /* ignoreFrozen */); - } - - boolean okToAnimate(boolean ignoreFrozen) { - final DisplayContent dc = getDisplayContent(); - return dc != null && dc.okToAnimate(ignoreFrozen); + return okToAnimate(false /* ignoreFrozen */, false /* ignoreScreenOn */); } boolean okToAnimate(boolean ignoreFrozen, boolean ignoreScreenOn) { diff --git a/services/core/java/com/android/server/wm/WindowContextListenerController.java b/services/core/java/com/android/server/wm/WindowContextListenerController.java index 86e356a876b5..cc527136eb51 100644 --- a/services/core/java/com/android/server/wm/WindowContextListenerController.java +++ b/services/core/java/com/android/server/wm/WindowContextListenerController.java @@ -17,7 +17,9 @@ package com.android.server.wm; import static android.view.Display.INVALID_DISPLAY; +import static android.view.Display.isSuspendedState; import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE; +import static android.window.WindowProviderService.isWindowProviderService; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE; import static com.android.internal.protolog.ProtoLogGroup.WM_ERROR; @@ -80,7 +82,7 @@ class WindowContextListenerController { * @param options a bundle used to pass window-related options. */ void registerWindowContainerListener(@NonNull IBinder clientToken, - @NonNull WindowContainer container, int ownerUid, @WindowType int type, + @NonNull WindowContainer<?> container, int ownerUid, @WindowType int type, @Nullable Bundle options) { WindowContextListenerImpl listener = mListeners.get(clientToken); if (listener == null) { @@ -103,6 +105,16 @@ class WindowContextListenerController { listener.unregister(); } + void dispatchPendingConfigurationIfNeeded(int displayId) { + for (int i = mListeners.size() - 1; i >= 0; --i) { + final WindowContextListenerImpl listener = mListeners.valueAt(i); + if (listener.getWindowContainer().getDisplayContent().getDisplayId() == displayId + && listener.mHasPendingConfiguration) { + listener.reportConfigToWindowTokenClient(); + } + } + } + /** * Verifies if the caller is allowed to do the operation to the listener specified by * {@code clientToken}. @@ -138,7 +150,7 @@ class WindowContextListenerController { return listener != null ? listener.mOptions : null; } - @Nullable WindowContainer getContainer(IBinder clientToken) { + @Nullable WindowContainer<?> getContainer(IBinder clientToken) { final WindowContextListenerImpl listener = mListeners.get(clientToken); return listener != null ? listener.mContainer : null; } @@ -163,7 +175,7 @@ class WindowContextListenerController { class WindowContextListenerImpl implements WindowContainerListener { @NonNull private final IBinder mClientToken; private final int mOwnerUid; - @NonNull private WindowContainer mContainer; + @NonNull private WindowContainer<?> mContainer; /** * The options from {@link Context#createWindowContext(int, Bundle)}. * <p>It can be used for choosing the {@link DisplayArea} where the window context @@ -177,7 +189,9 @@ class WindowContextListenerController { private int mLastReportedDisplay = INVALID_DISPLAY; private Configuration mLastReportedConfig; - private WindowContextListenerImpl(IBinder clientToken, WindowContainer container, + private boolean mHasPendingConfiguration; + + private WindowContextListenerImpl(IBinder clientToken, WindowContainer<?> container, int ownerUid, @WindowType int type, @Nullable Bundle options) { mClientToken = clientToken; mContainer = Objects.requireNonNull(container); @@ -197,11 +211,11 @@ class WindowContextListenerController { /** TEST ONLY: returns the {@link WindowContainer} of the listener */ @VisibleForTesting - WindowContainer getWindowContainer() { + WindowContainer<?> getWindowContainer() { return mContainer; } - private void updateContainer(@NonNull WindowContainer newContainer) { + private void updateContainer(@NonNull WindowContainer<?> newContainer) { Objects.requireNonNull(newContainer); if (mContainer.equals(newContainer)) { @@ -246,12 +260,20 @@ class WindowContextListenerController { if (mDeathRecipient == null) { throw new IllegalStateException("Invalid client token: " + mClientToken); } - - if (mLastReportedConfig == null) { - mLastReportedConfig = new Configuration(); + // If the display of window context associated window container is suspended, don't + // report the configuration update. Note that we still dispatch the configuration update + // to WindowProviderService to make it compatible with Service#onConfigurationChanged. + // Service always receives #onConfigurationChanged callback regardless of display state. + if (!isWindowProviderService(mOptions) + && isSuspendedState(mContainer.getDisplayContent().getDisplayInfo().state)) { + mHasPendingConfiguration = true; + return; } final Configuration config = mContainer.getConfiguration(); final int displayId = mContainer.getDisplayContent().getDisplayId(); + if (mLastReportedConfig == null) { + mLastReportedConfig = new Configuration(); + } if (config.equals(mLastReportedConfig) && displayId == mLastReportedDisplay) { // No changes since last reported time. return; @@ -266,6 +288,7 @@ class WindowContextListenerController { } catch (RemoteException e) { ProtoLog.w(WM_ERROR, "Could not report config changes to the window token client."); } + mHasPendingConfiguration = false; } @Override @@ -283,7 +306,7 @@ class WindowContextListenerController { // If we cannot obtain the DisplayContent, the DisplayContent may also be removed. // We should proceed the removal process. if (dc != null) { - final DisplayArea da = dc.findAreaForToken(windowToken); + final DisplayArea<?> da = dc.findAreaForToken(windowToken); updateContainer(da); return; } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index cc7485c317c8..fa47700b7fe7 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -154,7 +154,6 @@ import android.app.IActivityTaskManager; import android.app.IAssistDataReceiver; import android.app.WindowConfiguration; import android.content.BroadcastReceiver; -import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; @@ -164,7 +163,6 @@ import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; import android.content.pm.TestUtilityService; import android.content.res.Configuration; -import android.content.res.Resources; import android.content.res.TypedArray; import android.database.ContentObserver; import android.graphics.Bitmap; @@ -1063,10 +1061,6 @@ public class WindowManagerService extends IWindowManager.Stub final HighRefreshRateDenylist mHighRefreshRateDenylist; - // Maintainer of a collection of all possible DisplayInfo for all configurations of the - // logical displays. - final PossibleDisplayInfoMapper mPossibleDisplayInfoMapper; - // If true, only the core apps and services are being launched because the device // is in a special boot mode, such as being encrypted or waiting for a decryption password. // For example, when this flag is true, there will be no wallpaper service. @@ -1242,7 +1236,6 @@ public class WindowManagerService extends IWindowManager.Stub mInputManager = inputManager; // Must be before createDisplayContentLocked. mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class); - mPossibleDisplayInfoMapper = new PossibleDisplayInfoMapper(mDisplayManagerInternal); mSurfaceControlFactory = surfaceControlFactory; mTransactionFactory = transactionFactory; @@ -8572,52 +8565,6 @@ public class WindowManagerService extends IWindowManager.Stub } } - @Override - public List<DisplayInfo> getPossibleDisplayInfo(int displayId, String packageName) { - final int callingUid = Binder.getCallingUid(); - final long origId = Binder.clearCallingIdentity(); - try { - synchronized (mGlobalLock) { - if (packageName == null || !isRecentsComponent(packageName, callingUid)) { - Slog.e(TAG, "Unable to verify uid for package " + packageName - + " for getPossibleMaximumWindowMetrics"); - return new ArrayList<>(); - } - - // Retrieve the DisplayInfo for all possible rotations across all possible display - // layouts. - return List.copyOf(mPossibleDisplayInfoMapper.getPossibleDisplayInfos(displayId)); - } - } finally { - Binder.restoreCallingIdentity(origId); - } - } - - /** - * Returns {@code true} when the calling package is the recents component. - */ - boolean isRecentsComponent(@NonNull String callingPackageName, int callingUid) { - String recentsPackage; - try { - String recentsComponent = mContext.getResources().getString( - R.string.config_recentsComponentName); - if (recentsComponent == null) { - return false; - } - recentsPackage = ComponentName.unflattenFromString(recentsComponent).getPackageName(); - } catch (Resources.NotFoundException e) { - Slog.e(TAG, "Unable to verify if recents component", e); - return false; - } - try { - return callingUid == mContext.getPackageManager().getPackageUid(callingPackageName, 0) - && callingPackageName.equals(recentsPackage); - } catch (PackageManager.NameNotFoundException e) { - Slog.e(TAG, "Unable to verify if recents component", e); - return false; - } - } - void grantEmbeddedWindowFocus(Session session, IBinder inputToken, boolean grantFocus) { synchronized (mGlobalLock) { final EmbeddedWindowController.EmbeddedWindow embeddedWindow = diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java index 877965e5bfde..42766bdb0732 100644 --- a/services/core/java/com/android/server/wm/WindowOrganizerController.java +++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java @@ -665,7 +665,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub sendTaskFragmentOperationFailure(organizer, errorCallbackToken, exception); break; } - tf1.setAdjacentTaskFragment(tf2); + tf1.setAdjacentTaskFragment(tf2, false /* moveAdjacentTogether */); effects |= TRANSACT_EFFECTS_LIFECYCLE; final Bundle bundle = hop.getLaunchOptions(); @@ -978,7 +978,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub throw new IllegalArgumentException("setAdjacentRootsHierarchyOp: Not created by" + " organizer root1=" + root1 + " root2=" + root2); } - root1.setAdjacentTaskFragment(root2); + root1.setAdjacentTaskFragment(root2, hop.getMoveAdjacentTogether()); return TRANSACT_EFFECTS_LIFECYCLE; } diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index e0c3cf968f5c..44d2a7f593d0 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -51,7 +51,6 @@ import static android.view.WindowManager.LayoutParams.FLAG_DIM_BEHIND; import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD; import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS; import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; -import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; import static android.view.WindowManager.LayoutParams.FLAG_SCALED; import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED; @@ -2882,10 +2881,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP } } - int getSurfaceTouchableRegion(Region region, int flags) { - final boolean modal = (flags & (FLAG_NOT_TOUCH_MODAL | FLAG_NOT_FOCUSABLE)) == 0; + void getSurfaceTouchableRegion(Region region, WindowManager.LayoutParams attrs) { + final boolean modal = attrs.isModal(); if (modal) { - flags |= FLAG_NOT_TOUCH_MODAL; if (mActivityRecord != null) { // Limit the outer touch to the activity root task region. updateRegionForModalActivityWindow(region); @@ -2917,8 +2915,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP if (mInvGlobalScale != 1.f) { region.scale(mInvGlobalScale); } - - return flags; } /** @@ -3766,10 +3762,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP * {@link WindowManager.LayoutParams#FLAG_NOT_TOUCH_MODAL touch modality.} */ void getEffectiveTouchableRegion(Region outRegion) { - final boolean modal = (mAttrs.flags & (FLAG_NOT_TOUCH_MODAL | FLAG_NOT_FOCUSABLE)) == 0; final DisplayContent dc = getDisplayContent(); - if (modal && dc != null) { + if (mAttrs.isModal() && dc != null) { outRegion.set(dc.getBounds()); cropRegionToRootTaskBoundsIfNeeded(outRegion); subtractTouchExcludeRegionIfNeeded(outRegion); @@ -5069,6 +5064,48 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP return false; } + private boolean shouldFinishAnimatingExit() { + // Exit animation might be applied soon. + if (inTransition()) { + ProtoLog.d(WM_DEBUG_APP_TRANSITIONS, "shouldWaitAnimatingExit: isTransition: %s", + this); + return false; + } + if (!mDisplayContent.okToAnimate()) { + return true; + } + // Exit animation is running. + if (isAnimating(TRANSITION | PARENTS, EXIT_ANIMATING_TYPES)) { + ProtoLog.d(WM_DEBUG_APP_TRANSITIONS, "shouldWaitAnimatingExit: isAnimating: %s", + this); + return false; + } + // If the wallpaper is currently behind this app window, we need to change both of + // them inside of a transaction to avoid artifacts. + if (mDisplayContent.mWallpaperController.isWallpaperTarget(this)) { + ProtoLog.d(WM_DEBUG_APP_TRANSITIONS, + "shouldWaitAnimatingExit: isWallpaperTarget: %s", this); + return false; + } + return true; + } + + /** + * If this is window is stuck in the animatingExit status, resume clean up procedure blocked + * by the exit animation. + */ + void cleanupAnimatingExitWindow() { + // TODO(b/205335975): WindowManagerService#tryStartExitingAnimation starts an exit animation + // and set #mAnimationExit. After the exit animation finishes, #onExitAnimationDone shall + // be called, but there seems to be a case that #onExitAnimationDone is not triggered, so + // a windows stuck in the animatingExit status. + if (mAnimatingExit && shouldFinishAnimatingExit()) { + ProtoLog.w(WM_DEBUG_APP_TRANSITIONS, "Clear window stuck on animatingExit status: %s", + this); + onExitAnimationDone(); + } + } + void onExitAnimationDone() { if (DEBUG_ANIM) Slog.v(TAG, "onExitAnimationDone in " + this + ": exiting=" + mAnimatingExit + " remove=" + mRemoveOnExit diff --git a/services/tests/mockingservicestests/src/com/android/server/location/injector/LocationAttributionHelperTest.java b/services/tests/mockingservicestests/src/com/android/server/location/injector/LocationAttributionHelperTest.java index e2e7f5dd7ba2..94dcdf92d9d4 100644 --- a/services/tests/mockingservicestests/src/com/android/server/location/injector/LocationAttributionHelperTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/location/injector/LocationAttributionHelperTest.java @@ -58,72 +58,86 @@ public class LocationAttributionHelperTest { @Test public void testLocationMonitoring() { CallerIdentity caller1 = CallerIdentity.forTest(1, 1, "test1", null); - Object key1 = new Object(); - Object key2 = new Object(); CallerIdentity caller2 = CallerIdentity.forTest(2, 2, "test2", null); - Object key3 = new Object(); - Object key4 = new Object(); - - mHelper.reportLocationStart(caller1, "gps", key1); - verify(mAppOpsHelper).startOpNoThrow(OP_MONITOR_LOCATION, caller1); - verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_LOCATION, caller1); - - mHelper.reportLocationStart(caller1, "gps", key2); - verify(mAppOpsHelper).startOpNoThrow(OP_MONITOR_LOCATION, caller1); - verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_LOCATION, caller1); - - mHelper.reportLocationStart(caller2, "gps", key3); - verify(mAppOpsHelper).startOpNoThrow(OP_MONITOR_LOCATION, caller2); - verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_LOCATION, caller2); - - mHelper.reportLocationStart(caller2, "gps", key4); - verify(mAppOpsHelper).startOpNoThrow(OP_MONITOR_LOCATION, caller2); - verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_LOCATION, caller2); - - mHelper.reportLocationStop(caller1, "gps", key2); - verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_LOCATION, caller1); - mHelper.reportLocationStop(caller1, "gps", key1); - verify(mAppOpsHelper).finishOp(OP_MONITOR_LOCATION, caller1); - - mHelper.reportLocationStop(caller2, "gps", key3); - verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_LOCATION, caller2); - mHelper.reportLocationStop(caller2, "gps", key4); - verify(mAppOpsHelper).finishOp(OP_MONITOR_LOCATION, caller2); + + mHelper.reportLocationStart(caller1); + verify(mAppOpsHelper).startOpNoThrow(OP_MONITOR_LOCATION, + CallerIdentity.forAggregation(caller1)); + verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_LOCATION, + CallerIdentity.forAggregation(caller1)); + + mHelper.reportLocationStart(caller1); + verify(mAppOpsHelper).startOpNoThrow(OP_MONITOR_LOCATION, + CallerIdentity.forAggregation(caller1)); + verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_LOCATION, + CallerIdentity.forAggregation(caller1)); + + mHelper.reportLocationStart(caller2); + verify(mAppOpsHelper).startOpNoThrow(OP_MONITOR_LOCATION, + CallerIdentity.forAggregation(caller2)); + verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_LOCATION, + CallerIdentity.forAggregation(caller2)); + + mHelper.reportLocationStart(caller2); + verify(mAppOpsHelper).startOpNoThrow(OP_MONITOR_LOCATION, + CallerIdentity.forAggregation(caller2)); + verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_LOCATION, + CallerIdentity.forAggregation(caller2)); + + mHelper.reportLocationStop(caller1); + verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_LOCATION, + CallerIdentity.forAggregation(caller1)); + mHelper.reportLocationStop(caller1); + verify(mAppOpsHelper).finishOp(OP_MONITOR_LOCATION, CallerIdentity.forAggregation(caller1)); + + mHelper.reportLocationStop(caller2); + verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_LOCATION, + CallerIdentity.forAggregation(caller2)); + mHelper.reportLocationStop(caller2); + verify(mAppOpsHelper).finishOp(OP_MONITOR_LOCATION, CallerIdentity.forAggregation(caller2)); } @Test public void testHighPowerLocationMonitoring() { CallerIdentity caller1 = CallerIdentity.forTest(1, 1, "test1", null); - Object key1 = new Object(); - Object key2 = new Object(); CallerIdentity caller2 = CallerIdentity.forTest(2, 2, "test2", null); - Object key3 = new Object(); - Object key4 = new Object(); - - mHelper.reportHighPowerLocationStart(caller1, "gps", key1); - verify(mAppOpsHelper).startOpNoThrow(OP_MONITOR_HIGH_POWER_LOCATION, caller1); - verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_HIGH_POWER_LOCATION, caller1); - - mHelper.reportHighPowerLocationStart(caller1, "gps", key2); - verify(mAppOpsHelper).startOpNoThrow(OP_MONITOR_HIGH_POWER_LOCATION, caller1); - verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_HIGH_POWER_LOCATION, caller1); - - mHelper.reportHighPowerLocationStart(caller2, "gps", key3); - verify(mAppOpsHelper).startOpNoThrow(OP_MONITOR_HIGH_POWER_LOCATION, caller2); - verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_HIGH_POWER_LOCATION, caller2); - - mHelper.reportHighPowerLocationStart(caller2, "gps", key4); - verify(mAppOpsHelper).startOpNoThrow(OP_MONITOR_HIGH_POWER_LOCATION, caller2); - verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_HIGH_POWER_LOCATION, caller2); - - mHelper.reportHighPowerLocationStop(caller1, "gps", key2); - verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_HIGH_POWER_LOCATION, caller1); - mHelper.reportHighPowerLocationStop(caller1, "gps", key1); - verify(mAppOpsHelper).finishOp(OP_MONITOR_HIGH_POWER_LOCATION, caller1); - - mHelper.reportHighPowerLocationStop(caller2, "gps", key3); - verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_HIGH_POWER_LOCATION, caller2); - mHelper.reportHighPowerLocationStop(caller2, "gps", key4); - verify(mAppOpsHelper).finishOp(OP_MONITOR_HIGH_POWER_LOCATION, caller2); + + mHelper.reportHighPowerLocationStart(caller1); + verify(mAppOpsHelper).startOpNoThrow(OP_MONITOR_HIGH_POWER_LOCATION, + CallerIdentity.forAggregation(caller1)); + verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_HIGH_POWER_LOCATION, + CallerIdentity.forAggregation(caller1)); + + mHelper.reportHighPowerLocationStart(caller1); + verify(mAppOpsHelper).startOpNoThrow(OP_MONITOR_HIGH_POWER_LOCATION, + CallerIdentity.forAggregation(caller1)); + verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_HIGH_POWER_LOCATION, + CallerIdentity.forAggregation(caller1)); + + mHelper.reportHighPowerLocationStart(caller2); + verify(mAppOpsHelper).startOpNoThrow(OP_MONITOR_HIGH_POWER_LOCATION, + CallerIdentity.forAggregation(caller2)); + verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_HIGH_POWER_LOCATION, + CallerIdentity.forAggregation(caller2)); + + mHelper.reportHighPowerLocationStart(caller2); + verify(mAppOpsHelper).startOpNoThrow(OP_MONITOR_HIGH_POWER_LOCATION, + CallerIdentity.forAggregation(caller2)); + verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_HIGH_POWER_LOCATION, + CallerIdentity.forAggregation(caller2)); + + mHelper.reportHighPowerLocationStop(caller1); + verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_HIGH_POWER_LOCATION, + CallerIdentity.forAggregation(caller1)); + mHelper.reportHighPowerLocationStop(caller1); + verify(mAppOpsHelper).finishOp(OP_MONITOR_HIGH_POWER_LOCATION, + CallerIdentity.forAggregation(caller1)); + + mHelper.reportHighPowerLocationStop(caller2); + verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_HIGH_POWER_LOCATION, + CallerIdentity.forAggregation(caller2)); + mHelper.reportHighPowerLocationStop(caller2); + verify(mAppOpsHelper).finishOp(OP_MONITOR_HIGH_POWER_LOCATION, + CallerIdentity.forAggregation(caller2)); } } diff --git a/services/tests/mockingservicestests/src/com/android/server/location/provider/LocationProviderManagerTest.java b/services/tests/mockingservicestests/src/com/android/server/location/provider/LocationProviderManagerTest.java index d0b2edadc714..890a5495ef16 100644 --- a/services/tests/mockingservicestests/src/com/android/server/location/provider/LocationProviderManagerTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/location/provider/LocationProviderManagerTest.java @@ -845,6 +845,48 @@ public class LocationProviderManagerTest { } @Test + public void testLocationMonitoring_multipleIdentities() { + CallerIdentity identity1 = CallerIdentity.forTest(CURRENT_USER, 1, + "mypackage", "attribution", "listener1"); + CallerIdentity identity2 = CallerIdentity.forTest(CURRENT_USER, 1, + "mypackage", "attribution", "listener2"); + + assertThat(mInjector.getAppOpsHelper().isAppOpStarted(OP_MONITOR_LOCATION, + IDENTITY.getPackageName())).isFalse(); + assertThat(mInjector.getAppOpsHelper().isAppOpStarted(OP_MONITOR_HIGH_POWER_LOCATION, + IDENTITY.getPackageName())).isFalse(); + + ILocationListener listener1 = createMockLocationListener(); + LocationRequest request1 = new LocationRequest.Builder(0).setWorkSource( + WORK_SOURCE).build(); + mManager.registerLocationRequest(request1, identity1, PERMISSION_FINE, listener1); + + ILocationListener listener2 = createMockLocationListener(); + LocationRequest request2 = new LocationRequest.Builder(0).setWorkSource( + WORK_SOURCE).build(); + mManager.registerLocationRequest(request2, identity2, PERMISSION_FINE, listener2); + + assertThat(mInjector.getAppOpsHelper().isAppOpStarted(OP_MONITOR_LOCATION, + "mypackage")).isTrue(); + assertThat(mInjector.getAppOpsHelper().isAppOpStarted(OP_MONITOR_HIGH_POWER_LOCATION, + "mypackage")).isTrue(); + + mManager.unregisterLocationRequest(listener2); + + assertThat(mInjector.getAppOpsHelper().isAppOpStarted(OP_MONITOR_LOCATION, + "mypackage")).isTrue(); + assertThat(mInjector.getAppOpsHelper().isAppOpStarted(OP_MONITOR_HIGH_POWER_LOCATION, + "mypackage")).isTrue(); + + mManager.unregisterLocationRequest(listener1); + + assertThat(mInjector.getAppOpsHelper().isAppOpStarted(OP_MONITOR_LOCATION, + "mypackage")).isFalse(); + assertThat(mInjector.getAppOpsHelper().isAppOpStarted(OP_MONITOR_HIGH_POWER_LOCATION, + "mypackage")).isFalse(); + } + + @Test public void testProviderRequest() { assertThat(mProvider.getRequest().isActive()).isFalse(); diff --git a/services/tests/mockingservicestests/src/com/android/server/wallpaper/LocalColorRepositoryTest.java b/services/tests/mockingservicestests/src/com/android/server/wallpaper/LocalColorRepositoryTest.java new file mode 100644 index 000000000000..ea7a9a45facd --- /dev/null +++ b/services/tests/mockingservicestests/src/com/android/server/wallpaper/LocalColorRepositoryTest.java @@ -0,0 +1,135 @@ +/* + * 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.server.wallpaper; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertTrue; + +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.when; +import static org.mockito.MockitoAnnotations.initMocks; + +import static java.util.Arrays.asList; + +import android.app.ILocalWallpaperColorConsumer; +import android.app.WallpaperColors; +import android.graphics.RectF; +import android.os.IBinder; + +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; + +import android.util.ArraySet; +import java.util.List; +import java.util.function.Consumer; + + +@RunWith(AndroidJUnit4.class) +public class LocalColorRepositoryTest { + private LocalColorRepository mRepo = new LocalColorRepository(); + @Mock + private IBinder mBinder1; + @Mock + private IBinder mBinder2; + @Mock + private ILocalWallpaperColorConsumer mCallback1; + @Mock + private ILocalWallpaperColorConsumer mCallback2; + + @Before + public void setUp() { + initMocks(this); + when(mCallback1.asBinder()).thenReturn(mBinder1); + when(mCallback2.asBinder()).thenReturn(mBinder2); + } + + @Test + public void testDisplayAreas() { + RectF area1 = new RectF(1, 0, 0, 0); + RectF area2 = new RectF(2, 1, 1, 1); + ArraySet<RectF> expectedAreas = new ArraySet(asList(area1, area2)); + + mRepo.addAreas(mCallback1, asList(area1), 0); + mRepo.addAreas(mCallback2, asList(area2), 0); + mRepo.addAreas(mCallback1, asList(new RectF(3, 1, 1, 1)), 1); + + assertEquals(expectedAreas, new ArraySet(mRepo.getAreasByDisplayId(0))); + assertEquals(new ArraySet(asList(new RectF(3, 1, 1, 1))), + new ArraySet(mRepo.getAreasByDisplayId(1))); + assertEquals(new ArraySet(), new ArraySet(mRepo.getAreasByDisplayId(2))); + } + + @Test + public void testAddAndRemoveAreas() { + RectF area1 = new RectF(1, 0, 0, 0); + RectF area2 = new RectF(2, 1, 1, 1); + + mRepo.addAreas(mCallback1, asList(area1), 0); + mRepo.addAreas(mCallback1, asList(area2), 0); + mRepo.addAreas(mCallback2, asList(area2), 1); + + List<RectF> removed = mRepo.removeAreas(mCallback1, asList(area1), 0); + assertEquals(new ArraySet(asList(area1)), new ArraySet(removed)); + // since we have another callback with a different area, we don't purge rid of any areas + removed = mRepo.removeAreas(mCallback1, asList(area2), 0); + assertEquals(new ArraySet(), new ArraySet(removed)); + } + + @Test + public void testAreaCallback() { + Consumer<ILocalWallpaperColorConsumer> consumer = mock(Consumer.class); + WallpaperColors colors = mock(WallpaperColors.class); + RectF area1 = new RectF(1, 0, 0, 0); + RectF area2 = new RectF(2, 1, 1, 1); + + mRepo.addAreas(mCallback1, asList(area1), 0); + mRepo.addAreas(mCallback1, asList(area2), 0); + mRepo.addAreas(mCallback2, asList(area2), 0); + + mRepo.forEachCallback(consumer, area1, 0); + Mockito.verify(consumer, times(1)).accept(eq(mCallback1)); + Mockito.verify(consumer, times(0)).accept(eq(mCallback2)); + mRepo.forEachCallback(consumer, area2, 0); + Mockito.verify(consumer, times(2)).accept(eq(mCallback1)); + Mockito.verify(consumer, times(1)).accept(eq(mCallback2)); + } + + @Test + public void unregisterCallbackWhenNoAreas() { + RectF area1 = new RectF(1, 0, 0, 0); + RectF area2 = new RectF(2, 1, 1, 1); + + assertFalse(mRepo.isCallbackAvailable(mCallback1)); + + mRepo.addAreas(mCallback1, asList(area1), 0); + mRepo.addAreas(mCallback1, asList(area2), 0); + + mRepo.removeAreas(mCallback1, asList(area1, area2), 0); + assertFalse(mRepo.isCallbackAvailable(mCallback1)); + + mRepo.addAreas(mCallback1, asList(area1), 0); + assertTrue(mRepo.isCallbackAvailable(mCallback1)); + } +} diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp index 339a5f916b4b..7020744d661c 100644 --- a/services/tests/servicestests/Android.bp +++ b/services/tests/servicestests/Android.bp @@ -110,6 +110,7 @@ android_test { data: [ ":JobTestApp", + ":StubTestApp", ], java_resources: [ diff --git a/services/tests/servicestests/AndroidTest.xml b/services/tests/servicestests/AndroidTest.xml index 5a0f1ee963a2..4c638d669019 100644 --- a/services/tests/servicestests/AndroidTest.xml +++ b/services/tests/servicestests/AndroidTest.xml @@ -28,6 +28,17 @@ <option name="test-file-name" value="SimpleServiceTestApp3.apk" /> </target_preparer> + <!-- Create place to store apks --> + <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer"> + <option name="run-command" value="mkdir -p /data/local/tmp/servicestests" /> + <option name="teardown-command" value="rm -rf /data/local/tmp/servicestests"/> + </target_preparer> + + <!-- Load additional APKs onto device --> + <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher"> + <option name="push" value="StubTestApp.apk->/data/local/tmp/servicestests/StubTestApp.apk"/> + </target_preparer> + <option name="test-tag" value="FrameworksServicesTests" /> <test class="com.android.tradefed.testtype.AndroidJUnitTest" > <option name="package" value="com.android.frameworks.servicestests" /> diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java index e3e3900c47e0..d192697827f6 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java @@ -143,8 +143,8 @@ public class BiometricSchedulerTest { final ClientMonitorCallbackConverter listener1 = mock(ClientMonitorCallbackConverter.class); - final BiometricPromptClientMonitor client1 = - new BiometricPromptClientMonitor(mContext, mToken, lazyDaemon1, listener1); + final TestAuthenticationClient client1 = + new TestAuthenticationClient(mContext, lazyDaemon1, mToken, listener1); final TestClientMonitor client2 = new TestClientMonitor(mContext, mToken, lazyDaemon2); final BaseClientMonitor.Callback callback1 = mock(BaseClientMonitor.Callback.class); @@ -180,8 +180,8 @@ public class BiometricSchedulerTest { @Test public void testCancelNotInvoked_whenOperationWaitingForCookie() { final HalClientMonitor.LazyDaemon<Object> lazyDaemon1 = () -> mock(Object.class); - final BiometricPromptClientMonitor client1 = new BiometricPromptClientMonitor(mContext, - mToken, lazyDaemon1, mock(ClientMonitorCallbackConverter.class)); + final TestAuthenticationClient client1 = new TestAuthenticationClient(mContext, + lazyDaemon1, mToken, mock(ClientMonitorCallbackConverter.class)); final BaseClientMonitor.Callback callback1 = mock(BaseClientMonitor.Callback.class); // Schedule a BiometricPrompt authentication request @@ -195,6 +195,8 @@ public class BiometricSchedulerTest { // should go back to idle, since in this case the framework has not even requested the HAL // to authenticate yet. mScheduler.cancelAuthenticationOrDetection(mToken, 1 /* requestId */); + assertTrue(client1.isAlreadyDone()); + assertTrue(client1.mDestroyed); assertNull(mScheduler.mCurrentOperation); } @@ -316,6 +318,10 @@ public class BiometricSchedulerTest { eq(BiometricConstants.BIOMETRIC_ERROR_CANCELED), eq(0) /* vendorCode */); assertNull(mScheduler.getCurrentClient()); + assertTrue(client1.isAlreadyDone()); + assertTrue(client1.mDestroyed); + assertTrue(client2.isAlreadyDone()); + assertTrue(client2.mDestroyed); } @Test @@ -465,39 +471,9 @@ public class BiometricSchedulerTest { return BiometricSchedulerProto.parseFrom(mScheduler.dumpProtoState(clearSchedulerBuffer)); } - private static class BiometricPromptClientMonitor extends AuthenticationClient<Object> { - - public BiometricPromptClientMonitor(@NonNull Context context, @NonNull IBinder token, - @NonNull LazyDaemon<Object> lazyDaemon, ClientMonitorCallbackConverter listener) { - super(context, lazyDaemon, token, listener, 0 /* targetUserId */, 0 /* operationId */, - false /* restricted */, TAG, 1 /* cookie */, false /* requireConfirmation */, - TEST_SENSOR_ID, true /* isStrongBiometric */, 0 /* statsModality */, - 0 /* statsClient */, null /* taskStackListener */, mock(LockoutTracker.class), - false /* isKeyguard */, true /* shouldVibrate */, - false /* isKeyguardBypassEnabled */); - } - - @Override - protected void stopHalOperation() { - } - - @Override - protected void startHalOperation() { - } - - @Override - protected void handleLifecycleAfterAuth(boolean authenticated) { - - } - - @Override - public boolean wasUserDetected() { - return false; - } - } - private static class TestAuthenticationClient extends AuthenticationClient<Object> { int mNumCancels = 0; + boolean mDestroyed = false; public TestAuthenticationClient(@NonNull Context context, @NonNull LazyDaemon<Object> lazyDaemon, @NonNull IBinder token, @@ -530,6 +506,13 @@ public class BiometricSchedulerTest { return false; } + @Override + public void destroy() { + mDestroyed = true; + super.destroy(); + } + + @Override public void cancel() { mNumCancels++; super.cancel(); @@ -595,6 +578,7 @@ public class BiometricSchedulerTest { @Override public void destroy() { + super.destroy(); mDestroyed = true; } diff --git a/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java index 03eba9bfc35c..ee0723b8b471 100644 --- a/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java @@ -18,8 +18,6 @@ package com.android.server.devicestate; import static android.hardware.devicestate.DeviceStateManager.INVALID_DEVICE_STATE; -import static com.google.common.truth.Truth.assertThat; - import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import static org.testng.Assert.assertEquals; @@ -183,10 +181,8 @@ public final class DeviceStateManagerServiceTest { assertEquals(mService.getCommittedState(), Optional.of(DEFAULT_DEVICE_STATE)); assertEquals(mService.getPendingState(), Optional.empty()); assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE)); - assertThat(mService.getSupportedStates()).asList().containsExactly(DEFAULT_DEVICE_STATE, - OTHER_DEVICE_STATE); - mProvider.notifySupportedDeviceStates(new DeviceState[]{DEFAULT_DEVICE_STATE}); + mProvider.notifySupportedDeviceStates(new DeviceState[]{ DEFAULT_DEVICE_STATE }); flushHandler(); // The current committed and requests states do not change because the current state remains @@ -194,10 +190,9 @@ public final class DeviceStateManagerServiceTest { assertEquals(mService.getCommittedState(), Optional.of(DEFAULT_DEVICE_STATE)); assertEquals(mService.getPendingState(), Optional.empty()); assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE)); - assertThat(mService.getSupportedStates()).asList().containsExactly(DEFAULT_DEVICE_STATE); assertArrayEquals(callback.getLastNotifiedInfo().supportedStates, - new int[]{DEFAULT_DEVICE_STATE.getIdentifier()}); + new int[] { DEFAULT_DEVICE_STATE.getIdentifier() }); } @Test @@ -212,11 +207,9 @@ public final class DeviceStateManagerServiceTest { assertEquals(mService.getCommittedState(), Optional.of(DEFAULT_DEVICE_STATE)); assertEquals(mService.getPendingState(), Optional.empty()); assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE)); - assertThat(mService.getSupportedStates()).asList().containsExactly(DEFAULT_DEVICE_STATE, - OTHER_DEVICE_STATE); - mProvider.notifySupportedDeviceStates(new DeviceState[]{DEFAULT_DEVICE_STATE, - OTHER_DEVICE_STATE}); + mProvider.notifySupportedDeviceStates(new DeviceState[]{ DEFAULT_DEVICE_STATE, + OTHER_DEVICE_STATE }); flushHandler(); // The current committed and requests states do not change because the current state remains @@ -224,8 +217,6 @@ public final class DeviceStateManagerServiceTest { assertEquals(mService.getCommittedState(), Optional.of(DEFAULT_DEVICE_STATE)); assertEquals(mService.getPendingState(), Optional.empty()); assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE)); - assertThat(mService.getSupportedStates()).asList().containsExactly(DEFAULT_DEVICE_STATE, - OTHER_DEVICE_STATE); // The callback wasn't notified about a change in supported states as the states have not // changed. diff --git a/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java b/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java index fbc1952b0faf..8279624f6b97 100644 --- a/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java +++ b/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java @@ -16,17 +16,12 @@ package com.android.server.display; -import static android.view.Display.DEFAULT_DISPLAY; -import static android.view.Display.DEFAULT_DISPLAY_GROUP; - import static com.android.server.display.DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED; import static com.android.server.display.DisplayAdapter.DISPLAY_DEVICE_EVENT_CHANGED; import static com.android.server.display.DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED; import static com.android.server.display.LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_ADDED; import static com.android.server.display.LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_REMOVED; -import static com.google.common.truth.Truth.assertThat; - import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; import static org.mockito.ArgumentMatchers.eq; @@ -60,7 +55,6 @@ import org.mockito.MockitoAnnotations; import java.io.InputStream; import java.io.OutputStream; import java.util.Arrays; -import java.util.Set; @SmallTest @Presubmit @@ -129,14 +123,14 @@ public class LogicalDisplayMapperTest { // add LogicalDisplay displayAdded = add(device); assertEquals(info(displayAdded).address, info(device).address); - assertEquals(DEFAULT_DISPLAY, id(displayAdded)); + assertEquals(Display.DEFAULT_DISPLAY, id(displayAdded)); // remove mDisplayDeviceRepo.onDisplayDeviceEvent(device, DISPLAY_DEVICE_EVENT_REMOVED); verify(mListenerMock).onLogicalDisplayEventLocked( mDisplayCaptor.capture(), eq(LOGICAL_DISPLAY_EVENT_REMOVED)); LogicalDisplay displayRemoved = mDisplayCaptor.getValue(); - assertEquals(DEFAULT_DISPLAY, id(displayRemoved)); + assertEquals(Display.DEFAULT_DISPLAY, id(displayRemoved)); assertEquals(displayAdded, displayRemoved); } @@ -161,11 +155,11 @@ public class LogicalDisplayMapperTest { LogicalDisplay display1 = add(device1); assertEquals(info(display1).address, info(device1).address); - assertNotEquals(DEFAULT_DISPLAY, id(display1)); + assertNotEquals(Display.DEFAULT_DISPLAY, id(display1)); LogicalDisplay display2 = add(device2); assertEquals(info(display2).address, info(device2).address); - assertEquals(DEFAULT_DISPLAY, id(display2)); + assertEquals(Display.DEFAULT_DISPLAY, id(display2)); } @Test @@ -177,12 +171,12 @@ public class LogicalDisplayMapperTest { LogicalDisplay display1 = add(device1); assertEquals(info(display1).address, info(device1).address); - assertEquals(DEFAULT_DISPLAY, id(display1)); + assertEquals(Display.DEFAULT_DISPLAY, id(display1)); LogicalDisplay display2 = add(device2); assertEquals(info(display2).address, info(device2).address); // Despite the flags, we can only have one default display - assertNotEquals(DEFAULT_DISPLAY, id(display2)); + assertNotEquals(Display.DEFAULT_DISPLAY, id(display2)); } @Test @@ -195,67 +189,7 @@ public class LogicalDisplayMapperTest { int [] ids = mLogicalDisplayMapper.getDisplayIdsLocked(Process.SYSTEM_UID); assertEquals(3, ids.length); Arrays.sort(ids); - assertEquals(DEFAULT_DISPLAY, ids[0]); - } - - @Test - public void testGetDisplayInfoForStateLocked_oneDisplayGroup_internalType() { - add(createDisplayDevice(Display.TYPE_INTERNAL, 600, 800, - DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY)); - add(createDisplayDevice(Display.TYPE_INTERNAL, 200, 800, - DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY)); - add(createDisplayDevice(Display.TYPE_INTERNAL, 700, 800, - DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY)); - - Set<DisplayInfo> displayInfos = mLogicalDisplayMapper.getDisplayInfoForStateLocked( - DeviceStateToLayoutMap.STATE_DEFAULT, DEFAULT_DISPLAY, DEFAULT_DISPLAY_GROUP); - assertThat(displayInfos.size()).isEqualTo(3); - for (DisplayInfo displayInfo : displayInfos) { - assertThat(displayInfo.displayId).isEqualTo(DEFAULT_DISPLAY); - assertThat(displayInfo.displayGroupId).isEqualTo(DEFAULT_DISPLAY_GROUP); - assertThat(displayInfo.logicalWidth).isAnyOf(600, 200, 700); - assertThat(displayInfo.logicalHeight).isEqualTo(800); - } - } - - @Test - public void testGetDisplayInfoForStateLocked_oneDisplayGroup_differentTypes() { - add(createDisplayDevice(Display.TYPE_INTERNAL, 600, 800, - DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY)); - add(createDisplayDevice(Display.TYPE_INTERNAL, 200, 800, - DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY)); - add(createDisplayDevice(Display.TYPE_EXTERNAL, 700, 800, - DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY)); - - Set<DisplayInfo> displayInfos = mLogicalDisplayMapper.getDisplayInfoForStateLocked( - DeviceStateToLayoutMap.STATE_DEFAULT, DEFAULT_DISPLAY, DEFAULT_DISPLAY_GROUP); - assertThat(displayInfos.size()).isEqualTo(2); - for (DisplayInfo displayInfo : displayInfos) { - assertThat(displayInfo.displayId).isEqualTo(DEFAULT_DISPLAY); - assertThat(displayInfo.displayGroupId).isEqualTo(DEFAULT_DISPLAY_GROUP); - assertThat(displayInfo.logicalWidth).isAnyOf(600, 200); - assertThat(displayInfo.logicalHeight).isEqualTo(800); - } - } - - @Test - public void testGetDisplayInfoForStateLocked_multipleDisplayGroups_defaultGroup() { - add(createDisplayDevice(Display.TYPE_INTERNAL, 600, 800, - DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY)); - add(createDisplayDevice(Display.TYPE_INTERNAL, 200, 800, - DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY)); - add(createDisplayDevice(Display.TYPE_VIRTUAL, 700, 800, - DisplayDeviceInfo.FLAG_OWN_DISPLAY_GROUP)); - - Set<DisplayInfo> displayInfos = mLogicalDisplayMapper.getDisplayInfoForStateLocked( - DeviceStateToLayoutMap.STATE_DEFAULT, DEFAULT_DISPLAY, DEFAULT_DISPLAY_GROUP); - assertThat(displayInfos.size()).isEqualTo(2); - for (DisplayInfo displayInfo : displayInfos) { - assertThat(displayInfo.displayId).isEqualTo(DEFAULT_DISPLAY); - assertThat(displayInfo.displayGroupId).isEqualTo(DEFAULT_DISPLAY_GROUP); - assertThat(displayInfo.logicalWidth).isAnyOf(600, 200); - assertThat(displayInfo.logicalHeight).isEqualTo(800); - } + assertEquals(Display.DEFAULT_DISPLAY, ids[0]); } @Test @@ -265,11 +199,11 @@ public class LogicalDisplayMapperTest { LogicalDisplay display2 = add(createDisplayDevice(Display.TYPE_INTERNAL, 600, 800, 0)); LogicalDisplay display3 = add(createDisplayDevice(Display.TYPE_VIRTUAL, 600, 800, 0)); - assertEquals(DEFAULT_DISPLAY_GROUP, + assertEquals(Display.DEFAULT_DISPLAY_GROUP, mLogicalDisplayMapper.getDisplayGroupIdFromDisplayIdLocked(id(display1))); - assertEquals(DEFAULT_DISPLAY_GROUP, + assertEquals(Display.DEFAULT_DISPLAY_GROUP, mLogicalDisplayMapper.getDisplayGroupIdFromDisplayIdLocked(id(display2))); - assertEquals(DEFAULT_DISPLAY_GROUP, + assertEquals(Display.DEFAULT_DISPLAY_GROUP, mLogicalDisplayMapper.getDisplayGroupIdFromDisplayIdLocked(id(display3))); } @@ -284,11 +218,11 @@ public class LogicalDisplayMapperTest { DisplayDeviceInfo.FLAG_OWN_DISPLAY_GROUP); LogicalDisplay display3 = add(device3); - assertEquals(DEFAULT_DISPLAY_GROUP, + assertEquals(Display.DEFAULT_DISPLAY_GROUP, mLogicalDisplayMapper.getDisplayGroupIdFromDisplayIdLocked(id(display1))); - assertEquals(DEFAULT_DISPLAY_GROUP, + assertEquals(Display.DEFAULT_DISPLAY_GROUP, mLogicalDisplayMapper.getDisplayGroupIdFromDisplayIdLocked(id(display2))); - assertNotEquals(DEFAULT_DISPLAY_GROUP, + assertNotEquals(Display.DEFAULT_DISPLAY_GROUP, mLogicalDisplayMapper.getDisplayGroupIdFromDisplayIdLocked(id(display3))); // Now switch it back to the default group by removing the flag and issuing an update @@ -297,7 +231,7 @@ public class LogicalDisplayMapperTest { mDisplayDeviceRepo.onDisplayDeviceEvent(device3, DISPLAY_DEVICE_EVENT_CHANGED); // Verify the new group is correct. - assertEquals(DEFAULT_DISPLAY_GROUP, + assertEquals(Display.DEFAULT_DISPLAY_GROUP, mLogicalDisplayMapper.getDisplayGroupIdFromDisplayIdLocked(id(display3))); } @@ -353,14 +287,14 @@ public class LogicalDisplayMapperTest { // add LogicalDisplay displayAdded = add(device); assertEquals(info(displayAdded).address, info(device).address); - assertNotEquals(DEFAULT_DISPLAY, id(displayAdded)); + assertNotEquals(Display.DEFAULT_DISPLAY, id(displayAdded)); // remove mDisplayDeviceRepo.onDisplayDeviceEvent(device, DISPLAY_DEVICE_EVENT_REMOVED); verify(mListenerMock).onLogicalDisplayEventLocked( mDisplayCaptor.capture(), eq(LOGICAL_DISPLAY_EVENT_REMOVED)); LogicalDisplay displayRemoved = mDisplayCaptor.getValue(); - assertNotEquals(DEFAULT_DISPLAY, id(displayRemoved)); + assertNotEquals(Display.DEFAULT_DISPLAY, id(displayRemoved)); } /** diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java index 976a588273a7..18992ecfd3a4 100644 --- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java @@ -16,6 +16,8 @@ package com.android.server.pm; +import static com.android.compatibility.common.util.ShellUtils.runShellCommand; + import static com.google.common.truth.Truth.assertWithMessage; import static org.junit.Assert.fail; @@ -27,9 +29,12 @@ import static java.lang.reflect.Modifier.isPublic; import static java.lang.reflect.Modifier.isStatic; import android.annotation.Nullable; +import android.app.AppGlobals; import android.content.IIntentReceiver; +import android.content.pm.IPackageManager; import android.content.pm.PackageManagerInternal; import android.os.Bundle; +import android.os.UserHandle; import android.util.SparseArray; import androidx.test.runner.AndroidJUnit4; @@ -62,8 +67,18 @@ import java.util.regex.Pattern; // bit FrameworksServicesTests:com.android.server.pm.PackageManagerServiceTest @RunWith(AndroidJUnit4.class) public class PackageManagerServiceTest { + + private static final String PACKAGE_NAME = "com.android.frameworks.servicestests"; + + private static final String TEST_DATA_PATH = "/data/local/tmp/servicestests/"; + private static final String TEST_APP_APK = "StubTestApp.apk"; + private static final String TEST_PKG_NAME = "com.android.servicestests.apps.stubapp"; + + private IPackageManager mIPackageManager; + @Before public void setUp() throws Exception { + mIPackageManager = AppGlobals.getPackageManager(); } @After @@ -599,4 +614,26 @@ public class PackageManagerServiceTest { Collections.sort(knownPackageIds); return knownPackageIds; } + + @Test + public void testSetSplashScreenTheme_samePackage_succeeds() throws Exception { + mIPackageManager.setSplashScreenTheme(PACKAGE_NAME, null /* themeName */, + UserHandle.myUserId()); + // Invoking setSplashScreenTheme on the same package shouldn't get any exception. + } + + @Test + public void testSetSplashScreenTheme_differentPackage_fails() throws Exception { + final File testApk = new File(TEST_DATA_PATH, TEST_APP_APK); + try { + runShellCommand("pm install " + testApk); + mIPackageManager.setSplashScreenTheme(TEST_PKG_NAME, null /* themeName */, + UserHandle.myUserId()); + fail("setSplashScreenTheme did not throw SecurityException as expected"); + } catch (SecurityException e) { + // expected + } finally { + runShellCommand("pm uninstall " + TEST_PKG_NAME); + } + } } diff --git a/services/tests/servicestests/test-apps/StubApp/Android.bp b/services/tests/servicestests/test-apps/StubApp/Android.bp new file mode 100644 index 000000000000..99deb3f5bbf0 --- /dev/null +++ b/services/tests/servicestests/test-apps/StubApp/Android.bp @@ -0,0 +1,37 @@ +// 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 { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + +android_test_helper_app { + name: "StubTestApp", + + sdk_version: "current", + + srcs: ["**/*.java"], + + dex_preopt: { + enabled: false, + }, + optimize: { + enabled: false, + }, +} diff --git a/services/tests/servicestests/test-apps/StubApp/AndroidManifest.xml b/services/tests/servicestests/test-apps/StubApp/AndroidManifest.xml new file mode 100644 index 000000000000..90172e77f958 --- /dev/null +++ b/services/tests/servicestests/test-apps/StubApp/AndroidManifest.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. +--> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.servicestests.apps.stubapp"> + + <application android:label="StubTestApp"> + <activity android:name=".TestActivity" + android:exported="true" /> + </application> + +</manifest>
\ No newline at end of file diff --git a/services/tests/servicestests/test-apps/StubApp/src/com/android/servicestests/apps/stubapp/TestActivity.java b/services/tests/servicestests/test-apps/StubApp/src/com/android/servicestests/apps/stubapp/TestActivity.java new file mode 100644 index 000000000000..0d94676aeb52 --- /dev/null +++ b/services/tests/servicestests/test-apps/StubApp/src/com/android/servicestests/apps/stubapp/TestActivity.java @@ -0,0 +1,22 @@ +/* + * 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.servicestests.apps.stubapp; + +import android.app.Activity; + +public class TestActivity extends Activity { +} diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java index fc2c162d058b..707e463424ae 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java @@ -1779,11 +1779,6 @@ public class ActivityRecordTests extends WindowTestsBase { anyInt() /* orientation */, anyInt() /* lastRotation */); // Set to visible so the activity can freeze the screen. activity.setVisibility(true); - // Update the display policy to make the screen fully turned on so the freeze is allowed - display.getDisplayPolicy().screenTurnedOn(null); - display.getDisplayPolicy().finishKeyguardDrawn(); - display.getDisplayPolicy().finishWindowsDrawn(); - display.getDisplayPolicy().finishScreenTurningOn(); display.rotateInDifferentOrientationIfNeeded(activity); display.setFixedRotationLaunchingAppUnchecked(activity); diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java index 6fa306b004a2..506270657e42 100644 --- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java @@ -334,6 +334,18 @@ public class AppTransitionControllerTest extends WindowTestsBase { } @Test + public void testExitAnimationDone_beforeAppTransition() { + final Task task = createTask(mDisplayContent); + final WindowState win = createAppWindow(task, ACTIVITY_TYPE_STANDARD, "Win"); + spyOn(win); + win.mAnimatingExit = true; + mDisplayContent.mAppTransition.setTimeout(); + mDisplayContent.mAppTransitionController.handleAppTransitionReady(); + + verify(win).onExitAnimationDone(); + } + + @Test public void testGetAnimationTargets_windowsAreBeingReplaced() { // [DisplayContent] -+- [Task1] - [ActivityRecord1] (opening, visible) // +- [AppWindow1] (being-replaced) diff --git a/services/tests/wmtests/src/com/android/server/wm/InputMethodMenuControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/InputMethodMenuControllerTest.java index d7daa57cc9da..407f9cfdbe3e 100644 --- a/services/tests/wmtests/src/com/android/server/wm/InputMethodMenuControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/InputMethodMenuControllerTest.java @@ -17,6 +17,7 @@ package com.android.server.wm; import static android.view.Display.DEFAULT_DISPLAY; +import static android.view.Display.STATE_ON; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer; @@ -70,7 +71,7 @@ public class InputMethodMenuControllerTest extends WindowTestsBase { @Before public void setUp() throws Exception { - // Let the Display to be created with the DualDisplay policy. + // Let the Display be created with the DualDisplay policy. final DisplayAreaPolicy.Provider policyProvider = new DualDisplayAreaGroupPolicyTest.DualDisplayTestPolicyProvider(); Mockito.doReturn(policyProvider).when(mWm).getDisplayAreaPolicyProvider(); @@ -78,6 +79,7 @@ public class InputMethodMenuControllerTest extends WindowTestsBase { mController = new InputMethodMenuController(mock(InputMethodManagerService.class)); mSecondaryDisplay = new DualDisplayAreaGroupPolicyTest.DualDisplayContent .Builder(mAtm, 1000, 1000).build(); + mSecondaryDisplay.getDisplayInfo().state = STATE_ON; // Mock addWindowTokenWithOptions to create a test window token. mIWindowManager = WindowManagerGlobal.getWindowManagerService(); diff --git a/services/tests/wmtests/src/com/android/server/wm/PossibleDisplayInfoMapperTests.java b/services/tests/wmtests/src/com/android/server/wm/PossibleDisplayInfoMapperTests.java deleted file mode 100644 index 6e0056821aab..000000000000 --- a/services/tests/wmtests/src/com/android/server/wm/PossibleDisplayInfoMapperTests.java +++ /dev/null @@ -1,182 +0,0 @@ -/* - * 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.server.wm; - -import static android.view.Display.DEFAULT_DISPLAY; -import static android.view.Display.FLAG_PRESENTATION; -import static android.view.Surface.ROTATION_0; -import static android.view.Surface.ROTATION_180; - -import static com.google.common.truth.Truth.assertThat; - -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.Mockito.when; - -import android.graphics.Rect; -import android.platform.test.annotations.Presubmit; -import android.util.ArraySet; -import android.view.DisplayInfo; - -import androidx.test.filters.MediumTest; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.util.Set; - - -/** - * Tests for {@link PossibleDisplayInfoMapper}. - * - * Build/Install/Run: - * atest WmTests:PossibleDisplayInfoMapperTests - */ -@MediumTest -@Presubmit -@RunWith(WindowTestRunner.class) -public class PossibleDisplayInfoMapperTests extends WindowTestsBase { - - private PossibleDisplayInfoMapper mDisplayInfoMapper; - private final Set<DisplayInfo> mPossibleDisplayInfo = new ArraySet<>(); - private DisplayInfo mDefaultDisplayInfo; - private DisplayInfo mSecondDisplayInfo; - - @Before - public void setUp() throws Exception { - mDisplayInfoMapper = mWm.mPossibleDisplayInfoMapper; - final DisplayInfo baseDisplayInfo = mWm.mRoot.getDisplayContent( - DEFAULT_DISPLAY).getDisplayInfo(); - when(mWm.mDisplayManagerInternal.getPossibleDisplayInfo(anyInt())).thenReturn( - mPossibleDisplayInfo); - - mDefaultDisplayInfo = new DisplayInfo(baseDisplayInfo); - initializeDisplayInfo(mDefaultDisplayInfo, DEFAULT_DISPLAY, new Rect(0, 0, 500, 800)); - mSecondDisplayInfo = new DisplayInfo(baseDisplayInfo); - // Use the same display id for any display in the same group, due to the assumption that - // any display in the same grouped can be swapped out for each other (while maintaining the - // display id). - initializeDisplayInfo(mSecondDisplayInfo, DEFAULT_DISPLAY, new Rect(0, 0, 600, 1600)); - mSecondDisplayInfo.flags |= FLAG_PRESENTATION; - } - - @Test - public void testInitialization_isEmpty() { - // Empty after initializing. - assertThat(mDisplayInfoMapper.getPossibleDisplayInfos(DEFAULT_DISPLAY)).isEmpty(); - - // Still empty after updating. - mDisplayInfoMapper.updatePossibleDisplayInfos(DEFAULT_DISPLAY); - assertThat(mDisplayInfoMapper.getPossibleDisplayInfos(DEFAULT_DISPLAY)).isEmpty(); - } - - @Test - public void testUpdatePossibleDisplayInfos_singleDisplay() { - mPossibleDisplayInfo.add(mDefaultDisplayInfo); - mDisplayInfoMapper.updatePossibleDisplayInfos(DEFAULT_DISPLAY); - - Set<DisplayInfo> displayInfos = mDisplayInfoMapper.getPossibleDisplayInfos(DEFAULT_DISPLAY); - // An entry for each possible rotation, for a display that can be in a single state. - assertThat(displayInfos.size()).isEqualTo(4); - assertPossibleDisplayInfoEntries(displayInfos, mDefaultDisplayInfo); - } - - @Test - public void testUpdatePossibleDisplayInfos_secondDisplayAdded_sameGroup() { - mPossibleDisplayInfo.add(mDefaultDisplayInfo); - mDisplayInfoMapper.updatePossibleDisplayInfos(DEFAULT_DISPLAY); - - assertThat(mDisplayInfoMapper.getPossibleDisplayInfos(DEFAULT_DISPLAY).size()).isEqualTo(4); - - // Add another display layout to the set of supported states. - mPossibleDisplayInfo.add(mSecondDisplayInfo); - mDisplayInfoMapper.updatePossibleDisplayInfos(DEFAULT_DISPLAY); - - Set<DisplayInfo> displayInfos = mDisplayInfoMapper.getPossibleDisplayInfos(DEFAULT_DISPLAY); - Set<DisplayInfo> defaultDisplayInfos = new ArraySet<>(); - Set<DisplayInfo> secondDisplayInfos = new ArraySet<>(); - for (DisplayInfo di : displayInfos) { - if ((di.flags & FLAG_PRESENTATION) != 0) { - secondDisplayInfos.add(di); - } else { - defaultDisplayInfos.add(di); - } - } - // An entry for each possible rotation, for the default display. - assertThat(defaultDisplayInfos).hasSize(4); - assertPossibleDisplayInfoEntries(defaultDisplayInfos, mDefaultDisplayInfo); - - // An entry for each possible rotation, for the second display. - assertThat(secondDisplayInfos).hasSize(4); - assertPossibleDisplayInfoEntries(secondDisplayInfos, mSecondDisplayInfo); - } - - @Test - public void testUpdatePossibleDisplayInfos_secondDisplayAdded_differentGroup() { - mPossibleDisplayInfo.add(mDefaultDisplayInfo); - mDisplayInfoMapper.updatePossibleDisplayInfos(DEFAULT_DISPLAY); - - assertThat(mDisplayInfoMapper.getPossibleDisplayInfos(DEFAULT_DISPLAY).size()).isEqualTo(4); - - // Add another display to a different group. - mSecondDisplayInfo.displayId = DEFAULT_DISPLAY + 1; - mSecondDisplayInfo.displayGroupId = mDefaultDisplayInfo.displayGroupId + 1; - mPossibleDisplayInfo.add(mSecondDisplayInfo); - mDisplayInfoMapper.updatePossibleDisplayInfos(mSecondDisplayInfo.displayId); - - Set<DisplayInfo> displayInfos = mDisplayInfoMapper.getPossibleDisplayInfos(DEFAULT_DISPLAY); - // An entry for each possible rotation, for the default display. - assertThat(displayInfos).hasSize(4); - assertPossibleDisplayInfoEntries(displayInfos, mDefaultDisplayInfo); - - Set<DisplayInfo> secondStateEntries = - mDisplayInfoMapper.getPossibleDisplayInfos(mSecondDisplayInfo.displayId); - // An entry for each possible rotation, for the second display. - assertThat(secondStateEntries).hasSize(4); - assertPossibleDisplayInfoEntries(secondStateEntries, mSecondDisplayInfo); - } - - private static void initializeDisplayInfo(DisplayInfo outDisplayInfo, int displayId, - Rect logicalBounds) { - outDisplayInfo.displayId = displayId; - outDisplayInfo.rotation = ROTATION_0; - outDisplayInfo.logicalWidth = logicalBounds.width(); - outDisplayInfo.logicalHeight = logicalBounds.height(); - } - - private static void assertPossibleDisplayInfoEntries(Set<DisplayInfo> displayInfos, - DisplayInfo expectedDisplayInfo) { - boolean[] seenEveryRotation = new boolean[4]; - for (DisplayInfo displayInfo : displayInfos) { - final int rotation = displayInfo.rotation; - seenEveryRotation[rotation] = true; - assertThat(displayInfo.displayId).isEqualTo(expectedDisplayInfo.displayId); - assertEqualsRotatedDisplayInfo(displayInfo, expectedDisplayInfo); - } - assertThat(seenEveryRotation).isEqualTo(new boolean[]{true, true, true, true}); - } - - private static void assertEqualsRotatedDisplayInfo(DisplayInfo actual, DisplayInfo expected) { - if (actual.rotation == ROTATION_0 || actual.rotation == ROTATION_180) { - assertThat(actual.logicalWidth).isEqualTo(expected.logicalWidth); - assertThat(actual.logicalHeight).isEqualTo(expected.logicalHeight); - } else { - assertThat(actual.logicalWidth).isEqualTo(expected.logicalHeight); - assertThat(actual.logicalHeight).isEqualTo(expected.logicalWidth); - } - } -} diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java index d68edbafb592..cdf6b59d4737 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java @@ -84,7 +84,7 @@ public class TaskDisplayAreaTests extends WindowTestsBase { mDisplayContent, WINDOWING_MODE_MULTI_WINDOW, ACTIVITY_TYPE_STANDARD); adjacentRootTask.mCreatedByOrganizer = true; final TaskDisplayArea taskDisplayArea = rootTask.getDisplayArea(); - adjacentRootTask.setAdjacentTaskFragment(rootTask); + adjacentRootTask.setAdjacentTaskFragment(rootTask, false /* moveTogether */); taskDisplayArea.setLaunchAdjacentFlagRootTask(adjacentRootTask); Task actualRootTask = taskDisplayArea.getLaunchRootTask( @@ -110,7 +110,7 @@ public class TaskDisplayAreaTests extends WindowTestsBase { final Task adjacentRootTask = createTask( mDisplayContent, WINDOWING_MODE_MULTI_WINDOW, ACTIVITY_TYPE_STANDARD); adjacentRootTask.mCreatedByOrganizer = true; - adjacentRootTask.setAdjacentTaskFragment(rootTask); + adjacentRootTask.setAdjacentTaskFragment(rootTask, false /* moveTogether */); taskDisplayArea.setLaunchRootTask(rootTask, new int[]{WINDOWING_MODE_MULTI_WINDOW}, new int[]{ACTIVITY_TYPE_STANDARD}); @@ -131,7 +131,7 @@ public class TaskDisplayAreaTests extends WindowTestsBase { mDisplayContent, WINDOWING_MODE_MULTI_WINDOW, ACTIVITY_TYPE_STANDARD); adjacentRootTask.mCreatedByOrganizer = true; final TaskDisplayArea taskDisplayArea = rootTask.getDisplayArea(); - adjacentRootTask.setAdjacentTaskFragment(rootTask); + adjacentRootTask.setAdjacentTaskFragment(rootTask, false /* moveTogether */); taskDisplayArea.setLaunchAdjacentFlagRootTask(adjacentRootTask); final Task actualRootTask = taskDisplayArea.getLaunchRootTask( diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java index 7014851ee210..dcaf9d7ae434 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java @@ -330,7 +330,7 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase { // Throw exception if the transaction is trying to change a window that is not organized by // the organizer. - mTransaction.setAdjacentRoots(mFragmentWindowToken, token2); + mTransaction.setAdjacentRoots(mFragmentWindowToken, token2, false /* moveTogether */); assertThrows(SecurityException.class, () -> { try { diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java index 6737b1ade785..730275cde40b 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java @@ -16,11 +16,14 @@ package com.android.server.wm; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.any; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.never; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.mockito.Mockito.clearInvocations; import android.graphics.Rect; @@ -91,6 +94,7 @@ public class TaskFragmentTest extends WindowTestsBase { final Rect endBounds = new Rect(500, 500, 1000, 1000); mTaskFragment.setBounds(startBounds); doReturn(true).when(mTaskFragment).isVisible(); + doReturn(true).when(mTaskFragment).isVisibleRequested(); clearInvocations(mTransaction); mTaskFragment.setBounds(endBounds); @@ -108,6 +112,25 @@ public class TaskFragmentTest extends WindowTestsBase { verify(mTransaction).setWindowCrop(mLeash, 500, 500); } + @Test + public void testNotOkToAnimate_doNotStartChangeTransition() { + mockSurfaceFreezerSnapshot(mTaskFragment.mSurfaceFreezer); + final Rect startBounds = new Rect(0, 0, 1000, 1000); + final Rect endBounds = new Rect(500, 500, 1000, 1000); + mTaskFragment.setBounds(startBounds); + doReturn(true).when(mTaskFragment).isVisible(); + doReturn(true).when(mTaskFragment).isVisibleRequested(); + + final DisplayPolicy displayPolicy = mDisplayContent.getDisplayPolicy(); + displayPolicy.screenTurnedOff(); + + assertFalse(mTaskFragment.okToAnimate()); + + mTaskFragment.setBounds(endBounds); + + verify(mTaskFragment, never()).initializeChangeTransition(any()); + } + /** * Tests that when a {@link TaskFragmentInfo} is generated from a {@link TaskFragment}, an * activity that has not yet been attached to a process because it is being initialized but diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java index ce568f152a5f..8c1045d995d6 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java @@ -59,6 +59,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.ArgumentMatchers.same; import static org.mockito.Mockito.atLeast; import static org.mockito.Mockito.clearInvocations; @@ -1365,6 +1366,25 @@ public class TaskTests extends WindowTestsBase { assertNotNull(activity.getTask().getDimmer()); } + @Test + public void testMoveToFront_moveAdjacentTask() { + final Task task1 = + createTask(mDisplayContent, WINDOWING_MODE_MULTI_WINDOW, ACTIVITY_TYPE_STANDARD); + final Task task2 = + createTask(mDisplayContent, WINDOWING_MODE_MULTI_WINDOW, ACTIVITY_TYPE_STANDARD); + spyOn(task2); + + task1.setAdjacentTaskFragment(task2, false /* moveTogether */); + task1.moveToFront("" /* reason */); + verify(task2, never()).moveToFrontInner(anyString(), isNull()); + + // Reset adjacent tasks to move together. + task1.setAdjacentTaskFragment(null, false /* moveTogether */); + task1.setAdjacentTaskFragment(task2, true /* moveTogether */); + task1.moveToFront("" /* reason */); + verify(task2).moveToFrontInner(anyString(), isNull()); + } + private Task getTestTask() { final Task task = new TaskBuilder(mSupervisor).setCreateActivity(true).build(); return task.getBottomMostTask(); diff --git a/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java b/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java index 0e504d326280..e0f69d4f2eaf 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java +++ b/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java @@ -165,6 +165,11 @@ class TestDisplayContent extends DisplayContent { doReturn(false).when(displayPolicy).hasStatusBar(); doReturn(false).when(newDisplay).supportsSystemDecorations(); } + // Update the display policy to make the screen fully turned on so animation is allowed + displayPolicy.screenTurnedOn(null /* screenOnListener */); + displayPolicy.finishKeyguardDrawn(); + displayPolicy.finishWindowsDrawn(); + displayPolicy.finishScreenTurningOn(); if (mStatusBarHeight > 0) { doReturn(true).when(displayPolicy).hasStatusBar(); doAnswer(invocation -> { diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowContextListenerControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowContextListenerControllerTests.java index e5eba57f223d..646647fcc4ca 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowContextListenerControllerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowContextListenerControllerTests.java @@ -17,22 +17,35 @@ package com.android.server.wm; import static android.view.Display.DEFAULT_DISPLAY; +import static android.view.Display.STATE_OFF; +import static android.view.Display.STATE_ON; import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG; +import static android.window.WindowProvider.KEY_IS_WINDOW_PROVIDER_SERVICE; + +import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; 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.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; import android.app.IWindowToken; import android.content.res.Configuration; import android.graphics.Rect; import android.os.Binder; +import android.os.Bundle; import android.os.IBinder; import android.platform.test.annotations.Presubmit; +import android.view.Display; +import android.view.DisplayInfo; import androidx.test.filters.SmallTest; @@ -55,12 +68,15 @@ public class WindowContextListenerControllerTests extends WindowTestsBase { private static final int ANOTHER_UID = 1000; private final IBinder mClientToken = new Binder(); - private WindowContainer mContainer; + private WindowContainer<?> mContainer; @Before public void setUp() { mController = new WindowContextListenerController(); mContainer = createTestWindowToken(TYPE_APPLICATION_OVERLAY, mDisplayContent); + // Make display on to verify configuration propagation. + mDefaultDisplay.getDisplayInfo().state = STATE_ON; + mDisplayContent.getDisplayInfo().state = STATE_ON; } @Test @@ -76,7 +92,7 @@ public class WindowContextListenerControllerTests extends WindowTestsBase { assertEquals(2, mController.mListeners.size()); - final WindowContainer container = createTestWindowToken(TYPE_APPLICATION_OVERLAY, + final WindowContainer<?> container = createTestWindowToken(TYPE_APPLICATION_OVERLAY, mDefaultDisplay); mController.registerWindowContainerListener(mClientToken, container, -1, TYPE_APPLICATION_OVERLAY, null /* options */); @@ -89,6 +105,7 @@ public class WindowContextListenerControllerTests extends WindowTestsBase { assertEquals(container, listener.getWindowContainer()); } + @UseTestDisplay @Test public void testRegisterWindowContextListenerClientConfigPropagation() { final TestWindowTokenClient clientToken = new TestWindowTokenClient(); @@ -107,7 +124,7 @@ public class WindowContextListenerControllerTests extends WindowTestsBase { assertEquals(mDisplayContent.mDisplayId, clientToken.mDisplayId); // Update the WindowContainer. - final WindowContainer container = createTestWindowToken(TYPE_APPLICATION_OVERLAY, + final WindowContainer<?> container = createTestWindowToken(TYPE_APPLICATION_OVERLAY, mDefaultDisplay); final Configuration config2 = container.getConfiguration(); final Rect bounds2 = new Rect(0, 0, 20, 20); @@ -174,7 +191,7 @@ public class WindowContextListenerControllerTests extends WindowTestsBase { .setDisplayContent(mDefaultDisplay) .setFromClientToken(true) .build(); - final DisplayArea da = windowContextCreatedToken.getDisplayArea(); + final DisplayArea<?> da = windowContextCreatedToken.getDisplayArea(); mController.registerWindowContainerListener(mClientToken, windowContextCreatedToken, TEST_UID, TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY, null /* options */); @@ -192,11 +209,12 @@ public class WindowContextListenerControllerTests extends WindowTestsBase { // Let the Display to be created with the DualDisplay policy. final DisplayAreaPolicy.Provider policyProvider = new DualDisplayAreaGroupPolicyTest.DualDisplayTestPolicyProvider(); - Mockito.doReturn(policyProvider).when(mWm).getDisplayAreaPolicyProvider(); + doReturn(policyProvider).when(mWm).getDisplayAreaPolicyProvider(); // Create a DisplayContent with dual RootDisplayArea DualDisplayAreaGroupPolicyTest.DualDisplayContent dualDisplayContent = new DualDisplayAreaGroupPolicyTest.DualDisplayContent .Builder(mAtm, 1000, 1000).build(); + dualDisplayContent.getDisplayInfo().state = STATE_ON; final DisplayArea.Tokens imeContainer = dualDisplayContent.getImeContainer(); // Put the ImeContainer to the first sub-RootDisplayArea dualDisplayContent.mFirstRoot.placeImeContainer(imeContainer); @@ -222,7 +240,62 @@ public class WindowContextListenerControllerTests extends WindowTestsBase { assertThat(mController.getContainer(mClientToken)).isEqualTo(imeContainer); } - private class TestWindowTokenClient extends IWindowToken.Stub { + @Test + public void testConfigUpdateForSuspendedWindowContext() { + final TestWindowTokenClient mockToken = new TestWindowTokenClient(); + spyOn(mockToken); + + mContainer.getDisplayContent().getDisplayInfo().state = STATE_OFF; + + final Configuration config1 = mContainer.getConfiguration(); + final Rect bounds1 = new Rect(0, 0, 10, 10); + config1.windowConfiguration.setBounds(bounds1); + config1.densityDpi = 100; + mContainer.onRequestedOverrideConfigurationChanged(config1); + + mController.registerWindowContainerListener(mockToken, mContainer, -1, + TYPE_APPLICATION_OVERLAY, null /* options */); + + verify(mockToken, never()).onConfigurationChanged(any(), anyInt()); + + // Turn on the display and verify if the client receive the callback + Display display = mContainer.getDisplayContent().getDisplay(); + spyOn(display); + Mockito.doAnswer(invocation -> { + final DisplayInfo info = mContainer.getDisplayContent().getDisplayInfo(); + info.state = STATE_ON; + ((DisplayInfo) invocation.getArgument(0)).copyFrom(info); + return null; + }).when(display).getDisplayInfo(any(DisplayInfo.class)); + + mContainer.getDisplayContent().onDisplayChanged(); + + assertThat(mockToken.mConfiguration).isEqualTo(config1); + assertThat(mockToken.mDisplayId).isEqualTo(mContainer.getDisplayContent().getDisplayId()); + } + + @Test + public void testReportConfigUpdateForSuspendedWindowProviderService() { + final TestWindowTokenClient clientToken = new TestWindowTokenClient(); + final Bundle options = new Bundle(); + options.putBoolean(KEY_IS_WINDOW_PROVIDER_SERVICE, true); + + mContainer.getDisplayContent().getDisplayInfo().state = STATE_OFF; + + final Configuration config1 = mContainer.getConfiguration(); + final Rect bounds1 = new Rect(0, 0, 10, 10); + config1.windowConfiguration.setBounds(bounds1); + config1.densityDpi = 100; + mContainer.onRequestedOverrideConfigurationChanged(config1); + + mController.registerWindowContainerListener(clientToken, mContainer, -1, + TYPE_APPLICATION_OVERLAY, options); + + assertThat(clientToken.mConfiguration).isEqualTo(config1); + assertThat(clientToken.mDisplayId).isEqualTo(mDisplayContent.mDisplayId); + } + + private static class TestWindowTokenClient extends IWindowToken.Stub { private Configuration mConfiguration; private int mDisplayId; private boolean mRemoved; diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java index 1eed79f189a8..75a87ba9e04d 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java @@ -554,7 +554,7 @@ public class WindowOrganizerTests extends WindowTestsBase { final RunningTaskInfo info2 = task2.getTaskInfo(); WindowContainerTransaction wct = new WindowContainerTransaction(); - wct.setAdjacentRoots(info1.token, info2.token); + wct.setAdjacentRoots(info1.token, info2.token, false /* moveTogether */); mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct); assertEquals(task1.getAdjacentTaskFragment(), task2); assertEquals(task2.getAdjacentTaskFragment(), task1); @@ -564,8 +564,8 @@ public class WindowOrganizerTests extends WindowTestsBase { mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct); assertEquals(dc.getDefaultTaskDisplayArea().mLaunchAdjacentFlagRootTask, task1); - task1.setAdjacentTaskFragment(null); - task2.setAdjacentTaskFragment(null); + task1.setAdjacentTaskFragment(null, false /* moveTogether */); + task2.setAdjacentTaskFragment(null, false /* moveTogether */); wct = new WindowContainerTransaction(); wct.clearLaunchAdjacentFlagRoot(info1.token); mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct); diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java index 88d8ba308b45..b997acfaadcf 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java @@ -200,6 +200,13 @@ class WindowTestsBase extends SystemServiceTestsBase { SystemServicesTestRule.checkHoldsLock(mWm.mGlobalLock); mDefaultDisplay = mWm.mRoot.getDefaultDisplay(); + // Update the display policy to make the screen fully turned on so animation is allowed + final DisplayPolicy displayPolicy = mDefaultDisplay.getDisplayPolicy(); + displayPolicy.screenTurnedOn(null /* screenOnListener */); + displayPolicy.finishKeyguardDrawn(); + displayPolicy.finishWindowsDrawn(); + displayPolicy.finishScreenTurningOn(); + mTransaction = mSystemServicesTestRule.mTransaction; mMockSession = mock(Session.class); diff --git a/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java b/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java index b3ba217955ea..049966c7310d 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java @@ -23,7 +23,6 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; -import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG; @@ -490,8 +489,8 @@ public class ZOrderingTests extends WindowTestsBase { createTask(mDisplayContent, WINDOWING_MODE_MULTI_WINDOW, ACTIVITY_TYPE_STANDARD); final WindowState splitWindow2 = createAppWindow(splitScreenTask2, ACTIVITY_TYPE_STANDARD, "splitWindow2"); - splitScreenTask1.setAdjacentTaskFragment(splitScreenTask2); - splitScreenTask2.setAdjacentTaskFragment(splitScreenTask1); + splitScreenTask1.setAdjacentTaskFragment(splitScreenTask2, true /* moveTogether */); + splitScreenTask2.setAdjacentTaskFragment(splitScreenTask1, true /* moveTogether */); final Task aboveTask = createTask(mDisplayContent, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD); @@ -501,8 +500,6 @@ public class ZOrderingTests extends WindowTestsBase { mDisplayContent.assignChildLayers(mTransaction); assertWindowHigher(splitWindow1, belowTaskWindow); - assertWindowHigher(splitWindow1, belowTaskWindow); - assertWindowHigher(splitWindow2, belowTaskWindow); assertWindowHigher(splitWindow2, belowTaskWindow); assertWindowHigher(mDockedDividerWindow, splitWindow1); assertWindowHigher(mDockedDividerWindow, splitWindow2); @@ -510,6 +507,39 @@ public class ZOrderingTests extends WindowTestsBase { assertWindowHigher(pinnedWindow, aboveTaskWindow); } + + @Test + public void testDockedDividerPosition_noAboveTask() { + final Task pinnedTask = + createTask(mDisplayContent, WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD); + final WindowState pinnedWindow = + createAppWindow(pinnedTask, ACTIVITY_TYPE_STANDARD, "pinnedWindow"); + + final Task belowTask = + createTask(mDisplayContent, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD); + final WindowState belowTaskWindow = + createAppWindow(belowTask, ACTIVITY_TYPE_STANDARD, "belowTaskWindow"); + + final Task splitScreenTask1 = + createTask(mDisplayContent, WINDOWING_MODE_MULTI_WINDOW, ACTIVITY_TYPE_STANDARD); + final WindowState splitWindow1 = + createAppWindow(splitScreenTask1, ACTIVITY_TYPE_STANDARD, "splitWindow1"); + final Task splitScreenTask2 = + createTask(mDisplayContent, WINDOWING_MODE_MULTI_WINDOW, ACTIVITY_TYPE_STANDARD); + final WindowState splitWindow2 = + createAppWindow(splitScreenTask2, ACTIVITY_TYPE_STANDARD, "splitWindow2"); + splitScreenTask1.setAdjacentTaskFragment(splitScreenTask2, true /* moveTogether */); + splitScreenTask2.setAdjacentTaskFragment(splitScreenTask1, true /* moveTogether */); + + mDisplayContent.assignChildLayers(mTransaction); + + assertWindowHigher(splitWindow1, belowTaskWindow); + assertWindowHigher(splitWindow2, belowTaskWindow); + assertWindowHigher(mDockedDividerWindow, splitWindow1); + assertWindowHigher(mDockedDividerWindow, splitWindow2); + assertWindowHigher(pinnedWindow, mDockedDividerWindow); + } + @Test public void testAttachNavBarWhenEnteringRecents_expectNavBarHigherThanIme() { // create RecentsAnimationController |