diff options
301 files changed, 6748 insertions, 1856 deletions
diff --git a/core/api/current.txt b/core/api/current.txt index 9a16390baf10..1d03370e698d 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -1298,7 +1298,7 @@ package android { field public static final int shortcutLongLabel = 16844074; // 0x101052a field public static final int shortcutShortLabel = 16844073; // 0x1010529 field public static final int shouldDisableView = 16843246; // 0x10101ee - field public static final int shouldUseDefaultDeviceStateChangeTransition; + field public static final int shouldUseDefaultDisplayStateChangeTransition; field public static final int showAsAction = 16843481; // 0x10102d9 field public static final int showDefault = 16843258; // 0x10101fa field public static final int showDividers = 16843561; // 0x1010329 @@ -6927,7 +6927,7 @@ package android.app { method public android.graphics.drawable.Drawable loadIcon(android.content.pm.PackageManager); method public CharSequence loadLabel(android.content.pm.PackageManager); method public android.graphics.drawable.Drawable loadThumbnail(android.content.pm.PackageManager); - method public boolean shouldUseDefaultDeviceStateChangeTransition(); + method public boolean shouldUseDefaultDisplayStateChangeTransition(); method public boolean supportsMultipleDisplays(); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.app.WallpaperInfo> CREATOR; diff --git a/core/api/test-current.txt b/core/api/test-current.txt index d484100373af..887f7617a17f 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -448,6 +448,7 @@ package android.app.admin { method @RequiresPermission("android.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS") public void resetDefaultCrossProfileIntentFilters(int); method @RequiresPermission(allOf={"android.permission.MANAGE_DEVICE_ADMINS", android.Manifest.permission.INTERACT_ACROSS_USERS_FULL}) public void setActiveAdmin(@NonNull android.content.ComponentName, boolean, int); method @RequiresPermission("android.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS") public boolean setDeviceOwner(@NonNull android.content.ComponentName, @Nullable String, int); + method @RequiresPermission("android.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS") public boolean setDeviceOwnerOnly(@NonNull android.content.ComponentName, @Nullable String, int); method @RequiresPermission("android.permission.MANAGE_DEVICE_ADMINS") public void setNextOperationSafety(int, int); field public static final String ACTION_DATA_SHARING_RESTRICTION_APPLIED = "android.app.action.DATA_SHARING_RESTRICTION_APPLIED"; field public static final String ACTION_DEVICE_POLICY_CONSTANTS_CHANGED = "android.app.action.DEVICE_POLICY_CONSTANTS_CHANGED"; diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 12025f98ada8..22091fcde86f 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -2507,12 +2507,11 @@ public class Activity extends ContextThemeWrapper * * <p>To get the voice interactor you need to call {@link #getVoiceInteractor()} * which would return non <code>null</code> only if there is an ongoing voice - * interaction session. You an also detect when the voice interactor is no + * interaction session. You can also detect when the voice interactor is no * longer valid because the voice interaction session that is backing is finished * by calling {@link VoiceInteractor#registerOnDestroyedCallback(Executor, Runnable)}. * - * <p>This method will be called only after {@link #onStart()} is being called and - * before {@link #onStop()} is being called. + * <p>This method will be called only after {@link #onStart()} and before {@link #onStop()}. * * <p>You should pass to the callback the currently supported direct actions which * cannot be <code>null</code> or contain <code>null</code> elements. diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 80554d7939f2..d0680f8c9268 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -526,9 +526,6 @@ public final class ActivityThread extends ClientTransactionHandler // A reusable token for other purposes, e.g. content capture, translation. It shouldn't be // used without security checks public IBinder shareableActivityToken; - // The token of the initial TaskFragment that embedded this activity. Do not rely on it - // after creation because the activity could be reparented. - @Nullable public IBinder mInitialTaskFragmentToken; int ident; @UnsupportedAppUsage Intent intent; @@ -622,8 +619,7 @@ public final class ActivityThread extends ClientTransactionHandler List<ReferrerIntent> pendingNewIntents, ActivityOptions activityOptions, boolean isForward, ProfilerInfo profilerInfo, ClientTransactionHandler client, IBinder assistToken, FixedRotationAdjustments fixedRotationAdjustments, - IBinder shareableActivityToken, boolean launchedFromBubble, - IBinder initialTaskFragmentToken) { + IBinder shareableActivityToken, boolean launchedFromBubble) { this.token = token; this.assistToken = assistToken; this.shareableActivityToken = shareableActivityToken; @@ -645,7 +641,6 @@ public final class ActivityThread extends ClientTransactionHandler mActivityOptions = activityOptions; mPendingFixedRotationAdjustments = fixedRotationAdjustments; mLaunchedFromBubble = launchedFromBubble; - mInitialTaskFragmentToken = initialTaskFragmentToken; init(); } diff --git a/core/java/android/app/ActivityTransitionCoordinator.java b/core/java/android/app/ActivityTransitionCoordinator.java index 4b87a647a80b..f5b3b40d88d6 100644 --- a/core/java/android/app/ActivityTransitionCoordinator.java +++ b/core/java/android/app/ActivityTransitionCoordinator.java @@ -871,6 +871,7 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver { if (view.isAttachedToWindow()) { tempMatrix.reset(); mSharedElementParentMatrices.get(i).invert(tempMatrix); + decor.transformMatrixToLocal(tempMatrix); GhostView.addGhost(view, decor, tempMatrix); ViewGroup parent = (ViewGroup) view.getParent(); if (moveWithParent && !isInTransitionGroup(parent, decor)) { diff --git a/core/java/android/app/DirectAction.java b/core/java/android/app/DirectAction.java index b0ed490369ad..ac3868b2ece9 100644 --- a/core/java/android/app/DirectAction.java +++ b/core/java/android/app/DirectAction.java @@ -22,14 +22,13 @@ import android.os.Bundle; import android.os.IBinder; import android.os.Parcel; import android.os.Parcelable; -import android.view.accessibility.AccessibilityNodeInfo; import com.android.internal.util.Preconditions; import java.util.Objects; /** - * Represents a abstract action that can be perform on this app. This are requested from + * Represents an abstract action that can be perform on this app. This are requested from * outside the app's UI (eg by SystemUI or assistant). The semantics of these actions are * not specified by the OS. This allows open-ended and scalable approach for defining how * an app interacts with components that expose alternative interaction models to the user diff --git a/core/java/android/app/WallpaperInfo.java b/core/java/android/app/WallpaperInfo.java index c552cb62749b..a969b10c15a3 100644 --- a/core/java/android/app/WallpaperInfo.java +++ b/core/java/android/app/WallpaperInfo.java @@ -81,7 +81,7 @@ public final class WallpaperInfo implements Parcelable { final int mContextDescriptionResource; final boolean mShowMetadataInPreview; final boolean mSupportsAmbientMode; - final boolean mShouldUseDefaultDeviceStateChangeTransition; + final boolean mShouldUseDefaultDisplayStateChangeTransition; final String mSettingsSliceUri; final boolean mSupportMultipleDisplays; @@ -146,9 +146,9 @@ public final class WallpaperInfo implements Parcelable { mSupportsAmbientMode = sa.getBoolean( com.android.internal.R.styleable.Wallpaper_supportsAmbientMode, false); - mShouldUseDefaultDeviceStateChangeTransition = sa.getBoolean( + mShouldUseDefaultDisplayStateChangeTransition = sa.getBoolean( com.android.internal.R.styleable - .Wallpaper_shouldUseDefaultDeviceStateChangeTransition, true); + .Wallpaper_shouldUseDefaultDisplayStateChangeTransition, true); mSettingsSliceUri = sa.getString( com.android.internal.R.styleable.Wallpaper_settingsSliceUri); mSupportMultipleDisplays = sa.getBoolean( @@ -175,7 +175,7 @@ public final class WallpaperInfo implements Parcelable { mSupportsAmbientMode = source.readInt() != 0; mSettingsSliceUri = source.readString(); mSupportMultipleDisplays = source.readInt() != 0; - mShouldUseDefaultDeviceStateChangeTransition = source.readInt() != 0; + mShouldUseDefaultDisplayStateChangeTransition = source.readInt() != 0; mService = ResolveInfo.CREATOR.createFromParcel(source); } @@ -400,24 +400,24 @@ public final class WallpaperInfo implements Parcelable { /** * Returns whether this wallpaper should receive default zooming updates when the device - * changes its state (e.g. when folding or unfolding a foldable device). + * changes its display state (e.g. when folding or unfolding a foldable device). * If set to false the wallpaper will not receive zoom events when changing the device state, * so it can implement its own transition instead. * <p> * This corresponds to the value {@link - * android.R.styleable#Wallpaper_shouldUseDefaultDeviceStateChangeTransition} in the + * android.R.styleable#Wallpaper_shouldUseDefaultDisplayStateChangeTransition} in the * XML description of the wallpaper. * <p> * The default value is {@code true}. * - * @see android.R.styleable#Wallpaper_shouldUseDefaultDeviceStateChangeTransition + * @see android.R.styleable#Wallpaper_shouldUseDefaultDisplayStateChangeTransition * @return {@code true} if wallpaper should receive default device state change * transition updates * - * @attr ref android.R.styleable#Wallpaper_shouldUseDefaultDeviceStateChangeTransition + * @attr ref android.R.styleable#Wallpaper_shouldUseDefaultDisplayStateChangeTransition */ - public boolean shouldUseDefaultDeviceStateChangeTransition() { - return mShouldUseDefaultDeviceStateChangeTransition; + public boolean shouldUseDefaultDisplayStateChangeTransition() { + return mShouldUseDefaultDisplayStateChangeTransition; } public void dump(Printer pw, String prefix) { @@ -450,7 +450,7 @@ public final class WallpaperInfo implements Parcelable { dest.writeInt(mSupportsAmbientMode ? 1 : 0); dest.writeString(mSettingsSliceUri); dest.writeInt(mSupportMultipleDisplays ? 1 : 0); - dest.writeInt(mShouldUseDefaultDeviceStateChangeTransition ? 1 : 0); + dest.writeInt(mShouldUseDefaultDisplayStateChangeTransition ? 1 : 0); mService.writeToParcel(dest, flags); } diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 12444ab9ab09..5b01a7d2de66 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -7726,27 +7726,64 @@ public class DevicePolicyManager { } /** - * @hide - * Sets the given package as the device owner. The package must already be installed. There - * must not already be a device owner. - * Only apps with the MANAGE_PROFILE_AND_DEVICE_OWNERS permission and the shell uid can call - * this method. - * Calling this after the setup phase of the primary user has completed is allowed only if - * the caller is the shell uid, and there are no additional users and no accounts. + * Sets the given package as the device owner. + * + * <p>Preconditions: + * <ul> + * <li>The package must already be installed. + * <li>There must not already be a device owner. + * <li>Only apps with the {@code MANAGE_PROFILE_AND_DEVICE_OWNERS} permission or the + * {@link Process#SHELL_UID Shell UID} can call this method. + * </ul> + * + * <p>Calling this after the setup phase of the device owner user has completed is allowed only + * if the caller is the {@link Process#SHELL_UID Shell UID}, and there are no additional users + * (except when the device runs on headless system user mode, in which case it could have exact + * one extra user, which is the current user - the device owner will be set in the + * {@link UserHandle#SYSTEM system} user and a profile owner will be set in the current user) + * and no accounts. + * * @param who the component name to be registered as device owner. * @param ownerName the human readable name of the institution that owns this device. * @param userId ID of the user on which the device owner runs. + * * @return whether the package was successfully registered as the device owner. - * @throws IllegalArgumentException if the package name is null or invalid + * + * @throws IllegalArgumentException if the package name is {@code null} or invalid. * @throws IllegalStateException If the preconditions mentioned are not met. + * + * @hide */ @TestApi @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) - public boolean setDeviceOwner( + public boolean setDeviceOwner(@NonNull ComponentName who, @Nullable String ownerName, + @UserIdInt int userId) { + if (mService != null) { + try { + return mService.setDeviceOwner(who, ownerName, userId, + /* setProfileOwnerOnCurrentUserIfNecessary= */ true); + } catch (RemoteException re) { + throw re.rethrowFromSystemServer(); + } + } + return false; + } + + /** + * Same as {@link #setDeviceOwner(ComponentName, String, int)}, but without setting the profile + * owner on current user when running on headless system user mode - should be used only by + * testing infra. + * + * @hide + */ + @TestApi + @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) + public boolean setDeviceOwnerOnly( @NonNull ComponentName who, @Nullable String ownerName, @UserIdInt int userId) { if (mService != null) { try { - return mService.setDeviceOwner(who, ownerName, userId); + return mService.setDeviceOwner(who, ownerName, userId, + /* setProfileOwnerOnCurrentUserIfNecessary= */ false); } catch (RemoteException re) { throw re.rethrowFromSystemServer(); } @@ -9734,6 +9771,27 @@ public class DevicePolicyManager { } /** + * @param userId The user for whom to retrieve information. + * @param restriction The restriction enforced by admin. It could be any user restriction or + * policy like {@link DevicePolicyManager#POLICY_DISABLE_CAMERA} and + * {@link DevicePolicyManager#POLICY_DISABLE_SCREEN_CAPTURE}. + * @return Details of admin and user which enforced the restriction for the userId. If + * restriction is null, profile owner for the user or device owner info is returned. + * @hide + */ + public @Nullable Bundle getEnforcingAdminAndUserDetails(int userId, + @Nullable String restriction) { + if (mService != null) { + try { + return mService.getEnforcingAdminAndUserDetails(userId, restriction); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + return null; + } + + /** * Hide or unhide packages. When a package is hidden it is unavailable for use, but the data and * actual package file remain. This function can be called by a device owner, profile owner, or * by a delegate given the {@link #DELEGATION_PACKAGE_ACCESS} scope via diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index b1364b500d4a..1c9187d8d22c 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -159,7 +159,7 @@ interface IDevicePolicyManager { void reportKeyguardDismissed(int userHandle); void reportKeyguardSecured(int userHandle); - boolean setDeviceOwner(in ComponentName who, String ownerName, int userId); + boolean setDeviceOwner(in ComponentName who, String ownerName, int userId, boolean setProfileOwnerOnCurrentUserIfNecessary); ComponentName getDeviceOwnerComponent(boolean callingUserOnly); boolean hasDeviceOwner(); String getDeviceOwnerName(); @@ -251,6 +251,7 @@ interface IDevicePolicyManager { boolean isNotificationListenerServicePermitted(in String packageName, int userId); Intent createAdminSupportIntent(in String restriction); + Bundle getEnforcingAdminAndUserDetails(int userId,String restriction); boolean setApplicationHidden(in ComponentName admin, in String callerPackage, in String packageName, boolean hidden, boolean parent); boolean isApplicationHidden(in ComponentName admin, in String callerPackage, in String packageName, boolean parent); diff --git a/core/java/android/app/servertransaction/ActivityResultItem.java b/core/java/android/app/servertransaction/ActivityResultItem.java index e059f177e344..27d104b59284 100644 --- a/core/java/android/app/servertransaction/ActivityResultItem.java +++ b/core/java/android/app/servertransaction/ActivityResultItem.java @@ -16,6 +16,8 @@ package android.app.servertransaction; +import static android.app.servertransaction.ActivityLifecycleItem.ON_RESUME; +import static android.app.servertransaction.ActivityLifecycleItem.UNDEFINED; import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER; import android.annotation.NonNull; @@ -23,6 +25,9 @@ import android.annotation.Nullable; import android.app.ActivityThread.ActivityClientRecord; import android.app.ClientTransactionHandler; import android.app.ResultInfo; +import android.app.compat.CompatChanges; +import android.compat.annotation.ChangeId; +import android.compat.annotation.EnabledAfter; import android.compat.annotation.UnsupportedAppUsage; import android.os.Build; import android.os.Parcel; @@ -41,11 +46,19 @@ public class ActivityResultItem extends ActivityTransactionItem { @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) private List<ResultInfo> mResultInfoList; - /* TODO(b/78294732) + /** + * Correct the lifecycle of activity result after {@link android.os.Build.VERSION_CODES#S} to + * guarantee that an activity gets activity result just before resume. + */ + @ChangeId + @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.S) + public static final long CALL_ACTIVITY_RESULT_BEFORE_RESUME = 78294732L; + @Override public int getPostExecutionState() { - return ON_RESUME; - }*/ + return CompatChanges.isChangeEnabled(CALL_ACTIVITY_RESULT_BEFORE_RESUME) + ? ON_RESUME : UNDEFINED; + } @Override public void execute(ClientTransactionHandler client, ActivityClientRecord r, diff --git a/core/java/android/app/servertransaction/LaunchActivityItem.java b/core/java/android/app/servertransaction/LaunchActivityItem.java index 37cbccb89735..34e4fcdb9140 100644 --- a/core/java/android/app/servertransaction/LaunchActivityItem.java +++ b/core/java/android/app/servertransaction/LaunchActivityItem.java @@ -73,7 +73,6 @@ public class LaunchActivityItem extends ClientTransactionItem { private IBinder mAssistToken; private IBinder mShareableActivityToken; private boolean mLaunchedFromBubble; - private IBinder mTaskFragmentToken; /** * It is only non-null if the process is the first time to launch activity. It is only an * optimization for quick look up of the interface so the field is ignored for comparison. @@ -87,7 +86,7 @@ public class LaunchActivityItem extends ClientTransactionItem { mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState, mPendingResults, mPendingNewIntents, mActivityOptions, mIsForward, mProfilerInfo, client, mAssistToken, mFixedRotationAdjustments, mShareableActivityToken, - mLaunchedFromBubble, mTaskFragmentToken); + mLaunchedFromBubble); client.addLaunchingActivity(token, r); client.updateProcessState(mProcState, false); client.updatePendingConfiguration(mCurConfig); @@ -125,7 +124,7 @@ public class LaunchActivityItem extends ClientTransactionItem { boolean isForward, ProfilerInfo profilerInfo, IBinder assistToken, IActivityClientController activityClientController, FixedRotationAdjustments fixedRotationAdjustments, IBinder shareableActivityToken, - boolean launchedFromBubble, IBinder taskFragmentToken) { + boolean launchedFromBubble) { LaunchActivityItem instance = ObjectPool.obtain(LaunchActivityItem.class); if (instance == null) { instance = new LaunchActivityItem(); @@ -134,7 +133,7 @@ public class LaunchActivityItem extends ClientTransactionItem { voiceInteractor, procState, state, persistentState, pendingResults, pendingNewIntents, activityOptions, isForward, profilerInfo, assistToken, activityClientController, fixedRotationAdjustments, shareableActivityToken, - launchedFromBubble, taskFragmentToken); + launchedFromBubble); return instance; } @@ -142,7 +141,7 @@ public class LaunchActivityItem extends ClientTransactionItem { @Override public void recycle() { setValues(this, null, 0, null, null, null, null, null, null, 0, null, null, null, null, - null, false, null, null, null, null, null, false, null); + null, false, null, null, null, null, null, false); ObjectPool.recycle(this); } @@ -173,7 +172,6 @@ public class LaunchActivityItem extends ClientTransactionItem { dest.writeTypedObject(mFixedRotationAdjustments, flags); dest.writeStrongBinder(mShareableActivityToken); dest.writeBoolean(mLaunchedFromBubble); - dest.writeStrongBinder(mTaskFragmentToken); } /** Read from Parcel. */ @@ -192,8 +190,7 @@ public class LaunchActivityItem extends ClientTransactionItem { in.readStrongBinder(), IActivityClientController.Stub.asInterface(in.readStrongBinder()), in.readTypedObject(FixedRotationAdjustments.CREATOR), in.readStrongBinder(), - in.readBoolean(), - in.readStrongBinder()); + in.readBoolean()); } public static final @NonNull Creator<LaunchActivityItem> CREATOR = @@ -232,8 +229,7 @@ public class LaunchActivityItem extends ClientTransactionItem { && Objects.equals(mProfilerInfo, other.mProfilerInfo) && Objects.equals(mAssistToken, other.mAssistToken) && Objects.equals(mFixedRotationAdjustments, other.mFixedRotationAdjustments) - && Objects.equals(mShareableActivityToken, other.mShareableActivityToken) - && Objects.equals(mTaskFragmentToken, other.mTaskFragmentToken); + && Objects.equals(mShareableActivityToken, other.mShareableActivityToken); } @Override @@ -256,7 +252,6 @@ public class LaunchActivityItem extends ClientTransactionItem { result = 31 * result + Objects.hashCode(mAssistToken); result = 31 * result + Objects.hashCode(mFixedRotationAdjustments); result = 31 * result + Objects.hashCode(mShareableActivityToken); - result = 31 * result + Objects.hashCode(mTaskFragmentToken); return result; } @@ -306,7 +301,7 @@ public class LaunchActivityItem extends ClientTransactionItem { ActivityOptions activityOptions, boolean isForward, ProfilerInfo profilerInfo, IBinder assistToken, IActivityClientController activityClientController, FixedRotationAdjustments fixedRotationAdjustments, IBinder shareableActivityToken, - boolean launchedFromBubble, IBinder taskFragmentToken) { + boolean launchedFromBubble) { instance.mIntent = intent; instance.mIdent = ident; instance.mInfo = info; @@ -328,6 +323,5 @@ public class LaunchActivityItem extends ClientTransactionItem { instance.mFixedRotationAdjustments = fixedRotationAdjustments; instance.mShareableActivityToken = shareableActivityToken; instance.mLaunchedFromBubble = launchedFromBubble; - instance.mTaskFragmentToken = taskFragmentToken; } } diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java index 8aa27853b462..dd147cc26e59 100644 --- a/core/java/android/appwidget/AppWidgetHostView.java +++ b/core/java/android/appwidget/AppWidgetHostView.java @@ -552,6 +552,10 @@ public class AppWidgetHostView extends FrameLayout { inflateAsync(rvToApply); return; } + // Prepare a local reference to the remote Context so we're ready to + // inflate any requested LayoutParams. + mRemoteContext = getRemoteContext(); + int layoutId = rvToApply.getLayoutId(); if (rvToApply.canRecycleView(mView)) { try { @@ -727,6 +731,9 @@ public class AppWidgetHostView extends FrameLayout { } catch (NameNotFoundException e) { Log.e(TAG, "Package name " + mInfo.providerInfo.packageName + " not found"); return mContext; + } catch (NullPointerException e) { + Log.e(TAG, "Error trying to create the remote context.", e); + return mContext; } } diff --git a/core/java/android/hardware/display/AmbientDisplayConfiguration.java b/core/java/android/hardware/display/AmbientDisplayConfiguration.java index a1f7aa12264b..f5b2ac586bd1 100644 --- a/core/java/android/hardware/display/AmbientDisplayConfiguration.java +++ b/core/java/android/hardware/display/AmbientDisplayConfiguration.java @@ -22,6 +22,9 @@ import android.os.Build; import android.os.SystemProperties; import android.provider.Settings; import android.text.TextUtils; +import android.util.Log; + +import java.util.Arrays; import com.android.internal.R; @@ -32,7 +35,7 @@ import com.android.internal.R; */ @TestApi public class AmbientDisplayConfiguration { - + private static final String TAG = "AmbientDisplayConfig"; private final Context mContext; private final boolean mAlwaysOnByDefault; @@ -141,11 +144,20 @@ public class AmbientDisplayConfiguration { } /** {@hide} */ - public String tapSensorType() { + private String tapSensorType() { return mContext.getResources().getString(R.string.config_dozeTapSensorType); } /** {@hide} */ + public String tapSensorType(int posture) { + return getSensorFromPostureMapping( + mContext.getResources().getStringArray(R.array.config_dozeTapSensorPostureMapping), + tapSensorType(), + posture + ); + } + + /** {@hide} */ public String longPressSensorType() { return mContext.getResources().getString(R.string.config_dozeLongPressSensorType); } @@ -241,4 +253,20 @@ public class AmbientDisplayConfiguration { private boolean boolSetting(String name, int user, int def) { return Settings.Secure.getIntForUser(mContext.getContentResolver(), name, def, user) != 0; } + + /** {@hide} */ + public static String getSensorFromPostureMapping( + String[] postureMapping, + String defaultValue, + int posture) { + String sensorType = defaultValue; + if (postureMapping != null && posture < postureMapping.length) { + sensorType = postureMapping[posture]; + } else { + Log.e(TAG, "Unsupported doze posture " + posture + + " postureMapping=" + Arrays.toString(postureMapping)); + } + + return TextUtils.isEmpty(sensorType) ? defaultValue : sensorType; + } } diff --git a/core/java/android/hardware/display/BrightnessInfo.java b/core/java/android/hardware/display/BrightnessInfo.java index c5d37c2d0b90..0dc8f92967fb 100644 --- a/core/java/android/hardware/display/BrightnessInfo.java +++ b/core/java/android/hardware/display/BrightnessInfo.java @@ -60,12 +60,18 @@ public final class BrightnessInfo implements Parcelable { /** Brightness */ public final float brightness; + /** Brightness after {@link DisplayPowerController} adjustments */ + public final float adjustedBrightness; + /** Current minimum supported brightness. */ public final float brightnessMinimum; /** Current maximum supported brightness. */ public final float brightnessMaximum; + /** Brightness values greater than this point are only used in High Brightness Mode. */ + public final float highBrightnessTransitionPoint; + /** * Current state of high brightness mode. * Can be any of HIGH_BRIGHTNESS_MODE_* values. @@ -73,11 +79,20 @@ public final class BrightnessInfo implements Parcelable { public final int highBrightnessMode; public BrightnessInfo(float brightness, float brightnessMinimum, float brightnessMaximum, - @HighBrightnessMode int highBrightnessMode) { + @HighBrightnessMode int highBrightnessMode, float highBrightnessTransitionPoint) { + this(brightness, brightness, brightnessMinimum, brightnessMaximum, highBrightnessMode, + highBrightnessTransitionPoint); + } + + public BrightnessInfo(float brightness, float adjustedBrightness, float brightnessMinimum, + float brightnessMaximum, @HighBrightnessMode int highBrightnessMode, + float highBrightnessTransitionPoint) { this.brightness = brightness; + this.adjustedBrightness = adjustedBrightness; this.brightnessMinimum = brightnessMinimum; this.brightnessMaximum = brightnessMaximum; this.highBrightnessMode = highBrightnessMode; + this.highBrightnessTransitionPoint = highBrightnessTransitionPoint; } /** @@ -103,9 +118,11 @@ public final class BrightnessInfo implements Parcelable { @Override public void writeToParcel(Parcel dest, int flags) { dest.writeFloat(brightness); + dest.writeFloat(adjustedBrightness); dest.writeFloat(brightnessMinimum); dest.writeFloat(brightnessMaximum); dest.writeInt(highBrightnessMode); + dest.writeFloat(highBrightnessTransitionPoint); } public static final @android.annotation.NonNull Creator<BrightnessInfo> CREATOR = @@ -123,9 +140,11 @@ public final class BrightnessInfo implements Parcelable { private BrightnessInfo(Parcel source) { brightness = source.readFloat(); + adjustedBrightness = source.readFloat(); brightnessMinimum = source.readFloat(); brightnessMaximum = source.readFloat(); highBrightnessMode = source.readInt(); + highBrightnessTransitionPoint = source.readFloat(); } } diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java index 1f11d10052fe..1a7ec7f99c95 100644 --- a/core/java/android/text/TextLine.java +++ b/core/java/android/text/TextLine.java @@ -782,7 +782,7 @@ public class TextLine { int spanStart = runStart; int spanLimit; - if (mSpanned == null) { + if (mSpanned == null || runStart == runLimit) { spanLimit = runLimit; } else { int target = after ? offset + 1 : offset; diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 3f530fe3432c..1255dad27eed 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -248,6 +248,8 @@ android:name="com.android.bluetooth.BluetoothMapContentObserver.action.MESSAGE_DELIVERY" /> <protected-broadcast android:name="android.bluetooth.pan.profile.action.CONNECTION_STATE_CHANGED" /> + <protected-broadcast android:name="android.bluetooth.action.LE_AUDIO_CONNECTION_STATE_CHANGED" /> + <protected-broadcast android:name="android.bluetooth.action.LE_AUDIO_ACTIVE_DEVICE_CHANGED" /> <protected-broadcast android:name="android.bluetooth.action.TETHERING_STATE_CHANGED" /> <protected-broadcast android:name="android.bluetooth.pbap.profile.action.CONNECTION_STATE_CHANGED" /> diff --git a/core/res/res/anim-ldrtl/task_close_exit.xml b/core/res/res/anim-ldrtl/task_close_exit.xml index 76fbdffd1760..0887019ca608 100644 --- a/core/res/res/anim-ldrtl/task_close_exit.xml +++ b/core/res/res/anim-ldrtl/task_close_exit.xml @@ -28,9 +28,4 @@ android:startOffset="0" android:duration="500"/> - <!-- This is needed to keep the animation running while task_open_enter completes --> - <alpha - android:fromAlpha="1.0" - android:toAlpha="1.0" - android:duration="600"/> -</set>
\ No newline at end of file +</set> diff --git a/core/res/res/anim-ldrtl/task_open_exit.xml b/core/res/res/anim-ldrtl/task_open_exit.xml index beb6fca5632a..88cdcceae415 100644 --- a/core/res/res/anim-ldrtl/task_open_exit.xml +++ b/core/res/res/anim-ldrtl/task_open_exit.xml @@ -28,9 +28,4 @@ android:startOffset="0" android:duration="500"/> - <!-- This is needed to keep the animation running while task_open_enter completes --> - <alpha - android:fromAlpha="1.0" - android:toAlpha="1.0" - android:duration="600"/> -</set>
\ No newline at end of file +</set> diff --git a/core/res/res/anim/task_close_exit.xml b/core/res/res/anim/task_close_exit.xml index 736f3f2083e5..3a8dd934cd17 100644 --- a/core/res/res/anim/task_close_exit.xml +++ b/core/res/res/anim/task_close_exit.xml @@ -30,9 +30,4 @@ android:startOffset="0" android:duration="500"/> - <!-- This is needed to keep the animation running while task_open_enter completes --> - <alpha - android:fromAlpha="1.0" - android:toAlpha="1.0" - android:duration="600"/> -</set>
\ No newline at end of file +</set> diff --git a/core/res/res/anim/task_open_exit.xml b/core/res/res/anim/task_open_exit.xml index d1703170e16f..21fec7f694bf 100644 --- a/core/res/res/anim/task_open_exit.xml +++ b/core/res/res/anim/task_open_exit.xml @@ -30,9 +30,4 @@ android:startOffset="0" android:duration="500"/> - <!-- This is needed to keep the animation running while task_open_enter completes --> - <alpha - android:fromAlpha="1.0" - android:toAlpha="1.0" - android:duration="600"/> -</set>
\ No newline at end of file +</set> diff --git a/core/res/res/values-mcc334-mnc020-af/strings.xml b/core/res/res/values-mcc334-mnc020-af/strings.xml new file mode 100644 index 000000000000..c9177f3cb772 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-af/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"STAWINGMISLUKKING -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"NIE INGETEKEN OP DIENS NIE -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Veelvuldige PDN-verbindings vir \'n bepaalde APN word nie toegelaat nie -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-am/strings.xml b/core/res/res/values-mcc334-mnc020-am/strings.xml new file mode 100644 index 000000000000..609fcf95630b --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-am/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"የማረጋገጫ አለመሳካት -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"ለአገልግሎት ደንበኝነት አልተመዘገበም -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"ለተሰጠው ኤፒኤን ብዙ የፒዲኤን ግንኙነቶች አይፈቀዱም -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-ar/strings.xml b/core/res/res/values-mcc334-mnc020-ar/strings.xml new file mode 100644 index 000000000000..ac7dec0da313 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-ar/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"تعذّرت المصادقة -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"غير مشترك في الخدمة -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"غير مسموح باتصالات PDN متعددة لاسم نقطة وصول محددة (APN) -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-as/strings.xml b/core/res/res/values-mcc334-mnc020-as/strings.xml new file mode 100644 index 000000000000..25b074eec145 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-as/strings.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <!-- no translation found for config_pdp_reject_user_authentication_failed (4683454131283459978) --> + <skip /> + <!-- no translation found for config_pdp_reject_service_not_subscribed (9021140729932308119) --> + <skip /> + <!-- no translation found for config_pdp_reject_multi_conn_to_same_pdn_not_allowed (3838388706348367865) --> + <skip /> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-az/strings.xml b/core/res/res/values-mcc334-mnc020-az/strings.xml new file mode 100644 index 000000000000..83b210d90eaa --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-az/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"DOĞRULAMA XƏTASI -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"XİDMƏTƏ ABUNƏ OLUNMAYIB -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Verilmiş APN üçün birdən çox PDN bağlantısına icazə verilmir -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-b+sr+Latn/strings.xml b/core/res/res/values-mcc334-mnc020-b+sr+Latn/strings.xml new file mode 100644 index 000000000000..b27e485e5f73 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-b+sr+Latn/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"POTVRDA IDENTITETA NIJE USPELA -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"NISTE PRETPLAĆENI NA USLUGU -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Nije dozvoljeno više PDN veza za određeni APN -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-be/strings.xml b/core/res/res/values-mcc334-mnc020-be/strings.xml new file mode 100644 index 000000000000..3ee9e8f1ce60 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-be/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"ЗБОЙ АЎТЭНТЫФІКАЦЫІ -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"У ВАС НЯМА ПАДПІСКІ НА СЭРВІС -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Да гэтага APN нельга падключаць некалькі сетак PDN -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-bg/strings.xml b/core/res/res/values-mcc334-mnc020-bg/strings.xml new file mode 100644 index 000000000000..257cf585ca21 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-bg/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"НЕУСПЕШНО УДОСТОВЕРЯВАНЕ -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"НЯМА АБОНАМЕНТ ЗА УСЛУГАТА -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Не е разрешено да има повече от една PDN връзка за дадено име на точката за достъп (APN) -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-bn/strings.xml b/core/res/res/values-mcc334-mnc020-bn/strings.xml new file mode 100644 index 000000000000..25b074eec145 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-bn/strings.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <!-- no translation found for config_pdp_reject_user_authentication_failed (4683454131283459978) --> + <skip /> + <!-- no translation found for config_pdp_reject_service_not_subscribed (9021140729932308119) --> + <skip /> + <!-- no translation found for config_pdp_reject_multi_conn_to_same_pdn_not_allowed (3838388706348367865) --> + <skip /> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-bs/strings.xml b/core/res/res/values-mcc334-mnc020-bs/strings.xml new file mode 100644 index 000000000000..4bf1b8f6cbae --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-bs/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"AUTENTIFIKACIJA NIJE USPJELA -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"NISTE PRETPLAĆENI NA USLUGU -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Više PDN veza za određeni APN nije dozvoljeno -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-ca/strings.xml b/core/res/res/values-mcc334-mnc020-ca/strings.xml new file mode 100644 index 000000000000..0ad1f1cfc77d --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-ca/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"ERROR D\'AUTENTICACIÓ -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"NO ESTÀS SUBSCRIT AL SERVEI -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"No es permeten diverses connexions PDN per a un APN determinat -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-cs/strings.xml b/core/res/res/values-mcc334-mnc020-cs/strings.xml new file mode 100644 index 000000000000..cfa1a44340da --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-cs/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"SELHÁNÍ OVĚŘENÍ -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"NEJSTE PŘIHLÁŠENI K ODBĚRU SLUŽBY -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"U jednoho APN není povoleno více než jedno připojení PDN -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-da/strings.xml b/core/res/res/values-mcc334-mnc020-da/strings.xml new file mode 100644 index 000000000000..7d349cf67f5c --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-da/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"GODKENDELSESFEJL -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"IKKE TILMELDT TJENESTEN -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Flere PDN-forbindelser for en given APN er ikke tilladt -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-de/strings.xml b/core/res/res/values-mcc334-mnc020-de/strings.xml new file mode 100644 index 000000000000..084bf46ee569 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-de/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"AUTHENTIFIZIERUNGSFEHLER -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"DIENST NICHT ABONNIERT -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Mehrere PDN-Verbindungen für einen bestimmten APN sind nicht zulässig -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-el/strings.xml b/core/res/res/values-mcc334-mnc020-el/strings.xml new file mode 100644 index 000000000000..27c5f9548a08 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-el/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"ΑΠΟΤΥΧΙΑ ΕΛΕΓΧΟΥ ΤΑΥΤΟΤΗΤΑΣ -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"ΔΕΝ ΕΓΙΝΕ ΕΓΓΡΑΦΗ ΣΤΗΝ ΥΠΗΡΕΣΙΑ -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Δεν επιτρέπονται πολλές συνδέσεις PDN για ένα δεδομένο APN -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-en-rAU/strings.xml b/core/res/res/values-mcc334-mnc020-en-rAU/strings.xml new file mode 100644 index 000000000000..6dce3455d452 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-en-rAU/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"AUTHENTICATION FAILURE -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"NOT SUBSCRIBED TO SERVICE -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Multiple PDN connections for a given APN not allowed -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-en-rCA/strings.xml b/core/res/res/values-mcc334-mnc020-en-rCA/strings.xml new file mode 100644 index 000000000000..6dce3455d452 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-en-rCA/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"AUTHENTICATION FAILURE -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"NOT SUBSCRIBED TO SERVICE -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Multiple PDN connections for a given APN not allowed -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-en-rGB/strings.xml b/core/res/res/values-mcc334-mnc020-en-rGB/strings.xml new file mode 100644 index 000000000000..6dce3455d452 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-en-rGB/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"AUTHENTICATION FAILURE -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"NOT SUBSCRIBED TO SERVICE -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Multiple PDN connections for a given APN not allowed -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-en-rIN/strings.xml b/core/res/res/values-mcc334-mnc020-en-rIN/strings.xml new file mode 100644 index 000000000000..6dce3455d452 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-en-rIN/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"AUTHENTICATION FAILURE -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"NOT SUBSCRIBED TO SERVICE -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Multiple PDN connections for a given APN not allowed -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-en-rXC/strings.xml b/core/res/res/values-mcc334-mnc020-en-rXC/strings.xml new file mode 100644 index 000000000000..ec8f4ab19bce --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-en-rXC/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"AUTHENTICATION FAILURE -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"NOT SUBSCRIBED TO SERVICE -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Multiple PDN connections for a given APN not allowed -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-es-rUS/strings.xml b/core/res/res/values-mcc334-mnc020-es-rUS/strings.xml new file mode 100644 index 000000000000..8cb181d371ee --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-es-rUS/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"FALLO EN LA AUTENTICACIÓN -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"NO TE SUSCRIBISTE AL SERVICIO -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"No se permiten varias conexiones PDN para un APN determinado -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-es/strings.xml b/core/res/res/values-mcc334-mnc020-es/strings.xml new file mode 100644 index 000000000000..0744699804e5 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-es/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"ERROR DE AUTENTICACIÓN -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"NO SUSCRITO AL SERVICIO -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"No se permiten varias conexiones PDN de un APN concreto -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-et/strings.xml b/core/res/res/values-mcc334-mnc020-et/strings.xml new file mode 100644 index 000000000000..a7e9e1665ee0 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-et/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"AUTENTIMINE EBAÕNNESTUS -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"TEENUST POLE TELLITUD -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Antud APN-i puhul pole mitu PDN-ühendust lubatud -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-eu/strings.xml b/core/res/res/values-mcc334-mnc020-eu/strings.xml new file mode 100644 index 000000000000..2d05b3fea78d --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-eu/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"EZIN IZAN DA AUTENTIFIKATU -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"EZ DAGO HARPIDETUTA ZERBITZURA -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Ezin da konektatu APN jakin bat PDN batera baino gehiagotara -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-fa/strings.xml b/core/res/res/values-mcc334-mnc020-fa/strings.xml new file mode 100644 index 000000000000..8bf364f5b118 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-fa/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"اصالتسنجی انجام نشد -۲۹-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"مشترک سرویس نیستید -۳۳-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"تعدادی از اتصالهای PDN مربوط به APN تعیینشده مجاز نیست -۵۵-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-fi/strings.xml b/core/res/res/values-mcc334-mnc020-fi/strings.xml new file mode 100644 index 000000000000..f8d01ba03fc4 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-fi/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"TODENNUS EPÄONNISTUI -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"PALVELUA EI TILATTU -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Useat yhteydet eivät ole sallittuja yhdelle APN:lle -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-fr-rCA/strings.xml b/core/res/res/values-mcc334-mnc020-fr-rCA/strings.xml new file mode 100644 index 000000000000..25b074eec145 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-fr-rCA/strings.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <!-- no translation found for config_pdp_reject_user_authentication_failed (4683454131283459978) --> + <skip /> + <!-- no translation found for config_pdp_reject_service_not_subscribed (9021140729932308119) --> + <skip /> + <!-- no translation found for config_pdp_reject_multi_conn_to_same_pdn_not_allowed (3838388706348367865) --> + <skip /> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-fr/strings.xml b/core/res/res/values-mcc334-mnc020-fr/strings.xml new file mode 100644 index 000000000000..6eaa7cd61589 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-fr/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"ÉCHEC DE L\'AUTHENTIFICATION -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"NON INSCRIT AU SERVICE -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Vous n\'êtes pas autorisé à avoir plusieurs connexions PDN pour un APN donné -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-gl/strings.xml b/core/res/res/values-mcc334-mnc020-gl/strings.xml new file mode 100644 index 000000000000..49baed94d1c7 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-gl/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"ERRO DE AUTENTICACIÓN -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"SEN SUBSCRICIÓN AO SERVIZO -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Non está permitido establecer varias conexións de tipo PDN para un determinado APN -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-gu/strings.xml b/core/res/res/values-mcc334-mnc020-gu/strings.xml new file mode 100644 index 000000000000..25b074eec145 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-gu/strings.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <!-- no translation found for config_pdp_reject_user_authentication_failed (4683454131283459978) --> + <skip /> + <!-- no translation found for config_pdp_reject_service_not_subscribed (9021140729932308119) --> + <skip /> + <!-- no translation found for config_pdp_reject_multi_conn_to_same_pdn_not_allowed (3838388706348367865) --> + <skip /> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-hi/strings.xml b/core/res/res/values-mcc334-mnc020-hi/strings.xml new file mode 100644 index 000000000000..8a11053764b9 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-hi/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"पुष्टि नहीं की जा सकी -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"सेवा की सदस्यता नहीं ली गई है -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"किसी भी एपीएन के लिए एक से ज़्यादा पीडीएन कनेक्शन की अनुमति नहीं है -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-hr/strings.xml b/core/res/res/values-mcc334-mnc020-hr/strings.xml new file mode 100644 index 000000000000..ff9b427e0df4 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-hr/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"AUTENTIFIKACIJA NIJE USPJELA -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"NISTE PRETPLAĆENI NA USLUGU -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Više PDN veza za određeni APN nije dopušteno -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-hu/strings.xml b/core/res/res/values-mcc334-mnc020-hu/strings.xml new file mode 100644 index 000000000000..42776c1e9619 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-hu/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"SIKERTELEN HITELESÍTÉS -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"NINCS ELŐFIZETÉSE A SZOLGÁLTATÁSRA -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Nem engedélyezett több PDN-kapcsolat egy adott APN-nél -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-hy/strings.xml b/core/res/res/values-mcc334-mnc020-hy/strings.xml new file mode 100644 index 000000000000..6633bb30e01d --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-hy/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"ՆՈՒՅՆԱԿԱՆԱՑՄԱՆ ՍԽԱԼ -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"ԴՈՒՔ ԲԱԺԱՆՈՐԴԱԳՐՎԱԾ ՉԵՔ ԱՅՍ ԾԱՌԱՅՈՒԹՅԱՆԸ -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Այս APN-ով չի թույլատրվում միանալ տվյալների փոխանցման մեկից ավել բաց ցանցի -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-in/strings.xml b/core/res/res/values-mcc334-mnc020-in/strings.xml new file mode 100644 index 000000000000..79a9dfdf971e --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-in/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"KEGAGALAN AUTENTIKASI -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"TIDAK BERLANGGANAN KE LAYANAN -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Beberapa koneksi PDN untuk APN tertentu tidak diizinkan -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-is/strings.xml b/core/res/res/values-mcc334-mnc020-is/strings.xml new file mode 100644 index 000000000000..c9049e8821aa --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-is/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"AUÐKENNING MISTÓKST -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"EKKI ÁSKRIFANDI AÐ ÞJÓNUSTU -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Margar PDN-tengingar fyrir tiltekinn aðgangsstað eru ekki leyfðar -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-it/strings.xml b/core/res/res/values-mcc334-mnc020-it/strings.xml new file mode 100644 index 000000000000..add9b0d24c20 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-it/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"ERRORE DI AUTENTICAZIONE -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"SOTTOSCRIZIONE AL SERVIZIO NON EFFETTUATA -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Più connessioni PDN per un dato APN non consentite -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-iw/strings.xml b/core/res/res/values-mcc334-mnc020-iw/strings.xml new file mode 100644 index 000000000000..b8b1ab5ad3b4 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-iw/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"האימות נכשל -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"לא נרשמת כמנוי לשירות -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"אין הרשאה למספר חיבורי PDN ל-APN מסוים -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-ja/strings.xml b/core/res/res/values-mcc334-mnc020-ja/strings.xml new file mode 100644 index 000000000000..ec543faa0119 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-ja/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"認証エラーが発生しました -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"サービスに登録していません -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"特定の APN に対する複数の PDN 接続は許可されていません -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-ka/strings.xml b/core/res/res/values-mcc334-mnc020-ka/strings.xml new file mode 100644 index 000000000000..e55057b90f4b --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-ka/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"ავტორიზაციის შეცდომა -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"გამოწერილი არ გაქვთ სერვისი -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"მრავალი PDN კავშირი მოცემული APN-ისთვის დაუშვებელია -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-kk/strings.xml b/core/res/res/values-mcc334-mnc020-kk/strings.xml new file mode 100644 index 000000000000..f19d2c727c22 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-kk/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"АУТЕНТИФИКАЦИЯЛАУ ҚАТЕСІ -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"ҚЫЗМЕТКЕ ЖАЗЫЛМАҒАН -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Бұл APN үшін бірнеше PDN-ге қосылуға рұқсат берілмеген -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-km/strings.xml b/core/res/res/values-mcc334-mnc020-km/strings.xml new file mode 100644 index 000000000000..08e1a0d8a6f3 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-km/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"មិនអាចផ្ទៀងផ្ទាត់បានទេ -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"មិនបានជាវសេវាកម្មទេ -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"ការតភ្ជាប់ PDN ច្រើនសម្រាប់ APN ដែលបានផ្ដល់មិនត្រូវបានអនុញ្ញាតទេ -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-kn/strings.xml b/core/res/res/values-mcc334-mnc020-kn/strings.xml new file mode 100644 index 000000000000..e5780b3e8abb --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-kn/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"ದೃಢೀಕರಣ ವಿಫಲಗೊಂಡಿದೆ -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"ಸೇವೆಗೆ ಸಬ್ಸ್ಕ್ರೈಬ್ ಮಾಡಿಲ್ಲ -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"ನೀಡಲಾದ APN ಗಾಗಿ ಬಹು PDN ಸಂಪರ್ಕಗಳನ್ನು ಅನುಮತಿಸಲಾಗುವುದಿಲ್ಲ -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-ko/strings.xml b/core/res/res/values-mcc334-mnc020-ko/strings.xml new file mode 100644 index 000000000000..444d05097663 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-ko/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"인증할 수 없음 -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"서비스 구독 중이 아님 -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"지정된 APN에 여러 PDN을 연결할 수 없음 -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-ky/strings.xml b/core/res/res/values-mcc334-mnc020-ky/strings.xml new file mode 100644 index 000000000000..240c6debee1c --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-ky/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"АНЫКТЫГЫ ТЕКШЕРИЛГЕН ЖОК -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"КЫЗМАТКА ЖАЗЫЛГАН ЭМЕССИЗ -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Бул APN менен бир нече PDN\'ге туташууга болбойт -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-lo/strings.xml b/core/res/res/values-mcc334-mnc020-lo/strings.xml new file mode 100644 index 000000000000..89eb9fc9f896 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-lo/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"ການພິສູດຢືນຢັນບໍ່ສຳເລັດ -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"ບໍ່ໄດ້ສະໝັກໃຊ້ບໍລິການ -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"ບໍ່ອະນຸຍາດການເຊື່ອມຕໍ່ PDN ຫຼາຍອັນສຳລັບ APN ທີ່ລະບຸ -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-lt/strings.xml b/core/res/res/values-mcc334-mnc020-lt/strings.xml new file mode 100644 index 000000000000..9157b8d72b81 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-lt/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"AUTENTIFIKAVIMO TRIKTIS -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"PASLAUGA NEPRENUMERUOJAMA -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Kelių PDN ryšiai su APN neleidžiami -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-lv/strings.xml b/core/res/res/values-mcc334-mnc020-lv/strings.xml new file mode 100644 index 000000000000..33af8634f1dc --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-lv/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"AUTENTIFIKĀCIJAS KĻŪME -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"PAKALPOJUMS NAV ABONĒTS -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Norādītajam APN nav atļauti vairāki PDN savienojumi -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-mk/strings.xml b/core/res/res/values-mcc334-mnc020-mk/strings.xml new file mode 100644 index 000000000000..5b6b62193440 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-mk/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"НЕУСПЕШНА ПРОВЕРКА -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"НЕ СТЕ ПРЕТПЛАТЕНИ НА УСЛУГАТА -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Не се дозволени повеќекратни PDN-врски за дадена APN -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-ml/strings.xml b/core/res/res/values-mcc334-mnc020-ml/strings.xml new file mode 100644 index 000000000000..d56b4c889896 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-ml/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"പരിശോധിച്ചുറപ്പിക്കൽ പരാജയം -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"സേവനം സബ്സ്ക്രൈബ് ചെയ്തിട്ടില്ല -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"നൽകിയിരിക്കുന്ന ഒരു APN-ൽ ഒന്നിലധികം PDN കണക്ഷനുകൾ അനുവദനീയമല്ല -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-mn/strings.xml b/core/res/res/values-mcc334-mnc020-mn/strings.xml new file mode 100644 index 000000000000..9eb4753155af --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-mn/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"БАТАЛГААЖУУЛЖ ЧАДСАНГҮЙ -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"ҮЙЛЧИЛГЭЭГ ЗАХИАЛААГҮЙ БАЙНА -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Өгсөн APN-д хэд хэдэн PDN холболтыг зөвшөөрдөггүй -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-mr/strings.xml b/core/res/res/values-mcc334-mnc020-mr/strings.xml new file mode 100644 index 000000000000..7adf6667ebaa --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-mr/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"ऑथेंटिकेशन यशस्वी झाले नाही -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"सेवेचे सदस्यत्व घेतलेले नाही -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"दिलेल्या APN साठी एकपेक्षा जास्त PDN कनेक्शनची अनुमती नाही -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-ms/strings.xml b/core/res/res/values-mcc334-mnc020-ms/strings.xml new file mode 100644 index 000000000000..cbae67e73bad --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-ms/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"KEGAGALAN PENGESAHAN -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"TIDAK MELANGGAN PERKHIDMATAN -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Sambungan berbilang PDN untuk APN yang diberikan tidak dibenarkan -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-my/strings.xml b/core/res/res/values-mcc334-mnc020-my/strings.xml new file mode 100644 index 000000000000..f1e7d6e24b83 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-my/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"အထောက်အထားစိစစ်ခြင်း မအောင်မြင်ပါ -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"ဝန်ဆောင်မှုကို စာရင်းသွင်းမထားပါ -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"ပေးထားသော APN အတွက် PDN ချိတ်ဆက်မှုအများအပြားကို ခွင့်မပြုပါ -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-nb/strings.xml b/core/res/res/values-mcc334-mnc020-nb/strings.xml new file mode 100644 index 000000000000..623f2d98663f --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-nb/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"AUTENTISERINGSFEIL -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"ABONNERER IKKE PÅ TJENESTEN -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Flere PDN-tilkoblinger for et gitt APN er ikke tillatt -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-ne/strings.xml b/core/res/res/values-mcc334-mnc020-ne/strings.xml new file mode 100644 index 000000000000..fd692766c5d2 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-ne/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"पुष्टि गर्न सकिएन -२९-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"सेवाको सदस्यता लिइएको छैन -३३-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"कुनै निश्चित APN का हकमा एकभन्दा बढी PDN कनेक्सन गर्ने अनुमति दिइएको छैन -५५-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-nl/strings.xml b/core/res/res/values-mcc334-mnc020-nl/strings.xml new file mode 100644 index 000000000000..40cb2fa4e6e2 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-nl/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"VERIFICATIE MISLUKT -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"NIET GEABONNEERD OP SERVICE -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Meerdere PDN-verbindingen voor een bepaalde APN niet toegestaan -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-or/strings.xml b/core/res/res/values-mcc334-mnc020-or/strings.xml new file mode 100644 index 000000000000..49810d511372 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-or/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"ପ୍ରାମାଣିକତା ବିଫଳ ହୋଇଛି -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"ସେବା ପାଇଁ ସଦସ୍ୟତା ନିଆଯାଇନାହିଁ -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"ଦିଆଯାଇଥିବା ଏକ APN ପାଇଁ ଏକାଧିକ PDN ସଂଯୋଗକୁ ଅନୁମତି ଦିଆଯାଇନାହିଁ -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-pa/strings.xml b/core/res/res/values-mcc334-mnc020-pa/strings.xml new file mode 100644 index 000000000000..3cf6bc88e70e --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-pa/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"ਪ੍ਰਮਾਣੀਕਰਨ ਅਸਫਲ -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"ਸੇਵਾ ਦੀ ਗਾਹਕੀ ਨਹੀਂ ਲਈ -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"ਕਿਸੇ ਵੀ APN ਲਈ ਇੱਕ ਤੋਂ ਵੱਧ PDN ਕਨੈਕਸ਼ਨਾਂ ਦੀ ਆਗਿਆ ਨਹੀਂ ਹੈ -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-pl/strings.xml b/core/res/res/values-mcc334-mnc020-pl/strings.xml new file mode 100644 index 000000000000..9c5fd78b9527 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-pl/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"BŁĄD UWIERZYTELNIANIA -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"USŁUGA NIESUBSKRYBOWANA -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Wielokrotne połączenia PDN w danym APN nie są dozwolone -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-pt-rBR/strings.xml b/core/res/res/values-mcc334-mnc020-pt-rBR/strings.xml new file mode 100644 index 000000000000..1292978cc840 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-pt-rBR/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"FALHA NA AUTENTICAÇÃO -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"A CONTA NÃO ESTÁ INSCRITA NO SERVIÇO -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Não é permitido ter várias conexões PDN para um determinado APN -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-pt-rPT/strings.xml b/core/res/res/values-mcc334-mnc020-pt-rPT/strings.xml new file mode 100644 index 000000000000..68248f3f6d94 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-pt-rPT/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"FALHA NA AUTENTICAÇÃO -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"NÃO SUBSCREVEU O SERVIÇO -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Não são permitidas várias ligações PDN para um determinado APN -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-pt/strings.xml b/core/res/res/values-mcc334-mnc020-pt/strings.xml new file mode 100644 index 000000000000..1292978cc840 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-pt/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"FALHA NA AUTENTICAÇÃO -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"A CONTA NÃO ESTÁ INSCRITA NO SERVIÇO -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Não é permitido ter várias conexões PDN para um determinado APN -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-ro/strings.xml b/core/res/res/values-mcc334-mnc020-ro/strings.xml new file mode 100644 index 000000000000..92564e977617 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-ro/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"EROARE DE AUTENTIFICARE -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"FĂRĂ ABONAMENT LA SERVICIU -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Nu se permit mai multe conexiuni PDN pentru un anumit APN -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-ru/strings.xml b/core/res/res/values-mcc334-mnc020-ru/strings.xml new file mode 100644 index 000000000000..f4647ba04139 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-ru/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"ОШИБКА АУТЕНТИФИКАЦИИ -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"НЕТ ПОДПИСКИ НА СЕРВИС -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Указанная точка доступа не поддерживает несколько PDN-соединений -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-si/strings.xml b/core/res/res/values-mcc334-mnc020-si/strings.xml new file mode 100644 index 000000000000..cb839758b29d --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-si/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"සත්යාපනය අසාර්ථකයි -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"සේවාවකට ග්රාහක වී නැත -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"දී ඇති APN එකක් සඳහා බහුවිධ PDN සම්බන්ධතා ඉඩ නොදේ -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-sk/strings.xml b/core/res/res/values-mcc334-mnc020-sk/strings.xml new file mode 100644 index 000000000000..77efe302ecc0 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-sk/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"NEPODARILO SA OVERIŤ -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"SLUŽBU NEODOBERÁTE -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Pre daný názov prístupového bodu (APN) nie je povolených viacero pripojení PDN -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-sl/strings.xml b/core/res/res/values-mcc334-mnc020-sl/strings.xml new file mode 100644 index 000000000000..118c3dde0411 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-sl/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"NAPAKA PRI PREVERJANJU PRISTNOSTI. -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"NISTE NAROČENI NA STORITEV. -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Za dano ime dostopne točke (APN) ni dovoljenih več povezav PDN. -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-sq/strings.xml b/core/res/res/values-mcc334-mnc020-sq/strings.xml new file mode 100644 index 000000000000..315a8abba377 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-sq/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"DËSHTIM NË VERIFIKIM -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"NUK JE ABONUAR NË SHËRBIM -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Disa lidhje PDN për një APN të caktuar nuk lejohen -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-sr/strings.xml b/core/res/res/values-mcc334-mnc020-sr/strings.xml new file mode 100644 index 000000000000..ddf0ce15aa78 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-sr/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"ПОТВРДА ИДЕНТИТЕТА НИЈЕ УСПЕЛА -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"НИСТЕ ПРЕТПЛАЋЕНИ НА УСЛУГУ -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Није дозвољено више PDN веза за одређени APN -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-sv/strings.xml b/core/res/res/values-mcc334-mnc020-sv/strings.xml new file mode 100644 index 000000000000..75bc6427cf55 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-sv/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"AUTENTISERINGSFEL -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"PRENUMERERAR INTE PÅ TJÄNSTEN -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Flera PDN-anslutningar för samma APN tillåts inte -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-sw/strings.xml b/core/res/res/values-mcc334-mnc020-sw/strings.xml new file mode 100644 index 000000000000..275f628eab06 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-sw/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"IMESHINDWA KUTHIBITISHA -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"HUJAJISAJILI KWENYE HUDUMA -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Miunganisho mingi ya PDN kwenye APN husika hairuhusiwi -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-ta/strings.xml b/core/res/res/values-mcc334-mnc020-ta/strings.xml new file mode 100644 index 000000000000..699ea71f7d8d --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-ta/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"அங்கீகரிக்க முடியவில்லை -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"சேவைக்குச் சந்தா பெறவில்லை -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"ஒரு APNக்குப் பல PDN இணைப்புகள் அனுமதிக்கப்படாது -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-te/strings.xml b/core/res/res/values-mcc334-mnc020-te/strings.xml new file mode 100644 index 000000000000..eee21aa44677 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-te/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"ప్రామాణీకరణ వైఫల్యం -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"ఈ సర్వీస్ కోసం సబ్స్క్రయిబ్ చేసుకోలేదు -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"ఈ APNలో బహుళ PDN కనెక్షన్లు అనుమతించబడవు -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-th/strings.xml b/core/res/res/values-mcc334-mnc020-th/strings.xml new file mode 100644 index 000000000000..e4e62f0a0417 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-th/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"การตรวจสอบสิทธิ์ล้มเหลว -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"ไม่ได้สมัครใช้บริการ -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"ไม่อนุญาตการเชื่อมต่อ PDN หลายรายการสำหรับ APN ที่กำหนด -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-tl/strings.xml b/core/res/res/values-mcc334-mnc020-tl/strings.xml new file mode 100644 index 000000000000..e05ef9ba28c3 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-tl/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"HINDI NA-AUTHENTICATE -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"HINDI NAKA-SUBSCRIBE SA SERBISYO -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Hindi pinapayagan ang maraming PDN na koneksyon para sa isang partikular na APN -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-tr/strings.xml b/core/res/res/values-mcc334-mnc020-tr/strings.xml new file mode 100644 index 000000000000..7c83aeee3d7f --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-tr/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"KİMLİK DOĞRULAMA HATASI -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"HİZMETE ABONE OLUNMADI -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Belirli bir APN için birden fazla PDN bağlantısına izin verilmez -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-uk/strings.xml b/core/res/res/values-mcc334-mnc020-uk/strings.xml new file mode 100644 index 000000000000..dc18a3ed520f --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-uk/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"ПОМИЛКА АВТЕНТИФІКАЦІЇ -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"НЕМАЄ ПІДПИСКИ НА СЕРВІС -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"З цієї APN не можна підключатися до кількох відкритих мереж -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-ur/strings.xml b/core/res/res/values-mcc334-mnc020-ur/strings.xml new file mode 100644 index 000000000000..25b074eec145 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-ur/strings.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <!-- no translation found for config_pdp_reject_user_authentication_failed (4683454131283459978) --> + <skip /> + <!-- no translation found for config_pdp_reject_service_not_subscribed (9021140729932308119) --> + <skip /> + <!-- no translation found for config_pdp_reject_multi_conn_to_same_pdn_not_allowed (3838388706348367865) --> + <skip /> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-uz/strings.xml b/core/res/res/values-mcc334-mnc020-uz/strings.xml new file mode 100644 index 000000000000..321aff2efbd2 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-uz/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"HAQIQIYLIK TEKSHIRUVIDA XATO -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"XIZMATGA OBUNA QILINMAGAN -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"APN uchun bir nechta PDN ulanishiga ruxsat berilmagan -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-vi/strings.xml b/core/res/res/values-mcc334-mnc020-vi/strings.xml new file mode 100644 index 000000000000..bb77bb5298c2 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-vi/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"KHÔNG XÁC THỰC ĐƯỢC -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"CHƯA ĐĂNG KÝ DỊCH VỤ -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Không cho phép có nhiều kết nối PDN với một APN đã cho -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-zh-rCN/strings.xml b/core/res/res/values-mcc334-mnc020-zh-rCN/strings.xml new file mode 100644 index 000000000000..25b074eec145 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-zh-rCN/strings.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <!-- no translation found for config_pdp_reject_user_authentication_failed (4683454131283459978) --> + <skip /> + <!-- no translation found for config_pdp_reject_service_not_subscribed (9021140729932308119) --> + <skip /> + <!-- no translation found for config_pdp_reject_multi_conn_to_same_pdn_not_allowed (3838388706348367865) --> + <skip /> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-zh-rHK/strings.xml b/core/res/res/values-mcc334-mnc020-zh-rHK/strings.xml new file mode 100644 index 000000000000..af2057828128 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-zh-rHK/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"認證錯誤 -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"未訂閱服務 -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"指定的 APN 不允許有多個 PDN 連線 -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-zh-rTW/strings.xml b/core/res/res/values-mcc334-mnc020-zh-rTW/strings.xml new file mode 100644 index 000000000000..2d74d5abfa55 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-zh-rTW/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"驗證失敗 -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"未訂閱服務 -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"指定的 APN 不允許有多個 PDN 連線 -55-"</string> +</resources> diff --git a/core/res/res/values-mcc334-mnc020-zu/strings.xml b/core/res/res/values-mcc334-mnc020-zu/strings.xml new file mode 100644 index 000000000000..ef0f3cbbde89 --- /dev/null +++ b/core/res/res/values-mcc334-mnc020-zu/strings.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/* +** Copyright 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. +*/ + --> + +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="config_pdp_reject_dialog_title" msgid="41208110171880430"></string> + <string name="config_pdp_reject_user_authentication_failed" msgid="4683454131283459978">"UKWEHLULEKA KOKUFAKAZELA UBUQINISO -29-"</string> + <string name="config_pdp_reject_service_not_subscribed" msgid="9021140729932308119">"AWUBHALISELE ISEVISI -33-"</string> + <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="3838388706348367865">"Uxhumano lwe-PDN oluningi lwe-APN enikeziwe aluvunyelwe -55-"</string> +</resources> diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml index eeb2b5760297..4bb06bb0145d 100644 --- a/core/res/res/values-mr/strings.xml +++ b/core/res/res/values-mr/strings.xml @@ -1040,7 +1040,7 @@ <string name="menu_space_shortcut_label" msgid="5949311515646872071">"स्पेस"</string> <string name="menu_enter_shortcut_label" msgid="6709499510082897320">"एंटर"</string> <string name="menu_delete_shortcut_label" msgid="4365787714477739080">"हटवा"</string> - <string name="search_go" msgid="2141477624421347086">"Search"</string> + <string name="search_go" msgid="2141477624421347086">"शोध"</string> <string name="search_hint" msgid="455364685740251925">"शोधा…"</string> <string name="searchview_description_search" msgid="1045552007537359343">"शोधा"</string> <string name="searchview_description_query" msgid="7430242366971716338">"शोध क्वेरी"</string> diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml index a75ef3d9487c..0cadb45eb0e5 100644 --- a/core/res/res/values-te/strings.xml +++ b/core/res/res/values-te/strings.xml @@ -124,7 +124,7 @@ <string name="roamingTextSearching" msgid="5323235489657753486">"సేవ కోసం శోధిస్తోంది"</string> <string name="wfcRegErrorTitle" msgid="3193072971584858020">"Wi‑Fi కాలింగ్ని సెటప్ చేయడం సాధ్యపడలేదు"</string> <string-array name="wfcOperatorErrorAlertMessages"> - <item msgid="468830943567116703">"Wi-Fiతో కాల్స్ను చేయడానికి మరియు మెసేజ్లను పంపించడానికి, మొదట ఈ సేవను సెటప్ చేయాల్సిందిగా మీ క్యారియర్కి చెప్పండి. ఆ తర్వాత సెట్టింగ్ల నుండి Wi-Fi కాలింగ్ని మళ్లీ ఆన్ చేయండి. (లోపం కోడ్: <xliff:g id="CODE">%1$s</xliff:g>)"</item> + <item msgid="468830943567116703">"Wi-Fiతో కాల్స్ను చేయడానికి, మెసేజ్లను పంపించడానికి, ముందుగా ఈ సర్వీస్ను సెటప్ చేయాల్సిందిగా మీ క్యారియర్ను అడగండి. ఆ తర్వాత సెట్టింగ్ల నుండి Wi-Fi కాలింగ్ను మళ్లీ ఆన్ చేయండి. (ఎర్రర్ కోడ్: <xliff:g id="CODE">%1$s</xliff:g>)"</item> </string-array> <string-array name="wfcOperatorErrorNotificationMessages"> <item msgid="4795145070505729156">"మీ క్యారియర్తో Wi‑Fi కాలింగ్ని నమోదు చేయడంలో సమస్య: <xliff:g id="CODE">%1$s</xliff:g>"</item> @@ -306,10 +306,10 @@ <string name="permgroupdesc_contacts" msgid="9163927941244182567">"మీ కాంటాక్ట్లను యాక్సెస్ చేయడానికి"</string> <string name="permgrouplab_location" msgid="1858277002233964394">"లొకేషన్"</string> <string name="permgroupdesc_location" msgid="1995955142118450685">"ఈ పరికర లొకేషన్ను యాక్సెస్ చేయడానికి"</string> - <string name="permgrouplab_calendar" msgid="6426860926123033230">"Calendar"</string> + <string name="permgrouplab_calendar" msgid="6426860926123033230">"క్యాలెండర్"</string> <string name="permgroupdesc_calendar" msgid="6762751063361489379">"మీ క్యాలెండర్ను యాక్సెస్ చేయడానికి"</string> <string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string> - <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS మెసేజ్లను పంపడం మరియు వీక్షించడం"</string> + <string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS మెసేజ్లను పంపడం, వీక్షించడం"</string> <string name="permgrouplab_storage" msgid="1938416135375282333">"ఫైల్స్, మీడియా"</string> <string name="permgroupdesc_storage" msgid="6351503740613026600">"మీ పరికరంలోని ఫోటోలు, మీడియా మరియు ఫైళ్లను యాక్సెస్ చేయడానికి"</string> <string name="permgrouplab_microphone" msgid="2480597427667420076">"మైక్రోఫోన్"</string> @@ -356,10 +356,10 @@ <string name="permdesc_processOutgoingCalls" msgid="7833149750590606334">"కాల్ను వేరే నంబర్కు దారి మళ్లించే లేదా మొత్తంగా కాల్ను ఆపివేసే ఎంపిక సహాయంతో అవుట్గోయింగ్ కాల్ సమయంలో డయల్ చేయబడుతున్న నంబర్ను చూడటానికి యాప్ను అనుమతిస్తుంది."</string> <string name="permlab_answerPhoneCalls" msgid="4131324833663725855">"ఫోన్ కాల్స్కు సమాధానమివ్వు"</string> <string name="permdesc_answerPhoneCalls" msgid="894386681983116838">"ఇన్కమింగ్ ఫోన్ కాల్స్కు సమాధానమివ్వడానికి యాప్ను అనుమతిస్తుంది."</string> - <string name="permlab_receiveSms" msgid="505961632050451881">"వచన మెసేజ్లను (SMS) స్వీకరించడం"</string> - <string name="permdesc_receiveSms" msgid="1797345626687832285">"SMS మెసేజ్లను స్వీకరించడానికి మరియు ప్రాసెస్ చేయడానికి యాప్ను అనుమతిస్తుంది. యాప్ మీ డివైజ్కు పంపబడిన మెసేజ్లను మీకు చూపకుండానే పర్యవేక్షించగలదని లేదా తొలగించగలదని దీని అర్థం."</string> - <string name="permlab_receiveMms" msgid="4000650116674380275">"వచన మెసేజ్లను (MMS) స్వీకరించడం"</string> - <string name="permdesc_receiveMms" msgid="958102423732219710">"MMS మెసేజ్లను స్వీకరించడానికి మరియు ప్రాసెస్ చేయడానికి యాప్ను అనుమతిస్తుంది. యాప్ మీ డివైజ్కు పంపబడిన మెసేజ్లను మీకు చూపకుండానే పర్యవేక్షించగలదని లేదా తొలగించగలదని దీని అర్థం."</string> + <string name="permlab_receiveSms" msgid="505961632050451881">"టెక్స్ట్ మెసేజ్లను (SMS) స్వీకరించడం"</string> + <string name="permdesc_receiveSms" msgid="1797345626687832285">"SMS మెసేజ్లను స్వీకరించడానికి, ప్రాసెస్ చేయడానికి యాప్ను అనుమతిస్తుంది. మీ డివైజ్కు వచ్చిన మెసేజ్లను మీకు చూపకుండానే యాప్ పర్యవేక్షించగలదని లేదా తొలగించగలదని దీని అర్థం."</string> + <string name="permlab_receiveMms" msgid="4000650116674380275">"టెక్స్ట్ మెసేజ్లను (MMS) స్వీకరించడం"</string> + <string name="permdesc_receiveMms" msgid="958102423732219710">"MMS మెసేజ్లను స్వీకరించడానికి, ప్రాసెస్ చేయడానికి యాప్ను అనుమతిస్తుంది. మీ డివైజ్కు వచ్చిన మెసేజ్లను మీకు చూపకుండానే యాప్ పర్యవేక్షించగలదని లేదా తొలగించగలదని దీని అర్థం."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"సెల్ ప్రసార మెసేజ్లను ఫార్వర్డ్ చేయడం"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"సెల్ ప్రసార మెసేజ్లను స్వీకరించినప్పుడు, వాటిని ఫార్వర్డ్ చేయడానికి సెల్ ప్రసార మాడ్యూల్కు కట్టుబడి ఉండేందుకు యాప్ను అనుమతిస్తుంది. ఎమర్జెన్సీ పరిస్థితుల గురించి మిమ్మల్ని హెచ్చరించడానికి కొన్ని లొకేషన్లలో సెల్ ప్రసార అలర్ట్లు డెలివరీ చేయబడతాయి. ఎమర్జెన్సీ సెల్ ప్రసార అలర్ట్ను స్వీకరించినప్పుడు హానికరమైన యాప్లు మీ పరికరం పనితీరుకు లేదా నిర్వహణకు ఆటంకం కలిగించే అవకాశం ఉంది."</string> <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"కొనసాగుతున్న కాల్స్ను మేనేజ్ చేయి"</string> @@ -368,14 +368,14 @@ <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"మీ పరికరం స్వీకరించిన సెల్ ప్రసార మెసేజ్లను చదవడానికి యాప్ను అనుమతిస్తుంది. ఎమర్జెన్సీ పరిస్థితుల గురించి మిమ్మల్ని హెచ్చరించడానికి కొన్ని లొకేషన్లలో సెల్ ప్రసార అలర్ట్లు డెలివరీ చేయబడతాయి. ఎమర్జెన్సీ సెల్ ప్రసార అలర్ట్ను స్వీకరించినప్పుడు హానికరమైన యాప్లు మీ పరికరం పనితీరుకు లేదా నిర్వహణకు ఆటంకం కలిగించే అవకాశం ఉంది."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"చందా చేయబడిన ఫీడ్లను చదవడం"</string> <string name="permdesc_subscribedFeedsRead" msgid="6911349196661811865">"ప్రస్తుతం సమకాలీకరించిన ఫీడ్ల గురించి వివరాలను పొందడానికి యాప్ను అనుమతిస్తుంది."</string> - <string name="permlab_sendSms" msgid="7757368721742014252">"SMS మెసేజ్లను పంపడం మరియు వీక్షించడం"</string> + <string name="permlab_sendSms" msgid="7757368721742014252">"SMS మెసేజ్లను పంపడం, వీక్షించడం"</string> <string name="permdesc_sendSms" msgid="6757089798435130769">"SMS మెసేజ్లు పంపడానికి యాప్ను అనుమతిస్తుంది. దీని వలన ఊహించని ఛార్జీలు విధించబడవచ్చు. హానికరమైన యాప్లు మీ నిర్ధారణ లేకుండానే మెసేజ్లను పంపడం ద్వారా మీకు డబ్బు ఖర్చయ్యేలా చేయవచ్చు."</string> - <string name="permlab_readSms" msgid="5164176626258800297">"మీ వచన మెసేజ్లు (SMS లేదా MMS) చదవడం"</string> - <string name="permdesc_readSms" product="tablet" msgid="7912990447198112829">"ఈ యాప్ మీ టాబ్లెట్లో నిల్వ చేసిన అన్ని SMS (వచన) మెసేజ్లను చదవగలదు."</string> - <string name="permdesc_readSms" product="tv" msgid="3054753345758011986">"ఈ యాప్ మీ Android TV పరికరంలో నిల్వ అయిన SMS (వచనం) సందేశాలన్నింటినీ చదవగలదు."</string> - <string name="permdesc_readSms" product="default" msgid="774753371111699782">"ఈ యాప్ మీ ఫోన్లో నిల్వ చేసిన అన్ని SMS (వచన) మెసేజ్లను చదవగలదు."</string> - <string name="permlab_receiveWapPush" msgid="4223747702856929056">"వచన మెసేజ్లను (WAP) స్వీకరించడం"</string> - <string name="permdesc_receiveWapPush" msgid="1638677888301778457">"WAP మెసేజ్లను స్వీకరించడానికి మరియు ప్రాసెస్ చేయడానికి యాప్ను అనుమతిస్తుంది. ఈ అనుమతి మీకు పంపబడిన మెసేజ్లను మీకు చూపకుండానే పర్యవేక్షించగల లేదా తొలగించగల సామర్థ్యాన్ని కలిగి ఉంటుంది."</string> + <string name="permlab_readSms" msgid="5164176626258800297">"మీ టెక్స్ట్ మెసేజ్లు (SMS లేదా MMS) చదవడం"</string> + <string name="permdesc_readSms" product="tablet" msgid="7912990447198112829">"ఈ యాప్ మీ టాబ్లెట్లో స్టోర్ చేసిన అన్ని SMS (టెక్స్ట్) మెసేజ్లను చదవగలదు."</string> + <string name="permdesc_readSms" product="tv" msgid="3054753345758011986">"ఈ యాప్ మీ Android TV పరికరంలో స్టోర్ అయిన SMS (టెక్స్ట్) మెసేజ్లు అన్నింటిని చదవగలదు."</string> + <string name="permdesc_readSms" product="default" msgid="774753371111699782">"ఈ యాప్ మీ ఫోన్లో నిల్వ చేసిన అన్ని SMS (టెక్స్ట్) మెసేజ్లను చదవగలదు."</string> + <string name="permlab_receiveWapPush" msgid="4223747702856929056">"టెక్స్ట్ మెసేజ్లను (WAP) స్వీకరించడం"</string> + <string name="permdesc_receiveWapPush" msgid="1638677888301778457">"WAP మెసేజ్లను స్వీకరించడానికి, ప్రాసెస్ చేయడానికి యాప్ను అనుమతిస్తుంది. ఈ అనుమతి మీకు వచ్చిన మెసేజ్లను మీకు చూపకుండానే పర్యవేక్షించగల లేదా తొలగించగల సామర్థ్యాన్ని కలిగి ఉంటుంది."</string> <string name="permlab_getTasks" msgid="7460048811831750262">"అమలవుతున్న యాప్లను పునరుద్ధరించడం"</string> <string name="permdesc_getTasks" msgid="7388138607018233726">"ప్రస్తుతం మరియు ఇటీవల అమలవుతున్న విధుల గురించి వివరణాత్మక సమాచారాన్ని తిరిగి పొందడానికి యాప్ను అనుమతిస్తుంది. ఇది పరికరంలో ఉపయోగించబడిన యాప్ల గురించి సమాచారాన్ని కనుగొనడానికి యాప్ను అనుమతించవచ్చు."</string> <string name="permlab_manageProfileAndDeviceOwners" msgid="639849495253987493">"ప్రొఫైల్ మరియు పరికర యజమానులను నిర్వహించడం"</string> @@ -431,9 +431,9 @@ <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"ఈ యాప్ మీ Android TV పరికరంలో నిల్వ చేసిన క్యాలెండర్ ఈవెంట్లన్నీ చదవగలదు, మీ క్యాలెండర్ డేటాను షేర్ చేయగలదు లేదా సేవ్ చేయగలదు."</string> <string name="permdesc_readCalendar" product="default" msgid="9118823807655829957">"ఈ యాప్ మీ ఫోన్లో నిల్వ చేసిన క్యాలెండర్ ఈవెంట్లన్నీ చదవగలదు మరియు మీ క్యాలెండర్ డేటాను షేర్ చేయగలదు లేదా సేవ్ చేయగలదు."</string> <string name="permlab_writeCalendar" msgid="6422137308329578076">"యజమానికి తెలియకుండానే క్యాలెండర్ ఈవెంట్లను జోడించి లేదా సవరించి, అతిథులకు ఇమెయిల్ పంపడం"</string> - <string name="permdesc_writeCalendar" product="tablet" msgid="8722230940717092850">"ఈ యాప్ మీ టాబ్లెట్లో క్యాలెండర్ ఈవెంట్లను జోడించగలదు, తీసివేయగలదు లేదా మార్చగలదు. ఈ యాప్ క్యాలెండర్ యజమానుల నుండి వచ్చినట్లుగా మెసేజ్లను పంపగలదు లేదా ఈవెంట్లను వాటి యజమానులకు తెలియకుండానే మార్చగలదు."</string> - <string name="permdesc_writeCalendar" product="tv" msgid="951246749004952706">"ఈ యాప్ మీ Android TV పరికరంలో క్యాలెండర్ ఈవెంట్లను జోడించగలదు, తీసివేయగలదు లేదా మార్చగలదు. ఈ యాప్ క్యాలెండర్ యజమానుల నుండి వచ్చినట్లుగా మెసేజ్లను పంపగలదు లేదా ఈవెంట్లను వాటి యజమానులకు తెలియకుండానే మార్చగలదు."</string> - <string name="permdesc_writeCalendar" product="default" msgid="5416380074475634233">"ఈ యాప్ మీ ఫోన్లో క్యాలెండర్ ఈవెంట్లను జోడించగలదు, తీసివేయగలదు లేదా మార్చగలదు. ఈ యాప్ క్యాలెండర్ యజమానుల నుండి వచ్చినట్లుగా మెసేజ్లను పంపగలదు లేదా ఈవెంట్లను వాటి యజమానులకు తెలియకుండానే మార్చగలదు."</string> + <string name="permdesc_writeCalendar" product="tablet" msgid="8722230940717092850">"ఈ యాప్ మీ టాబ్లెట్లో క్యాలెండర్ ఈవెంట్లను జోడించగలదు, తీసివేయగలదు లేదా మార్చగలదు. ఈ యాప్ క్యాలెండర్ ఓనర్ల నుండి వచ్చినట్లుగా మెసేజ్లను పంపగలదు లేదా ఈవెంట్లను వాటి ఓనర్లకు తెలియకుండానే మార్చగలదు."</string> + <string name="permdesc_writeCalendar" product="tv" msgid="951246749004952706">"ఈ యాప్ మీ Android TV పరికరంలో క్యాలెండర్ ఈవెంట్లను జోడించగలదు, తీసివేయగలదు లేదా మార్చగలదు. ఈ యాప్ క్యాలెండర్ ఓనర్ల నుండి వచ్చినట్లుగా మెసేజ్లను పంపగలదు లేదా ఈవెంట్లను వాటి ఓనర్లకు తెలియకుండానే మార్చగలదు."</string> + <string name="permdesc_writeCalendar" product="default" msgid="5416380074475634233">"ఈ యాప్ మీ ఫోన్లో క్యాలెండర్ ఈవెంట్లను జోడించగలదు, తీసివేయగలదు లేదా మార్చగలదు. ఈ యాప్ క్యాలెండర్ ఓనర్ల నుండి వచ్చినట్లుగా మెసేజ్లను పంపగలదు, లేదా ఈవెంట్లను వాటి ఓనర్లకు తెలియకుండానే మార్చగలదు."</string> <string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"అదనపు లొకేషన్ ప్రొవైడర్ కమాండ్లను యాక్సెస్ చేయడం"</string> <string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"అదనపు లొకేషన్ ప్రొవైడర్ కమాండ్లను యాక్సెస్ చేయడానికి యాప్ను అనుమతిస్తుంది. ఇది GPS లేదా ఇతర లొకేషన్ సోర్స్ల నిర్వహణలో యాప్ ప్రమేయం ఉండేలా అనుమతించవచ్చు."</string> <string name="permlab_accessFineLocation" msgid="6426318438195622966">"స్క్రీన్పై ఉన్నప్పుడు మాత్రమే ఖచ్చితమైన లొకేషన్ను యాక్సెస్ చేయండి"</string> @@ -817,7 +817,7 @@ <string name="phoneTypeTtyTdd" msgid="532038552105328779">"TTY TDD"</string> <string name="phoneTypeWorkMobile" msgid="7522314392003565121">"కార్యాలయ మొబైల్"</string> <string name="phoneTypeWorkPager" msgid="3748332310638505234">"కార్యాలయ పేజర్"</string> - <string name="phoneTypeAssistant" msgid="757550783842231039">"Assistant"</string> + <string name="phoneTypeAssistant" msgid="757550783842231039">"అసిస్టెంట్"</string> <string name="phoneTypeMms" msgid="1799747455131365989">"MMS"</string> <string name="eventTypeCustom" msgid="3257367158986466481">"అనుకూలం"</string> <string name="eventTypeBirthday" msgid="7770026752793912283">"పుట్టినరోజు"</string> @@ -850,7 +850,7 @@ <string name="orgTypeOther" msgid="5450675258408005553">"ఇతరం"</string> <string name="orgTypeCustom" msgid="1126322047677329218">"అనుకూలం"</string> <string name="relationTypeCustom" msgid="282938315217441351">"అనుకూలం"</string> - <string name="relationTypeAssistant" msgid="4057605157116589315">"Assistant"</string> + <string name="relationTypeAssistant" msgid="4057605157116589315">"అసిస్టెంట్"</string> <string name="relationTypeBrother" msgid="7141662427379247820">"సోదరుడు"</string> <string name="relationTypeChild" msgid="9076258911292693601">"బిడ్డ"</string> <string name="relationTypeDomesticPartner" msgid="7825306887697559238">"జీవిత భాగస్వామి"</string> @@ -1014,7 +1014,7 @@ <string name="permlab_setAlarm" msgid="1158001610254173567">"అలారం సెట్ చేయడం"</string> <string name="permdesc_setAlarm" msgid="2185033720060109640">"ఇన్స్టాల్ చేయబడిన అలారం గడియారం యాప్లో అలారంను సెట్ చేయడానికి యాప్ను అనుమతిస్తుంది. కొన్ని అలారం గల గడియారం యాప్లు ఈ ఫీచర్ను అమలు చేయకపోవచ్చు."</string> <string name="permlab_addVoicemail" msgid="4770245808840814471">"వాయిస్ మెయిల్ను జోడించడం"</string> - <string name="permdesc_addVoicemail" msgid="5470312139820074324">"మీ వాయిస్ మెయిల్ ఇన్బాక్స్కి మెసేజ్లను జోడించడానికి యాప్ను అనుమతిస్తుంది."</string> + <string name="permdesc_addVoicemail" msgid="5470312139820074324">"మీ వాయిస్ మెయిల్ ఇన్బాక్స్కు మెసేజ్లను జోడించడానికి యాప్ను అనుమతిస్తుంది."</string> <string name="permlab_writeGeolocationPermissions" msgid="8605631647492879449">"బ్రౌజర్ భౌగోళిక స్థానం అనుమతులను సవరించడం"</string> <string name="permdesc_writeGeolocationPermissions" msgid="5817346421222227772">"బ్రౌజర్ యొక్క భౌగోళిక లొకేషన్ అనుమతులను సవరించడానికి యాప్ను అనుమతిస్తుంది. హానికరమైన యాప్లు ఏకపక్ష వెబ్ సైట్లకు లొకేషన్ సమాచారాన్ని అనుమతించడానికి దీన్ని ఉపయోగించవచ్చు."</string> <string name="save_password_message" msgid="2146409467245462965">"మీరు బ్రౌజర్ ఈ పాస్వర్డ్ను గుర్తుపెట్టుకోవాలని కోరుకుంటున్నారా?"</string> @@ -2010,7 +2010,7 @@ <string name="app_category_image" msgid="7307840291864213007">"ఫోటోలు, ఇమేజ్లు"</string> <string name="app_category_social" msgid="2278269325488344054">"సామాజికం & కమ్యూనికేషన్"</string> <string name="app_category_news" msgid="1172762719574964544">"వార్తలు & వార్తాపత్రికలు"</string> - <string name="app_category_maps" msgid="6395725487922533156">"Maps & నావిగేషన్"</string> + <string name="app_category_maps" msgid="6395725487922533156">"మ్యాప్స్ & నావిగేషన్"</string> <string name="app_category_productivity" msgid="1844422703029557883">"ఉత్పాదకత"</string> <string name="app_category_accessibility" msgid="6643521607848547683">"యాక్సెసిబిలిటీ"</string> <string name="device_storage_monitor_notification_channel" msgid="5164244565844470758">"పరికర నిల్వ"</string> @@ -2055,7 +2055,7 @@ <string name="etws_primary_default_message_earthquake" msgid="8401079517718280669">"ప్రశాంతంగా ఉండండి మరియు దగ్గర్లో తలదాచుకోండి."</string> <string name="etws_primary_default_message_tsunami" msgid="5828171463387976279">"వెంటనే తీర ప్రాంతాలు మరియు నదీ పరీవాహక ప్రాంతాలను ఖాళీ చేసి మెట్ట ప్రాంతాలకు తరలి వెళ్లండి."</string> <string name="etws_primary_default_message_earthquake_and_tsunami" msgid="4888224011071875068">"ప్రశాంతంగా ఉండండి మరియు దగ్గర్లో తలదాచుకోండి."</string> - <string name="etws_primary_default_message_test" msgid="4583367373909549421">"అత్యవసర మెసేజ్ల పరీక్ష"</string> + <string name="etws_primary_default_message_test" msgid="4583367373909549421">"అత్యవసర మెసేజ్ల టెస్ట్"</string> <string name="notification_reply_button_accessibility" msgid="5235776156579456126">"రిప్లయి పంపండి"</string> <string name="etws_primary_default_message_others" msgid="7958161706019130739"></string> <string name="mmcc_authentication_reject" msgid="4891965994643876369">"వాయిస్ కోసం SIM అనుమతించబడదు"</string> @@ -2101,7 +2101,7 @@ <string name="nas_upgrade_notification_enable_action" msgid="3046406808378726874">"సరే"</string> <string name="nas_upgrade_notification_disable_action" msgid="3794833210043497982">"ఆఫ్ చేయండి"</string> <string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"మరింత తెలుసుకోండి"</string> - <string name="nas_upgrade_notification_learn_more_content" msgid="3735480566983530650">"Android 12లో Android అనుకూల నోటిఫికేషన్లను, మెరుగైన నోటిఫికేషన్లు భర్తీ చేశాయి. సూచించిన చర్యలు, రిప్లయిలను ఈ ఫీచర్ చూపించి, మీ నోటిఫికేషన్లను ఆర్గనైజ్ చేస్తుంది.\n\nకాంటాక్ట్ పేర్లు, మెసేజ్లు లాంటి వ్యక్తిగత సమాచారంతో సహా నోటిఫికేషన్ కంటెంట్ను మెరుగైన నోటిఫికేషన్లు యాక్సెస్ చేయవచ్చు. ఫోన్ కాల్స్కు సమాధానమివ్వడం, \'అంతరాయం కలిగించవద్దు\' ఆప్షన్ను కంట్రోల్ చేయడం లాంటి నోటిఫికేషన్లను విస్మరించడం లేదా ప్రతిస్పందించడం కూడా ఈ ఫీచర్ చేయగలదు."</string> + <string name="nas_upgrade_notification_learn_more_content" msgid="3735480566983530650">"Android 12లో Android అనుకూల నోటిఫికేషన్లను, మెరుగైన నోటిఫికేషన్లు రీప్లేస్ చేశాయి. ఈ ఫీచర్, సూచించిన చర్యలను, రిప్లయిలను చూపించి, మీ నోటిఫికేషన్లను ఆర్గనైజ్ చేస్తుంది.\n\nకాంటాక్ట్ పేర్లు, మెసేజ్లు లాంటి వ్యక్తిగత సమాచారంతో పాటు నోటిఫికేషన్ కంటెంట్ను మెరుగైన నోటిఫికేషన్లు యాక్సెస్ చేస్తాయి. ఫోన్ కాల్స్కు సమాధానమివ్వడం, \'అంతరాయం కలిగించవద్దు\' ఆప్షన్ను కంట్రోల్ చేయడం వంటి నోటిఫికేషన్లను విస్మరించడం లేదా వాటికి ప్రతిస్పందించడం కూడా ఈ ఫీచర్ చేయగలదు."</string> <string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"రొటీన్ మోడ్ సమాచార నోటిఫికేషన్"</string> <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"మామూలుగా ఛార్జ్ చేసేలోపు బ్యాటరీ ఖాళీ కావచ్చు"</string> <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"బ్యాటరీ జీవితకాలాన్ని పెంచడానికి బ్యాటరీ సేవర్ యాక్టివేట్ చేయబడింది"</string> diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 53396407904a..77820d1dfa38 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -8372,8 +8372,8 @@ <attr name="supportsAmbientMode" format="boolean" /> <!-- Indicates that this wallpaper service should receive zoom transition updates when - changing the device state (e.g. when folding or unfolding a foldable device). - When this value is set to true + changing the display state of the device (e.g. when folding or unfolding + a foldable device). When this value is set to true {@link android.service.wallpaper.WallpaperService.Engine} could receive zoom updates before or after changing the device state. Wallpapers receive zoom updates using {@link android.service.wallpaper.WallpaperService.Engine#onZoomChanged(float)} and @@ -8381,8 +8381,8 @@ {@link android.service.wallpaper.WallpaperService.Engine} is created and not destroyed. Default value is true. Corresponds to - {@link android.app.WallpaperInfo#shouldUseDefaultDeviceStateChangeTransition()} --> - <attr name="shouldUseDefaultDeviceStateChangeTransition" format="boolean" /> + {@link android.app.WallpaperInfo#shouldUseDefaultDisplayStateChangeTransition()} --> + <attr name="shouldUseDefaultDisplayStateChangeTransition" format="boolean" /> <!-- Uri that specifies a settings Slice for this wallpaper. --> <attr name="settingsSliceUri" format="string"/> diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml index b191584345ef..59d6005ba193 100644 --- a/core/res/res/values/colors.xml +++ b/core/res/res/values/colors.xml @@ -246,37 +246,37 @@ <!-- Lightest shade of the accent color used by the system. White. This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_accent1_0">#ffffff</color> - <!-- Shade of the accent system color at 99% lightness. + <!-- Shade of the accent system color at 99% perceptual luminance (L* in L*a*b* color space). This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_accent1_10">#F9FCFF</color> - <!-- Shade of the accent system color at 95% lightness. + <!-- Shade of the accent system color at 95% perceptual luminance (L* in L*a*b* color space). This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_accent1_50">#E0F3FF</color> - <!-- Shade of the accent system color at 90% lightness. + <!-- Shade of the accent system color at 90% perceptual luminance (L* in L*a*b* color space). This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_accent1_100">#C1E8FF</color> - <!-- Shade of the accent system color at 80% lightness. + <!-- Shade of the accent system color at 80% perceptual luminance (L* in L*a*b* color space). This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_accent1_200">#76D1FF</color> - <!-- Shade of the accent system color at 70% lightness. + <!-- Shade of the accent system color at 70% perceptual luminance (L* in L*a*b* color space). This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_accent1_300">#4BB6E8</color> - <!-- Shade of the accent system color at 60% lightness. + <!-- Shade of the accent system color at 60% perceptual luminance (L* in L*a*b* color space). This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_accent1_400">#219BCC</color> - <!-- Shade of the accent system color at 49% lightness. + <!-- Shade of the accent system color at 49.6% perceptual luminance (L* in L*a*b* color space). This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_accent1_500">#007FAC</color> - <!-- Shade of the accent system color at 40% lightness. + <!-- Shade of the accent system color at 40% perceptual luminance (L* in L*a*b* color space). This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_accent1_600">#00668B</color> - <!-- Shade of the accent system color at 30% lightness. + <!-- Shade of the accent system color at 30% perceptual luminance (L* in L*a*b* color space). This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_accent1_700">#004C69</color> - <!-- Shade of the accent system color at 20% lightness. + <!-- Shade of the accent system color at 20% perceptual luminance (L* in L*a*b* color space). This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_accent1_800">#003549</color> - <!-- Shade of the accent system color at 10% lightness. + <!-- Shade of the accent system color at 10% perceptual luminance (L* in L*a*b* color space). This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_accent1_900">#001E2C</color> <!-- Darkest shade of the accent color used by the system. Black. @@ -286,37 +286,37 @@ <!-- Lightest shade of the secondary accent color used by the system. White. This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_accent2_0">#ffffff</color> - <!-- Shade of the secondary accent system color at 99% lightness. + <!-- Shade of the secondary accent system color at 99% perceptual luminance (L* in L*a*b* color space). This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_accent2_10">#F9FCFF</color> - <!-- Shade of the secondary accent system color at 95% lightness. + <!-- Shade of the secondary accent system color at 95% perceptual luminance (L* in L*a*b* color space). This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_accent2_50">#E0F3FF</color> - <!-- Shade of the secondary accent system color at 90% lightness. + <!-- Shade of the secondary accent system color at 90% perceptual luminance (L* in L*a*b* color space). This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_accent2_100">#D1E5F4</color> - <!-- Shade of the secondary accent system color at 80% lightness. + <!-- Shade of the secondary accent system color at 80% perceptual luminance (L* in L*a*b* color space). This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_accent2_200">#B5CAD7</color> - <!-- Shade of the secondary accent system color at 70% lightness. + <!-- Shade of the secondary accent system color at 70% perceptual luminance (L* in L*a*b* color space). This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_accent2_300">#9AAEBB</color> - <!-- Shade of the secondary accent system color at 60% lightness. + <!-- Shade of the secondary accent system color at 60% perceptual luminance (L* in L*a*b* color space). This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_accent2_400">#8094A0</color> - <!-- Shade of the secondary accent system color at 49% lightness. + <!-- Shade of the secondary accent system color at 49.6% perceptual luminance (L* in L*a*b* color space). This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_accent2_500">#657985</color> - <!-- Shade of the secondary accent system color at 40% lightness. + <!-- Shade of the secondary accent system color at 40% perceptual luminance (L* in L*a*b* color space). This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_accent2_600">#4E616C</color> - <!-- Shade of the secondary accent system color at 30% lightness. + <!-- Shade of the secondary accent system color at 30% perceptual luminance (L* in L*a*b* color space). This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_accent2_700">#374955</color> - <!-- Shade of the secondary accent system color at 20% lightness. + <!-- Shade of the secondary accent system color at 20% perceptual luminance (L* in L*a*b* color space). This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_accent2_800">#20333D</color> - <!-- Shade of the secondary accent system color at 10% lightness. + <!-- Shade of the secondary accent system color at 10% perceptual luminance (L* in L*a*b* color space). This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_accent2_900">#091E28</color> <!-- Darkest shade of the secondary accent color used by the system. Black. @@ -326,37 +326,37 @@ <!-- Lightest shade of the tertiary accent color used by the system. White. This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_accent3_0">#ffffff</color> - <!-- Shade of the tertiary accent system color at 99% lightness. + <!-- Shade of the tertiary accent system color at 99% perceptual luminance (L* in L*a*b* color space). This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_accent3_10">#FFFBFF</color> - <!-- Shade of the tertiary accent system color at 95% lightness. + <!-- Shade of the tertiary accent system color at 95% perceptual luminance (L* in L*a*b* color space). This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_accent3_50">#F5EEFF</color> - <!-- Shade of the tertiary accent system color at 90% lightness. + <!-- Shade of the tertiary accent system color at 90% perceptual luminance (L* in L*a*b* color space). This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_accent3_100">#E6DEFF</color> - <!-- Shade of the tertiary accent system color at 80% lightness. + <!-- Shade of the tertiary accent system color at 80% perceptual luminance (L* in L*a*b* color space). This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_accent3_200">#CAC1EA</color> - <!-- Shade of the tertiary accent system color at 70% lightness. + <!-- Shade of the tertiary accent system color at 70% perceptual luminance (L* in L*a*b* color space). This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_accent3_300">#AEA6CE</color> - <!-- Shade of the tertiary accent system color at 60% lightness. + <!-- Shade of the tertiary accent system color at 60% perceptual luminance (L* in L*a*b* color space). This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_accent3_400">#938CB1</color> - <!-- Shade of the tertiary accent system color at 49% lightness. + <!-- Shade of the tertiary accent system color at 49% perceptual luminance (L* in L*a*b* color space). This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_accent3_500">#787296</color> - <!-- Shade of the tertiary accent system color at 40% lightness. + <!-- Shade of the tertiary accent system color at 40% perceptual luminance (L* in L*a*b* color space). This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_accent3_600">#605A7C</color> - <!-- Shade of the tertiary accent system color at 30% lightness. + <!-- Shade of the tertiary accent system color at 30% perceptual luminance (L* in L*a*b* color space). This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_accent3_700">#484264</color> - <!-- Shade of the tertiary accent system color at 20% lightness. + <!-- Shade of the tertiary accent system color at 20% perceptual luminance (L* in L*a*b* color space). This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_accent3_800">#322C4C</color> - <!-- Shade of the tertiary accent system color at 10% lightness. + <!-- Shade of the tertiary accent system color at 10% perceptual luminance (L* in L*a*b* color space). This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_accent3_900">#1D1736</color> <!-- Darkest shade of the tertiary accent color used by the system. Black. @@ -366,37 +366,37 @@ <!-- Lightest shade of the neutral color used by the system. White. This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_neutral1_0">#ffffff</color> - <!-- Shade of the neutral system color at 99% lightness. + <!-- Shade of the neutral system color at 99% perceptual luminance (L* in L*a*b* color space). This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_neutral1_10">#FCFCFF</color> - <!-- Shade of the neutral system color at 95% lightness. + <!-- Shade of the neutral system color at 95% perceptual luminance (L* in L*a*b* color space). This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_neutral1_50">#F0F0F3</color> - <!-- Shade of the neutral system color at 90% lightness. + <!-- Shade of the neutral system color at 90% perceptual luminance (L* in L*a*b* color space). This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_neutral1_100">#E1E3E5</color> - <!-- Shade of the neutral system color at 80% lightness. + <!-- Shade of the neutral system color at 80% perceptual luminance (L* in L*a*b* color space). This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_neutral1_200">#C5C7C9</color> - <!-- Shade of the neutral system color at 70% lightness. + <!-- Shade of the neutral system color at 70% perceptual luminance (L* in L*a*b* color space). This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_neutral1_300">#AAABAE</color> - <!-- Shade of the neutral system color at 60% lightness. + <!-- Shade of the neutral system color at 60% perceptual luminance (L* in L*a*b* color space). This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_neutral1_400">#8F9193</color> - <!-- Shade of the neutral system color at 49% lightness. + <!-- Shade of the neutral system color at 49% perceptual luminance (L* in L*a*b* color space). This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_neutral1_500">#747679</color> - <!-- Shade of the neutral system color at 40% lightness. + <!-- Shade of the neutral system color at 40% perceptual luminance (L* in L*a*b* color space). This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_neutral1_600">#5C5F61</color> - <!-- Shade of the neutral system color at 30% lightness. + <!-- Shade of the neutral system color at 30% perceptual luminance (L* in L*a*b* color space). This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_neutral1_700">#454749</color> - <!-- Shade of the neutral system color at 20% lightness. + <!-- Shade of the neutral system color at 20% perceptual luminance (L* in L*a*b* color space). This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_neutral1_800">#2E3133</color> - <!-- Shade of the neutral system color at 10% lightness. + <!-- Shade of the neutral system color at 10% perceptual luminance (L* in L*a*b* color space). This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_neutral1_900">#191C1E</color> <!-- Darkest shade of the neutral color used by the system. Black. @@ -406,37 +406,37 @@ <!-- Lightest shade of the secondary neutral color used by the system. White. This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_neutral2_0">#ffffff</color> - <!-- Shade of the secondary neutral system color at 99% lightness. + <!-- Shade of the secondary neutral system color at 99% perceptual luminance (L* in L*a*b* color space). This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_neutral2_10">#F9FCFF</color> - <!-- Shade of the secondary neutral system color at 95% lightness. + <!-- Shade of the secondary neutral system color at 95% perceptual luminance (L* in L*a*b* color space). This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_neutral2_50">#EBF1F8</color> - <!-- Shade of the secondary neutral system color at 90% lightness. + <!-- Shade of the secondary neutral system color at 90% perceptual luminance (L* in L*a*b* color space). This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_neutral2_100">#DCE3E9</color> - <!-- Shade of the secondary neutral system color at 80% lightness. + <!-- Shade of the secondary neutral system color at 80% perceptual luminance (L* in L*a*b* color space). This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_neutral2_200">#C0C7CD</color> - <!-- Shade of the secondary neutral system color at 70% lightness. + <!-- Shade of the secondary neutral system color at 70% perceptual luminance (L* in L*a*b* color space). This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_neutral2_300">#A5ACB2</color> - <!-- Shade of the secondary neutral system color at 60% lightness. + <!-- Shade of the secondary neutral system color at 60% perceptual luminance (L* in L*a*b* color space). This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_neutral2_400">#8A9297</color> - <!-- Shade of the secondary neutral system color at 49% lightness. + <!-- Shade of the secondary neutral system color at 49% perceptual luminance (L* in L*a*b* color space). This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_neutral2_500">#70777C</color> - <!-- Shade of the secondary neutral system color at 40% lightness. + <!-- Shade of the secondary neutral system color at 40% perceptual luminance (L* in L*a*b* color space). This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_neutral2_600">#585F65</color> - <!-- Shade of the secondary neutral system color at 30% lightness. + <!-- Shade of the secondary neutral system color at 30% perceptual luminance (L* in L*a*b* color space). This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_neutral2_700">#40484D</color> - <!-- Shade of the secondary neutral system color at 20% lightness. + <!-- Shade of the secondary neutral system color at 20% perceptual luminance (L* in L*a*b* color space). This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_neutral2_800">#2A3136</color> - <!-- Shade of the secondary neutral system color at 10% lightness. + <!-- Shade of the secondary neutral system color at 10% perceptual luminance (L* in L*a*b* color space). This value can be overlaid at runtime by OverlayManager RROs. --> <color name="system_neutral2_900">#161C20</color> <!-- Darkest shade of the secondary neutral color used by the system. Black. diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 219d0650588f..ddc9f0225025 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -2323,6 +2323,15 @@ <!-- Type of the tap sensor. Empty if tap is not supported. --> <string name="config_dozeTapSensorType" translatable="false"></string> + <!-- Type of the ambient tap sensor per device posture (defined by WM Jetpack posture). + Unspecified values use config_dozeTapSensor --> + <string-array name="config_dozeTapSensorPostureMapping" translatable="false"> + <item></item> <!-- UNKNOWN --> + <item></item> <!-- CLOSED --> + <item></item> <!-- HALF_OPENED --> + <item></item> <!-- OPENED --> + </string-array> + <!-- Type of the long press sensor. Empty if long press is not supported. --> <string name="config_dozeLongPressSensorType" translatable="false"></string> @@ -4915,16 +4924,15 @@ device orientation. --> <bool name="config_letterboxIsReachabilityEnabled">false</bool> - <!-- Default horizonal position of a center of the letterboxed app window when reachability is - enabled and an app is fullscreen in landscape device orientation. - 0 corresponds to the left side of the screen and 1 to the right side. If given value < 0.0 - or > 1, it is ignored and right positionis used (1.0). The position multiplier is changed - to a symmetrical value computed as (1 - current multiplier) after each double tap in the - letterbox area. --> - <item name="config_letterboxDefaultPositionMultiplierForReachability" - format="float" type="dimen"> - 0.9 - </item> + <!-- Default horizonal position of the letterboxed app window when reachability is + enabled and an app is fullscreen in landscape device orientation. When reachability is + enabled, the position can change between left, center and right. This config defines the + default one: + - Option 0 - Left. + - Option 1 - Center. + - Option 2 - Right. + If given value is outside of this range, the option 1 (center) is assummed. --> + <integer name="config_letterboxDefaultPositionForReachability">1</integer> <!-- If true, hide the display cutout with display area --> <bool name="config_hideDisplayCutoutWithDisplayArea">false</bool> diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml index 9ed4e65f7c91..ab923d0b8023 100644 --- a/core/res/res/values/dimens.xml +++ b/core/res/res/values/dimens.xml @@ -60,6 +60,9 @@ <!-- How much we expand the touchable region of the status bar below the notch to catch touches that just start below the notch. --> <dimen name="display_cutout_touchable_region_size">12dp</dimen> + <!-- The default margin used in immersive mode to capture the start of a swipe gesture from the + edge of the screen to show the system bars. --> + <dimen name="system_gestures_start_threshold">24dp</dimen> <!-- Height of the bottom navigation bar frame; this is different than navigation_bar_height where that is the height reported to all the other windows to resize themselves around the diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index e17daf09e4da..462b1883e29d 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -3221,7 +3221,7 @@ <eat-comment /> <staging-public-group type="attr" first-id="0x01ff0000"> - <public name="shouldUseDefaultDeviceStateChangeTransition" /> + <public name="shouldUseDefaultDisplayStateChangeTransition" /> </staging-public-group> <staging-public-group type="id" first-id="0x01fe0000"> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 4e8d915ca295..758990df7159 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -1745,6 +1745,7 @@ <java-symbol type="dimen" name="taskbar_frame_height" /> <java-symbol type="dimen" name="status_bar_height" /> <java-symbol type="dimen" name="display_cutout_touchable_region_size" /> + <java-symbol type="dimen" name="system_gestures_start_threshold" /> <java-symbol type="dimen" name="quick_qs_offset_height" /> <java-symbol type="drawable" name="ic_jog_dial_sound_off" /> <java-symbol type="drawable" name="ic_jog_dial_sound_on" /> @@ -3255,6 +3256,7 @@ <java-symbol type="string" name="config_dozeDoubleTapSensorType" /> <java-symbol type="string" name="config_dozeTapSensorType" /> + <java-symbol type="array" name="config_dozeTapSensorPostureMapping" /> <java-symbol type="bool" name="config_dozePulsePickup" /> <!-- Used for MimeIconUtils. --> @@ -4262,7 +4264,7 @@ <java-symbol type="color" name="config_letterboxBackgroundColor" /> <java-symbol type="dimen" name="config_letterboxHorizontalPositionMultiplier" /> <java-symbol type="bool" name="config_letterboxIsReachabilityEnabled" /> - <java-symbol type="dimen" name="config_letterboxDefaultPositionMultiplierForReachability" /> + <java-symbol type="integer" name="config_letterboxDefaultPositionForReachability" /> <java-symbol type="bool" name="config_hideDisplayCutoutWithDisplayArea" /> diff --git a/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java b/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java index 50639be57f22..3e261a7113ac 100644 --- a/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java +++ b/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java @@ -157,7 +157,7 @@ public class ObjectPoolTests { .setPendingResults(resultInfoList()).setPendingNewIntents(referrerIntentList()) .setIsForward(true).setAssistToken(assistToken) .setShareableActivityToken(shareableActivityToken) - .setTaskFragmentToken(new Binder()).build(); + .build(); LaunchActivityItem emptyItem = new LaunchActivityItemBuilder().build(); LaunchActivityItem item = itemSupplier.get(); diff --git a/core/tests/coretests/src/android/app/servertransaction/TestUtils.java b/core/tests/coretests/src/android/app/servertransaction/TestUtils.java index 1173c9210ed5..75da0bfba581 100644 --- a/core/tests/coretests/src/android/app/servertransaction/TestUtils.java +++ b/core/tests/coretests/src/android/app/servertransaction/TestUtils.java @@ -112,7 +112,6 @@ class TestUtils { private IBinder mShareableActivityToken; private FixedRotationAdjustments mFixedRotationAdjustments; private boolean mLaunchedFromBubble; - private IBinder mTaskFragmentToken; LaunchActivityItemBuilder setIntent(Intent intent) { mIntent = intent; @@ -214,18 +213,13 @@ class TestUtils { return this; } - LaunchActivityItemBuilder setTaskFragmentToken(IBinder taskFragmentToken) { - mTaskFragmentToken = taskFragmentToken; - return this; - } - LaunchActivityItem build() { return LaunchActivityItem.obtain(mIntent, mIdent, mInfo, mCurConfig, mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mProcState, mState, mPersistentState, mPendingResults, mPendingNewIntents, mActivityOptions, mIsForward, mProfilerInfo, mAssistToken, null /* activityClientController */, mFixedRotationAdjustments, - mShareableActivityToken, mLaunchedFromBubble, mTaskFragmentToken); + mShareableActivityToken, mLaunchedFromBubble); } } } diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java index 98c9afd2eb6b..df0c64c810c6 100644 --- a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java +++ b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java @@ -209,7 +209,6 @@ public class TransactionParcelTests { .setPendingNewIntents(referrerIntentList()).setIsForward(true) .setAssistToken(new Binder()).setFixedRotationAdjustments(fixedRotationAdjustments) .setShareableActivityToken(new Binder()) - .setTaskFragmentToken(new Binder()) .build(); writeAndPrepareForReading(item); diff --git a/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java b/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java index 516a5d288c0f..269d8424a78f 100644 --- a/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java +++ b/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java @@ -299,7 +299,7 @@ public class ActivityThreadClientTest { null /* activityOptions */, true /* isForward */, null /* profilerInfo */, mThread /* client */, null /* asssitToken */, null /* fixedRotationAdjustments */, null /* shareableActivityToken */, - false /* launchedFromBubble */, null /* taskfragmentToken */); + false /* launchedFromBubble */); } @Override diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java index e1c8b11a835c..42b438041d7a 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java @@ -172,7 +172,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen void handleActivityCreated(@NonNull Activity launchedActivity) { final List<EmbeddingRule> splitRules = getSplitRules(); final TaskFragmentContainer currentContainer = getContainerWithActivity( - launchedActivity.getActivityToken(), launchedActivity); + launchedActivity.getActivityToken()); // Check if the activity is configured to always be expanded. if (shouldExpand(launchedActivity, null, splitRules)) { @@ -262,29 +262,9 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen */ @Nullable TaskFragmentContainer getContainerWithActivity(@NonNull IBinder activityToken) { - return getContainerWithActivity(activityToken, null /* activityToAdd */); - } - - /** - * This method can only be called from {@link #onActivityCreated(Activity)}, use - * {@link #getContainerWithActivity(IBinder) } otherwise. - * - * Returns a container that this activity is registered with. The activity could be created - * before the container appeared, adding the activity to the container if so. - */ - @Nullable - private TaskFragmentContainer getContainerWithActivity(@NonNull IBinder activityToken, - Activity activityToAdd) { - final IBinder taskFragmentToken = ActivityThread.currentActivityThread().getActivityClient( - activityToken).mInitialTaskFragmentToken; for (TaskFragmentContainer container : mContainers) { if (container.hasActivity(activityToken)) { return container; - } else if (container.getTaskFragmentToken().equals(taskFragmentToken)) { - if (activityToAdd != null) { - container.addPendingAppearedActivity(activityToAdd); - } - return container; } } diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java index 25292b905fe8..81be21cbd7aa 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java @@ -252,7 +252,8 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer { // Getting the parent bounds using the updated container - it will have the recent value. final Rect parentBounds = getParentContainerBounds(updatedContainer); final SplitRule rule = splitContainer.getSplitRule(); - final Activity activity = splitContainer.getPrimaryContainer().getTopNonFinishingActivity(); + final TaskFragmentContainer primaryContainer = splitContainer.getPrimaryContainer(); + final Activity activity = primaryContainer.getTopNonFinishingActivity(); if (activity == null) { return; } @@ -264,10 +265,12 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer { // If the task fragments are not registered yet, the positions will be updated after they // are created again. - resizeTaskFragmentIfRegistered(wct, splitContainer.getPrimaryContainer(), - primaryRectBounds); - resizeTaskFragmentIfRegistered(wct, splitContainer.getSecondaryContainer(), - secondaryRectBounds); + resizeTaskFragmentIfRegistered(wct, primaryContainer, primaryRectBounds); + final TaskFragmentContainer secondaryContainer = splitContainer.getSecondaryContainer(); + resizeTaskFragmentIfRegistered(wct, secondaryContainer, secondaryRectBounds); + + setAdjacentTaskFragments(wct, primaryContainer.getTaskFragmentToken(), + secondaryContainer.getTaskFragmentToken(), rule); } /** diff --git a/libs/WindowManager/Shell/res/color/unfold_transition_background.xml b/libs/WindowManager/Shell/res/color/unfold_transition_background.xml new file mode 100644 index 000000000000..63289a3f75d9 --- /dev/null +++ b/libs/WindowManager/Shell/res/color/unfold_transition_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"> + <!-- Matches taskbar color --> + <item android:color="@android:color/system_neutral2_500" android:lStar="35" /> +</selector> diff --git a/libs/WindowManager/Shell/res/layout/split_outline.xml b/libs/WindowManager/Shell/res/layout/split_outline.xml index 4e2a77f213a0..13a30f5a0423 100644 --- a/libs/WindowManager/Shell/res/layout/split_outline.xml +++ b/libs/WindowManager/Shell/res/layout/split_outline.xml @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. --> -<com.android.wm.shell.splitscreen.OutlineRoot +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> @@ -23,4 +23,4 @@ android:layout_height="match_parent" android:layout_width="match_parent" /> -</com.android.wm.shell.splitscreen.OutlineRoot> +</FrameLayout> diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java index df4f2383c062..fa58fcda3d3b 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java @@ -27,6 +27,8 @@ import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.annotations.ExternalThread; import com.android.wm.shell.draganddrop.DragAndDropController; import com.android.wm.shell.freeform.FreeformTaskListener; +import com.android.wm.shell.fullscreen.FullscreenTaskListener; +import com.android.wm.shell.fullscreen.FullscreenUnfoldController; import com.android.wm.shell.legacysplitscreen.LegacySplitScreenController; import com.android.wm.shell.pip.phone.PipTouchHandler; import com.android.wm.shell.splitscreen.SplitScreenController; @@ -52,6 +54,7 @@ public class ShellInitImpl { private final Optional<AppPairsController> mAppPairsOptional; private final Optional<PipTouchHandler> mPipTouchHandlerOptional; private final FullscreenTaskListener mFullscreenTaskListener; + private final Optional<FullscreenUnfoldController> mFullscreenUnfoldController; private final Optional<FreeformTaskListener> mFreeformTaskListenerOptional; private final ShellExecutor mMainExecutor; private final Transitions mTransitions; @@ -71,6 +74,7 @@ public class ShellInitImpl { Optional<AppPairsController> appPairsOptional, Optional<PipTouchHandler> pipTouchHandlerOptional, FullscreenTaskListener fullscreenTaskListener, + Optional<FullscreenUnfoldController> fullscreenUnfoldTransitionController, Optional<Optional<FreeformTaskListener>> freeformTaskListenerOptional, Transitions transitions, StartingWindowController startingWindow, @@ -86,6 +90,7 @@ public class ShellInitImpl { mAppPairsOptional = appPairsOptional; mFullscreenTaskListener = fullscreenTaskListener; mPipTouchHandlerOptional = pipTouchHandlerOptional; + mFullscreenUnfoldController = fullscreenUnfoldTransitionController; mFreeformTaskListenerOptional = freeformTaskListenerOptional.flatMap(f -> f); mTransitions = transitions; mMainExecutor = mainExecutor; @@ -128,6 +133,8 @@ public class ShellInitImpl { mFreeformTaskListenerOptional.ifPresent(f -> mShellTaskOrganizer.addListenerForType( f, ShellTaskOrganizer.TASK_LISTENER_TYPE_FREEFORM)); + + mFullscreenUnfoldController.ifPresent(FullscreenUnfoldController::init); } @ExternalThread 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 d3265346036a..d925a9218a77 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java @@ -233,14 +233,14 @@ public class ShellTaskOrganizer extends TaskOrganizer implements + " already exists"); } mTaskListeners.put(listenerType, listener); + } - // Notify the listener of all existing tasks with the given type. - for (int i = mTasks.size() - 1; i >= 0; --i) { - final TaskAppearedInfo data = mTasks.valueAt(i); - final TaskListener taskListener = getTaskListener(data.getTaskInfo()); - if (taskListener != listener) continue; - listener.onTaskAppeared(data.getTaskInfo(), data.getLeash()); - } + // Notify the listener of all existing tasks with the given type. + for (int i = mTasks.size() - 1; i >= 0; --i) { + final TaskAppearedInfo data = mTasks.valueAt(i); + final TaskListener taskListener = getTaskListener(data.getTaskInfo()); + if (taskListener != listener) continue; + listener.onTaskAppeared(data.getTaskInfo(), data.getLeash()); } } } @@ -266,8 +266,12 @@ public class ShellTaskOrganizer extends TaskOrganizer implements tasks.add(data); } - // Remove listener - mTaskListeners.removeAt(index); + // Remove listener, there can be the multiple occurrences, so search the whole list. + for (int i = mTaskListeners.size() - 1; i >= 0; --i) { + if (mTaskListeners.valueAt(i) == listener) { + mTaskListeners.removeAt(i); + } + } // Associate tasks with new listeners if needed. for (int i = tasks.size() - 1; i >= 0; --i) { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java b/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java index c2cb72a530a3..10d7725b6184 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java @@ -27,7 +27,6 @@ import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_UNDEF import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_TASK_ORG; import android.app.ActivityManager; -import android.graphics.Rect; import android.view.SurfaceControl; import android.view.SurfaceSession; import android.window.WindowContainerToken; @@ -40,6 +39,7 @@ import com.android.internal.protolog.common.ProtoLog; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.DisplayImeController; +import com.android.wm.shell.common.DisplayInsetsController; import com.android.wm.shell.common.SurfaceUtils; import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.common.split.SplitLayout; @@ -69,6 +69,7 @@ class AppPair implements ShellTaskOrganizer.TaskListener, SplitLayout.SplitLayou private final SyncTransactionQueue mSyncQueue; private final DisplayController mDisplayController; private final DisplayImeController mDisplayImeController; + private final DisplayInsetsController mDisplayInsetsController; private SplitLayout mSplitLayout; private final SplitWindowManager.ParentContainerCallbacks mParentContainerCallbacks = @@ -80,7 +81,12 @@ class AppPair implements ShellTaskOrganizer.TaskListener, SplitLayout.SplitLayou @Override public void onLeashReady(SurfaceControl leash) { - mSyncQueue.runInSync(t -> t.show(leash)); + mSyncQueue.runInSync(t -> t + .show(leash) + .setLayer(leash, SPLIT_DIVIDER_LAYER) + .setPosition(leash, + mSplitLayout.getDividerBounds().left, + mSplitLayout.getDividerBounds().top)); } }; @@ -89,6 +95,7 @@ class AppPair implements ShellTaskOrganizer.TaskListener, SplitLayout.SplitLayou mSyncQueue = controller.getSyncTransactionQueue(); mDisplayController = controller.getDisplayController(); mDisplayImeController = controller.getDisplayImeController(); + mDisplayInsetsController = controller.getDisplayInsetsController(); } int getRootTaskId() { @@ -125,6 +132,7 @@ class AppPair implements ShellTaskOrganizer.TaskListener, SplitLayout.SplitLayou mDisplayController.getDisplayContext(mRootTaskInfo.displayId), mRootTaskInfo.configuration, this /* layoutChangeListener */, mParentContainerCallbacks, mDisplayImeController, mController.getTaskOrganizer()); + mDisplayInsetsController.addInsetsChangedListener(mRootTaskInfo.displayId, mSplitLayout); final WindowContainerToken token1 = task1.token; final WindowContainerToken token2 = task2.token; @@ -190,22 +198,17 @@ class AppPair implements ShellTaskOrganizer.TaskListener, SplitLayout.SplitLayou if (mTaskLeash1 == null || mTaskLeash2 == null) return; mSplitLayout.init(); - final SurfaceControl dividerLeash = mSplitLayout.getDividerLeash(); - final Rect dividerBounds = mSplitLayout.getDividerBounds(); - - // TODO: Is there more we need to do here? - mSyncQueue.runInSync(t -> { - t.setLayer(dividerLeash, SPLIT_DIVIDER_LAYER) - .setPosition(mTaskLeash1, mTaskInfo1.positionInParent.x, - mTaskInfo1.positionInParent.y) - .setPosition(mTaskLeash2, mTaskInfo2.positionInParent.x, - mTaskInfo2.positionInParent.y) - .setPosition(dividerLeash, dividerBounds.left, dividerBounds.top) - .show(dividerLeash) - .show(mRootTaskLeash) - .show(mTaskLeash1) - .show(mTaskLeash2); - }); + + mSyncQueue.runInSync(t -> t + .show(mRootTaskLeash) + .show(mTaskLeash1) + .show(mTaskLeash2) + .setPosition(mTaskLeash1, + mTaskInfo1.positionInParent.x, + mTaskInfo1.positionInParent.y) + .setPosition(mTaskLeash2, + mTaskInfo2.positionInParent.x, + mTaskInfo2.positionInParent.y)); } @Override @@ -227,10 +230,9 @@ class AppPair implements ShellTaskOrganizer.TaskListener, SplitLayout.SplitLayou } mRootTaskInfo = taskInfo; - if (mSplitLayout != null) { - if (mSplitLayout.updateConfiguration(mRootTaskInfo.configuration)) { - onLayoutChanged(mSplitLayout); - } + if (mSplitLayout != null + && mSplitLayout.updateConfiguration(mRootTaskInfo.configuration)) { + onLayoutChanged(mSplitLayout); } } else if (taskInfo.taskId == getTaskId1()) { mTaskInfo1 = taskInfo; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPairsController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPairsController.java index b159333e9a0e..53234ab971d6 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPairsController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPairsController.java @@ -29,6 +29,7 @@ import com.android.internal.protolog.common.ProtoLog; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.DisplayImeController; +import com.android.wm.shell.common.DisplayInsetsController; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.SyncTransactionQueue; @@ -50,14 +51,17 @@ public class AppPairsController { private final SparseArray<AppPair> mActiveAppPairs = new SparseArray<>(); private final DisplayController mDisplayController; private final DisplayImeController mDisplayImeController; + private final DisplayInsetsController mDisplayInsetsController; public AppPairsController(ShellTaskOrganizer organizer, SyncTransactionQueue syncQueue, DisplayController displayController, ShellExecutor mainExecutor, - DisplayImeController displayImeController) { + DisplayImeController displayImeController, + DisplayInsetsController displayInsetsController) { mTaskOrganizer = organizer; mSyncQueue = syncQueue; mDisplayController = displayController; mDisplayImeController = displayImeController; + mDisplayInsetsController = displayInsetsController; mMainExecutor = mainExecutor; } @@ -148,6 +152,10 @@ public class AppPairsController { return mDisplayImeController; } + DisplayInsetsController getDisplayInsetsController() { + return mDisplayInsetsController; + } + public void dump(@NonNull PrintWriter pw, String prefix) { final String innerPrefix = prefix + " "; final String childPrefix = innerPrefix + " "; 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 1c308a3daf34..596a2f4467c3 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 @@ -189,24 +189,28 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange final int rotation = configuration.windowConfiguration.getRotation(); final Rect rootBounds = configuration.windowConfiguration.getBounds(); final int orientation = configuration.orientation; - if (rotation != mRotation || !mRootBounds.equals(rootBounds) - || orientation != mOrientation) { - mContext = mContext.createConfigurationContext(configuration); - mSplitWindowManager.setConfiguration(configuration); - mOrientation = orientation; - mTempRect.set(mRootBounds); - mRootBounds.set(rootBounds); - mDividerSnapAlgorithm = getSnapAlgorithm(mContext, mRootBounds); - initDividerPosition(mTempRect); - affectsLayout = true; + + if (mOrientation == orientation + && rotation == mRotation + && mRootBounds.equals(rootBounds)) { + return false; } + mContext = mContext.createConfigurationContext(configuration); + mSplitWindowManager.setConfiguration(configuration); + mOrientation = orientation; + mTempRect.set(mRootBounds); + mRootBounds.set(rootBounds); + mRotation = rotation; + mDividerSnapAlgorithm = getSnapAlgorithm(mContext, mRootBounds); + initDividerPosition(mTempRect); + if (mInitialized) { release(); init(); } - return affectsLayout; + return true; } private void initDividerPosition(Rect oldBounds) { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/FullscreenTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/fullscreen/FullscreenTaskListener.java index 006730d333eb..3f17f2ba9394 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/FullscreenTaskListener.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/fullscreen/FullscreenTaskListener.java @@ -14,25 +14,31 @@ * limitations under the License. */ -package com.android.wm.shell; +package com.android.wm.shell.fullscreen; + +import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_FULLSCREEN; import static com.android.wm.shell.ShellTaskOrganizer.taskListenerTypeToString; -import android.app.ActivityManager; +import android.app.ActivityManager.RunningTaskInfo; +import android.app.TaskInfo; import android.graphics.Point; import android.util.Slog; import android.util.SparseArray; +import android.util.SparseBooleanArray; import android.view.SurfaceControl; import androidx.annotation.NonNull; import com.android.internal.protolog.common.ProtoLog; +import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.protolog.ShellProtoLogGroup; import com.android.wm.shell.transition.Transitions; import java.io.PrintWriter; +import java.util.Optional; /** * Organizes tasks presented in {@link android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN}. @@ -43,13 +49,17 @@ public class FullscreenTaskListener implements ShellTaskOrganizer.TaskListener { private final SyncTransactionQueue mSyncQueue; private final SparseArray<TaskData> mDataByTaskId = new SparseArray<>(); + private final AnimatableTasksListener mAnimatableTasksListener = new AnimatableTasksListener(); + private final FullscreenUnfoldController mFullscreenUnfoldController; - public FullscreenTaskListener(SyncTransactionQueue syncQueue) { + public FullscreenTaskListener(SyncTransactionQueue syncQueue, + Optional<FullscreenUnfoldController> unfoldController) { mSyncQueue = syncQueue; + mFullscreenUnfoldController = unfoldController.orElse(null); } @Override - public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash) { + public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) { if (mDataByTaskId.get(taskInfo.taskId) != null) { throw new IllegalStateException("Task appeared more than once: #" + taskInfo.taskId); } @@ -67,11 +77,16 @@ public class FullscreenTaskListener implements ShellTaskOrganizer.TaskListener { t.setMatrix(leash, 1, 0, 0, 1); t.show(leash); }); + + mAnimatableTasksListener.onTaskAppeared(taskInfo); } @Override - public void onTaskInfoChanged(ActivityManager.RunningTaskInfo taskInfo) { + public void onTaskInfoChanged(RunningTaskInfo taskInfo) { if (Transitions.ENABLE_SHELL_TRANSITIONS) return; + + mAnimatableTasksListener.onTaskInfoChanged(taskInfo); + final TaskData data = mDataByTaskId.get(taskInfo.taskId); final Point positionInParent = taskInfo.positionInParent; if (!positionInParent.equals(data.positionInParent)) { @@ -83,12 +98,15 @@ public class FullscreenTaskListener implements ShellTaskOrganizer.TaskListener { } @Override - public void onTaskVanished(ActivityManager.RunningTaskInfo taskInfo) { + public void onTaskVanished(RunningTaskInfo taskInfo) { if (mDataByTaskId.get(taskInfo.taskId) == null) { Slog.e(TAG, "Task already vanished: #" + taskInfo.taskId); return; } + + mAnimatableTasksListener.onTaskVanished(taskInfo); mDataByTaskId.remove(taskInfo.taskId); + ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Fullscreen Task Vanished: #%d", taskInfo.taskId); } @@ -125,4 +143,65 @@ public class FullscreenTaskListener implements ShellTaskOrganizer.TaskListener { this.positionInParent = positionInParent; } } + + class AnimatableTasksListener { + private final SparseBooleanArray mTaskIds = new SparseBooleanArray(); + + public void onTaskAppeared(RunningTaskInfo taskInfo) { + final boolean isApplicable = isAnimatable(taskInfo); + if (isApplicable) { + mTaskIds.put(taskInfo.taskId, true); + + if (mFullscreenUnfoldController != null) { + SurfaceControl leash = mDataByTaskId.get(taskInfo.taskId).surface; + mFullscreenUnfoldController.onTaskAppeared(taskInfo, leash); + } + } + } + + public void onTaskInfoChanged(RunningTaskInfo taskInfo) { + final boolean isCurrentlyApplicable = mTaskIds.get(taskInfo.taskId); + final boolean isApplicable = isAnimatable(taskInfo); + + if (isCurrentlyApplicable) { + if (isApplicable) { + // Still applicable, send update + if (mFullscreenUnfoldController != null) { + mFullscreenUnfoldController.onTaskInfoChanged(taskInfo); + } + } else { + // Became inapplicable + if (mFullscreenUnfoldController != null) { + mFullscreenUnfoldController.onTaskVanished(taskInfo); + } + mTaskIds.put(taskInfo.taskId, false); + } + } else { + if (isApplicable) { + // Became applicable + mTaskIds.put(taskInfo.taskId, true); + + if (mFullscreenUnfoldController != null) { + SurfaceControl leash = mDataByTaskId.get(taskInfo.taskId).surface; + mFullscreenUnfoldController.onTaskAppeared(taskInfo, leash); + } + } + } + } + + public void onTaskVanished(RunningTaskInfo taskInfo) { + final boolean isCurrentlyApplicable = mTaskIds.get(taskInfo.taskId); + if (isCurrentlyApplicable && mFullscreenUnfoldController != null) { + mFullscreenUnfoldController.onTaskVanished(taskInfo); + } + mTaskIds.put(taskInfo.taskId, false); + } + + private boolean isAnimatable(TaskInfo taskInfo) { + // Filter all visible tasks that are not launcher tasks + // We do not animate launcher as it handles the animation by itself + return taskInfo != null && taskInfo.isVisible && taskInfo.getConfiguration() + .windowConfiguration.getActivityType() != ACTIVITY_TYPE_HOME; + } + } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/fullscreen/FullscreenUnfoldController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/fullscreen/FullscreenUnfoldController.java new file mode 100644 index 000000000000..08ab85cab97b --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/fullscreen/FullscreenUnfoldController.java @@ -0,0 +1,268 @@ +/* + * 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.fullscreen; + +import static android.graphics.Color.blue; +import static android.graphics.Color.green; +import static android.graphics.Color.red; +import static android.util.MathUtils.lerp; +import static android.view.Display.DEFAULT_DISPLAY; + +import android.animation.RectEvaluator; +import android.animation.TypeEvaluator; +import android.annotation.NonNull; +import android.app.ActivityManager; +import android.app.TaskInfo; +import android.content.Context; +import android.graphics.Matrix; +import android.graphics.Rect; +import android.util.SparseArray; +import android.view.InsetsSource; +import android.view.InsetsState; +import android.view.SurfaceControl; + +import com.android.internal.policy.ScreenDecorationsUtils; +import com.android.wm.shell.R; +import com.android.wm.shell.RootTaskDisplayAreaOrganizer; +import com.android.wm.shell.common.DisplayInsetsController; +import com.android.wm.shell.common.DisplayInsetsController.OnInsetsChangedListener; +import com.android.wm.shell.unfold.ShellUnfoldProgressProvider; +import com.android.wm.shell.unfold.ShellUnfoldProgressProvider.UnfoldListener; + +import java.util.concurrent.Executor; + +/** + * Controls full screen app unfold transition: animating cropping window and scaling when + * folding or unfolding a foldable device. + */ +public final class FullscreenUnfoldController implements UnfoldListener, + OnInsetsChangedListener { + + private static final float[] FLOAT_9 = new float[9]; + private static final TypeEvaluator<Rect> RECT_EVALUATOR = new RectEvaluator(new Rect()); + + private static final float HORIZONTAL_START_MARGIN = 0.08f; + private static final float VERTICAL_START_MARGIN = 0.03f; + private static final float END_SCALE = 1f; + private static final float START_SCALE = END_SCALE - VERTICAL_START_MARGIN * 2; + private static final int BACKGROUND_LAYER_Z_INDEX = -1; + + private final Context mContext; + private final Executor mExecutor; + private final ShellUnfoldProgressProvider mProgressProvider; + private final RootTaskDisplayAreaOrganizer mRootTaskDisplayAreaOrganizer; + private final DisplayInsetsController mDisplayInsetsController; + + private final SparseArray<AnimationContext> mAnimationContextByTaskId = new SparseArray<>(); + + private SurfaceControl mBackgroundLayer; + private InsetsSource mTaskbarInsetsSource; + + private final float mWindowCornerRadiusPx; + private final float[] mBackgroundColor; + private final float mExpandedTaskBarHeight; + + private final SurfaceControl.Transaction mTransaction = new SurfaceControl.Transaction(); + + public FullscreenUnfoldController( + @NonNull Context context, + @NonNull Executor executor, + @NonNull ShellUnfoldProgressProvider progressProvider, + @NonNull RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer, + @NonNull DisplayInsetsController displayInsetsController + ) { + mContext = context; + mExecutor = executor; + mRootTaskDisplayAreaOrganizer = rootTaskDisplayAreaOrganizer; + mProgressProvider = progressProvider; + mDisplayInsetsController = displayInsetsController; + mWindowCornerRadiusPx = ScreenDecorationsUtils.getWindowCornerRadius(context); + mExpandedTaskBarHeight = context.getResources().getDimensionPixelSize( + com.android.internal.R.dimen.taskbar_frame_height); + mBackgroundColor = getBackgroundColor(); + } + + /** + * Initializes the controller + */ + public void init() { + mProgressProvider.addListener(mExecutor, this); + mDisplayInsetsController.addInsetsChangedListener(DEFAULT_DISPLAY, this); + } + + @Override + public void onStateChangeProgress(float progress) { + if (mAnimationContextByTaskId.size() == 0) return; + + ensureBackground(); + + for (int i = mAnimationContextByTaskId.size() - 1; i >= 0; i--) { + final AnimationContext context = mAnimationContextByTaskId.valueAt(i); + + context.mCurrentCropRect.set(RECT_EVALUATOR + .evaluate(progress, context.mStartCropRect, context.mEndCropRect)); + + float scale = lerp(START_SCALE, END_SCALE, progress); + context.mMatrix.setScale(scale, scale, context.mCurrentCropRect.exactCenterX(), + context.mCurrentCropRect.exactCenterY()); + + mTransaction.setWindowCrop(context.mLeash, context.mCurrentCropRect) + .setMatrix(context.mLeash, context.mMatrix, FLOAT_9) + .setCornerRadius(context.mLeash, mWindowCornerRadiusPx); + } + + mTransaction.apply(); + } + + @Override + public void onStateChangeFinished() { + for (int i = mAnimationContextByTaskId.size() - 1; i >= 0; i--) { + final AnimationContext context = mAnimationContextByTaskId.valueAt(i); + resetSurface(context); + } + + removeBackground(); + mTransaction.apply(); + } + + @Override + public void insetsChanged(InsetsState insetsState) { + mTaskbarInsetsSource = insetsState.getSource(InsetsState.ITYPE_EXTRA_NAVIGATION_BAR); + for (int i = mAnimationContextByTaskId.size() - 1; i >= 0; i--) { + AnimationContext context = mAnimationContextByTaskId.valueAt(i); + context.update(mTaskbarInsetsSource, context.mTaskInfo); + } + } + + /** + * Called when a new matching task appeared + */ + public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash) { + AnimationContext animationContext = new AnimationContext(leash, mTaskbarInsetsSource, + taskInfo); + mAnimationContextByTaskId.put(taskInfo.taskId, animationContext); + } + + /** + * Called when matching task changed + */ + public void onTaskInfoChanged(ActivityManager.RunningTaskInfo taskInfo) { + AnimationContext animationContext = mAnimationContextByTaskId.get(taskInfo.taskId); + if (animationContext != null) { + animationContext.update(mTaskbarInsetsSource, taskInfo); + } + } + + /** + * Called when matching task vanished + */ + public void onTaskVanished(ActivityManager.RunningTaskInfo taskInfo) { + AnimationContext animationContext = mAnimationContextByTaskId.get(taskInfo.taskId); + if (animationContext != null) { + resetSurface(animationContext); + mAnimationContextByTaskId.remove(taskInfo.taskId); + } + + if (mAnimationContextByTaskId.size() == 0) { + removeBackground(); + } + + mTransaction.apply(); + } + + private void resetSurface(AnimationContext context) { + mTransaction + .setWindowCrop(context.mLeash, null) + .setCornerRadius(context.mLeash, 0.0F) + .setMatrix(context.mLeash, 1.0F, 0.0F, 0.0F, 1.0F) + .setPosition(context.mLeash, + (float) context.mTaskInfo.positionInParent.x, + (float) context.mTaskInfo.positionInParent.y); + } + + private void ensureBackground() { + if (mBackgroundLayer != null) return; + + SurfaceControl.Builder colorLayerBuilder = new SurfaceControl.Builder() + .setName("app-unfold-background") + .setCallsite("AppUnfoldTransitionController") + .setColorLayer(); + mRootTaskDisplayAreaOrganizer.attachToDisplayArea(DEFAULT_DISPLAY, colorLayerBuilder); + mBackgroundLayer = colorLayerBuilder.build(); + + mTransaction + .setColor(mBackgroundLayer, mBackgroundColor) + .show(mBackgroundLayer) + .setLayer(mBackgroundLayer, BACKGROUND_LAYER_Z_INDEX); + } + + private void removeBackground() { + if (mBackgroundLayer == null) return; + if (mBackgroundLayer.isValid()) { + mTransaction.remove(mBackgroundLayer); + } + mBackgroundLayer = null; + } + + private float[] getBackgroundColor() { + int colorInt = mContext.getResources().getColor(R.color.unfold_transition_background); + return new float[]{ + (float) red(colorInt) / 255.0F, + (float) green(colorInt) / 255.0F, + (float) blue(colorInt) / 255.0F + }; + } + + private class AnimationContext { + final SurfaceControl mLeash; + final Rect mStartCropRect = new Rect(); + final Rect mEndCropRect = new Rect(); + final Rect mCurrentCropRect = new Rect(); + final Matrix mMatrix = new Matrix(); + + TaskInfo mTaskInfo; + + private AnimationContext(SurfaceControl leash, + InsetsSource taskBarInsetsSource, + TaskInfo taskInfo) { + this.mLeash = leash; + update(taskBarInsetsSource, taskInfo); + } + + private void update(InsetsSource taskBarInsetsSource, TaskInfo taskInfo) { + mTaskInfo = taskInfo; + mStartCropRect.set(mTaskInfo.getConfiguration().windowConfiguration.getBounds()); + + if (taskBarInsetsSource != null) { + // Only insets the cropping window with task bar when it's expanded + if (taskBarInsetsSource.getFrame().height() >= mExpandedTaskBarHeight) { + mStartCropRect.inset(taskBarInsetsSource + .calculateVisibleInsets(mStartCropRect)); + } + } + + mEndCropRect.set(mStartCropRect); + + int horizontalMargin = (int) (mEndCropRect.width() * HORIZONTAL_START_MARGIN); + mStartCropRect.left = mEndCropRect.left + horizontalMargin; + mStartCropRect.right = mEndCropRect.right - horizontalMargin; + int verticalMargin = (int) (mEndCropRect.height() * VERTICAL_START_MARGIN); + mStartCropRect.top = mEndCropRect.top + verticalMargin; + mStartCropRect.bottom = mEndCropRect.bottom - verticalMargin; + } + } +} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/OutlineManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/OutlineManager.java index 0b763f2d05f7..a459c8dbfa34 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/OutlineManager.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/OutlineManager.java @@ -22,19 +22,23 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMA import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; +import android.annotation.Nullable; import android.content.Context; import android.content.res.Configuration; import android.graphics.PixelFormat; import android.graphics.Rect; import android.os.Binder; import android.view.IWindow; +import android.view.InsetsSource; +import android.view.InsetsState; import android.view.LayoutInflater; import android.view.SurfaceControl; import android.view.SurfaceControlViewHost; -import android.view.WindowInsets; +import android.view.View; +import android.view.ViewGroup; import android.view.WindowManager; -import android.view.WindowMetrics; import android.view.WindowlessWindowManager; +import android.widget.FrameLayout; import com.android.wm.shell.R; @@ -45,17 +49,22 @@ import com.android.wm.shell.R; class OutlineManager extends WindowlessWindowManager { private static final String WINDOW_NAME = "SplitOutlineLayer"; private final Context mContext; - private final Rect mOutlineBounds = new Rect(); - private final Rect mTmpBounds = new Rect(); + private final Rect mRootBounds = new Rect(); + private final Rect mTempRect = new Rect(); + private final Rect mLastOutlineBounds = new Rect(); + private final InsetsState mInsetsState = new InsetsState(); + private final int mExpandedTaskBarHeight; + private OutlineView mOutlineView; private SurfaceControlViewHost mViewHost; private SurfaceControl mHostLeash; private SurfaceControl mLeash; - private int mOutlineColor; OutlineManager(Context context, Configuration configuration) { super(configuration, null /* rootSurface */, null /* hostInputToken */); mContext = context.createWindowContext(context.getDisplay(), TYPE_APPLICATION_OVERLAY, null /* options */); + mExpandedTaskBarHeight = mContext.getResources().getDimensionPixelSize( + com.android.internal.R.dimen.taskbar_frame_height); } @Override @@ -63,65 +72,110 @@ class OutlineManager extends WindowlessWindowManager { b.setParent(mHostLeash); } - boolean drawOutlineBounds(Rect rootBounds) { - if (mLeash == null || mViewHost == null) return false; - - computeOutlineBounds(mContext, rootBounds, mTmpBounds); - if (mOutlineBounds.equals(mTmpBounds)) { - return false; - } - mOutlineBounds.set(mTmpBounds); - - ((OutlineRoot) mViewHost.getView()).updateOutlineBounds(mOutlineBounds, mOutlineColor); - final WindowManager.LayoutParams lp = - (WindowManager.LayoutParams) mViewHost.getView().getLayoutParams(); - lp.width = rootBounds.width(); - lp.height = rootBounds.height(); - mViewHost.relayout(lp); - - return true; - } - - void inflate(SurfaceControl.Transaction t, SurfaceControl hostLeash, int color) { + void inflate(SurfaceControl rootLeash, Rect rootBounds) { if (mLeash != null || mViewHost != null) return; - mHostLeash = hostLeash; - mOutlineColor = color; + mHostLeash = rootLeash; + mRootBounds.set(rootBounds); mViewHost = new SurfaceControlViewHost(mContext, mContext.getDisplay(), this); - final OutlineRoot rootView = (OutlineRoot) LayoutInflater.from(mContext) + + final FrameLayout rootLayout = (FrameLayout) LayoutInflater.from(mContext) .inflate(R.layout.split_outline, null); + mOutlineView = rootLayout.findViewById(R.id.split_outline); final WindowManager.LayoutParams lp = new WindowManager.LayoutParams( 0 /* width */, 0 /* height */, TYPE_APPLICATION_OVERLAY, FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCHABLE, PixelFormat.TRANSLUCENT); + lp.width = mRootBounds.width(); + lp.height = mRootBounds.height(); lp.token = new Binder(); lp.setTitle(WINDOW_NAME); lp.privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION | PRIVATE_FLAG_TRUSTED_OVERLAY; // TODO(b/189839391): Set INPUT_FEATURE_NO_INPUT_CHANNEL after WM supports // TRUSTED_OVERLAY for windowless window without input channel. - mViewHost.setView(rootView, lp); + mViewHost.setView(rootLayout, lp); mLeash = getSurfaceControl(mViewHost.getWindowToken()); - t.setLayer(mLeash, Integer.MAX_VALUE); + + drawOutline(); } void release() { if (mViewHost != null) { mViewHost.release(); + mViewHost = null; } + mRootBounds.setEmpty(); + mLastOutlineBounds.setEmpty(); + mOutlineView = null; + mHostLeash = null; + mLeash = null; + } + + @Nullable + SurfaceControl getOutlineLeash() { + return mLeash; } - private static void computeOutlineBounds(Context context, Rect rootBounds, Rect outBounds) { - computeDisplayStableBounds(context, outBounds); - outBounds.intersect(rootBounds); + void setVisibility(boolean visible) { + if (mOutlineView != null) { + mOutlineView.setVisibility(visible ? View.VISIBLE : View.INVISIBLE); + } + } + + void setRootBounds(Rect rootBounds) { + if (mViewHost == null || mViewHost.getView() == null) { + return; + } + + if (!mRootBounds.equals(rootBounds)) { + WindowManager.LayoutParams lp = + (WindowManager.LayoutParams) mViewHost.getView().getLayoutParams(); + lp.width = rootBounds.width(); + lp.height = rootBounds.height(); + mViewHost.relayout(lp); + mRootBounds.set(rootBounds); + drawOutline(); + } + } + + void onInsetsChanged(InsetsState insetsState) { + if (!mInsetsState.equals(insetsState)) { + mInsetsState.set(insetsState); + drawOutline(); + } + } + + private void computeOutlineBounds(Rect rootBounds, InsetsState insetsState, Rect outBounds) { + outBounds.set(rootBounds); + final InsetsSource taskBarInsetsSource = + insetsState.getSource(InsetsState.ITYPE_EXTRA_NAVIGATION_BAR); + // Only insets the divider bar with task bar when it's expanded so that the rounded corners + // will be drawn against task bar. + if (taskBarInsetsSource.getFrame().height() >= mExpandedTaskBarHeight) { + outBounds.inset(taskBarInsetsSource.calculateVisibleInsets(outBounds)); + } + // Offset the coordinate from screen based to surface based. outBounds.offset(-rootBounds.left, -rootBounds.top); } - private static void computeDisplayStableBounds(Context context, Rect outBounds) { - final WindowMetrics windowMetrics = - context.getSystemService(WindowManager.class).getMaximumWindowMetrics(); - outBounds.set(windowMetrics.getBounds()); - outBounds.inset(windowMetrics.getWindowInsets().getInsets( - WindowInsets.Type.systemBars() | WindowInsets.Type.displayCutout())); + void drawOutline() { + if (mOutlineView == null) { + return; + } + + computeOutlineBounds(mRootBounds, mInsetsState, mTempRect); + if (mTempRect.equals(mLastOutlineBounds)) { + return; + } + + ViewGroup.MarginLayoutParams lp = + (ViewGroup.MarginLayoutParams) mOutlineView.getLayoutParams(); + lp.leftMargin = mTempRect.left; + lp.topMargin = mTempRect.top; + lp.width = mTempRect.width(); + lp.height = mTempRect.height(); + mOutlineView.setLayoutParams(lp); + mLastOutlineBounds.set(mTempRect); } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/OutlineRoot.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/OutlineRoot.java deleted file mode 100644 index 71d48eeca71d..000000000000 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/OutlineRoot.java +++ /dev/null @@ -1,62 +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.wm.shell.splitscreen; - -import android.content.Context; -import android.graphics.Rect; -import android.util.AttributeSet; -import android.widget.FrameLayout; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import com.android.wm.shell.R; - -/** Root layout for holding split outline. */ -public class OutlineRoot extends FrameLayout { - public OutlineRoot(@NonNull Context context) { - super(context); - } - - public OutlineRoot(@NonNull Context context, - @Nullable AttributeSet attrs) { - super(context, attrs); - } - - public OutlineRoot(@NonNull Context context, @Nullable AttributeSet attrs, - int defStyleAttr) { - super(context, attrs, defStyleAttr); - } - - public OutlineRoot(@NonNull Context context, @Nullable AttributeSet attrs, - int defStyleAttr, - int defStyleRes) { - super(context, attrs, defStyleAttr, defStyleRes); - } - - private OutlineView mOutlineView; - - @Override - protected void onFinishInflate() { - super.onFinishInflate(); - mOutlineView = findViewById(R.id.split_outline); - } - - void updateOutlineBounds(Rect bounds, int color) { - mOutlineView.updateOutlineBounds(bounds, color); - } -} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/OutlineView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/OutlineView.java index ea66180e3dd2..94dd9b24875a 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/OutlineView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/OutlineView.java @@ -16,13 +16,17 @@ package com.android.wm.shell.splitscreen; +import static android.view.RoundedCorner.POSITION_BOTTOM_LEFT; +import static android.view.RoundedCorner.POSITION_BOTTOM_RIGHT; +import static android.view.RoundedCorner.POSITION_TOP_LEFT; +import static android.view.RoundedCorner.POSITION_TOP_RIGHT; + import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Path; -import android.graphics.Rect; -import android.graphics.Region; import android.util.AttributeSet; +import android.view.RoundedCorner; import android.view.View; import androidx.annotation.NonNull; @@ -33,44 +37,46 @@ import com.android.internal.R; /** View for drawing split outline. */ public class OutlineView extends View { private final Paint mPaint = new Paint(); - private final Rect mBounds = new Rect(); - - public OutlineView(@NonNull Context context) { - super(context); - } + private final Path mPath = new Path(); + private final float[] mRadii = new float[8]; - public OutlineView(@NonNull Context context, - @Nullable AttributeSet attrs) { + public OutlineView(@NonNull Context context, @Nullable AttributeSet attrs) { super(context, attrs); + mPaint.setStyle(Paint.Style.STROKE); + mPaint.setStrokeWidth( + getResources().getDimension(R.dimen.accessibility_focus_highlight_stroke_width)); + mPaint.setColor(getResources().getColor(R.color.system_accent1_100, null)); } - public OutlineView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); + @Override + protected void onAttachedToWindow() { + // TODO(b/200850654): match the screen corners with the actual display decor. + mRadii[0] = mRadii[1] = getCornerRadius(POSITION_TOP_LEFT); + mRadii[2] = mRadii[3] = getCornerRadius(POSITION_TOP_RIGHT); + mRadii[4] = mRadii[5] = getCornerRadius(POSITION_BOTTOM_RIGHT); + mRadii[6] = mRadii[7] = getCornerRadius(POSITION_BOTTOM_LEFT); } - public OutlineView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, - int defStyleRes) { - super(context, attrs, defStyleAttr, defStyleRes); + private int getCornerRadius(@RoundedCorner.Position int position) { + final RoundedCorner roundedCorner = getDisplay().getRoundedCorner(position); + return roundedCorner == null ? 0 : roundedCorner.getRadius(); } @Override - protected void onFinishInflate() { - super.onFinishInflate(); - mPaint.setStyle(Paint.Style.STROKE); - mPaint.setStrokeWidth(getResources() - .getDimension(R.dimen.accessibility_focus_highlight_stroke_width)); + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + if (changed) { + mPath.reset(); + mPath.addRoundRect(0, 0, getWidth(), getHeight(), mRadii, Path.Direction.CW); + } } - void updateOutlineBounds(Rect bounds, int color) { - if (mBounds.equals(bounds) && mPaint.getColor() == color) return; - mBounds.set(bounds); - mPaint.setColor(color); + @Override + protected void onDraw(Canvas canvas) { + canvas.drawPath(mPath, mPaint); } @Override - protected void onDraw(Canvas canvas) { - if (mBounds.isEmpty()) return; - final Path path = new Region(mBounds).getBoundaryPath(); - canvas.drawPath(path, mPaint); + public boolean hasOverlappingRendering() { + return false; } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java index 2b19bb965fed..0e7ccd3515c4 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java @@ -17,15 +17,19 @@ package com.android.wm.shell.splitscreen; import android.annotation.CallSuper; +import android.annotation.Nullable; import android.app.ActivityManager; import android.content.Context; -import android.graphics.Color; import android.graphics.Rect; +import android.view.InsetsSourceControl; +import android.view.InsetsState; +import android.view.SurfaceControl; import android.view.SurfaceSession; import android.window.WindowContainerToken; import android.window.WindowContainerTransaction; import com.android.wm.shell.ShellTaskOrganizer; +import com.android.wm.shell.common.DisplayInsetsController; import com.android.wm.shell.common.SyncTransactionQueue; /** @@ -34,7 +38,8 @@ import com.android.wm.shell.common.SyncTransactionQueue; * * @see StageCoordinator */ -class SideStage extends StageTaskListener { +class SideStage extends StageTaskListener implements + DisplayInsetsController.OnInsetsChangedListener { private static final String TAG = SideStage.class.getSimpleName(); private final Context mContext; private OutlineManager mOutlineManager; @@ -77,33 +82,61 @@ class SideStage extends StageTaskListener { return true; } + @Nullable + public SurfaceControl getOutlineLeash() { + return mOutlineManager.getOutlineLeash(); + } + + @Override + @CallSuper + public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash) { + super.onTaskAppeared(taskInfo, leash); + if (isRootTask(taskInfo)) { + mOutlineManager = new OutlineManager(mContext, taskInfo.configuration); + enableOutline(true); + } + } + + @Override + @CallSuper + public void onTaskInfoChanged(ActivityManager.RunningTaskInfo taskInfo) { + super.onTaskInfoChanged(taskInfo); + if (isRootTask(taskInfo)) { + mOutlineManager.setRootBounds(taskInfo.configuration.windowConfiguration.getBounds()); + } + } + + private boolean isRootTask(ActivityManager.RunningTaskInfo taskInfo) { + return mRootTaskInfo != null && mRootTaskInfo.taskId == taskInfo.taskId; + } + void enableOutline(boolean enable) { + if (mOutlineManager == null) { + return; + } + if (enable) { - if (mOutlineManager == null && mRootTaskInfo != null) { - mOutlineManager = new OutlineManager(mContext, mRootTaskInfo.configuration); - mSyncQueue.runInSync(t -> mOutlineManager.inflate(t, mRootLeash, Color.YELLOW)); - updateOutlineBounds(); + if (mRootTaskInfo != null) { + mOutlineManager.inflate(mRootLeash, + mRootTaskInfo.configuration.windowConfiguration.getBounds()); } } else { - if (mOutlineManager != null) { - mOutlineManager.release(); - mOutlineManager = null; - } + mOutlineManager.release(); } } - private void updateOutlineBounds() { - if (mOutlineManager == null || mRootTaskInfo == null || !mRootTaskInfo.isVisible) return; - mOutlineManager.drawOutlineBounds( - mRootTaskInfo.configuration.windowConfiguration.getBounds()); + void setOutlineVisibility(boolean visible) { + mOutlineManager.setVisibility(visible); } @Override - @CallSuper - public void onTaskInfoChanged(ActivityManager.RunningTaskInfo taskInfo) { - super.onTaskInfoChanged(taskInfo); - if (mRootTaskInfo != null && mRootTaskInfo.taskId == taskInfo.taskId) { - updateOutlineBounds(); - } + public void insetsChanged(InsetsState insetsState) { + mOutlineManager.onInsetsChanged(insetsState); + } + + @Override + public void insetsControlChanged(InsetsState insetsState, + InsetsSourceControl[] activeControls) { + insetsChanged(insetsState); } } 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 6527cabb0d34..ac68b3b8a6a9 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 @@ -257,11 +257,6 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, } } - final RemoteAnimationTarget divider = mStageCoordinator.getDividerBarLegacyTarget(); - if (divider.leash != null) { - t.show(divider.leash); - } - t.apply(); if (finishedCallback != null) { try { @@ -300,7 +295,9 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, } transaction.apply(); transaction.close(); - return new RemoteAnimationTarget[]{mStageCoordinator.getDividerBarLegacyTarget()}; + return new RemoteAnimationTarget[]{ + mStageCoordinator.getDividerBarLegacyTarget(), + mStageCoordinator.getOutlineLegacyTarget()}; } /** 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 a046c42b2391..d7a6cfff6c6f 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 @@ -201,6 +201,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, mSurfaceSession); mDisplayImeController = displayImeController; mDisplayInsetsController = displayInsetsController; + mDisplayInsetsController.addInsetsChangedListener(mDisplayId, mSideStage); mRootTDAOrganizer.registerListener(displayId, this); final DeviceStateManager deviceStateManager = mContext.getSystemService(DeviceStateManager.class); @@ -682,6 +683,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, t.setVisibility(mSideStage.mRootLeash, bothStageVisible) .setVisibility(mMainStage.mRootLeash, bothStageVisible); applyDividerVisibility(t); + applyOutlineVisibility(t); } }); } @@ -703,6 +705,19 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, } } + private void applyOutlineVisibility(SurfaceControl.Transaction t) { + final SurfaceControl outlineLeash = mSideStage.getOutlineLeash(); + if (outlineLeash == null) { + return; + } + + if (mDividerVisible) { + t.show(outlineLeash).setLayer(outlineLeash, SPLIT_DIVIDER_LAYER); + } else { + t.hide(outlineLeash); + } + } + private void onStageHasChildrenChanged(StageListenerImpl stageListener) { final boolean hasChildren = stageListener.mHasChildren; final boolean isSideStage = stageListener == mSideStageListener; @@ -762,6 +777,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, @Override public void onLayoutChanging(SplitLayout layout) { mSyncQueue.runInSync(t -> updateSurfaceBounds(layout, t)); + mSideStage.setOutlineVisibility(false); } @Override @@ -770,6 +786,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, updateWindowBounds(layout, wct); mSyncQueue.queue(wct); mSyncQueue.runInSync(t -> updateSurfaceBounds(layout, t)); + mSideStage.setOutlineVisibility(true); mLogger.logResize(mSplitLayout.getDividerPositionAsFraction()); } @@ -1145,6 +1162,18 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, null /* taskInfo */, false /* allowEnterPip */, TYPE_DOCK_DIVIDER); } + RemoteAnimationTarget getOutlineLegacyTarget() { + final Rect bounds = mSideStage.mRootTaskInfo.configuration.windowConfiguration.getBounds(); + // Leverage TYPE_DOCK_DIVIDER type when wrapping outline remote animation target in order to + // distinguish as a split auxiliary target in Launcher. + return new RemoteAnimationTarget(-1 /* taskId */, -1 /* mode */, + mSideStage.getOutlineLeash(), false /* isTranslucent */, null /* clipRect */, + null /* contentInsets */, Integer.MAX_VALUE /* prefixOrderIndex */, + new android.graphics.Point(0, 0) /* position */, bounds, bounds, + new WindowConfiguration(), true, null /* startLeash */, null /* startBounds */, + null /* taskInfo */, false /* allowEnterPip */, TYPE_DOCK_DIVIDER); + } + @Override public void dump(@NonNull PrintWriter pw, String prefix) { final String innerPrefix = prefix + " "; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java index 15b4ff970203..4140332f50a3 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java @@ -138,8 +138,11 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener { mRootTaskInfo = taskInfo; mCallbacks.onRootTaskAppeared(); sendStatusChanged(); - mSyncQueue.runInSync(t -> mDimLayer = - SurfaceUtils.makeDimLayer(t, mRootLeash, "Dim layer", mSurfaceSession)); + mSyncQueue.runInSync(t -> { + t.hide(mRootLeash); + mDimLayer = + SurfaceUtils.makeDimLayer(t, mRootLeash, "Dim layer", mSurfaceSession); + }); } else if (taskInfo.parentTaskId == mRootTaskInfo.taskId) { final int taskId = taskInfo.taskId; mChildrenLeashes.put(taskId, leash); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/ShellUnfoldProgressProvider.java b/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/ShellUnfoldProgressProvider.java new file mode 100644 index 000000000000..74e48120bf1a --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/ShellUnfoldProgressProvider.java @@ -0,0 +1,44 @@ +/* + * 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.unfold; + +import android.annotation.FloatRange; + +import java.util.concurrent.Executor; + +/** + * Wrapper interface for unfold transition progress provider for the Shell + * @see com.android.systemui.unfold.UnfoldTransitionProgressProvider + */ +public interface ShellUnfoldProgressProvider { + + /** + * Adds a transition listener + */ + void addListener(Executor executor, UnfoldListener listener); + + /** + * Listener for receiving unfold updates + */ + interface UnfoldListener { + default void onStateChangeStarted() {} + + default void onStateChangeProgress(@FloatRange(from = 0.0, to = 1.0) float progress) {} + + default void onStateChangeFinished() {} + } +} diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java index 6b74b620dad7..d5acbbcf7d2c 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java @@ -197,6 +197,43 @@ public class ShellTaskOrganizerTests { } @Test + public void testAddListenerForMultipleTypes() { + RunningTaskInfo taskInfo1 = createTaskInfo(1, WINDOWING_MODE_FULLSCREEN); + mOrganizer.onTaskAppeared(taskInfo1, null); + RunningTaskInfo taskInfo2 = createTaskInfo(2, WINDOWING_MODE_MULTI_WINDOW); + mOrganizer.onTaskAppeared(taskInfo2, null); + + TrackingTaskListener listener = new TrackingTaskListener(); + mOrganizer.addListenerForType(listener, + TASK_LISTENER_TYPE_MULTI_WINDOW, TASK_LISTENER_TYPE_FULLSCREEN); + + // onTaskAppeared event should be delivered once for each taskInfo. + assertTrue(listener.appeared.contains(taskInfo1)); + assertTrue(listener.appeared.contains(taskInfo2)); + assertEquals(2, listener.appeared.size()); + } + + @Test + public void testRemoveListenerForMultipleTypes() { + RunningTaskInfo taskInfo1 = createTaskInfo(1, WINDOWING_MODE_FULLSCREEN); + mOrganizer.onTaskAppeared(taskInfo1, null); + RunningTaskInfo taskInfo2 = createTaskInfo(2, WINDOWING_MODE_MULTI_WINDOW); + mOrganizer.onTaskAppeared(taskInfo2, null); + + TrackingTaskListener listener = new TrackingTaskListener(); + mOrganizer.addListenerForType(listener, + TASK_LISTENER_TYPE_MULTI_WINDOW, TASK_LISTENER_TYPE_FULLSCREEN); + + mOrganizer.removeListener(listener); + + // If listener is removed properly, onTaskInfoChanged event shouldn't be delivered. + mOrganizer.onTaskInfoChanged(taskInfo1); + assertTrue(listener.infoChanged.isEmpty()); + mOrganizer.onTaskInfoChanged(taskInfo2); + assertTrue(listener.infoChanged.isEmpty()); + } + + @Test public void testWindowingModeChange() { RunningTaskInfo taskInfo = createTaskInfo(1, WINDOWING_MODE_MULTI_WINDOW); TrackingTaskListener mwListener = new TrackingTaskListener(); diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/apppairs/TestAppPairsController.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/apppairs/TestAppPairsController.java index 27c626170a4b..294bc1276291 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/apppairs/TestAppPairsController.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/apppairs/TestAppPairsController.java @@ -21,6 +21,7 @@ import static org.mockito.Mockito.mock; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.DisplayImeController; +import com.android.wm.shell.common.DisplayInsetsController; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.SyncTransactionQueue; @@ -30,7 +31,7 @@ public class TestAppPairsController extends AppPairsController { public TestAppPairsController(ShellTaskOrganizer organizer, SyncTransactionQueue syncQueue, DisplayController displayController) { super(organizer, syncQueue, displayController, mock(ShellExecutor.class), - mock(DisplayImeController.class)); + mock(DisplayImeController.class), mock(DisplayInsetsController.class)); mPool = new TestAppPairsPool(this); setPairsPool(mPool); } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/fullscreen/FullscreenTaskListenerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/fullscreen/FullscreenTaskListenerTest.java new file mode 100644 index 000000000000..d6f7e54ae369 --- /dev/null +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/fullscreen/FullscreenTaskListenerTest.java @@ -0,0 +1,151 @@ +/* + * 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.fullscreen; + +import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +import android.app.ActivityManager.RunningTaskInfo; +import android.app.WindowConfiguration; +import android.content.res.Configuration; +import android.graphics.Point; +import android.view.SurfaceControl; + +import androidx.test.filters.SmallTest; + +import com.android.wm.shell.common.SyncTransactionQueue; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.InOrder; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.util.Optional; + +@SmallTest +public class FullscreenTaskListenerTest { + + @Mock + private SyncTransactionQueue mSyncQueue; + @Mock + private FullscreenUnfoldController mUnfoldController; + @Mock + private SurfaceControl mSurfaceControl; + + private Optional<FullscreenUnfoldController> mFullscreenUnfoldController; + + private FullscreenTaskListener mListener; + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + mFullscreenUnfoldController = Optional.of(mUnfoldController); + mListener = new FullscreenTaskListener(mSyncQueue, mFullscreenUnfoldController); + } + + @Test + public void testAnimatableTaskAppeared_notifiesUnfoldController() { + RunningTaskInfo info = createTaskInfo(/* visible */ true, /* taskId */ 0); + + mListener.onTaskAppeared(info, mSurfaceControl); + + verify(mUnfoldController).onTaskAppeared(eq(info), any()); + } + + @Test + public void testMultipleAnimatableTasksAppeared_notifiesUnfoldController() { + RunningTaskInfo animatable1 = createTaskInfo(/* visible */ true, /* taskId */ 0); + RunningTaskInfo animatable2 = createTaskInfo(/* visible */ true, /* taskId */ 1); + + mListener.onTaskAppeared(animatable1, mSurfaceControl); + mListener.onTaskAppeared(animatable2, mSurfaceControl); + + InOrder order = inOrder(mUnfoldController); + order.verify(mUnfoldController).onTaskAppeared(eq(animatable1), any()); + order.verify(mUnfoldController).onTaskAppeared(eq(animatable2), any()); + } + + @Test + public void testNonAnimatableTaskAppeared_doesNotNotifyUnfoldController() { + RunningTaskInfo info = createTaskInfo(/* visible */ false, /* taskId */ 0); + + mListener.onTaskAppeared(info, mSurfaceControl); + + verifyNoMoreInteractions(mUnfoldController); + } + + @Test + public void testNonAnimatableTaskChanged_doesNotNotifyUnfoldController() { + RunningTaskInfo info = createTaskInfo(/* visible */ false, /* taskId */ 0); + mListener.onTaskAppeared(info, mSurfaceControl); + + mListener.onTaskInfoChanged(info); + + verifyNoMoreInteractions(mUnfoldController); + } + + @Test + public void testNonAnimatableTaskVanished_doesNotNotifyUnfoldController() { + RunningTaskInfo info = createTaskInfo(/* visible */ false, /* taskId */ 0); + mListener.onTaskAppeared(info, mSurfaceControl); + + mListener.onTaskVanished(info); + + verifyNoMoreInteractions(mUnfoldController); + } + + @Test + public void testAnimatableTaskBecameInactive_notifiesUnfoldController() { + RunningTaskInfo animatableTask = createTaskInfo(/* visible */ true, /* taskId */ 0); + mListener.onTaskAppeared(animatableTask, mSurfaceControl); + RunningTaskInfo notAnimatableTask = createTaskInfo(/* visible */ false, /* taskId */ 0); + + mListener.onTaskInfoChanged(notAnimatableTask); + + verify(mUnfoldController).onTaskVanished(eq(notAnimatableTask)); + } + + @Test + public void testAnimatableTaskVanished_notifiesUnfoldController() { + RunningTaskInfo taskInfo = createTaskInfo(/* visible */ true, /* taskId */ 0); + mListener.onTaskAppeared(taskInfo, mSurfaceControl); + + mListener.onTaskVanished(taskInfo); + + verify(mUnfoldController).onTaskVanished(eq(taskInfo)); + } + + private RunningTaskInfo createTaskInfo(boolean visible, int taskId) { + final RunningTaskInfo info = spy(new RunningTaskInfo()); + info.isVisible = visible; + info.positionInParent = new Point(); + when(info.getWindowingMode()).thenReturn(WindowConfiguration.WINDOWING_MODE_FULLSCREEN); + final Configuration configuration = new Configuration(); + configuration.windowConfiguration.setActivityType(ACTIVITY_TYPE_STANDARD); + when(info.getConfiguration()).thenReturn(configuration); + info.taskId = taskId; + return info; + } +} diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SideStageTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SideStageTests.java index 69ead3ac9cf9..3a2516ec9366 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SideStageTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SideStageTests.java @@ -29,6 +29,7 @@ import android.view.SurfaceControl; import android.view.SurfaceSession; import android.window.WindowContainerTransaction; +import androidx.test.annotation.UiThreadTest; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; @@ -58,6 +59,7 @@ public class SideStageTests extends ShellTestCase { private SideStage mSideStage; @Before + @UiThreadTest public void setup() { MockitoAnnotations.initMocks(this); mRootTask = new TestRunningTaskInfoBuilder().build(); diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java index d357e778fe35..8dce454eb078 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java @@ -51,6 +51,7 @@ import android.window.TransitionInfo; import android.window.TransitionRequestInfo; import android.window.WindowContainerTransaction; +import androidx.test.annotation.UiThreadTest; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; @@ -96,6 +97,7 @@ public class SplitTransitionTests extends ShellTestCase { private ActivityManager.RunningTaskInfo mSideChild; @Before + @UiThreadTest public void setup() { MockitoAnnotations.initMocks(this); final ShellExecutor mockExecutor = mock(ShellExecutor.class); diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java index 1a30f164f9a8..0916dd1f71bd 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java @@ -62,6 +62,7 @@ public final class StageTaskListenerTests { @Mock private SyncTransactionQueue mSyncQueue; @Captor private ArgumentCaptor<SyncTransactionQueue.TransactionRunnable> mRunnableCaptor; private SurfaceSession mSurfaceSession = new SurfaceSession(); + private SurfaceControl mSurfaceControl; private ActivityManager.RunningTaskInfo mRootTask; private StageTaskListener mStageTaskListener; @@ -76,7 +77,8 @@ public final class StageTaskListenerTests { mSurfaceSession); mRootTask = new TestRunningTaskInfoBuilder().build(); mRootTask.parentTaskId = INVALID_TASK_ID; - mStageTaskListener.onTaskAppeared(mRootTask, new SurfaceControl()); + mSurfaceControl = new SurfaceControl.Builder(mSurfaceSession).setName("test").build(); + mStageTaskListener.onTaskAppeared(mRootTask, mSurfaceControl); } @Test @@ -103,7 +105,7 @@ public final class StageTaskListenerTests { final ActivityManager.RunningTaskInfo childTask = new TestRunningTaskInfoBuilder().setParentTaskId(mRootTask.taskId).build(); - mStageTaskListener.onTaskAppeared(childTask, new SurfaceControl()); + mStageTaskListener.onTaskAppeared(childTask, mSurfaceControl); assertThat(mStageTaskListener.mChildrenTaskInfo.contains(childTask.taskId)).isTrue(); verify(mCallbacks).onStatusChanged(eq(mRootTask.isVisible), eq(true)); diff --git a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/Tile.java b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/Tile.java index 8f3e4bd87aa7..220cf6b5c38a 100644 --- a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/Tile.java +++ b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/Tile.java @@ -18,6 +18,7 @@ package com.android.settingslib.drawer; import static com.android.settingslib.drawer.TileUtils.META_DATA_KEY_ORDER; import static com.android.settingslib.drawer.TileUtils.META_DATA_KEY_PROFILE; +import static com.android.settingslib.drawer.TileUtils.META_DATA_NEW_TASK; import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON; import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_KEYHINT; import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_SUMMARY; @@ -329,6 +330,18 @@ public abstract class Tile implements Parcelable { } /** + * Whether the {@link Activity} should be launched in a separate task. + */ + public boolean isNewTask(Context context) { + ensureMetadataNotStale(context); + if (mMetaData != null + && mMetaData.containsKey(META_DATA_NEW_TASK)) { + return mMetaData.getBoolean(META_DATA_NEW_TASK); + } + return false; + } + + /** * Ensures metadata is not stale for this tile. */ private void ensureMetadataNotStale(Context context) { diff --git a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java index a2bec334f206..acc0087f6dcf 100644 --- a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java +++ b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java @@ -230,6 +230,13 @@ public class TileUtils { public static final String META_DATA_KEY_PROFILE = "com.android.settings.profile"; /** + * Name of the meta-data item that should be set in the AndroidManifest.xml + * to specify whether the {@link android.app.Activity} should be launched in a separate task. + * This should be a boolean value {@code true} or {@code false}, set using {@code android:value} + */ + public static final String META_DATA_NEW_TASK = "com.android.settings.new_task"; + + /** * Build a list of DashboardCategory. */ public static List<DashboardCategory> getCategories(Context context, diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml index 656fe6a9476a..eafa87bbbf7d 100644 --- a/packages/SettingsLib/res/values-as/strings.xml +++ b/packages/SettingsLib/res/values-as/strings.xml @@ -558,7 +558,7 @@ <string name="user_new_profile_name" msgid="2405500423304678841">"নতুন প্ৰ\'ফাইল"</string> <string name="user_info_settings_title" msgid="6351390762733279907">"ব্যৱহাৰকাৰীৰ তথ্য"</string> <string name="profile_info_settings_title" msgid="105699672534365099">"প্ৰ\'ফাইলৰ তথ্য"</string> - <string name="user_need_lock_message" msgid="4311424336209509301">"আপুনি সীমিত প্ৰ\'ফাইল এটা সৃষ্টি কৰাৰ আগেয়ে, আপোনাৰ ব্যক্তিগত ডেটা আৰু এপবিলাকক সুৰক্ষিত কৰিবলৈ স্ক্ৰীণ লক এটা নিৰ্ধাৰণ কৰিব লাগিব।"</string> + <string name="user_need_lock_message" msgid="4311424336209509301">"আপুনি সীমিত প্ৰ’ফাইল এটা সৃষ্টি কৰাৰ আগেয়ে, আপোনাৰ ব্যক্তিগত ডেটা আৰু এপ্বিলাকক সুৰক্ষিত কৰিবলৈ স্ক্ৰীন লক এটা নিৰ্ধাৰণ কৰিব লাগিব।"</string> <string name="user_set_lock_button" msgid="1427128184982594856">"লক ছেট কৰক"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g>লৈ সলনি কৰক"</string> <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"নতুন ব্যৱহাৰকাৰী সৃষ্টি কৰি থকা হৈছে…"</string> diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml index 6f8f99b03be6..545cf9524564 100644 --- a/packages/SettingsLib/res/values-te/strings.xml +++ b/packages/SettingsLib/res/values-te/strings.xml @@ -90,7 +90,7 @@ <string name="bluetooth_profile_pbap" msgid="7064307749579335765">"కాంటాక్ట్ షేరింగ్"</string> <string name="bluetooth_profile_pbap_summary" msgid="2955819694801952056">"కాంటాక్ట్ షేరింగ్ కోసం ఉపయోగించండి"</string> <string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"ఇంటర్నెట్ కనెక్షన్ షేరింగ్"</string> - <string name="bluetooth_profile_map" msgid="8907204701162107271">"వచన మెసేజ్లు"</string> + <string name="bluetooth_profile_map" msgid="8907204701162107271">"టెక్స్ట్ మెసేజ్లు"</string> <string name="bluetooth_profile_sap" msgid="8304170950447934386">"SIM యాక్సెస్"</string> <string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"HD ఆడియో: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string> <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"HD ఆడియో"</string> diff --git a/packages/SystemUI/res-keyguard/color/numpad_key_color_secondary.xml b/packages/SystemUI/res-keyguard/color/numpad_key_color_secondary.xml new file mode 100644 index 000000000000..08c66a24348c --- /dev/null +++ b/packages/SystemUI/res-keyguard/color/numpad_key_color_secondary.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<selector xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"> + <item android:color="?androidprv:attr/colorAccentSecondaryVariant"/> +</selector>
\ No newline at end of file diff --git a/packages/SystemUI/res-keyguard/values/styles.xml b/packages/SystemUI/res-keyguard/values/styles.xml index 6fd83c55b656..6e89fb0169ab 100644 --- a/packages/SystemUI/res-keyguard/values/styles.xml +++ b/packages/SystemUI/res-keyguard/values/styles.xml @@ -17,8 +17,7 @@ */ --> -<resources - xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"> +<resources xmlns:android="http://schemas.android.com/apk/res/android"> <!-- Keyguard PIN pad styles --> <style name="Keyguard.TextView" parent="@android:style/Widget.DeviceDefault.TextView"> <item name="android:textSize">@dimen/kg_status_line_font_size</item> @@ -59,11 +58,11 @@ <item name="android:textColor">?android:attr/textColorPrimary</item> </style> <style name="NumPadKey.Delete"> - <item name="android:colorControlNormal">?androidprv:attr/colorAccentSecondaryVariant</item> + <item name="android:colorControlNormal">@color/numpad_key_color_secondary</item> <item name="android:src">@drawable/ic_backspace_24dp</item> </style> <style name="NumPadKey.Enter"> - <item name="android:colorControlNormal">?androidprv:attr/colorAccentSecondaryVariant</item> + <item name="android:colorControlNormal">@color/numpad_key_color_secondary</item> <item name="android:src">@drawable/ic_keyboard_tab_36dp</item> </style> <style name="Widget.TextView.NumPadKey.Klondike" diff --git a/packages/SystemUI/res/layout/global_screenshot_static.xml b/packages/SystemUI/res/layout/global_screenshot_static.xml index 6a9254cad8f4..21c5ab04eb9a 100644 --- a/packages/SystemUI/res/layout/global_screenshot_static.xml +++ b/packages/SystemUI/res/layout/global_screenshot_static.xml @@ -130,13 +130,4 @@ app:layout_constraintStart_toStartOf="@id/global_screenshot_preview" app:layout_constraintTop_toTopOf="@id/global_screenshot_preview" android:elevation="@dimen/screenshot_preview_elevation"/> - <View - android:id="@+id/screenshot_transition_view" - android:layout_width="0dp" - android:layout_height="0dp" - android:visibility="invisible" - app:layout_constraintStart_toStartOf="@id/global_screenshot_preview" - app:layout_constraintTop_toTopOf="@id/global_screenshot_preview" - app:layout_constraintEnd_toEndOf="@id/global_screenshot_preview" - app:layout_constraintBottom_toBottomOf="@id/global_screenshot_preview"/> </androidx.constraintlayout.widget.ConstraintLayout> diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml index 4b6e58fbd1e5..18315f1dff42 100644 --- a/packages/SystemUI/res/layout/status_bar_expanded.xml +++ b/packages/SystemUI/res/layout/status_bar_expanded.xml @@ -25,12 +25,6 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:background="@android:color/transparent"> - <FrameLayout - android:id="@+id/big_clock_container" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:visibility="gone" /> - <ViewStub android:id="@+id/keyguard_qs_user_switch_stub" android:layout="@layout/keyguard_qs_user_switch" diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml index 93ac0404fe87..57e70a6772a0 100644 --- a/packages/SystemUI/res/values-bn/strings.xml +++ b/packages/SystemUI/res/values-bn/strings.xml @@ -1175,8 +1175,7 @@ <string name="unlock_to_view_networks" msgid="5072880496312015676">"নেটওয়ার্ক দেখার জন্য আনলক করুন"</string> <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"নেটওয়ার্ক সার্চ করা হচ্ছে…"</string> <string name="wifi_failed_connect_message" msgid="4161863112079000071">"নেটওয়ার্কে কানেক্ট করা যায়নি"</string> - <!-- no translation found for wifi_wont_autoconnect_for_now (5782282612749867762) --> - <skip /> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"এখন ওয়াই-ফাই নিজে থেকে কানেক্ট হবে না"</string> <string name="see_all_networks" msgid="3773666844913168122">"সবকটি দেখুন"</string> <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"নেটওয়ার্ক বদলাতে ইথারনেট ডিসকানেক্ট করুন"</string> </resources> diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml index 79281156e00b..e713cb79f6dc 100644 --- a/packages/SystemUI/res/values-gu/strings.xml +++ b/packages/SystemUI/res/values-gu/strings.xml @@ -1175,8 +1175,7 @@ <string name="unlock_to_view_networks" msgid="5072880496312015676">"વાઇ-ફાઇ નેટવર્ક જોવા માટે અનલૉક કરો"</string> <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"નેટવર્ક શોધી રહ્યાં છીએ…"</string> <string name="wifi_failed_connect_message" msgid="4161863112079000071">"નેટવર્ક સાથે કનેક્ટ કરવામાં નિષ્ફળ થયાં"</string> - <!-- no translation found for wifi_wont_autoconnect_for_now (5782282612749867762) --> - <skip /> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"હમણાં પૂરતું વાઇ-ફાઇ ઑટોમૅટિક રીતે કનેક્ટ થશે નહીં"</string> <string name="see_all_networks" msgid="3773666844913168122">"બધા જુઓ"</string> <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"બીજા નેટવર્ક પર જવા માટે, ઇથરનેટ ડિસ્કનેક્ટ કરો"</string> </resources> diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml index 0a28735aadd1..ca69a82a1295 100644 --- a/packages/SystemUI/res/values-kn/strings.xml +++ b/packages/SystemUI/res/values-kn/strings.xml @@ -1175,8 +1175,7 @@ <string name="unlock_to_view_networks" msgid="5072880496312015676">"ನೆಟ್ವರ್ಕ್ಗಳನ್ನು ವೀಕ್ಷಿಸಲು ಅನ್ಲಾಕ್ ಮಾಡಿ"</string> <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"ನೆಟ್ವರ್ಕ್ಗಳನ್ನು ಹುಡುಕಲಾಗುತ್ತಿದೆ…"</string> <string name="wifi_failed_connect_message" msgid="4161863112079000071">"ನೆಟ್ವರ್ಕ್ಗೆ ಕನೆಕ್ಟ್ ಮಾಡಲು ವಿಫಲವಾಗಿದೆ"</string> - <!-- no translation found for wifi_wont_autoconnect_for_now (5782282612749867762) --> - <skip /> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"ಸದ್ಯದ ಮಟ್ಟಿಗೆ ವೈ-ಫೈ ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಕನೆಕ್ಟ್ ಆಗುವುದಿಲ್ಲ"</string> <string name="see_all_networks" msgid="3773666844913168122">"ಎಲ್ಲವನ್ನೂ ನೋಡಿ"</string> <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"ನೆಟ್ವರ್ಕ್ಗಳನ್ನು ಬದಲಿಸಲು, ಇಥರ್ನೆಟ್ ಅನ್ನು ಡಿಸ್ಕನೆಕ್ಟ್ ಮಾಡಿ"</string> </resources> diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml index 50fb26c7a297..666f9edf8e59 100644 --- a/packages/SystemUI/res/values-my/strings.xml +++ b/packages/SystemUI/res/values-my/strings.xml @@ -1175,7 +1175,7 @@ <string name="unlock_to_view_networks" msgid="5072880496312015676">"ကွန်ရက်များကြည့်ရန် ဖွင့်ပါ"</string> <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"ကွန်ရက်များကို ရှာဖွေနေသည်…"</string> <string name="wifi_failed_connect_message" msgid="4161863112079000071">"ကွန်ရက်သို့ ချိတ်ဆက်၍မရပါ"</string> - <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi-Fi က ယခု အလိုအလျောက် ချိတ်ဆက်မည်မဟုတ်ပါ"</string> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi-Fi က လောလောဆယ် အလိုအလျောက် ချိတ်ဆက်မည်မဟုတ်ပါ"</string> <string name="see_all_networks" msgid="3773666844913168122">"အားလုံးကြည့်ရန်"</string> <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"ကွန်ရက်ပြောင်းရန် အီသာနက်ကို ချိတ်ဆက်မှုဖြုတ်ပါ"</string> </resources> diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml index dda2830bbc8c..95b8a63fa581 100644 --- a/packages/SystemUI/res/values-te/strings.xml +++ b/packages/SystemUI/res/values-te/strings.xml @@ -101,7 +101,7 @@ <string name="screenrecord_background_processing_label" msgid="7244617554884238898">"స్క్రీన్ రికార్డింగ్ అవుతోంది"</string> <string name="screenrecord_channel_description" msgid="4147077128486138351">"స్క్రీన్ రికార్డ్ సెషన్ కోసం ఆన్గోయింగ్ నోటిఫికేషన్"</string> <string name="screenrecord_start_label" msgid="1750350278888217473">"రికార్డింగ్ను ప్రారంభించాలా?"</string> - <string name="screenrecord_description" msgid="1123231719680353736">"రికార్డ్ చేస్తున్నప్పుడు, Android సిస్టమ్ మీ స్క్రీన్పై ప్రదర్శించబడిన లేదా మీ పరికరం నుండి ప్లే చేయబడిన ఏ సున్నితమైన సమాచారాన్నైనా క్యాప్చర్ చేయగలదు. ఈ సమాచారంలో, పాస్వర్డ్లు, పేమెంట్ వివరాలు, ఫోటోలు, మెసేజ్లు, ఆడియో ఉంటాయి."</string> + <string name="screenrecord_description" msgid="1123231719680353736">"రికార్డ్ చేస్తున్నప్పుడు, Android సిస్టమ్ మీ స్క్రీన్పై ప్రదర్శించబడిన లేదా మీ పరికరం నుండి ప్లే చేయబడిన ఏ సున్నితమైన సమాచారాన్నయినా క్యాప్చర్ చేయగలదు. ఈ సమాచారంలో, పాస్వర్డ్లు, పేమెంట్ వివరాలు, ఫోటోలు, మెసేజ్లు, ఆడియో కూడా ఉంటాయి."</string> <string name="screenrecord_audio_label" msgid="6183558856175159629">"ఆడియోను రికార్డ్ చేయి"</string> <string name="screenrecord_device_audio_label" msgid="9016927171280567791">"పరికరం ఆడియో"</string> <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"మీ పరికరం నుండి వచ్చే సంగీతం, కాల్స్, రింగ్టోన్ల వంటి ధ్వనులు"</string> @@ -507,7 +507,7 @@ <string name="battery_saver_notification_title" msgid="8419266546034372562">"బ్యాటరీ సేవర్ ఆన్లో ఉంది"</string> <string name="battery_saver_notification_text" msgid="2617841636449016951">"పనితీరుని మరియు నేపథ్య డేటాను తగ్గిస్తుంది"</string> <string name="battery_saver_notification_action_text" msgid="6022091913807026887">"బ్యాటరీ సేవర్ను ఆఫ్ చేయండి"</string> - <string name="media_projection_dialog_text" msgid="1755705274910034772">"రికార్డ్ చేస్తున్నప్పుడు లేదా ప్రసారం చేస్తున్నప్పుడు, మీ స్క్రీన్పై ప్రదర్శించబడిన లేదా మీ పరికరం నుండి ప్లే చేయబడిన సమాచారం మొత్తాన్ని, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> యాక్సెస్ చేయగలుగుతుంది. ఈ సమాచారంలో, పాస్వర్డ్లు, చెల్లింపు వివరాలు, ఫోటోలు, మెసేజ్లు, మీరు ప్లే చేసే ఆడియో వంటివి ఉంటాయి."</string> + <string name="media_projection_dialog_text" msgid="1755705274910034772">"రికార్డ్ చేస్తున్నప్పుడు లేదా ప్రసారం చేస్తున్నప్పుడు, మీ స్క్రీన్పై ప్రదర్శించబడిన లేదా మీ పరికరం నుండి ప్లే చేయబడిన సమాచారం మొత్తాన్ని, <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> యాక్సెస్ చేయగలుగుతుంది. ఈ సమాచారంలో, పాస్వర్డ్లు, పేమెంట్ వివరాలు, ఫోటోలు, మెసేజ్లు, మీరు ప్లే చేసే ఆడియో వంటివి ఉంటాయి."</string> <string name="media_projection_dialog_service_text" msgid="958000992162214611">"రికార్డ్ చేస్తున్నప్పుడు లేదా ప్రసారం చేస్తున్నప్పుడు మీ స్క్రీన్పై ప్రదర్శించబడిన లేదా మీ పరికరం నుండి ప్లే చేయబడిన సమాచారం మొత్తాన్ని, ఈ ఫంక్షన్ను అందిస్తున్న సర్వీస్ యాక్సెస్ చేయగలదు. ఈ సమాచారంలో, పాస్వర్డ్లు, పేమెంట్ వివరాలు, ఫోటోలు, మెసేజ్లు, మీరు ప్లే చేసే ఆడియో వంటివి ఉంటాయి."</string> <string name="media_projection_dialog_service_title" msgid="2888507074107884040">"రికార్డ్ చేయడం లేదా ప్రసారం చేయడం ప్రారంభించాలా?"</string> <string name="media_projection_dialog_title" msgid="3316063622495360646">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>తో రికార్డ్ చేయడం లేదా ప్రసారం చేయడం ప్రారంభించాలా?"</string> @@ -1145,7 +1145,7 @@ <string name="status_before_loading" msgid="1500477307859631381">"కంటెంట్ త్వరలో కనిపిస్తుంది"</string> <string name="missed_call" msgid="4228016077700161689">"మిస్డ్ కాల్"</string> <string name="messages_count_overflow_indicator" msgid="7850934067082006043">"<xliff:g id="NUMBER">%d</xliff:g>+"</string> - <string name="people_tile_description" msgid="8154966188085545556">"ఇటీవలి మెసేజ్లు, మిస్డ్ కాల్స్, అలాగే స్టేటస్ అప్డేట్లను చూడండి"</string> + <string name="people_tile_description" msgid="8154966188085545556">"ఇటీవలి మెసేజ్లు, మిస్స్డ్ కాల్స్, అలాగే స్టేటస్ అప్డేట్లను చూడండి"</string> <string name="people_tile_title" msgid="6589377493334871272">"సంభాషణ"</string> <string name="paused_by_dnd" msgid="7856941866433556428">"అంతరాయం కలిగించవద్దు ద్వారా పాజ్ చేయబడింది"</string> <string name="new_notification_text_content_description" msgid="2915029960094389291">"<xliff:g id="NAME">%1$s</xliff:g> మెసేజ్ను పంపారు: <xliff:g id="NOTIFICATION">%2$s</xliff:g>"</string> diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml index da431826c278..44b91ad7419e 100644 --- a/packages/SystemUI/res/values-ur/strings.xml +++ b/packages/SystemUI/res/values-ur/strings.xml @@ -1175,8 +1175,7 @@ <string name="unlock_to_view_networks" msgid="5072880496312015676">"نیٹ ورکس کو دیکھنے کے لیے غیر مقفل کریں"</string> <string name="wifi_empty_list_wifi_on" msgid="3864376632067585377">"نیٹ ورکس تلاش کیے جا رہے ہیں…"</string> <string name="wifi_failed_connect_message" msgid="4161863112079000071">"نیٹ ورک سے منسلک ہونے میں ناکام ہو گیا"</string> - <!-- no translation found for wifi_wont_autoconnect_for_now (5782282612749867762) --> - <skip /> + <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"ابھی Wi-Fi خود کار طور پر منسلک نہیں ہوگا"</string> <string name="see_all_networks" msgid="3773666844913168122">"سبھی دیکھیں"</string> <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"نیٹ ورکس پر سوئچ کرنے کیلئے، ایتھرنیٹ غیر منسلک کریں"</string> </resources> diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index 73643c8d8684..d0de876a6b27 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -191,6 +191,15 @@ low powered state yet. --> <bool name="doze_single_tap_uses_prox">true</bool> + <!-- Doze: whether the single tap sensor uses the proximity sensor in the given posture. + See doze_single_tap_uses_prox for usage. --> + <integer-array name="doze_single_tap_uses_prox_posture_mapping"> + <item>1</item> <!-- UNKNOWN --> + <item>1</item> <!-- CLOSED --> + <item>1</item> <!-- HALF_OPENED --> + <item>1</item> <!-- OPENED --> + </integer-array> + <!-- Doze: whether the long press sensor uses the proximity sensor. If both this parameter and doze_selectively_register_prox are true, registration for the sensor will be delayed when the device first enters dozing but the device has not entered its @@ -211,9 +220,27 @@ always-on display) --> <string name="doze_brightness_sensor_type" translatable="false"></string> + <!-- Name of a sensor per posture state that provides a low-power estimate of the desired + display brightness, suitable to listen to while the device is asleep (e.g. during + always-on display) --> + <string-array name="doze_brightness_sensor_name_posture_mapping" translatable="false"> + <!-- UNKNOWN --> + <!-- CLOSED --> + <!-- HALF_OPENED --> + <!-- OPENED --> + </string-array> + <!-- Override value to use for proximity sensor. --> <string name="proximity_sensor_type" translatable="false"></string> + <!-- Sensor type per posture state to use for proximity sensor --> + <string-array name="proximity_sensor_posture_mapping" translatable="false"> + <!-- UNKNOWN --> + <!-- CLOSED --> + <!-- HALF_OPENED --> + <!-- OPENED --> + </string-array> + <!-- If using proximity_sensor_type, specifies a threshold value to distinguish near and far break points. A sensor value less than this is considered "near". --> <item name="proximity_sensor_threshold" translatable="false" format="float" type="dimen"></item> @@ -227,6 +254,15 @@ <!-- Override value to use for proximity sensor as confirmation for proximity_sensor_type. --> <string name="proximity_sensor_secondary_type" translatable="false"></string> + <!-- Sensor type per posture state to use for proximity sensor as a confirmation for + proximity_sensor_type. --> + <string-array name="proximity_sensor_secondary_posture_mapping" translatable="false"> + <!-- UNKNOWN --> + <!-- CLOSED --> + <!-- HALF_OPENED --> + <!-- OPENED --> + </string-array> + <!-- If using proximity_sensor_secondary_type, specifies a threshold value to distinguish near and far break points. A sensor value less than this is considered "near". --> <item name="proximity_sensor_secondary_threshold" translatable="false" format="float" diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java index 8f14cd858f1e..f81f0b9ca2c3 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java @@ -11,6 +11,7 @@ import android.util.AttributeSet; import android.util.TypedValue; import android.view.View; import android.view.ViewGroup; +import android.view.ViewTreeObserver.OnPreDrawListener; import android.widget.FrameLayout; import android.widget.RelativeLayout; @@ -93,6 +94,7 @@ public class KeyguardClockSwitch extends RelativeLayout { private int[] mColorPalette; private int mClockSwitchYAmount; + @VisibleForTesting boolean mChildrenAreLaidOut = false; public KeyguardClockSwitch(Context context, AttributeSet attrs) { super(context, attrs); @@ -284,11 +286,31 @@ public class KeyguardClockSwitch extends RelativeLayout { if (mDisplayedClockSize != null && clockSize == mDisplayedClockSize) { return false; } - animateClockChange(clockSize == LARGE); - mDisplayedClockSize = clockSize; + + // let's make sure clock is changed only after all views were laid out so we can + // translate them properly + if (mChildrenAreLaidOut) { + animateClockChange(clockSize == LARGE); + mDisplayedClockSize = clockSize; + } else { + getViewTreeObserver().addOnPreDrawListener(new OnPreDrawListener() { + @Override + public boolean onPreDraw() { + switchToClock(clockSize); + getViewTreeObserver().removeOnPreDrawListener(this); + return true; + } + }); + } return true; } + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + super.onLayout(changed, l, t, r, b); + mChildrenAreLaidOut = true; + } + public Paint getPaint() { return mClockView.getPaint(); } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardMessageArea.java b/packages/SystemUI/src/com/android/keyguard/KeyguardMessageArea.java index 62411dbff5fd..11eeac2272ff 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardMessageArea.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardMessageArea.java @@ -153,6 +153,10 @@ public class KeyguardMessageArea extends TextView implements SecurityMessageDisp colorState = mNextMessageColorState; mNextMessageColorState = ColorStateList.valueOf(DEFAULT_COLOR); } + if (mAltBouncerShowing) { + // alt bouncer has a black scrim, so always show the text in white + colorState = ColorStateList.valueOf(Color.WHITE); + } setTextColor(colorState); } diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java index 14e5991f35d2..be326da8d3bf 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java @@ -37,6 +37,7 @@ import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.util.concurrency.DelayableExecutor; import com.android.systemui.util.sensors.ProximitySensor; import com.android.systemui.util.sensors.ThresholdSensor; +import com.android.systemui.util.sensors.ThresholdSensorEvent; import com.android.systemui.util.time.SystemClock; import java.util.Collections; @@ -405,7 +406,7 @@ class FalsingCollectorImpl implements FalsingCollector { mProximitySensor.unregister(mSensorEventListener); } - private void onProximityEvent(ThresholdSensor.ThresholdSensorEvent proximityEvent) { + private void onProximityEvent(ThresholdSensorEvent proximityEvent) { // TODO: some of these classifiers might allow us to abort early, meaning we don't have to // make these calls. mFalsingManager.onProximityEvent(new ProximityEventImpl(proximityEvent)); @@ -423,9 +424,9 @@ class FalsingCollectorImpl implements FalsingCollector { } private static class ProximityEventImpl implements FalsingManager.ProximityEvent { - private ThresholdSensor.ThresholdSensorEvent mThresholdSensorEvent; + private ThresholdSensorEvent mThresholdSensorEvent; - ProximityEventImpl(ThresholdSensor.ThresholdSensorEvent thresholdSensorEvent) { + ProximityEventImpl(ThresholdSensorEvent thresholdSensorEvent) { mThresholdSensorEvent = thresholdSensorEvent; } @Override diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java index 2d873f26c0c2..fa2384268b15 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java @@ -24,8 +24,6 @@ import android.app.INotificationManager; import android.content.Context; import android.content.SharedPreferences; import android.content.om.OverlayManager; -import android.hardware.SensorManager; -import android.hardware.devicestate.DeviceStateManager; import android.hardware.display.AmbientDisplayConfiguration; import android.hardware.display.ColorDisplayManager; import android.os.Handler; @@ -56,22 +54,18 @@ import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.doze.AlwaysOnDisplayPolicy; import com.android.systemui.dump.DumpManager; import com.android.systemui.keyguard.KeyguardViewMediator; -import com.android.systemui.keyguard.LifecycleScreenStatusProvider; import com.android.systemui.qs.ReduceBrightColorsController; import com.android.systemui.settings.UserTracker; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.DevicePolicyManagerWrapper; import com.android.systemui.shared.system.TaskStackChangeListeners; import com.android.systemui.shared.system.WindowManagerWrapper; +import com.android.systemui.statusbar.connectivity.NetworkController; import com.android.systemui.statusbar.phone.AutoHideController; import com.android.systemui.statusbar.phone.ConfigurationControllerImpl; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.DataSaverController; -import com.android.systemui.statusbar.policy.NetworkController; import com.android.systemui.theme.ThemeOverlayApplier; -import com.android.systemui.unfold.UnfoldTransitionFactory; -import com.android.systemui.unfold.UnfoldTransitionProgressProvider; -import com.android.systemui.unfold.config.UnfoldTransitionConfig; import com.android.systemui.util.leak.LeakDetector; import com.android.systemui.util.settings.SecureSettings; @@ -287,37 +281,6 @@ public class DependencyProvider { /** */ @Provides @SysUISingleton - public UnfoldTransitionProgressProvider provideUnfoldTransitionProgressProvider( - Context context, - UnfoldTransitionConfig config, - LifecycleScreenStatusProvider screenStatusProvider, - DeviceStateManager deviceStateManager, - SensorManager sensorManager, - @Main Executor executor, - @Main Handler handler - ) { - return UnfoldTransitionFactory - .createUnfoldTransitionProgressProvider( - context, - config, - screenStatusProvider, - deviceStateManager, - sensorManager, - handler, - executor - ); - } - - /** */ - @Provides - @SysUISingleton - public UnfoldTransitionConfig provideUnfoldTransitionConfig(Context context) { - return UnfoldTransitionFactory.createConfig(context); - } - - /** */ - @Provides - @SysUISingleton public Choreographer providesChoreographer() { return Choreographer.getInstance(); } diff --git a/packages/SystemUI/src/com/android/systemui/dagger/GlobalModule.java b/packages/SystemUI/src/com/android/systemui/dagger/GlobalModule.java index 648f345205db..18f85196aa0b 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/GlobalModule.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/GlobalModule.java @@ -24,6 +24,7 @@ import com.android.internal.logging.UiEventLogger; import com.android.internal.logging.UiEventLoggerImpl; import com.android.systemui.dagger.qualifiers.TestHarness; import com.android.systemui.plugins.PluginsModule; +import com.android.systemui.unfold.UnfoldTransitionModule; import com.android.systemui.util.concurrency.GlobalConcurrencyModule; import javax.inject.Singleton; @@ -49,6 +50,7 @@ import dagger.Provides; @Module(includes = { FrameworkServicesModule.class, GlobalConcurrencyModule.class, + UnfoldTransitionModule.class, PluginsModule.class, }) public class GlobalModule { diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java index 55e6154b829d..3cefce83393a 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java @@ -47,6 +47,7 @@ import com.android.keyguard.KeyguardUpdateMonitor; import com.android.systemui.biometrics.AuthController; import com.android.systemui.plugins.SensorManagerPlugin; import com.android.systemui.statusbar.phone.DozeParameters; +import com.android.systemui.statusbar.policy.DevicePostureController; import com.android.systemui.util.sensors.AsyncSensorManager; import com.android.systemui.util.sensors.ProximitySensor; import com.android.systemui.util.settings.SecureSettings; @@ -82,6 +83,9 @@ public class DozeSensors { private boolean mListeningTouchScreenSensors; private boolean mListeningProxSensors; + @DevicePostureController.DevicePostureInt + private int mDevicePosture; + // whether to only register sensors that use prox when the display state is dozing or off private boolean mSelectivelyRegisterProxSensors; @@ -106,7 +110,8 @@ public class DozeSensors { DozeParameters dozeParameters, AmbientDisplayConfiguration config, WakeLock wakeLock, Callback callback, Consumer<Boolean> proxCallback, DozeLog dozeLog, ProximitySensor proximitySensor, SecureSettings secureSettings, - AuthController authController) { + AuthController authController, + int devicePosture) { mContext = context; mSensorManager = sensorManager; mConfig = config; @@ -120,6 +125,7 @@ public class DozeSensors { mListeningProxSensors = !mSelectivelyRegisterProxSensors; mScreenOffUdfpsEnabled = config.screenOffUdfpsEnabled(KeyguardUpdateMonitor.getCurrentUser()); + mDevicePosture = devicePosture; boolean udfpsEnrolled = authController.isUdfpsEnrolled(KeyguardUpdateMonitor.getCurrentUser()); @@ -142,7 +148,7 @@ public class DozeSensors { false /* requires prox */, dozeLog), new TriggerSensor( - findSensorWithType(config.doubleTapSensorType()), + findSensor(config.doubleTapSensorType()), Settings.Secure.DOZE_DOUBLE_TAP_GESTURE, true /* configured */, DozeLog.REASON_SENSOR_DOUBLE_TAP, @@ -150,7 +156,7 @@ public class DozeSensors { true /* touchscreen */, dozeLog), new TriggerSensor( - findSensorWithType(config.tapSensorType()), + findSensor(config.tapSensorType(mDevicePosture)), Settings.Secure.DOZE_TAP_SCREEN_GESTURE, true /* settingDef */, true /* configured */, @@ -158,10 +164,10 @@ public class DozeSensors { false /* reports touch coordinates */, true /* touchscreen */, false /* ignoresSetting */, - dozeParameters.singleTapUsesProx() /* requiresProx */, + dozeParameters.singleTapUsesProx(mDevicePosture) /* requiresProx */, dozeLog), new TriggerSensor( - findSensorWithType(config.longPressSensorType()), + findSensor(config.longPressSensorType()), Settings.Secure.DOZE_PULSE_ON_LONG_PRESS, false /* settingDef */, true /* configured */, @@ -172,7 +178,7 @@ public class DozeSensors { dozeParameters.longPressUsesProx() /* requiresProx */, dozeLog), new TriggerSensor( - findSensorWithType(config.udfpsLongPressSensorType()), + findSensor(config.udfpsLongPressSensorType()), "doze_pulse_on_auth", true /* settingDef */, udfpsEnrolled && (alwaysOn || mScreenOffUdfpsEnabled), @@ -200,7 +206,7 @@ public class DozeSensors { mConfig.getWakeLockScreenDebounce(), dozeLog), new TriggerSensor( - findSensorWithType(config.quickPickupSensorType()), + findSensor(config.quickPickupSensorType()), Settings.Secure.DOZE_QUICK_PICKUP_GESTURE, true /* setting default */, config.quickPickupSensorEnabled(KeyguardUpdateMonitor.getCurrentUser()) @@ -238,21 +244,29 @@ public class DozeSensors { mDebounceFrom = SystemClock.uptimeMillis(); } - private Sensor findSensorWithType(String type) { - return findSensorWithType(mSensorManager, type); + private Sensor findSensor(String type) { + return findSensor(mSensorManager, type, null); } /** - * Utility method to find a {@link Sensor} for the supplied string type. + * Utility method to find a {@link Sensor} for the supplied string type and string name. + * + * Return the first sensor in the list that matches the specified inputs. Ignores type or name + * if the input is null or empty. + * + * @param type sensorType + * @parm name sensorName, to differentiate between sensors with the same type */ - public static Sensor findSensorWithType(SensorManager sensorManager, String type) { - if (TextUtils.isEmpty(type)) { - return null; - } - List<Sensor> sensorList = sensorManager.getSensorList(Sensor.TYPE_ALL); - for (Sensor s : sensorList) { - if (type.equals(s.getStringType())) { - return s; + public static Sensor findSensor(SensorManager sensorManager, String type, String name) { + final boolean isNameSpecified = !TextUtils.isEmpty(name); + final boolean isTypeSpecified = !TextUtils.isEmpty(type); + if (isNameSpecified || isTypeSpecified) { + final List<Sensor> sensors = sensorManager.getSensorList(Sensor.TYPE_ALL); + for (Sensor sensor : sensors) { + if ((!isNameSpecified || name.equals(sensor.getName())) + && (!isTypeSpecified || type.equals(sensor.getStringType()))) { + return sensor; + } } } return null; @@ -370,6 +384,8 @@ public class DozeSensors { /** Dump current state */ public void dump(PrintWriter pw) { pw.println("mListening=" + mListening); + pw.println("mDevicePosture=" + + DevicePostureController.devicePostureToString(mDevicePosture)); pw.println("mListeningTouchScreenSensors=" + mListeningTouchScreenSensors); pw.println("mSelectivelyRegisterProxSensors=" + mSelectivelyRegisterProxSensors); pw.println("mListeningProxSensors=" + mListeningProxSensors); diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java index 756adca724e9..b17f078e24ef 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java @@ -41,10 +41,12 @@ import com.android.systemui.dock.DockManager; import com.android.systemui.doze.DozeMachine.State; import com.android.systemui.doze.dagger.DozeScope; import com.android.systemui.statusbar.phone.DozeParameters; +import com.android.systemui.statusbar.policy.DevicePostureController; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.util.Assert; import com.android.systemui.util.concurrency.DelayableExecutor; import com.android.systemui.util.sensors.AsyncSensorManager; +import com.android.systemui.util.sensors.ProximityCheck; import com.android.systemui.util.sensors.ProximitySensor; import com.android.systemui.util.settings.SecureSettings; import com.android.systemui.util.wakelock.WakeLock; @@ -89,12 +91,15 @@ public class DozeTriggers implements DozeMachine.Part { private final TriggerReceiver mBroadcastReceiver = new TriggerReceiver(); private final DockEventListener mDockEventListener = new DockEventListener(); private final DockManager mDockManager; - private final ProximitySensor.ProximityCheck mProxCheck; + private final ProximityCheck mProxCheck; private final BroadcastDispatcher mBroadcastDispatcher; private final AuthController mAuthController; private final DelayableExecutor mMainExecutor; private final KeyguardStateController mKeyguardStateController; private final UiEventLogger mUiEventLogger; + private final DevicePostureController mDevicePostureController; + + private @DevicePostureController.DevicePostureInt int mDevicePosture; private long mNotificationPulseTime; private boolean mPulsePending; @@ -177,12 +182,14 @@ public class DozeTriggers implements DozeMachine.Part { AmbientDisplayConfiguration config, DozeParameters dozeParameters, AsyncSensorManager sensorManager, WakeLock wakeLock, DockManager dockManager, - ProximitySensor proximitySensor, ProximitySensor.ProximityCheck proxCheck, + ProximitySensor proximitySensor, + ProximityCheck proxCheck, DozeLog dozeLog, BroadcastDispatcher broadcastDispatcher, SecureSettings secureSettings, AuthController authController, @Main DelayableExecutor mainExecutor, UiEventLogger uiEventLogger, - KeyguardStateController keyguardStateController) { + KeyguardStateController keyguardStateController, + DevicePostureController devicePostureController) { mContext = context; mDozeHost = dozeHost; mConfig = config; @@ -190,9 +197,11 @@ public class DozeTriggers implements DozeMachine.Part { mSensorManager = sensorManager; mWakeLock = wakeLock; mAllowPulseTriggers = true; + mDevicePostureController = devicePostureController; + mDevicePosture = devicePostureController.getDevicePosture(); mDozeSensors = new DozeSensors(context, mSensorManager, dozeParameters, config, wakeLock, this::onSensor, this::onProximityFar, dozeLog, proximitySensor, - secureSettings, authController); + secureSettings, authController, mDevicePosture); mUiModeManager = mContext.getSystemService(UiModeManager.class); mDockManager = dockManager; mProxCheck = proxCheck; diff --git a/packages/SystemUI/src/com/android/systemui/doze/dagger/DozeModule.java b/packages/SystemUI/src/com/android/systemui/doze/dagger/DozeModule.java index 9c6e02a7924e..571b666e4573 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/dagger/DozeModule.java +++ b/packages/SystemUI/src/com/android/systemui/doze/dagger/DozeModule.java @@ -38,6 +38,7 @@ import com.android.systemui.doze.DozeTriggers; import com.android.systemui.doze.DozeUi; import com.android.systemui.doze.DozeWallpaperState; import com.android.systemui.statusbar.phone.DozeParameters; +import com.android.systemui.statusbar.policy.DevicePostureController; import com.android.systemui.util.sensors.AsyncSensorManager; import com.android.systemui.util.wakelock.DelayedWakeLock; import com.android.systemui.util.wakelock.WakeLock; @@ -94,8 +95,15 @@ public abstract class DozeModule { @Provides @BrightnessSensor static Optional<Sensor> providesBrightnessSensor( - AsyncSensorManager sensorManager, Context context) { - return Optional.ofNullable(DozeSensors.findSensorWithType(sensorManager, - context.getString(R.string.doze_brightness_sensor_type))); + AsyncSensorManager sensorManager, + Context context, + DozeParameters dozeParameters, + DevicePostureController devicePostureController) { + return Optional.ofNullable( + DozeSensors.findSensor( + sensorManager, + context.getString(R.string.doze_brightness_sensor_type), + dozeParameters.brightnessName(devicePostureController.getDevicePosture()) + )); } } diff --git a/packages/SystemUI/src/com/android/systemui/dump/DumpManager.kt b/packages/SystemUI/src/com/android/systemui/dump/DumpManager.kt index b0f3959119c8..21a1b75224b2 100644 --- a/packages/SystemUI/src/com/android/systemui/dump/DumpManager.kt +++ b/packages/SystemUI/src/com/android/systemui/dump/DumpManager.kt @@ -18,11 +18,11 @@ package com.android.systemui.dump import android.util.ArrayMap import com.android.systemui.Dumpable -import com.android.systemui.dagger.SysUISingleton import com.android.systemui.log.LogBuffer import java.io.FileDescriptor import java.io.PrintWriter import javax.inject.Inject +import javax.inject.Singleton /** * Maintains a registry of things that should be dumped when a bug report is taken @@ -33,7 +33,7 @@ import javax.inject.Inject * * See [DumpHandler] for more information on how and when this information is dumped. */ -@SysUISingleton +@Singleton open class DumpManager @Inject constructor() { private val dumpables: MutableMap<String, RegisteredDumpable<Dumpable>> = ArrayMap() private val buffers: MutableMap<String, RegisteredDumpable<LogBuffer>> = ArrayMap() diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/LifecycleScreenStatusProvider.kt b/packages/SystemUI/src/com/android/systemui/keyguard/LifecycleScreenStatusProvider.kt index f25ec5591e3a..044a57ced3fc 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/LifecycleScreenStatusProvider.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/LifecycleScreenStatusProvider.kt @@ -15,12 +15,12 @@ */ package com.android.systemui.keyguard -import com.android.systemui.dagger.SysUISingleton import com.android.systemui.unfold.updates.screen.ScreenStatusProvider import com.android.systemui.unfold.updates.screen.ScreenStatusProvider.ScreenListener import javax.inject.Inject +import javax.inject.Singleton -@SysUISingleton +@Singleton class LifecycleScreenStatusProvider @Inject constructor(screenLifecycle: ScreenLifecycle) : ScreenStatusProvider, ScreenLifecycle.Observer { diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ScreenLifecycle.java b/packages/SystemUI/src/com/android/systemui/keyguard/ScreenLifecycle.java index 30983aacd7d2..d17c39a81dae 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ScreenLifecycle.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ScreenLifecycle.java @@ -19,18 +19,18 @@ package com.android.systemui.keyguard; import android.os.Trace; import com.android.systemui.Dumpable; -import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dump.DumpManager; import java.io.FileDescriptor; import java.io.PrintWriter; import javax.inject.Inject; +import javax.inject.Singleton; /** * Tracks the screen lifecycle. */ -@SysUISingleton +@Singleton public class ScreenLifecycle extends Lifecycle<ScreenLifecycle.Observer> implements Dumpable { public static final int SCREEN_OFF = 0; diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java index a1a630aca94c..7622d663301d 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java @@ -195,7 +195,8 @@ public class NavigationBarController implements mNavigationModeController.addListener(this); mTaskbarDelegate = taskbarDelegate; mTaskbarDelegate.setOverviewProxyService(commandQueue, overviewProxyService, - navigationBarA11yHelper, navigationModeController, sysUiFlagsContainer); + navigationBarA11yHelper, navigationModeController, sysUiFlagsContainer, + dumpManager); mIsTablet = isTablet(mContext); mUserTracker = userTracker; diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java index 71d2a73c73f6..4d29612951cc 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java @@ -20,6 +20,7 @@ import static android.app.StatusBarManager.NAVIGATION_HINT_BACK_ALT; import static android.app.StatusBarManager.NAVIGATION_HINT_IME_SHOWN; import static android.app.StatusBarManager.WINDOW_STATE_SHOWING; import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE; +import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_CLICKABLE; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE; @@ -34,15 +35,23 @@ import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_S import android.app.StatusBarManager; import android.app.StatusBarManager.WindowVisibleState; +import android.content.ComponentCallbacks; import android.content.Context; +import android.content.res.Configuration; +import android.hardware.display.DisplayManager; import android.inputmethodservice.InputMethodService; import android.os.IBinder; +import android.view.Display; import android.view.InsetsVisibilities; import android.view.View; import android.view.WindowInsetsController.Behavior; +import androidx.annotation.NonNull; + import com.android.internal.view.AppearanceRegion; import com.android.systemui.Dependency; +import com.android.systemui.Dumpable; +import com.android.systemui.dump.DumpManager; import com.android.systemui.model.SysUiState; import com.android.systemui.navigationbar.gestural.EdgeBackGestureHandler; import com.android.systemui.recents.OverviewProxyService; @@ -50,12 +59,16 @@ import com.android.systemui.shared.recents.utilities.Utilities; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.statusbar.CommandQueue; +import java.io.FileDescriptor; +import java.io.PrintWriter; + import javax.inject.Inject; import javax.inject.Singleton; @Singleton public class TaskbarDelegate implements CommandQueue.Callbacks, - OverviewProxyService.OverviewProxyListener, NavigationModeController.ModeChangedListener { + OverviewProxyService.OverviewProxyListener, NavigationModeController.ModeChangedListener, + ComponentCallbacks, Dumpable { private final EdgeBackGestureHandler mEdgeBackGestureHandler; @@ -71,24 +84,30 @@ public class TaskbarDelegate implements CommandQueue.Callbacks, private int mDisabledFlags; private @WindowVisibleState int mTaskBarWindowState = WINDOW_STATE_SHOWING; private @Behavior int mBehavior; + private final Context mContext; + private final DisplayManager mDisplayManager; + private Context mWindowContext; @Inject public TaskbarDelegate(Context context) { mEdgeBackGestureHandler = Dependency.get(EdgeBackGestureHandler.Factory.class) .create(context); + mContext = context; + mDisplayManager = mContext.getSystemService(DisplayManager.class); } public void setOverviewProxyService(CommandQueue commandQueue, OverviewProxyService overviewProxyService, NavigationBarA11yHelper navigationBarA11yHelper, NavigationModeController navigationModeController, - SysUiState sysUiState) { + SysUiState sysUiState, DumpManager dumpManager) { // TODO: adding this in the ctor results in a dagger dependency cycle :( mCommandQueue = commandQueue; mOverviewProxyService = overviewProxyService; mNavigationBarA11yHelper = navigationBarA11yHelper; mNavigationModeController = navigationModeController; mSysUiState = sysUiState; + dumpManager.registerDumpable(this); } public void destroy() { @@ -97,6 +116,10 @@ public class TaskbarDelegate implements CommandQueue.Callbacks, mNavigationModeController.removeListener(this); mNavigationBarA11yHelper.removeA11yEventListener(mNavA11yEventListener); mEdgeBackGestureHandler.onNavBarDetached(); + if (mWindowContext != null) { + mWindowContext.unregisterComponentCallbacks(this); + mWindowContext = null; + } } public void init(int displayId) { @@ -107,6 +130,10 @@ public class TaskbarDelegate implements CommandQueue.Callbacks, mNavigationModeController.addListener(this)); mNavigationBarA11yHelper.registerA11yEventListener(mNavA11yEventListener); mEdgeBackGestureHandler.onNavBarAttached(); + // Initialize component callback + Display display = mDisplayManager.getDisplay(displayId); + mWindowContext = mContext.createWindowContext(display, TYPE_APPLICATION, null); + mWindowContext.registerComponentCallbacks(this); // Set initial state for any listeners updateSysuiFlags(); } @@ -193,4 +220,22 @@ public class TaskbarDelegate implements CommandQueue.Callbacks, private boolean allowSystemGestureIgnoringBarVisibility() { return mBehavior != BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE; } + + @Override + public void onConfigurationChanged(Configuration configuration) { + mEdgeBackGestureHandler.onConfigurationChanged(configuration); + } + + @Override + public void onLowMemory() {} + + @Override + public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) { + pw.println("TaskbarDelegate (displayId=" + mDisplayId + "):"); + pw.println(" mNavigationIconHints=" + mNavigationIconHints); + pw.println(" mDisabledFlags=" + mDisabledFlags); + pw.println(" mTaskBarWindowState=" + mTaskBarWindowState); + pw.println(" mBehavior=" + mBehavior); + mEdgeBackGestureHandler.dump(pw); + } } diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java index bf1a98fa39e6..c6da3420ffe9 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java @@ -101,8 +101,8 @@ public class EdgeBackGestureHandler extends CurrentUserTracker private static final int MAX_NUM_LOGGED_PREDICTIONS = 10; private static final int MAX_NUM_LOGGED_GESTURES = 10; - // Temporary log until b/176302696 is resolved - static final boolean DEBUG_MISSING_GESTURE = false; + // Temporary log until b/201642126 is resolved + static final boolean DEBUG_MISSING_GESTURE = true; static final String DEBUG_MISSING_GESTURE_TAG = "NoBackGesture"; private static final boolean ENABLE_PER_WINDOW_INPUT_ROTATION = diff --git a/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrierGroupController.java b/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrierGroupController.java index 953f9fb10657..fec61d911577 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrierGroupController.java +++ b/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrierGroupController.java @@ -42,8 +42,8 @@ import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.flags.FeatureFlags; import com.android.systemui.plugins.ActivityStarter; -import com.android.systemui.statusbar.policy.NetworkController; -import com.android.systemui.statusbar.policy.NetworkController.MobileDataIndicators; +import com.android.systemui.statusbar.connectivity.NetworkController; +import com.android.systemui.statusbar.connectivity.NetworkController.MobileDataIndicators; import com.android.systemui.util.CarrierConfigTracker; import java.util.function.Consumer; 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 04f089d31664..9de6ceb2de4b 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java @@ -51,13 +51,13 @@ import com.android.systemui.qs.QSDetailItems.Item; import com.android.systemui.qs.QSHost; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; +import com.android.systemui.statusbar.connectivity.NetworkController; +import com.android.systemui.statusbar.connectivity.NetworkController.WifiIndicators; import com.android.systemui.statusbar.phone.SystemUIDialog; import com.android.systemui.statusbar.policy.CastController; import com.android.systemui.statusbar.policy.CastController.CastDevice; import com.android.systemui.statusbar.policy.HotspotController; import com.android.systemui.statusbar.policy.KeyguardStateController; -import com.android.systemui.statusbar.policy.NetworkController; -import com.android.systemui.statusbar.policy.NetworkController.WifiIndicators; import java.util.ArrayList; import java.util.LinkedHashMap; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java index b1af8416e06d..35dadd45eb3e 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java @@ -56,11 +56,11 @@ import com.android.systemui.qs.QSHost; import com.android.systemui.qs.SignalTileView; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; +import com.android.systemui.statusbar.connectivity.NetworkController; +import com.android.systemui.statusbar.connectivity.NetworkController.IconState; +import com.android.systemui.statusbar.connectivity.NetworkController.MobileDataIndicators; +import com.android.systemui.statusbar.connectivity.NetworkController.SignalCallback; import com.android.systemui.statusbar.phone.SystemUIDialog; -import com.android.systemui.statusbar.policy.NetworkController; -import com.android.systemui.statusbar.policy.NetworkController.IconState; -import com.android.systemui.statusbar.policy.NetworkController.MobileDataIndicators; -import com.android.systemui.statusbar.policy.NetworkController.SignalCallback; import javax.inject.Inject; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java index 530804ed09e7..98d0a72685ba 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java @@ -52,13 +52,13 @@ import com.android.systemui.qs.QSHost; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSTileImpl; import com.android.systemui.qs.tiles.dialog.InternetDialogFactory; -import com.android.systemui.statusbar.policy.NetworkController; -import com.android.systemui.statusbar.policy.NetworkController.AccessPointController; -import com.android.systemui.statusbar.policy.NetworkController.IconState; -import com.android.systemui.statusbar.policy.NetworkController.MobileDataIndicators; -import com.android.systemui.statusbar.policy.NetworkController.SignalCallback; -import com.android.systemui.statusbar.policy.NetworkController.WifiIndicators; -import com.android.systemui.statusbar.policy.WifiIcons; +import com.android.systemui.statusbar.connectivity.NetworkController; +import com.android.systemui.statusbar.connectivity.NetworkController.AccessPointController; +import com.android.systemui.statusbar.connectivity.NetworkController.IconState; +import com.android.systemui.statusbar.connectivity.NetworkController.MobileDataIndicators; +import com.android.systemui.statusbar.connectivity.NetworkController.SignalCallback; +import com.android.systemui.statusbar.connectivity.NetworkController.WifiIndicators; +import com.android.systemui.statusbar.connectivity.WifiIcons; import java.io.FileDescriptor; import java.io.PrintWriter; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java index 41a3020191a6..e6e7e21263bb 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java @@ -52,11 +52,11 @@ import com.android.systemui.qs.QSHost; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSIconViewImpl; import com.android.systemui.qs.tileimpl.QSTileImpl; -import com.android.systemui.statusbar.policy.NetworkController; -import com.android.systemui.statusbar.policy.NetworkController.AccessPointController; -import com.android.systemui.statusbar.policy.NetworkController.SignalCallback; -import com.android.systemui.statusbar.policy.NetworkController.WifiIndicators; -import com.android.systemui.statusbar.policy.WifiIcons; +import com.android.systemui.statusbar.connectivity.NetworkController; +import com.android.systemui.statusbar.connectivity.NetworkController.AccessPointController; +import com.android.systemui.statusbar.connectivity.NetworkController.SignalCallback; +import com.android.systemui.statusbar.connectivity.NetworkController.WifiIndicators; +import com.android.systemui.statusbar.connectivity.WifiIcons; import com.android.wifitrackerlib.WifiEntry; import java.util.List; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java index aaba5efc92f6..b9cd08e8ac77 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 @@ -75,9 +75,9 @@ import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.plugins.ActivityStarter; +import com.android.systemui.statusbar.connectivity.NetworkController; +import com.android.systemui.statusbar.connectivity.NetworkController.AccessPointController; import com.android.systemui.statusbar.policy.KeyguardStateController; -import com.android.systemui.statusbar.policy.NetworkController; -import com.android.systemui.statusbar.policy.NetworkController.AccessPointController; import com.android.systemui.toast.SystemUIToast; import com.android.systemui.toast.ToastFactory; import com.android.systemui.util.CarrierConfigTracker; diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java b/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java index 31d51f1d1a60..a42b34cf23d0 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java @@ -326,18 +326,11 @@ public class LongScreenshotActivity extends Activity { | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); mTransitionView.setImageBitmap(mOutputBitmap); + mTransitionView.setVisibility(View.VISIBLE); mTransitionView.setTransitionName( ChooserActivity.FIRST_IMAGE_PREVIEW_TRANSITION_NAME); // TODO: listen for transition completing instead of finishing onStop mTransitionStarted = true; - int[] locationOnScreen = new int[2]; - mTransitionView.getLocationOnScreen(locationOnScreen); - int[] locationInWindow = new int[2]; - mTransitionView.getLocationInWindow(locationInWindow); - int deltaX = locationOnScreen[0] - locationInWindow[0]; - int deltaY = locationOnScreen[1] - locationInWindow[1]; - mTransitionView.setX(mTransitionView.getX() - deltaX); - mTransitionView.setY(mTransitionView.getY() - deltaY); startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(this, mTransitionView, ChooserActivity.FIRST_IMAGE_PREVIEW_TRANSITION_NAME).toBundle()); diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java index 8def475c192c..5b4db1449b34 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java @@ -940,12 +940,10 @@ public class ScreenshotController { */ private Supplier<ActionTransition> getActionTransitionSupplier() { return () -> { - View preview = mScreenshotView.getTransitionView(); - preview.setX(preview.getX() - mScreenshotView.getStaticLeftMargin()); Pair<ActivityOptions, ExitTransitionCoordinator> transition = ActivityOptions.startSharedElementAnimation( mWindow, new ScreenshotExitTransitionCallbacksSupplier(true).get(), - null, Pair.create(mScreenshotView.getTransitionView(), + null, Pair.create(mScreenshotView.getScreenshotPreview(), ChooserActivity.FIRST_IMAGE_PREVIEW_TRANSITION_NAME)); transition.second.startExit(); diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java index dfb39e300450..7222b0313fb4 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java @@ -137,13 +137,11 @@ public class ScreenshotView extends FrameLayout implements private int mNavMode; private boolean mOrientationPortrait; private boolean mDirectionLTR; - private int mStaticLeftMargin; private ScreenshotSelectorView mScreenshotSelectorView; private ImageView mScrollingScrim; private View mScreenshotStatic; private ImageView mScreenshotPreview; - private View mTransitionView; private View mScreenshotPreviewBorder; private ImageView mScrollablePreview; private ImageView mScreenshotFlash; @@ -341,7 +339,6 @@ public class ScreenshotView extends FrameLayout implements mScrollingScrim = requireNonNull(findViewById(R.id.screenshot_scrolling_scrim)); mScreenshotStatic = requireNonNull(findViewById(R.id.global_screenshot_static)); mScreenshotPreview = requireNonNull(findViewById(R.id.global_screenshot_preview)); - mTransitionView = requireNonNull(findViewById(R.id.screenshot_transition_view)); mScreenshotPreviewBorder = requireNonNull( findViewById(R.id.global_screenshot_preview_border)); mScreenshotPreview.setClipToOutline(true); @@ -387,12 +384,8 @@ public class ScreenshotView extends FrameLayout implements requestFocus(); } - View getTransitionView() { - return mTransitionView; - } - - int getStaticLeftMargin() { - return mStaticLeftMargin; + View getScreenshotPreview() { + return mScreenshotPreview; } /** @@ -442,7 +435,6 @@ public class ScreenshotView extends FrameLayout implements Math.max(navBarInsets.bottom, waterfall.bottom)); } } - mStaticLeftMargin = p.leftMargin; mScreenshotStatic.setLayoutParams(p); mScreenshotStatic.requestLayout(); } diff --git a/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseDialog.kt b/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseDialog.kt new file mode 100644 index 000000000000..c50365f1bf38 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseDialog.kt @@ -0,0 +1,74 @@ +package com.android.systemui.sensorprivacy + +import android.content.Context +import android.content.DialogInterface +import android.content.res.Resources +import android.text.Html +import android.view.LayoutInflater +import android.view.View +import android.view.WindowManager +import android.widget.ImageView +import com.android.internal.widget.DialogTitle +import com.android.systemui.R +import com.android.systemui.statusbar.phone.SystemUIDialog + +class SensorUseDialog( + context: Context, + val sensor: Int, + val clickListener: DialogInterface.OnClickListener +) : SystemUIDialog(context) { + + // TODO move to onCreate (b/200815309) + init { + window!!.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED) + window!!.addSystemFlags( + WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS) + + val layoutInflater = LayoutInflater.from(context) + val customTitleView = layoutInflater.inflate(R.layout.sensor_use_started_title, null) + customTitleView.requireViewById<DialogTitle>(R.id.sensor_use_started_title_message) + .setText(when (sensor) { + SensorUseStartedActivity.MICROPHONE -> + R.string.sensor_privacy_start_use_mic_dialog_title + SensorUseStartedActivity.CAMERA -> + R.string.sensor_privacy_start_use_camera_dialog_title + SensorUseStartedActivity.ALL_SENSORS -> + R.string.sensor_privacy_start_use_mic_camera_dialog_title + else -> Resources.ID_NULL + }) + customTitleView.requireViewById<ImageView>(R.id.sensor_use_microphone_icon).visibility = + if (sensor == SensorUseStartedActivity.MICROPHONE || + sensor == SensorUseStartedActivity.ALL_SENSORS) { + View.VISIBLE + } else { + View.GONE + } + customTitleView.requireViewById<ImageView>(R.id.sensor_use_camera_icon).visibility = + if (sensor == SensorUseStartedActivity.CAMERA || + sensor == SensorUseStartedActivity.ALL_SENSORS) { + View.VISIBLE + } else { + View.GONE + } + + setCustomTitle(customTitleView) + setMessage(Html.fromHtml(context.getString(when (sensor) { + SensorUseStartedActivity.MICROPHONE -> + R.string.sensor_privacy_start_use_mic_dialog_content + SensorUseStartedActivity.CAMERA -> + R.string.sensor_privacy_start_use_camera_dialog_content + SensorUseStartedActivity.ALL_SENSORS -> + R.string.sensor_privacy_start_use_mic_camera_dialog_content + else -> Resources.ID_NULL + }), 0)) + + setButton(BUTTON_POSITIVE, + context.getString(com.android.internal.R.string + .sensor_privacy_start_use_dialog_turn_on_button), clickListener) + setButton(BUTTON_NEGATIVE, + context.getString(com.android.internal.R.string + .cancel), clickListener) + + setCancelable(false) + } +} diff --git a/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseStartedActivity.kt b/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseStartedActivity.kt index f0fb5ebf9e1d..b0071d92481d 100644 --- a/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseStartedActivity.kt +++ b/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseStartedActivity.kt @@ -16,33 +16,28 @@ package com.android.systemui.sensorprivacy +import android.app.Activity +import android.app.AlertDialog import android.content.DialogInterface +import android.content.DialogInterface.BUTTON_NEGATIVE +import android.content.DialogInterface.BUTTON_POSITIVE import android.content.Intent import android.content.Intent.EXTRA_PACKAGE_NAME -import android.content.pm.PackageManager -import android.content.res.Resources import android.hardware.SensorPrivacyManager import android.hardware.SensorPrivacyManager.EXTRA_ALL_SENSORS import android.hardware.SensorPrivacyManager.EXTRA_SENSOR import android.hardware.SensorPrivacyManager.Sources.DIALOG import android.os.Bundle import android.os.Handler -import android.text.Html -import android.view.View.GONE -import android.view.View.VISIBLE -import android.widget.ImageView -import com.android.internal.app.AlertActivity -import com.android.internal.widget.DialogTitle -import com.android.systemui.R +import com.android.internal.util.FrameworkStatsLog.PRIVACY_TOGGLE_DIALOG_INTERACTION +import com.android.internal.util.FrameworkStatsLog.PRIVACY_TOGGLE_DIALOG_INTERACTION__ACTION__CANCEL +import com.android.internal.util.FrameworkStatsLog.PRIVACY_TOGGLE_DIALOG_INTERACTION__ACTION__ENABLE +import com.android.internal.util.FrameworkStatsLog.write import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.statusbar.phone.KeyguardDismissUtil import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController import com.android.systemui.statusbar.policy.KeyguardStateController import javax.inject.Inject -import com.android.internal.util.FrameworkStatsLog.PRIVACY_TOGGLE_DIALOG_INTERACTION -import com.android.internal.util.FrameworkStatsLog.PRIVACY_TOGGLE_DIALOG_INTERACTION__ACTION__ENABLE -import com.android.internal.util.FrameworkStatsLog.PRIVACY_TOGGLE_DIALOG_INTERACTION__ACTION__CANCEL -import com.android.internal.util.FrameworkStatsLog.write /** * Dialog to be shown on top of apps that are attempting to use a sensor (e.g. microphone) which is @@ -55,7 +50,7 @@ class SensorUseStartedActivity @Inject constructor( private val keyguardStateController: KeyguardStateController, private val keyguardDismissUtil: KeyguardDismissUtil, @Background private val bgHandler: Handler -) : AlertActivity(), DialogInterface.OnClickListener { +) : Activity(), DialogInterface.OnClickListener { companion object { private val LOG_TAG = SensorUseStartedActivity::class.java.simpleName @@ -63,9 +58,9 @@ class SensorUseStartedActivity @Inject constructor( private const val SUPPRESS_REMINDERS_REMOVAL_DELAY_MILLIS = 2000L private const val UNLOCK_DELAY_MILLIS = 200L - private const val CAMERA = SensorPrivacyManager.Sensors.CAMERA - private const val MICROPHONE = SensorPrivacyManager.Sensors.MICROPHONE - private const val ALL_SENSORS = Integer.MAX_VALUE + internal const val CAMERA = SensorPrivacyManager.Sensors.CAMERA + internal const val MICROPHONE = SensorPrivacyManager.Sensors.MICROPHONE + internal const val ALL_SENSORS = Integer.MAX_VALUE } private var sensor = -1 @@ -74,6 +69,8 @@ class SensorUseStartedActivity @Inject constructor( private lateinit var sensorPrivacyListener: IndividualSensorPrivacyController.Callback + private var mDialog: AlertDialog? = null + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -91,7 +88,7 @@ class SensorUseStartedActivity @Inject constructor( IndividualSensorPrivacyController.Callback { _, _ -> if (!sensorPrivacyController.isSensorBlocked(MICROPHONE) && !sensorPrivacyController.isSensorBlocked(CAMERA)) { - dismiss() + finish() } } @@ -109,71 +106,22 @@ class SensorUseStartedActivity @Inject constructor( } } sensorPrivacyListener = - IndividualSensorPrivacyController.Callback { - whichSensor: Int, isBlocked: Boolean -> + IndividualSensorPrivacyController.Callback { whichSensor: Int, + isBlocked: Boolean -> if (whichSensor == sensor && !isBlocked) { - dismiss() + finish() } } sensorPrivacyController.addCallback(sensorPrivacyListener) - sensorPrivacyController.addCallback { _, isBlocked -> - if (!isBlocked) { - dismiss() - } - } - } - - mAlertParams.apply { - try { - mCustomTitleView = mInflater.inflate(R.layout.sensor_use_started_title, null) - mCustomTitleView.findViewById<DialogTitle>(R.id.sensor_use_started_title_message)!! - .setText(when (sensor) { - MICROPHONE -> - R.string.sensor_privacy_start_use_mic_dialog_title - CAMERA -> - R.string.sensor_privacy_start_use_camera_dialog_title - ALL_SENSORS -> - R.string.sensor_privacy_start_use_mic_camera_dialog_title - else -> Resources.ID_NULL - }) - - mCustomTitleView.findViewById<ImageView>(R.id.sensor_use_microphone_icon)!! - .visibility = if (sensor == MICROPHONE || sensor == ALL_SENSORS) { - VISIBLE - } else { - GONE - } - mCustomTitleView.findViewById<ImageView>(R.id.sensor_use_camera_icon)!! - .visibility = if (sensor == CAMERA || sensor == ALL_SENSORS) { - VISIBLE - } else { - GONE - } - - mMessage = Html.fromHtml(getString(when (sensor) { - MICROPHONE -> - R.string.sensor_privacy_start_use_mic_dialog_content - CAMERA -> - R.string.sensor_privacy_start_use_camera_dialog_content - ALL_SENSORS -> - R.string.sensor_privacy_start_use_mic_camera_dialog_content - else -> Resources.ID_NULL - }, packageManager.getApplicationInfo(sensorUsePackageName, 0) - .loadLabel(packageManager)), 0) - } catch (e: PackageManager.NameNotFoundException) { + if (!sensorPrivacyController.isSensorBlocked(sensor)) { finish() return } - - mPositiveButtonText = getString( - com.android.internal.R.string.sensor_privacy_start_use_dialog_turn_on_button) - mNegativeButtonText = getString(android.R.string.cancel) - mPositiveButtonListener = this@SensorUseStartedActivity - mNegativeButtonListener = this@SensorUseStartedActivity } - setupAlert() + mDialog = SensorUseDialog(this, sensor, this) + mDialog!!.show() } override fun onStart() { @@ -212,7 +160,7 @@ class SensorUseStartedActivity @Inject constructor( } } - dismiss() + finish() } override fun onStop() { @@ -229,6 +177,7 @@ class SensorUseStartedActivity @Inject constructor( override fun onDestroy() { super.onDestroy() + mDialog?.dismiss() sensorPrivacyController.removeCallback(sensorPrivacyListener) } @@ -263,4 +212,4 @@ class SensorUseStartedActivity @Inject constructor( .suppressSensorPrivacyReminders(sensor, suppressed) } } -}
\ No newline at end of file +} diff --git a/packages/SystemUI/src/com/android/systemui/sensorprivacy/television/TvUnblockSensorActivity.java b/packages/SystemUI/src/com/android/systemui/sensorprivacy/television/TvUnblockSensorActivity.java index 8cd3632b65ba..cc5cf4b63f99 100644 --- a/packages/SystemUI/src/com/android/systemui/sensorprivacy/television/TvUnblockSensorActivity.java +++ b/packages/SystemUI/src/com/android/systemui/sensorprivacy/television/TvUnblockSensorActivity.java @@ -24,6 +24,7 @@ import android.hardware.SensorPrivacyManager; import android.os.Bundle; import android.util.Log; import android.view.View; +import android.view.WindowManager; import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; @@ -57,6 +58,8 @@ public class TvUnblockSensorActivity extends TvBottomSheetActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + getWindow().addSystemFlags( + WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); boolean allSensors = getIntent().getBooleanExtra(SensorPrivacyManager.EXTRA_ALL_SENSORS, false); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/OperatorNameViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/OperatorNameViewController.java index e49f48f2cf49..bcba5cc09c5d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/OperatorNameViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/OperatorNameViewController.java @@ -26,7 +26,7 @@ import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.KeyguardUpdateMonitorCallback; import com.android.systemui.demomode.DemoModeCommandReceiver; import com.android.systemui.plugins.DarkIconDispatcher; -import com.android.systemui.statusbar.policy.NetworkController; +import com.android.systemui.statusbar.connectivity.NetworkController; import com.android.systemui.tuner.TunerService; import com.android.systemui.util.ViewController; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessPointControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/AccessPointControllerImpl.java index 6d6320e6962d..a23d73d7ed84 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessPointControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/AccessPointControllerImpl.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.systemui.statusbar.policy; +package com.android.systemui.statusbar.connectivity; import android.content.Context; import android.content.Intent; @@ -55,6 +55,7 @@ import java.util.concurrent.Executor; import javax.inject.Inject; +/** */ public class AccessPointControllerImpl implements NetworkController.AccessPointController, WifiPickerTracker.WifiPickerTrackerCallback, LifecycleOwner { @@ -116,17 +117,19 @@ public class AccessPointControllerImpl super.finalize(); } + /** */ public boolean canConfigWifi() { return !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_WIFI, new UserHandle(mCurrentUser)); } + /** */ public boolean canConfigMobileData() { return !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS, UserHandle.of(mCurrentUser)) && mUserTracker.getUserInfo().isAdmin(); } - public void onUserSwitched(int newUserId) { + void onUserSwitched(int newUserId) { mCurrentUser = newUserId; } @@ -225,7 +228,7 @@ public class AccessPointControllerImpl } } - public void dump(PrintWriter pw) { + void dump(PrintWriter pw) { IndentingPrintWriter ipw = new IndentingPrintWriter(pw); ipw.println("AccessPointControllerImpl:"); ipw.increaseIndent(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/CallbackHandler.java index 7ac6d63430d6..052a789200e6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/CallbackHandler.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.android.systemui.statusbar.policy; +package com.android.systemui.statusbar.connectivity; import android.os.Handler; import android.os.Looper; @@ -22,11 +22,11 @@ import android.telephony.SubscriptionInfo; import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.dagger.qualifiers.Main; -import com.android.systemui.statusbar.policy.NetworkController.EmergencyListener; -import com.android.systemui.statusbar.policy.NetworkController.IconState; -import com.android.systemui.statusbar.policy.NetworkController.MobileDataIndicators; -import com.android.systemui.statusbar.policy.NetworkController.SignalCallback; -import com.android.systemui.statusbar.policy.NetworkController.WifiIndicators; +import com.android.systemui.statusbar.connectivity.NetworkController.EmergencyListener; +import com.android.systemui.statusbar.connectivity.NetworkController.IconState; +import com.android.systemui.statusbar.connectivity.NetworkController.MobileDataIndicators; +import com.android.systemui.statusbar.connectivity.NetworkController.SignalCallback; +import com.android.systemui.statusbar.connectivity.NetworkController.WifiIndicators; import java.io.PrintWriter; import java.text.SimpleDateFormat; @@ -235,7 +235,7 @@ public class CallbackHandler extends Handler implements EmergencyListener, Signa .append("icon=").append(icon) .toString(); recordLastCallback(log); - obtainMessage(MSG_ETHERNET_CHANGED, icon).sendToTarget();; + obtainMessage(MSG_ETHERNET_CHANGED, icon).sendToTarget(); } @Override @@ -252,14 +252,14 @@ public class CallbackHandler extends Handler implements EmergencyListener, Signa .toString(); recordLastCallback(log); } - obtainMessage(MSG_AIRPLANE_MODE_CHANGED, icon).sendToTarget();; + obtainMessage(MSG_AIRPLANE_MODE_CHANGED, icon).sendToTarget(); } - public void setListening(EmergencyListener listener, boolean listening) { + void setListening(EmergencyListener listener, boolean listening) { obtainMessage(MSG_ADD_REMOVE_EMERGENCY, listening ? 1 : 0, 0, listener).sendToTarget(); } - public void setListening(SignalCallback listener, boolean listening) { + void setListening(SignalCallback listener, boolean listening) { obtainMessage(MSG_ADD_REMOVE_SIGNAL, listening ? 1 : 0, 0, listener).sendToTarget(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/EthernetIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/EthernetIcons.java index b391bd9cf651..196aad99dcb5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/EthernetIcons.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/EthernetIcons.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.systemui.statusbar.policy; +package com.android.systemui.statusbar.connectivity; import com.android.systemui.R; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/EthernetSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/EthernetSignalController.java index 80b75a740965..c9d40adde644 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/EthernetSignalController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/EthernetSignalController.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.android.systemui.statusbar.policy; +package com.android.systemui.statusbar.connectivity; import android.content.Context; import android.net.NetworkCapabilities; @@ -21,12 +21,12 @@ import android.net.NetworkCapabilities; import com.android.settingslib.AccessibilityContentDescriptions; import com.android.settingslib.SignalIcon.IconGroup; import com.android.settingslib.SignalIcon.State; -import com.android.systemui.statusbar.policy.NetworkController.IconState; -import com.android.systemui.statusbar.policy.NetworkController.SignalCallback; +import com.android.systemui.statusbar.connectivity.NetworkController.IconState; +import com.android.systemui.statusbar.connectivity.NetworkController.SignalCallback; import java.util.BitSet; - +/** */ public class EthernetSignalController extends SignalController<State, IconGroup> { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalController.java index a543c7c95d16..20ef4eec0b97 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalController.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.android.systemui.statusbar.policy; +package com.android.systemui.statusbar.connectivity; import static com.android.settingslib.mobile.MobileMappings.getDefaultIcons; import static com.android.settingslib.mobile.MobileMappings.getIconKey; @@ -58,9 +58,9 @@ import com.android.settingslib.mobile.TelephonyIcons; import com.android.settingslib.net.SignalStrengthUtil; import com.android.systemui.R; import com.android.systemui.flags.FeatureFlags; -import com.android.systemui.statusbar.policy.NetworkController.IconState; -import com.android.systemui.statusbar.policy.NetworkController.MobileDataIndicators; -import com.android.systemui.statusbar.policy.NetworkController.SignalCallback; +import com.android.systemui.statusbar.connectivity.NetworkController.IconState; +import com.android.systemui.statusbar.connectivity.NetworkController.MobileDataIndicators; +import com.android.systemui.statusbar.connectivity.NetworkController.SignalCallback; import com.android.systemui.util.CarrierConfigTracker; import java.io.PrintWriter; @@ -245,7 +245,7 @@ public class MobileSignalController extends SignalController<MobileState, Mobile mProviderModelSetting = featureFlags.isProviderModelSettingEnabled(); } - public void setConfiguration(Config config) { + void setConfiguration(Config config) { mConfig = config; updateInflateSignalStrength(); mNetworkToIconLookup = mapIconSets(mConfig); @@ -253,12 +253,12 @@ public class MobileSignalController extends SignalController<MobileState, Mobile updateTelephony(); } - public void setAirplaneMode(boolean airplaneMode) { + void setAirplaneMode(boolean airplaneMode) { mCurrentState.airplaneMode = airplaneMode; notifyListenersIfNecessary(); } - public void setUserSetupComplete(boolean userSetup) { + void setUserSetupComplete(boolean userSetup) { mCurrentState.userSetup = userSetup; notifyListenersIfNecessary(); } @@ -272,7 +272,7 @@ public class MobileSignalController extends SignalController<MobileState, Mobile notifyListenersIfNecessary(); } - public void setCarrierNetworkChangeMode(boolean carrierNetworkChangeMode) { + void setCarrierNetworkChangeMode(boolean carrierNetworkChangeMode) { mCurrentState.carrierNetworkChangeMode = carrierNetworkChangeMode; updateTelephony(); } @@ -413,7 +413,7 @@ public class MobileSignalController extends SignalController<MobileState, Mobile if (mCurrentState.dataSim) { // If using provider model behavior, only show QS icons if the state is also default if (pm && !mCurrentState.isDefault) { - return new QsInfo(qsTypeIcon, qsIcon, qsDescription); + return new QsInfo(qsTypeIcon, qsIcon, qsDescription); } if (mCurrentState.showQuickSettingsRatIcon() || mConfig.alwaysShowDataRatIcon) { @@ -501,7 +501,7 @@ public class MobileSignalController extends SignalController<MobileState, Mobile return mCurrentState.carrierNetworkChangeMode; } - public void handleBroadcast(Intent intent) { + void handleBroadcast(Intent intent) { String action = intent.getAction(); if (action.equals(TelephonyManager.ACTION_SERVICE_PROVIDERS_UPDATED)) { updateNetworkName(intent.getBooleanExtra(TelephonyManager.EXTRA_SHOW_SPN, false), @@ -740,10 +740,10 @@ public class MobileSignalController extends SignalController<MobileState, Mobile * mTelephonyDisplayInfo, and mSimState. It should be called any time one of these is updated. * This will call listeners if necessary. */ - private final void updateTelephony() { + private void updateTelephony() { if (Log.isLoggable(mTag, Log.DEBUG)) { - Log.d(mTag, "updateTelephonySignalStrength: hasService=" + - Utils.isInService(mServiceState) + " ss=" + mSignalStrength + Log.d(mTag, "updateTelephonySignalStrength: hasService=" + + Utils.isInService(mServiceState) + " ss=" + mSignalStrength + " displayInfo=" + mTelephonyDisplayInfo); } checkDefaultData(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkController.java index 9aec9038fadb..143309658779 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkController.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.systemui.statusbar.policy; +package com.android.systemui.statusbar.connectivity; import android.content.Context; import android.content.Intent; @@ -22,29 +22,44 @@ import android.telephony.SubscriptionInfo; import com.android.settingslib.net.DataUsageController; import com.android.systemui.demomode.DemoMode; -import com.android.systemui.statusbar.policy.NetworkController.SignalCallback; +import com.android.systemui.statusbar.connectivity.NetworkController.SignalCallback; +import com.android.systemui.statusbar.policy.CallbackController; +import com.android.systemui.statusbar.policy.DataSaverController; import com.android.wifitrackerlib.MergedCarrierEntry; import com.android.wifitrackerlib.WifiEntry; import java.util.List; +/** */ public interface NetworkController extends CallbackController<SignalCallback>, DemoMode { - + /** */ boolean hasMobileDataFeature(); + /** */ void setWifiEnabled(boolean enabled); + /** */ AccessPointController getAccessPointController(); + /** */ DataUsageController getMobileDataController(); + /** */ DataSaverController getDataSaverController(); + /** */ String getMobileDataNetworkName(); + /** */ boolean isMobileDataNetworkInService(); + /** */ int getNumberSubscriptions(); + /** */ boolean hasVoiceCallingFeature(); + /** */ void addEmergencyListener(EmergencyListener listener); + /** */ void removeEmergencyListener(EmergencyListener listener); + /** */ boolean hasEmergencyCryptKeeperText(); + /** */ boolean isRadioOn(); /** @@ -143,7 +158,8 @@ public interface NetworkController extends CallbackController<SignalCallback>, D } } - public interface SignalCallback { + /** */ + interface SignalCallback { /** * Callback for listeners to be able to update the state of any UI tracking connectivity of * WiFi networks. @@ -156,14 +172,19 @@ public interface NetworkController extends CallbackController<SignalCallback>, D */ default void setMobileDataIndicators(MobileDataIndicators mobileDataIndicators) {} + /** */ default void setSubs(List<SubscriptionInfo> subs) {} + /** */ default void setNoSims(boolean show, boolean simDetected) {} + /** */ default void setEthernetIndicators(IconState icon) {} + /** */ default void setIsAirplaneMode(IconState icon) {} + /** */ default void setMobileDataEnabled(boolean enabled) {} /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java index 156def5a6183..d9b0ee7e9921 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.systemui.statusbar.policy; +package com.android.systemui.statusbar.connectivity; import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; @@ -76,7 +76,12 @@ import com.android.systemui.flags.FeatureFlags; import com.android.systemui.qs.tiles.dialog.InternetDialogFactory; import com.android.systemui.qs.tiles.dialog.InternetDialogUtil; import com.android.systemui.settings.CurrentUserTracker; +import com.android.systemui.statusbar.policy.ConfigurationController; +import com.android.systemui.statusbar.policy.DataSaverController; +import com.android.systemui.statusbar.policy.DataSaverControllerImpl; +import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener; +import com.android.systemui.statusbar.policy.EncryptionHelper; import com.android.systemui.telephony.TelephonyListenerManager; import com.android.systemui.util.CarrierConfigTracker; @@ -376,11 +381,10 @@ public class NetworkControllerImpl extends BroadcastReceiver @Override public void onCapabilitiesChanged( - Network network, NetworkCapabilities networkCapabilities) { - boolean lastValidated = (mLastNetworkCapabilities != null) && - mLastNetworkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED); - boolean validated = - networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED); + Network network, NetworkCapabilities networkCapabilities) { + boolean lastValidated = (mLastNetworkCapabilities != null) + && mLastNetworkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED); + boolean validated = networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED); // This callback is invoked a lot (i.e. when RSSI changes), so avoid updating // icons when connectivity state has remained the same. @@ -544,19 +548,23 @@ public class NetworkControllerImpl extends BroadcastReceiver return mDataUsageController; } + /** */ public void addEmergencyListener(EmergencyListener listener) { mCallbackHandler.setListening(listener, true); mCallbackHandler.setEmergencyCallsOnly(isEmergencyOnly()); } + /** */ public void removeEmergencyListener(EmergencyListener listener) { mCallbackHandler.setListening(listener, false); } + /** */ public boolean hasMobileDataFeature() { return mHasMobileDataFeature; } + /** */ public boolean hasVoiceCallingFeature() { return mPhone.getPhoneType() != TelephonyManager.PHONE_TYPE_NONE; } @@ -661,7 +669,7 @@ public class NetworkControllerImpl extends BroadcastReceiver } } - public boolean isEmergencyOnly() { + boolean isEmergencyOnly() { if (mMobileSignalControllers.size() == 0) { // When there are no active subscriptions, determine emengency state from last // broadcast. @@ -690,8 +698,10 @@ public class NetworkControllerImpl extends BroadcastReceiver if (mMobileSignalControllers.size() == 1) { mEmergencySource = EMERGENCY_ASSUMED_VOICE_CONTROLLER + mMobileSignalControllers.keyAt(0); - if (DEBUG) Log.d(TAG, "Getting assumed emergency from " - + mMobileSignalControllers.keyAt(0)); + if (DEBUG) { + Log.d(TAG, "Getting assumed emergency from " + + mMobileSignalControllers.keyAt(0)); + } return mMobileSignalControllers.valueAt(0).getState().isEmergency; } if (DEBUG) Log.e(TAG, "Cannot find controller for voice sub: " + voiceSubId); @@ -915,7 +925,7 @@ public class NetworkControllerImpl extends BroadcastReceiver @GuardedBy("mLock") @VisibleForTesting - public void setCurrentSubscriptionsLocked(List<SubscriptionInfo> subscriptions) { + void setCurrentSubscriptionsLocked(List<SubscriptionInfo> subscriptions) { Collections.sort(subscriptions, new Comparator<SubscriptionInfo>() { @Override public int compare(SubscriptionInfo lhs, SubscriptionInfo rhs) { @@ -1125,6 +1135,7 @@ public class NetworkControllerImpl extends BroadcastReceiver mEthernetSignalController.updateConnectivity(mConnectedTransports, mValidatedTransports); } + /** */ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println("NetworkController state:"); @@ -1178,7 +1189,7 @@ public class NetworkControllerImpl extends BroadcastReceiver mCallbackHandler.dump(pw); } - private static final String emergencyToString(int emergencySource) { + private static String emergencyToString(int emergencySource) { if (emergencySource > EMERGENCY_NO_SUB) { return "ASSUMED_VOICE_CONTROLLER(" + (emergencySource - EMERGENCY_VOICE_CONTROLLER) + ")"; @@ -1423,10 +1434,12 @@ public class NetworkControllerImpl extends BroadcastReceiver return info; } + /** */ public boolean hasEmergencyCryptKeeperText() { return EncryptionHelper.IS_DATA_ENCRYPTED; } + /** */ public boolean isRadioOn() { return !mAirplaneMode; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/SignalController.java index 4b6722c17b85..d23dba579be6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/SignalController.java @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.android.systemui.statusbar.policy; +package com.android.systemui.statusbar.connectivity; -import static com.android.systemui.statusbar.policy.NetworkControllerImpl.TAG; +import static com.android.systemui.statusbar.connectivity.NetworkControllerImpl.TAG; import android.annotation.NonNull; import android.content.Context; @@ -23,8 +23,8 @@ import android.util.Log; import com.android.settingslib.SignalIcon.IconGroup; import com.android.settingslib.SignalIcon.State; -import com.android.systemui.statusbar.policy.NetworkController.IconState; -import com.android.systemui.statusbar.policy.NetworkController.SignalCallback; +import com.android.systemui.statusbar.connectivity.NetworkController.IconState; +import com.android.systemui.statusbar.connectivity.NetworkController.SignalCallback; import java.io.PrintWriter; import java.util.BitSet; @@ -83,7 +83,7 @@ public abstract class SignalController<T extends State, I extends IconGroup> { return mCurrentState; } - public void updateConnectivity(BitSet connectedTransports, BitSet validatedTransports) { + void updateConnectivity(BitSet connectedTransports, BitSet validatedTransports) { mCurrentState.inetCondition = validatedTransports.get(mTransportType) ? 1 : 0; notifyListenersIfNecessary(); } @@ -114,7 +114,7 @@ public abstract class SignalController<T extends State, I extends IconGroup> { return false; } - public void saveLastState() { + void saveLastState() { if (RECORD_HISTORY) { recordLastState(); } @@ -161,7 +161,7 @@ public abstract class SignalController<T extends State, I extends IconGroup> { } } - public void notifyListenersIfNecessary() { + void notifyListenersIfNecessary() { if (isDirty()) { saveLastState(); notifyListeners(); @@ -192,7 +192,7 @@ public abstract class SignalController<T extends State, I extends IconGroup> { mHistoryIndex = (mHistoryIndex + 1) % HISTORY_SIZE; } - public void dump(PrintWriter pw) { + void dump(PrintWriter pw) { pw.println(" - " + mTag + " -----"); pw.println(" Current State: " + mCurrentState); if (RECORD_HISTORY) { @@ -210,7 +210,7 @@ public abstract class SignalController<T extends State, I extends IconGroup> { } } - public final void notifyListeners() { + final void notifyListeners() { notifyListeners(mCallbackHandler); } @@ -219,7 +219,7 @@ public abstract class SignalController<T extends State, I extends IconGroup> { * based on current state, and only need to be called in the scenario where * mCurrentState != mLastState. */ - public abstract void notifyListeners(SignalCallback callback); + abstract void notifyListeners(SignalCallback callback); /** * Generate a blank T. diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/WifiIcons.java index 577cc4fd16b6..3c449ad270ef 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiIcons.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/WifiIcons.java @@ -14,12 +14,13 @@ * limitations under the License. */ -package com.android.systemui.statusbar.policy; +package com.android.systemui.statusbar.connectivity; import com.android.settingslib.AccessibilityContentDescriptions; import com.android.settingslib.R; import com.android.settingslib.SignalIcon.IconGroup; +/** */ public class WifiIcons { static final int[] WIFI_FULL_ICONS = { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/WifiSignalController.java index 3f7ddc6c1538..3622a66767a3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/WifiSignalController.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.android.systemui.statusbar.policy; +package com.android.systemui.statusbar.connectivity; import static android.net.wifi.WifiManager.TrafficStateCallback.DATA_ACTIVITY_IN; import static android.net.wifi.WifiManager.TrafficStateCallback.DATA_ACTIVITY_INOUT; @@ -37,14 +37,15 @@ import com.android.settingslib.mobile.TelephonyIcons; import com.android.settingslib.wifi.WifiStatusTracker; import com.android.systemui.R; import com.android.systemui.flags.FeatureFlags; -import com.android.systemui.statusbar.policy.NetworkController.IconState; -import com.android.systemui.statusbar.policy.NetworkController.MobileDataIndicators; -import com.android.systemui.statusbar.policy.NetworkController.SignalCallback; -import com.android.systemui.statusbar.policy.NetworkController.WifiIndicators; +import com.android.systemui.statusbar.connectivity.NetworkController.IconState; +import com.android.systemui.statusbar.connectivity.NetworkController.MobileDataIndicators; +import com.android.systemui.statusbar.connectivity.NetworkController.SignalCallback; +import com.android.systemui.statusbar.connectivity.NetworkController.WifiIndicators; import java.io.PrintWriter; import java.util.Objects; +/** */ public class WifiSignalController extends SignalController<WifiSignalController.WifiState, IconGroup> { private final boolean mHasMobileDataFeature; 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 ea00d920c9b0..6730afaafdef 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java @@ -252,11 +252,12 @@ public interface StatusBarDependenciesModule { ActivityStarter activityStarter, @Main Executor mainExecutor, IActivityManager iActivityManager, - OngoingCallLogger logger) { + OngoingCallLogger logger, + DumpManager dumpManager) { OngoingCallController ongoingCallController = new OngoingCallController( notifCollection, featureFlags, systemClock, activityStarter, mainExecutor, - iActivityManager, logger); + iActivityManager, logger, dumpManager); ongoingCallController.init(); return ongoingCallController; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt index a76389b1bbc8..bdade2c6c2c9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt @@ -86,6 +86,7 @@ class LockscreenSmartspaceController @Inject constructor( var stateChangeListener = object : View.OnAttachStateChangeListener { override fun onViewAttachedToWindow(v: View) { smartspaceViews.add(v as SmartspaceView) + connectSession() updateTextColorFromWallpaper() statusBarStateListener.onDozeAmountChanged(0f, statusBarStateController.dozeAmount) @@ -93,6 +94,10 @@ class LockscreenSmartspaceController @Inject constructor( override fun onViewDetachedFromWindow(v: View) { smartspaceViews.remove(v as SmartspaceView) + + if (smartspaceViews.isEmpty()) { + disconnect() + } } } 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 4400909d0bff..278f09b45b4c 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 @@ -254,6 +254,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable private boolean mExpandedInThisMotion; private boolean mShouldShowShelfOnly; protected boolean mScrollingEnabled; + private boolean mIsCurrentUserSetup; protected FooterView mFooterView; protected EmptyShadeView mEmptyShadeView; private boolean mDismissAllInProgress; @@ -693,6 +694,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable boolean showDismissView = mClearAllEnabled && mController.hasActiveClearableNotifications(ROWS_ALL); boolean showFooterView = (showDismissView || getVisibleNotificationCount() > 0) + && mIsCurrentUserSetup // see: b/193149550 && mStatusBarState != StatusBarState.KEYGUARD && !mUnlockedScreenOffAnimationController.isScreenOffAnimationPlaying() && !mIsRemoteInputActive; @@ -5621,6 +5623,16 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable } /** + * Sets whether the current user is set up, which is required to show the footer (b/193149550) + */ + public void setCurrentUserSetup(boolean isCurrentUserSetup) { + if (mIsCurrentUserSetup != isCurrentUserSetup) { + mIsCurrentUserSetup = isCurrentUserSetup; + updateFooter(); + } + } + + /** * A listener that is notified when the empty space below the notifications is clicked on */ @ShadeViewRefactor(RefactorComponent.SHADE_VIEW) 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 75eb88fbcfc8..9fe06a0ddbdc 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 @@ -119,6 +119,8 @@ import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.phone.dagger.StatusBarComponent; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener; +import com.android.systemui.statusbar.policy.DeviceProvisionedController; +import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener; import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener; import com.android.systemui.statusbar.policy.ZenModeController; import com.android.systemui.tuner.TunerService; @@ -146,6 +148,7 @@ public class NotificationStackScrollLayoutController { private final HeadsUpManagerPhone mHeadsUpManager; private final NotificationRoundnessManager mNotificationRoundnessManager; private final TunerService mTunerService; + private final DeviceProvisionedController mDeviceProvisionedController; private final DynamicPrivacyController mDynamicPrivacyController; private final ConfigurationController mConfigurationController; private final ZenModeController mZenModeController; @@ -226,6 +229,28 @@ public class NotificationStackScrollLayoutController { } }; + private final DeviceProvisionedListener mDeviceProvisionedListener = + new DeviceProvisionedListener() { + @Override + public void onDeviceProvisionedChanged() { + updateCurrentUserIsSetup(); + } + + @Override + public void onUserSwitched() { + updateCurrentUserIsSetup(); + } + + @Override + public void onUserSetupChanged() { + updateCurrentUserIsSetup(); + } + + private void updateCurrentUserIsSetup() { + mView.setCurrentUserSetup(mDeviceProvisionedController.isCurrentUserSetup()); + } + }; + private final DynamicPrivacyController.Listener mDynamicPrivacyControllerListener = () -> { if (mView.isExpanded()) { // The bottom might change because we're using the final actual height of the view @@ -600,6 +625,7 @@ public class NotificationStackScrollLayoutController { HeadsUpManagerPhone headsUpManager, NotificationRoundnessManager notificationRoundnessManager, TunerService tunerService, + DeviceProvisionedController deviceProvisionedController, DynamicPrivacyController dynamicPrivacyController, ConfigurationController configurationController, SysuiStatusBarStateController statusBarStateController, @@ -636,6 +662,7 @@ public class NotificationStackScrollLayoutController { mHeadsUpManager = headsUpManager; mNotificationRoundnessManager = notificationRoundnessManager; mTunerService = tunerService; + mDeviceProvisionedController = deviceProvisionedController; mDynamicPrivacyController = dynamicPrivacyController; mConfigurationController = configurationController; mStatusBarStateController = statusBarStateController; @@ -787,6 +814,9 @@ public class NotificationStackScrollLayoutController { return Unit.INSTANCE; }); + // callback is invoked synchronously, updating mView immediately + mDeviceProvisionedController.addCallback(mDeviceProvisionedListener); + if (mView.isAttachedToWindow()) { mOnAttachStateChangeListener.onViewAttachedToWindow(mView); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java index c16cc125aece..989f6b85668b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java @@ -46,6 +46,8 @@ import com.android.systemui.statusbar.DisableFlagsLogger.DisableState; import com.android.systemui.statusbar.OperatorNameView; import com.android.systemui.statusbar.OperatorNameViewController; import com.android.systemui.statusbar.StatusBarState; +import com.android.systemui.statusbar.connectivity.NetworkController; +import com.android.systemui.statusbar.connectivity.NetworkController.SignalCallback; import com.android.systemui.statusbar.events.SystemStatusAnimationCallback; import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler; import com.android.systemui.statusbar.phone.StatusBarIconController.DarkIconManager; @@ -53,8 +55,6 @@ import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController; import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallListener; import com.android.systemui.statusbar.policy.EncryptionHelper; import com.android.systemui.statusbar.policy.KeyguardStateController; -import com.android.systemui.statusbar.policy.NetworkController; -import com.android.systemui.statusbar.policy.NetworkController.SignalCallback; import org.jetbrains.annotations.NotNull; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java index a8c62fe2984c..5bf982b908cd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java @@ -22,6 +22,7 @@ import android.os.PowerManager; import android.os.SystemProperties; import android.os.UserHandle; import android.provider.Settings; +import android.util.Log; import android.util.MathUtils; import androidx.annotation.NonNull; @@ -35,6 +36,7 @@ import com.android.systemui.doze.DozeScreenState; import com.android.systemui.dump.DumpManager; import com.android.systemui.flags.FeatureFlags; import com.android.systemui.statusbar.policy.BatteryController; +import com.android.systemui.statusbar.policy.DevicePostureController; import com.android.systemui.tuner.TunerService; import java.io.FileDescriptor; @@ -256,9 +258,20 @@ public class DozeParameters implements } /** + * Whether the single tap sensor uses the proximity sensor for this device posture. + */ + public boolean singleTapUsesProx(@DevicePostureController.DevicePostureInt int devicePosture) { + return getPostureSpecificBool( + mResources.getIntArray(R.array.doze_single_tap_uses_prox_posture_mapping), + singleTapUsesProx(), + devicePosture + ); + } + + /** * Whether the single tap sensor uses the proximity sensor. */ - public boolean singleTapUsesProx() { + private boolean singleTapUsesProx() { return mResources.getBoolean(R.bool.doze_single_tap_uses_prox); } @@ -270,6 +283,17 @@ public class DozeParameters implements } /** + * Sensor to use for brightness changes. + */ + public String brightnessName(@DevicePostureController.DevicePostureInt int posture) { + return AmbientDisplayConfiguration.getSensorFromPostureMapping( + mResources.getStringArray(R.array.doze_brightness_sensor_name_posture_mapping), + null /* defaultValue */, + posture + ); + } + + /** * Callback to listen for DozeParameter changes. */ public void addCallback(Callback callback) { @@ -308,6 +332,20 @@ public class DozeParameters implements pw.println(getSelectivelyRegisterSensorsUsingProx()); } + private boolean getPostureSpecificBool( + int[] postureMapping, + boolean defaultSensorBool, + int posture) { + boolean bool = defaultSensorBool; + if (posture < postureMapping.length) { + bool = postureMapping[posture] != 0; + } else { + Log.e("DozeParameters", "Unsupported doze posture " + posture); + } + + return bool; + } + interface Callback { /** * Invoked when the value of getAlwaysOn may have changed. diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java index 893aa6d6bc45..5feb4053f833 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java @@ -101,8 +101,8 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat @Override public void onOverlayChanged() { - KeyguardStatusBarViewController.this.onThemeChanged(); mView.onOverlayChanged(); + KeyguardStatusBarViewController.this.onThemeChanged(); } @Override 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 4db983bf4834..4862d1617837 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java @@ -305,7 +305,6 @@ public class NotificationPanelViewController extends PanelViewController { private KeyguardUserSwitcherController mKeyguardUserSwitcherController; private KeyguardStatusBarView mKeyguardStatusBar; private KeyguardStatusBarViewController mKeyguardStatusBarViewController; - private ViewGroup mBigClockContainer; @VisibleForTesting QS mQs; private FrameLayout mQsFrame; private KeyguardStatusViewController mKeyguardStatusViewController; @@ -802,7 +801,6 @@ public class NotificationPanelViewController extends PanelViewController { private void onFinishInflate() { loadDimens(); mKeyguardStatusBar = mView.findViewById(R.id.keyguard_header); - mBigClockContainer = mView.findViewById(R.id.big_clock_container); FrameLayout userAvatarContainer = null; KeyguardUserSwitcherView keyguardUserSwitcherView = null; @@ -1085,7 +1083,6 @@ public class NotificationPanelViewController extends PanelViewController { R.layout.keyguard_user_switcher /* layoutId */, showKeyguardUserSwitcher /* enabled */); - mBigClockContainer.removeAllViews(); updateViewControllers(mView.findViewById(R.id.keyguard_status_view), userAvatarView, keyguardUserSwitcherView); @@ -2184,7 +2181,6 @@ public class NotificationPanelViewController extends PanelViewController { if (mBarState == StatusBarState.SHADE_LOCKED || mBarState == KEYGUARD) { updateKeyguardBottomAreaAlpha(); positionClockAndNotifications(); - updateBigClockAlpha(); } if (mAccessibilityManager.isEnabled()) { @@ -2957,20 +2953,6 @@ public class NotificationPanelViewController extends PanelViewController { mLockIconViewController.setAlpha(alpha); } - /** - * Custom clock fades away when user drags up to unlock or pulls down quick settings. - * - * Updates alpha of custom clock to match the alpha of the KeyguardBottomArea. See - * {@link #updateKeyguardBottomAreaAlpha}. - */ - private void updateBigClockAlpha() { - float expansionAlpha = MathUtils.map( - isUnlockHintRunning() ? 0 : KeyguardBouncer.ALPHA_EXPANSION_THRESHOLD, 1f, 0f, 1f, - getExpandedFraction()); - float alpha = Math.min(expansionAlpha, 1 - computeQsExpansionFraction()); - mBigClockContainer.setAlpha(alpha); - } - @Override protected void onExpandingStarted() { super.onExpandingStarted(); @@ -3328,7 +3310,6 @@ public class NotificationPanelViewController extends PanelViewController { } mNotificationStackScrollLayoutController.setExpandedHeight(expandedHeight); updateKeyguardBottomAreaAlpha(); - updateBigClockAlpha(); updateStatusBarIcons(); } 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 3bdc08be63e6..2130e028e863 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -199,6 +199,7 @@ import com.android.systemui.statusbar.PowerButtonReveal; import com.android.systemui.statusbar.PulseExpansionHandler; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.SysuiStatusBarStateController; +import com.android.systemui.statusbar.connectivity.NetworkController; import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler; import com.android.systemui.statusbar.notification.DynamicPrivacyController; import com.android.systemui.statusbar.notification.NotificationActivityStarter; @@ -226,7 +227,6 @@ import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener; import com.android.systemui.statusbar.policy.ExtensionController; import com.android.systemui.statusbar.policy.KeyguardStateController; -import com.android.systemui.statusbar.policy.NetworkController; import com.android.systemui.statusbar.policy.UserInfoControllerImpl; import com.android.systemui.statusbar.policy.UserSwitcherController; import com.android.systemui.tuner.TunerService; 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 5bc97a5b316d..18fd9d3c6651 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java @@ -1149,7 +1149,6 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb public void showBouncerMessage(String message, ColorStateList colorState) { if (isShowingAlternateAuth()) { if (mKeyguardMessageAreaController != null) { - mKeyguardMessageAreaController.setNextMessageColor(colorState); mKeyguardMessageAreaController.setMessage(message); } } else { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java index 71364320839c..fbd9ef7e3707 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java @@ -26,11 +26,11 @@ import com.android.settingslib.mobile.TelephonyIcons; import com.android.systemui.R; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.flags.FeatureFlags; -import com.android.systemui.statusbar.policy.NetworkController; -import com.android.systemui.statusbar.policy.NetworkController.IconState; -import com.android.systemui.statusbar.policy.NetworkController.MobileDataIndicators; -import com.android.systemui.statusbar.policy.NetworkController.WifiIndicators; -import com.android.systemui.statusbar.policy.NetworkControllerImpl; +import com.android.systemui.statusbar.connectivity.NetworkController; +import com.android.systemui.statusbar.connectivity.NetworkController.IconState; +import com.android.systemui.statusbar.connectivity.NetworkController.MobileDataIndicators; +import com.android.systemui.statusbar.connectivity.NetworkController.WifiIndicators; +import com.android.systemui.statusbar.connectivity.NetworkControllerImpl; import com.android.systemui.statusbar.policy.SecurityController; import com.android.systemui.tuner.TunerService; import com.android.systemui.tuner.TunerService.Tunable; 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 0d43b9323a39..568970790a18 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 @@ -62,6 +62,7 @@ import com.android.systemui.statusbar.NotificationViewHierarchyManager; import com.android.systemui.statusbar.OperatorNameViewController; import com.android.systemui.statusbar.PulseExpansionHandler; import com.android.systemui.statusbar.SysuiStatusBarStateController; +import com.android.systemui.statusbar.connectivity.NetworkController; import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler; import com.android.systemui.statusbar.notification.DynamicPrivacyController; import com.android.systemui.statusbar.notification.NotificationEntryManager; @@ -104,7 +105,6 @@ import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.ExtensionController; import com.android.systemui.statusbar.policy.KeyguardStateController; -import com.android.systemui.statusbar.policy.NetworkController; import com.android.systemui.statusbar.policy.UserInfoControllerImpl; import com.android.systemui.statusbar.policy.UserSwitcherController; import com.android.systemui.tuner.TunerService; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt index eeff010e0bdf..ab6ee89627ef 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt @@ -26,10 +26,12 @@ import android.util.Log import android.view.View import androidx.annotation.VisibleForTesting import com.android.internal.jank.InteractionJankMonitor +import com.android.systemui.Dumpable import com.android.systemui.R import com.android.systemui.animation.ActivityLaunchAnimator import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Main +import com.android.systemui.dump.DumpManager import com.android.systemui.plugins.ActivityStarter import com.android.systemui.flags.FeatureFlags import com.android.systemui.statusbar.notification.collection.NotificationEntry @@ -37,6 +39,8 @@ import com.android.systemui.statusbar.notification.collection.notifcollection.Co import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener import com.android.systemui.statusbar.policy.CallbackController import com.android.systemui.util.time.SystemClock +import java.io.FileDescriptor +import java.io.PrintWriter import java.util.concurrent.Executor import javax.inject.Inject @@ -51,13 +55,14 @@ class OngoingCallController @Inject constructor( private val activityStarter: ActivityStarter, @Main private val mainExecutor: Executor, private val iActivityManager: IActivityManager, - private val logger: OngoingCallLogger -) : CallbackController<OngoingCallListener> { + private val logger: OngoingCallLogger, + private val dumpManager: DumpManager, +) : CallbackController<OngoingCallListener>, Dumpable { /** Non-null if there's an active call notification. */ private var callNotificationInfo: CallNotificationInfo? = null /** True if the application managing the call is visible to the user. */ - private var isCallAppVisible: Boolean = true + private var isCallAppVisible: Boolean = false private var chipView: View? = null private var uidObserver: IUidObserver.Stub? = null @@ -103,16 +108,7 @@ class OngoingCallController @Inject constructor( } } - // Fix for b/199600334 - override fun onEntryCleanUp(entry: NotificationEntry) { - removeChipIfNeeded(entry) - } - override fun onEntryRemoved(entry: NotificationEntry, reason: Int) { - removeChipIfNeeded(entry) - } - - private fun removeChipIfNeeded(entry: NotificationEntry) { if (entry.sbn.key == callNotificationInfo?.key) { removeChip() } @@ -120,6 +116,7 @@ class OngoingCallController @Inject constructor( } fun init() { + dumpManager.registerDumpable(this) if (featureFlags.isOngoingCallStatusBarChipEnabled) { notifCollection.addCollectionListener(notifListener) } @@ -299,6 +296,11 @@ class OngoingCallController @Inject constructor( */ fun hasValidStartTime(): Boolean = callStartTime > 0 } + + override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<out String>) { + pw.println("Active call notification: $callNotificationInfo") + pw.println("Call app visible: $isCallAppVisible") + } } private fun isCallNotification(entry: NotificationEntry): Boolean { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DevicePostureController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DevicePostureController.java index fbfa5e5ea109..bbba19d61b5a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DevicePostureController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DevicePostureController.java @@ -46,10 +46,31 @@ public interface DevicePostureController extends CallbackController<Callback> { int DEVICE_POSTURE_HALF_OPENED = 2; int DEVICE_POSTURE_OPENED = 3; int DEVICE_POSTURE_FLIPPED = 4; + int SUPPORTED_POSTURES_SIZE = DEVICE_POSTURE_FLIPPED + 1; /** Return the current device posture. */ @DevicePostureInt int getDevicePosture(); + /** + * String representation of DevicePostureInt. + */ + static String devicePostureToString(@DevicePostureInt int posture) { + switch (posture) { + case DEVICE_POSTURE_CLOSED: + return "DEVICE_POSTURE_CLOSED"; + case DEVICE_POSTURE_HALF_OPENED: + return "DEVICE_POSTURE_HALF_OPENED"; + case DEVICE_POSTURE_OPENED: + return "DEVICE_POSTURE_OPENED"; + case DEVICE_POSTURE_FLIPPED: + return "DEVICE_POSTURE_FLIPPED"; + case DEVICE_POSTURE_UNKNOWN: + return "DEVICE_POSTURE_UNKNOWN"; + default: + return "UNSUPPORTED POSTURE posture=" + posture; + } + } + /** Callback to be notified about device posture changes. */ interface Callback { /** Called when the posture changes. */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java index 1eec639670ee..92908790770a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java @@ -23,7 +23,9 @@ import com.android.internal.R; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.settings.UserTracker; -import com.android.systemui.statusbar.policy.AccessPointControllerImpl; +import com.android.systemui.statusbar.connectivity.AccessPointControllerImpl; +import com.android.systemui.statusbar.connectivity.NetworkController; +import com.android.systemui.statusbar.connectivity.NetworkControllerImpl; import com.android.systemui.statusbar.policy.BluetoothController; import com.android.systemui.statusbar.policy.BluetoothControllerImpl; import com.android.systemui.statusbar.policy.CastController; @@ -42,8 +44,6 @@ import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.statusbar.policy.KeyguardStateControllerImpl; import com.android.systemui.statusbar.policy.LocationController; import com.android.systemui.statusbar.policy.LocationControllerImpl; -import com.android.systemui.statusbar.policy.NetworkController; -import com.android.systemui.statusbar.policy.NetworkControllerImpl; import com.android.systemui.statusbar.policy.NextAlarmController; import com.android.systemui.statusbar.policy.NextAlarmControllerImpl; import com.android.systemui.statusbar.policy.RotationLockController; diff --git a/packages/SystemUI/src/com/android/systemui/unfold/ShellUnfoldProgressProvider.kt b/packages/SystemUI/src/com/android/systemui/unfold/ShellUnfoldProgressProvider.kt new file mode 100644 index 000000000000..4a884359d315 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/unfold/ShellUnfoldProgressProvider.kt @@ -0,0 +1,49 @@ +/* + * 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.unfold + +import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener +import com.android.wm.shell.unfold.ShellUnfoldProgressProvider +import com.android.wm.shell.unfold.ShellUnfoldProgressProvider.UnfoldListener +import java.util.concurrent.Executor + +class ShellUnfoldProgressProvider( + private val unfoldProgressProvider: UnfoldTransitionProgressProvider +) : ShellUnfoldProgressProvider { + + override fun addListener(executor: Executor, listener: UnfoldListener) { + unfoldProgressProvider.addCallback(object : TransitionProgressListener { + override fun onTransitionStarted() { + executor.execute { + listener.onStateChangeStarted() + } + } + + override fun onTransitionProgress(progress: Float) { + executor.execute { + listener.onStateChangeProgress(progress) + } + } + + override fun onTransitionFinished() { + executor.execute { + listener.onStateChangeFinished() + } + } + }) + } +} diff --git a/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTransitionModule.kt b/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTransitionModule.kt new file mode 100644 index 000000000000..b23aa20dcaa4 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTransitionModule.kt @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.unfold + +import android.content.Context +import android.hardware.SensorManager +import android.hardware.devicestate.DeviceStateManager +import android.os.Handler +import com.android.systemui.dagger.qualifiers.Main +import com.android.systemui.keyguard.LifecycleScreenStatusProvider +import com.android.systemui.unfold.config.UnfoldTransitionConfig +import com.android.wm.shell.unfold.ShellUnfoldProgressProvider +import dagger.Lazy +import dagger.Module +import dagger.Provides +import java.util.Optional +import java.util.concurrent.Executor +import javax.inject.Singleton + +@Module +class UnfoldTransitionModule { + + @Provides + @Singleton + fun provideUnfoldTransitionProgressProvider( + context: Context, + config: UnfoldTransitionConfig, + screenStatusProvider: LifecycleScreenStatusProvider, + deviceStateManager: DeviceStateManager, + sensorManager: SensorManager, + @Main executor: Executor, + @Main handler: Handler + ): UnfoldTransitionProgressProvider = + createUnfoldTransitionProgressProvider( + context, + config, + screenStatusProvider, + deviceStateManager, + sensorManager, + handler, + executor + ) + + @Provides + @Singleton + fun provideUnfoldTransitionConfig(context: Context): UnfoldTransitionConfig = + createConfig(context) + + @Provides + @Singleton + fun provideShellProgressProvider( + config: UnfoldTransitionConfig, + provider: Lazy<UnfoldTransitionProgressProvider> + ): Optional<ShellUnfoldProgressProvider> = + if (config.isEnabled) { + Optional.ofNullable(ShellUnfoldProgressProvider(provider.get())) + } else { + Optional.empty() + } +} diff --git a/packages/SystemUI/src/com/android/systemui/util/WallpaperController.kt b/packages/SystemUI/src/com/android/systemui/util/WallpaperController.kt index a9810458fe90..2c01a7003a16 100644 --- a/packages/SystemUI/src/com/android/systemui/util/WallpaperController.kt +++ b/packages/SystemUI/src/com/android/systemui/util/WallpaperController.kt @@ -40,8 +40,8 @@ class WallpaperController @Inject constructor(private val wallpaperManager: Wall this.wallpaperInfo = wallpaperInfo } - private val shouldUseDefaultDeviceStateChangeTransition: Boolean - get() = wallpaperInfo?.shouldUseDefaultDeviceStateChangeTransition() + private val shouldUseDefaultDisplayStateChangeTransition: Boolean + get() = wallpaperInfo?.shouldUseDefaultDisplayStateChangeTransition() ?: true fun setNotificationShadeZoom(zoomOut: Float) { @@ -50,7 +50,7 @@ class WallpaperController @Inject constructor(private val wallpaperManager: Wall } fun setUnfoldTransitionZoom(zoomOut: Float) { - if (shouldUseDefaultDeviceStateChangeTransition) { + if (shouldUseDefaultDisplayStateChangeTransition) { unfoldTransitionZoomOut = zoomOut updateZoom() } diff --git a/packages/SystemUI/src/com/android/systemui/util/sensors/PostureDependentProximitySensor.java b/packages/SystemUI/src/com/android/systemui/util/sensors/PostureDependentProximitySensor.java new file mode 100644 index 000000000000..28cba8e16970 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/util/sensors/PostureDependentProximitySensor.java @@ -0,0 +1,109 @@ +/* + * 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.util.sensors; + +import android.util.Log; + +import androidx.annotation.NonNull; + +import com.android.systemui.statusbar.policy.DevicePostureController; +import com.android.systemui.util.concurrency.DelayableExecutor; +import com.android.systemui.util.concurrency.Execution; + +import javax.inject.Inject; + +/** + * Proximity sensor that changes proximity sensor usage based on the current posture. + * Posture -> prox sensor mapping can be found in SystemUI config overlays at: + * - proximity_sensor_posture_mapping + * - proximity_sensor_secondary_posture_mapping. + * where the array indices correspond to the following postures: + * [UNKNOWN, CLOSED, HALF_OPENED, OPENED] + */ +class PostureDependentProximitySensor extends ProximitySensorImpl { + private final ThresholdSensor[] mPostureToPrimaryProxSensorMap; + private final ThresholdSensor[] mPostureToSecondaryProxSensorMap; + + @Inject + PostureDependentProximitySensor( + @PrimaryProxSensor ThresholdSensor[] postureToPrimaryProxSensorMap, + @SecondaryProxSensor ThresholdSensor[] postureToSecondaryProxSensorMap, + @NonNull DelayableExecutor delayableExecutor, + @NonNull Execution execution, + @NonNull DevicePostureController devicePostureController + ) { + super( + postureToPrimaryProxSensorMap[0], + postureToSecondaryProxSensorMap[0], + delayableExecutor, + execution + ); + mPostureToPrimaryProxSensorMap = postureToPrimaryProxSensorMap; + mPostureToSecondaryProxSensorMap = postureToSecondaryProxSensorMap; + mDevicePosture = devicePostureController.getDevicePosture(); + devicePostureController.addCallback(mDevicePostureCallback); + + chooseSensors(); + } + private void chooseSensors() { + if (mDevicePosture >= mPostureToPrimaryProxSensorMap.length + || mDevicePosture >= mPostureToSecondaryProxSensorMap.length) { + Log.e("PostureDependentProxSensor", + "unsupported devicePosture=" + mDevicePosture); + return; + } + + ThresholdSensor newPrimaryProx = mPostureToPrimaryProxSensorMap[mDevicePosture]; + ThresholdSensor newSecondaryProx = mPostureToSecondaryProxSensorMap[mDevicePosture]; + + if (newPrimaryProx != mPrimaryThresholdSensor + || newSecondaryProx != mSecondaryThresholdSensor) { + logDebug("Register new proximity sensors newPosture=" + + DevicePostureController.devicePostureToString(mDevicePosture)); + unregisterInternal(); + + if (mPrimaryThresholdSensor != null) { + mPrimaryThresholdSensor.unregister(mPrimaryEventListener); + } + if (mSecondaryThresholdSensor != null) { + mSecondaryThresholdSensor.unregister(mSecondaryEventListener); + } + + mPrimaryThresholdSensor = newPrimaryProx; + mSecondaryThresholdSensor = newSecondaryProx; + + mInitializedListeners = false; + registerInternal(); + } + } + + private final DevicePostureController.Callback mDevicePostureCallback = + posture -> { + if (mDevicePosture == posture) { + return; + } + + mDevicePosture = posture; + chooseSensors(); + }; + + @Override + public String toString() { + return String.format("{posture=%s, proximitySensor=%s}", + DevicePostureController.devicePostureToString(mDevicePosture), super.toString()); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/util/sensors/ProximityCheck.java b/packages/SystemUI/src/com/android/systemui/util/sensors/ProximityCheck.java new file mode 100644 index 000000000000..a8a6341cc5ee --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/util/sensors/ProximityCheck.java @@ -0,0 +1,90 @@ +/* + * 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.util.sensors; + +import com.android.systemui.dagger.qualifiers.Main; +import com.android.systemui.util.concurrency.DelayableExecutor; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Consumer; + +import javax.inject.Inject; + +/** + * Convenience class allowing for briefly checking the proximity sensor. + */ +public class ProximityCheck implements Runnable { + + private final ProximitySensor mSensor; + private final DelayableExecutor mDelayableExecutor; + private List<Consumer<Boolean>> mCallbacks = new ArrayList<>(); + private final ThresholdSensor.Listener mListener; + private final AtomicBoolean mRegistered = new AtomicBoolean(); + + @Inject + public ProximityCheck( + ProximitySensor sensor, + @Main DelayableExecutor delayableExecutor) { + mSensor = sensor; + mSensor.setTag("prox_check"); + mDelayableExecutor = delayableExecutor; + mListener = this::onProximityEvent; + } + + /** Set a descriptive tag for the sensors registration. */ + public void setTag(String tag) { + mSensor.setTag(tag); + } + + @Override + public void run() { + unregister(); + onProximityEvent(null); + } + + /** + * Query the proximity sensor, timing out if no result. + */ + public void check(long timeoutMs, Consumer<Boolean> callback) { + if (!mSensor.isLoaded()) { + callback.accept(null); + return; + } + mCallbacks.add(callback); + if (!mRegistered.getAndSet(true)) { + mSensor.register(mListener); + mDelayableExecutor.executeDelayed(this, timeoutMs); + } + } + + private void unregister() { + mSensor.unregister(mListener); + mRegistered.set(false); + } + + private void onProximityEvent(ThresholdSensorEvent proximityEvent) { + mCallbacks.forEach( + booleanConsumer -> + booleanConsumer.accept( + proximityEvent == null ? null : proximityEvent.getBelow())); + mCallbacks.clear(); + unregister(); + mRegistered.set(false); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java b/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java index bd1103982017..d3f1c93195a1 100644 --- a/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java +++ b/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019 The Android Open Source Project + * 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. @@ -16,149 +16,24 @@ package com.android.systemui.util.sensors; -import android.hardware.SensorManager; -import android.util.Log; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.systemui.dagger.qualifiers.Main; -import com.android.systemui.util.concurrency.DelayableExecutor; -import com.android.systemui.util.concurrency.Execution; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.function.Consumer; - -import javax.inject.Inject; - /** - * Wrapper around SensorManager customized for the Proximity sensor. - * - * The ProximitySensor supports the concept of a primary and a - * secondary hardware sensor. The primary sensor is used for a first - * pass check if the phone covered. When triggered, it then checks - * the secondary sensor for confirmation (if there is one). It does - * not send a proximity event until the secondary sensor confirms (or - * rejects) the reading. The secondary sensor is, in fact, the source - * of truth. - * - * This is necessary as sometimes keeping the secondary sensor on for - * extends periods is undesirable. It may, however, result in increased - * latency for proximity readings. - * - * Phones should configure this via a config.xml overlay. If no - * proximity sensor is set (primary or secondary) we fall back to the - * default Sensor.TYPE_PROXIMITY. If proximity_sensor_type is set in - * config.xml, that will be used as the primary sensor. If - * proximity_sensor_secondary_type is set, that will function as the - * secondary sensor. If no secondary is set, only the primary will be - * used. + * Wrapper class for a dual ProximitySensor which supports a secondary sensor gated upon the + * primary). */ -public class ProximitySensor implements ThresholdSensor { - private static final String TAG = "ProxSensor"; - private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); - private static final long SECONDARY_PING_INTERVAL_MS = 5000; - - private final ThresholdSensor mPrimaryThresholdSensor; - private final ThresholdSensor mSecondaryThresholdSensor; - private final DelayableExecutor mDelayableExecutor; - private final Execution mExecution; - private final List<ThresholdSensor.Listener> mListeners = new ArrayList<>(); - private String mTag = null; - @VisibleForTesting protected boolean mPaused; - private ThresholdSensorEvent mLastPrimaryEvent; - @VisibleForTesting - ThresholdSensorEvent mLastEvent; - private boolean mRegistered; - private final AtomicBoolean mAlerting = new AtomicBoolean(); - private Runnable mCancelSecondaryRunnable; - private boolean mInitializedListeners = false; - private boolean mSecondarySafe = false; - - private final ThresholdSensor.Listener mPrimaryEventListener = this::onPrimarySensorEvent; - - private final ThresholdSensor.Listener mSecondaryEventListener = - new ThresholdSensor.Listener() { - @Override - public void onThresholdCrossed(ThresholdSensorEvent event) { - // If we no longer have a "below" signal and the secondary sensor is not - // considered "safe", then we need to turn it off. - if (!mSecondarySafe - && (mLastPrimaryEvent == null - || !mLastPrimaryEvent.getBelow() - || !event.getBelow())) { - chooseSensor(); - if (mLastPrimaryEvent == null || !mLastPrimaryEvent.getBelow()) { - // Only check the secondary as long as the primary thinks we're near. - if (mCancelSecondaryRunnable != null) { - mCancelSecondaryRunnable.run(); - mCancelSecondaryRunnable = null; - } - return; - } else { - // Check this sensor again in a moment. - mCancelSecondaryRunnable = mDelayableExecutor.executeDelayed(() -> { - // This is safe because we know that mSecondaryThresholdSensor - // is loaded, otherwise we wouldn't be here. - mPrimaryThresholdSensor.pause(); - mSecondaryThresholdSensor.resume(); - }, - SECONDARY_PING_INTERVAL_MS); - } - } - logDebug("Secondary sensor event: " + event.getBelow() + "."); - - if (!mPaused) { - onSensorEvent(event); - } - } - }; - - @Inject - public ProximitySensor( - @PrimaryProxSensor ThresholdSensor primary, - @SecondaryProxSensor ThresholdSensor secondary, - @Main DelayableExecutor delayableExecutor, - Execution execution) { - mPrimaryThresholdSensor = primary; - mSecondaryThresholdSensor = secondary; - mDelayableExecutor = delayableExecutor; - mExecution = execution; - } - - @Override - public void setTag(String tag) { - mTag = tag; - mPrimaryThresholdSensor.setTag(tag + ":primary"); - mSecondaryThresholdSensor.setTag(tag + ":secondary"); - } - - @Override - public void setDelay(int delay) { - mExecution.assertIsMainThread(); - mPrimaryThresholdSensor.setDelay(delay); - mSecondaryThresholdSensor.setDelay(delay); - } - +public interface ProximitySensor extends ThresholdSensor { /** - * Unregister with the {@link SensorManager} without unsetting listeners on this object. + * Returns true if we are registered with the SensorManager. */ - @Override - public void pause() { - mExecution.assertIsMainThread(); - mPaused = true; - unregisterInternal(); - } + boolean isRegistered(); /** - * Register with the {@link SensorManager}. No-op if no listeners are registered on this object. + * Whether the proximity sensor reports near. Can return null if no information has been + * received yet. */ - @Override - public void resume() { - mExecution.assertIsMainThread(); - mPaused = false; - registerInternal(); - } + Boolean isNear(); + + /** Update all listeners with the last value this class received from the sensor. */ + void alertListeners(); /** * Sets that it is safe to leave the secondary sensor on indefinitely. @@ -166,249 +41,5 @@ public class ProximitySensor implements ThresholdSensor { * The secondary sensor will be turned on if there are any registered listeners, regardless * of what is reported by the primary sensor. */ - public void setSecondarySafe(boolean safe) { - mSecondarySafe = mSecondaryThresholdSensor.isLoaded() && safe; - chooseSensor(); - } - - /** - * Returns true if we are registered with the SensorManager. - */ - public boolean isRegistered() { - return mRegistered; - } - - /** - * Returns {@code false} if a Proximity sensor is not available. - */ - @Override - public boolean isLoaded() { - return mPrimaryThresholdSensor.isLoaded(); - } - - /** - * Add a listener. - * - * Registers itself with the {@link SensorManager} if this is the first listener - * added. If the ProximitySensor is paused, it will be registered when resumed. - */ - @Override - public void register(ThresholdSensor.Listener listener) { - mExecution.assertIsMainThread(); - if (!isLoaded()) { - return; - } - - if (mListeners.contains(listener)) { - logDebug("ProxListener registered multiple times: " + listener); - } else { - mListeners.add(listener); - } - registerInternal(); - } - - protected void registerInternal() { - mExecution.assertIsMainThread(); - if (mRegistered || mPaused || mListeners.isEmpty()) { - return; - } - if (!mInitializedListeners) { - mPrimaryThresholdSensor.pause(); - mSecondaryThresholdSensor.pause(); - mPrimaryThresholdSensor.register(mPrimaryEventListener); - mSecondaryThresholdSensor.register(mSecondaryEventListener); - mInitializedListeners = true; - } - logDebug("Registering sensor listener"); - - mRegistered = true; - chooseSensor(); - } - - private void chooseSensor() { - mExecution.assertIsMainThread(); - if (!mRegistered || mPaused || mListeners.isEmpty()) { - return; - } - if (mSecondarySafe) { - mSecondaryThresholdSensor.resume(); - mPrimaryThresholdSensor.pause(); - } else { - mPrimaryThresholdSensor.resume(); - mSecondaryThresholdSensor.pause(); - } - } - - /** - * Remove a listener. - * - * If all listeners are removed from an instance of this class, - * it will unregister itself with the SensorManager. - */ - @Override - public void unregister(ThresholdSensor.Listener listener) { - mExecution.assertIsMainThread(); - mListeners.remove(listener); - if (mListeners.size() == 0) { - unregisterInternal(); - } - } - - protected void unregisterInternal() { - mExecution.assertIsMainThread(); - if (!mRegistered) { - return; - } - logDebug("unregistering sensor listener"); - mPrimaryThresholdSensor.pause(); - mSecondaryThresholdSensor.pause(); - if (mCancelSecondaryRunnable != null) { - mCancelSecondaryRunnable.run(); - mCancelSecondaryRunnable = null; - } - mLastPrimaryEvent = null; // Forget what we know. - mLastEvent = null; - mRegistered = false; - } - - public Boolean isNear() { - return isLoaded() && mLastEvent != null ? mLastEvent.getBelow() : null; - } - - /** Update all listeners with the last value this class received from the sensor. */ - public void alertListeners() { - mExecution.assertIsMainThread(); - if (mAlerting.getAndSet(true)) { - return; - } - if (mLastEvent != null) { - ThresholdSensorEvent lastEvent = mLastEvent; // Listeners can null out mLastEvent. - List<ThresholdSensor.Listener> listeners = new ArrayList<>(mListeners); - listeners.forEach(proximitySensorListener -> - proximitySensorListener.onThresholdCrossed(lastEvent)); - } - - mAlerting.set(false); - } - - private void onPrimarySensorEvent(ThresholdSensorEvent event) { - mExecution.assertIsMainThread(); - if (mLastPrimaryEvent != null && event.getBelow() == mLastPrimaryEvent.getBelow()) { - return; - } - - mLastPrimaryEvent = event; - - if (mSecondarySafe && mSecondaryThresholdSensor.isLoaded()) { - logDebug("Primary sensor reported " + (event.getBelow() ? "near" : "far") - + ". Checking secondary."); - if (mCancelSecondaryRunnable == null) { - mSecondaryThresholdSensor.resume(); - } - return; - } - - - if (!mSecondaryThresholdSensor.isLoaded()) { // No secondary - logDebug("Primary sensor event: " + event.getBelow() + ". No secondary."); - onSensorEvent(event); - } else if (event.getBelow()) { // Covered? Check secondary. - logDebug("Primary sensor event: " + event.getBelow() + ". Checking secondary."); - if (mCancelSecondaryRunnable != null) { - mCancelSecondaryRunnable.run(); - } - mSecondaryThresholdSensor.resume(); - } else { // Uncovered. Report immediately. - onSensorEvent(event); - } - } - - private void onSensorEvent(ThresholdSensorEvent event) { - mExecution.assertIsMainThread(); - if (mLastEvent != null && event.getBelow() == mLastEvent.getBelow()) { - return; - } - - if (!mSecondarySafe && !event.getBelow()) { - chooseSensor(); - } - - mLastEvent = event; - alertListeners(); - } - - @Override - public String toString() { - return String.format("{registered=%s, paused=%s, near=%s, primarySensor=%s, " - + "secondarySensor=%s secondarySafe=%s}", - isRegistered(), mPaused, isNear(), mPrimaryThresholdSensor, - mSecondaryThresholdSensor, mSecondarySafe); - } - - /** - * Convenience class allowing for briefly checking the proximity sensor. - */ - public static class ProximityCheck implements Runnable { - - private final ProximitySensor mSensor; - private final DelayableExecutor mDelayableExecutor; - private List<Consumer<Boolean>> mCallbacks = new ArrayList<>(); - private final ThresholdSensor.Listener mListener; - private final AtomicBoolean mRegistered = new AtomicBoolean(); - - @Inject - public ProximityCheck(ProximitySensor sensor, @Main DelayableExecutor delayableExecutor) { - mSensor = sensor; - mSensor.setTag("prox_check"); - mDelayableExecutor = delayableExecutor; - mListener = this::onProximityEvent; - } - - /** Set a descriptive tag for the sensors registration. */ - public void setTag(String tag) { - mSensor.setTag(tag); - } - - @Override - public void run() { - unregister(); - onProximityEvent(null); - } - - /** - * Query the proximity sensor, timing out if no result. - */ - public void check(long timeoutMs, Consumer<Boolean> callback) { - if (!mSensor.isLoaded()) { - callback.accept(null); - return; - } - mCallbacks.add(callback); - if (!mRegistered.getAndSet(true)) { - mSensor.register(mListener); - mDelayableExecutor.executeDelayed(this, timeoutMs); - } - } - - private void unregister() { - mSensor.unregister(mListener); - mRegistered.set(false); - } - - private void onProximityEvent(ThresholdSensorEvent proximityEvent) { - mCallbacks.forEach( - booleanConsumer -> - booleanConsumer.accept( - proximityEvent == null ? null : proximityEvent.getBelow())); - mCallbacks.clear(); - unregister(); - mRegistered.set(false); - } - } - - private void logDebug(String msg) { - if (DEBUG) { - Log.d(TAG, (mTag != null ? "[" + mTag + "] " : "") + msg); - } - } + void setSecondarySafe(boolean safe); } diff --git a/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensorImpl.java b/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensorImpl.java new file mode 100644 index 000000000000..e639313ac649 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensorImpl.java @@ -0,0 +1,360 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.util.sensors; + +import android.hardware.SensorManager; +import android.util.Log; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.systemui.dagger.qualifiers.Main; +import com.android.systemui.statusbar.policy.DevicePostureController; +import com.android.systemui.util.concurrency.DelayableExecutor; +import com.android.systemui.util.concurrency.Execution; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; + +import javax.inject.Inject; + +/** + * Wrapper around SensorManager customized for the Proximity sensor. + * + * The ProximitySensor supports the concept of a primary and a + * secondary hardware sensor. The primary sensor is used for a first + * pass check if the phone covered. When triggered, it then checks + * the secondary sensor for confirmation (if there is one). It does + * not send a proximity event until the secondary sensor confirms (or + * rejects) the reading. The secondary sensor is, in fact, the source + * of truth. + * + * This is necessary as sometimes keeping the secondary sensor on for + * extends periods is undesirable. It may, however, result in increased + * latency for proximity readings. + * + * Phones should configure this via a config.xml overlay. If no + * proximity sensor is set (primary or secondary) we fall back to the + * default Sensor.TYPE_PROXIMITY. If proximity_sensor_type is set in + * config.xml, that will be used as the primary sensor. If + * proximity_sensor_secondary_type is set, that will function as the + * secondary sensor. If no secondary is set, only the primary will be + * used. + */ +class ProximitySensorImpl implements ProximitySensor { + private static final String TAG = "ProxSensor"; + private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); + private static final long SECONDARY_PING_INTERVAL_MS = 5000; + + ThresholdSensor mPrimaryThresholdSensor; + ThresholdSensor mSecondaryThresholdSensor; + private final DelayableExecutor mDelayableExecutor; + private final Execution mExecution; + private final List<ThresholdSensor.Listener> mListeners = new ArrayList<>(); + private String mTag = null; + @VisibleForTesting protected boolean mPaused; + private ThresholdSensorEvent mLastPrimaryEvent; + @VisibleForTesting + ThresholdSensorEvent mLastEvent; + private boolean mRegistered; + private final AtomicBoolean mAlerting = new AtomicBoolean(); + private Runnable mCancelSecondaryRunnable; + boolean mInitializedListeners = false; + private boolean mSecondarySafe = false; // safe to skip primary sensor check and use secondary + protected @DevicePostureController.DevicePostureInt int mDevicePosture; + + final ThresholdSensor.Listener mPrimaryEventListener = this::onPrimarySensorEvent; + + final ThresholdSensor.Listener mSecondaryEventListener = + new ThresholdSensor.Listener() { + @Override + public void onThresholdCrossed(ThresholdSensorEvent event) { + // If we no longer have a "below" signal and the secondary sensor is not + // considered "safe", then we need to turn it off. + if (!mSecondarySafe + && (mLastPrimaryEvent == null + || !mLastPrimaryEvent.getBelow() + || !event.getBelow())) { + chooseSensor(); + if (mLastPrimaryEvent == null || !mLastPrimaryEvent.getBelow()) { + // Only check the secondary as long as the primary thinks we're near. + if (mCancelSecondaryRunnable != null) { + mCancelSecondaryRunnable.run(); + mCancelSecondaryRunnable = null; + } + return; + } else { + // Check this sensor again in a moment. + mCancelSecondaryRunnable = mDelayableExecutor.executeDelayed(() -> { + // This is safe because we know that mSecondaryThresholdSensor + // is loaded, otherwise we wouldn't be here. + mPrimaryThresholdSensor.pause(); + mSecondaryThresholdSensor.resume(); + }, + SECONDARY_PING_INTERVAL_MS); + } + } + logDebug("Secondary sensor event: " + event.getBelow() + "."); + + if (!mPaused) { + onSensorEvent(event); + } + } + }; + + @Inject + ProximitySensorImpl( + @PrimaryProxSensor ThresholdSensor primary, + @SecondaryProxSensor ThresholdSensor secondary, + @Main DelayableExecutor delayableExecutor, + Execution execution) { + mPrimaryThresholdSensor = primary; + mSecondaryThresholdSensor = secondary; + mDelayableExecutor = delayableExecutor; + mExecution = execution; + } + + @Override + public void setTag(String tag) { + mTag = tag; + mPrimaryThresholdSensor.setTag(tag + ":primary"); + mSecondaryThresholdSensor.setTag(tag + ":secondary"); + } + + @Override + public void setDelay(int delay) { + mExecution.assertIsMainThread(); + mPrimaryThresholdSensor.setDelay(delay); + mSecondaryThresholdSensor.setDelay(delay); + } + + /** + * Unregister with the {@link SensorManager} without unsetting listeners on this object. + */ + @Override + public void pause() { + mExecution.assertIsMainThread(); + mPaused = true; + unregisterInternal(); + } + + /** + * Register with the {@link SensorManager}. No-op if no listeners are registered on this object. + */ + @Override + public void resume() { + mExecution.assertIsMainThread(); + mPaused = false; + registerInternal(); + } + + @Override + public void setSecondarySafe(boolean safe) { + mSecondarySafe = mSecondaryThresholdSensor.isLoaded() && safe; + chooseSensor(); + } + + /** + * Returns true if we are registered with the SensorManager. + */ + @Override + public boolean isRegistered() { + return mRegistered; + } + + /** + * Returns {@code false} if a Proximity sensor is not available. + */ + @Override + public boolean isLoaded() { + return mPrimaryThresholdSensor.isLoaded(); + } + + /** + * Add a listener. + * + * Registers itself with the {@link SensorManager} if this is the first listener + * added. If the ProximitySensor is paused, it will be registered when resumed. + */ + @Override + public void register(ThresholdSensor.Listener listener) { + mExecution.assertIsMainThread(); + if (!isLoaded()) { + return; + } + + if (mListeners.contains(listener)) { + logDebug("ProxListener registered multiple times: " + listener); + } else { + mListeners.add(listener); + } + registerInternal(); + } + + protected void registerInternal() { + mExecution.assertIsMainThread(); + if (mRegistered || mPaused || mListeners.isEmpty()) { + return; + } + if (!mInitializedListeners) { + mPrimaryThresholdSensor.pause(); + mSecondaryThresholdSensor.pause(); + mPrimaryThresholdSensor.register(mPrimaryEventListener); + mSecondaryThresholdSensor.register(mSecondaryEventListener); + mInitializedListeners = true; + } + + mRegistered = true; + chooseSensor(); + } + + private void chooseSensor() { + mExecution.assertIsMainThread(); + if (!mRegistered || mPaused || mListeners.isEmpty()) { + return; + } + if (mSecondarySafe) { + mSecondaryThresholdSensor.resume(); + mPrimaryThresholdSensor.pause(); + } else { + mPrimaryThresholdSensor.resume(); + mSecondaryThresholdSensor.pause(); + } + } + + /** + * Remove a listener. + * + * If all listeners are removed from an instance of this class, + * it will unregister itself with the SensorManager. + */ + @Override + public void unregister(ThresholdSensor.Listener listener) { + mExecution.assertIsMainThread(); + mListeners.remove(listener); + if (mListeners.size() == 0) { + unregisterInternal(); + } + } + + @Override + public String getName() { + return mPrimaryThresholdSensor.getName(); + } + + @Override + public String getType() { + return mPrimaryThresholdSensor.getType(); + } + + protected void unregisterInternal() { + mExecution.assertIsMainThread(); + if (!mRegistered) { + return; + } + logDebug("unregistering sensor listener"); + mPrimaryThresholdSensor.pause(); + mSecondaryThresholdSensor.pause(); + if (mCancelSecondaryRunnable != null) { + mCancelSecondaryRunnable.run(); + mCancelSecondaryRunnable = null; + } + mLastPrimaryEvent = null; // Forget what we know. + mLastEvent = null; + mRegistered = false; + } + + @Override + public Boolean isNear() { + return isLoaded() && mLastEvent != null ? mLastEvent.getBelow() : null; + } + + @Override + public void alertListeners() { + mExecution.assertIsMainThread(); + if (mAlerting.getAndSet(true)) { + return; + } + if (mLastEvent != null) { + ThresholdSensorEvent lastEvent = mLastEvent; // Listeners can null out mLastEvent. + List<ThresholdSensor.Listener> listeners = new ArrayList<>(mListeners); + listeners.forEach(proximitySensorListener -> + proximitySensorListener.onThresholdCrossed(lastEvent)); + } + + mAlerting.set(false); + } + + private void onPrimarySensorEvent(ThresholdSensorEvent event) { + mExecution.assertIsMainThread(); + if (mLastPrimaryEvent != null && event.getBelow() == mLastPrimaryEvent.getBelow()) { + return; + } + + mLastPrimaryEvent = event; + + if (mSecondarySafe && mSecondaryThresholdSensor.isLoaded()) { + logDebug("Primary sensor reported " + (event.getBelow() ? "near" : "far") + + ". Checking secondary."); + if (mCancelSecondaryRunnable == null) { + mSecondaryThresholdSensor.resume(); + } + return; + } + + + if (!mSecondaryThresholdSensor.isLoaded()) { // No secondary + logDebug("Primary sensor event: " + event.getBelow() + ". No secondary."); + onSensorEvent(event); + } else if (event.getBelow()) { // Covered? Check secondary. + logDebug("Primary sensor event: " + event.getBelow() + ". Checking secondary."); + if (mCancelSecondaryRunnable != null) { + mCancelSecondaryRunnable.run(); + } + mSecondaryThresholdSensor.resume(); + } else { // Uncovered. Report immediately. + onSensorEvent(event); + } + } + + private void onSensorEvent(ThresholdSensorEvent event) { + mExecution.assertIsMainThread(); + if (mLastEvent != null && event.getBelow() == mLastEvent.getBelow()) { + return; + } + + if (!mSecondarySafe && !event.getBelow()) { + chooseSensor(); + } + + mLastEvent = event; + alertListeners(); + } + + @Override + public String toString() { + return String.format("{registered=%s, paused=%s, near=%s, posture=%s, primarySensor=%s, " + + "secondarySensor=%s secondarySafe=%s}", + isRegistered(), mPaused, isNear(), mDevicePosture, mPrimaryThresholdSensor, + mSecondaryThresholdSensor, mSecondarySafe); + } + + void logDebug(String msg) { + if (DEBUG) { + Log.d(TAG, (mTag != null ? "[" + mTag + "] " : "") + msg); + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/util/sensors/SensorModule.java b/packages/SystemUI/src/com/android/systemui/util/sensors/SensorModule.java index 11e7df8bd85f..0be6068c22a4 100644 --- a/packages/SystemUI/src/com/android/systemui/util/sensors/SensorModule.java +++ b/packages/SystemUI/src/com/android/systemui/util/sensors/SensorModule.java @@ -16,11 +16,23 @@ package com.android.systemui.util.sensors; +import android.content.res.Resources; import android.hardware.Sensor; import android.hardware.SensorManager; +import android.text.TextUtils; +import android.util.Log; + +import androidx.annotation.NonNull; import com.android.systemui.R; +import com.android.systemui.dagger.qualifiers.Main; +import com.android.systemui.statusbar.policy.DevicePostureController; +import com.android.systemui.util.concurrency.DelayableExecutor; + +import java.util.HashMap; +import java.util.Map; +import dagger.Lazy; import dagger.Module; import dagger.Provides; @@ -31,8 +43,10 @@ import dagger.Provides; public class SensorModule { @Provides @PrimaryProxSensor - static ThresholdSensor providePrimaryProxSensor(SensorManager sensorManager, - ThresholdSensorImpl.Builder thresholdSensorBuilder) { + static ThresholdSensor providePrimaryProximitySensor( + SensorManager sensorManager, + ThresholdSensorImpl.Builder thresholdSensorBuilder + ) { try { return thresholdSensorBuilder .setSensorDelay(SensorManager.SENSOR_DELAY_NORMAL) @@ -52,8 +66,9 @@ public class SensorModule { @Provides @SecondaryProxSensor - static ThresholdSensor provideSecondaryProxSensor( - ThresholdSensorImpl.Builder thresholdSensorBuilder) { + static ThresholdSensor provideSecondaryProximitySensor( + ThresholdSensorImpl.Builder thresholdSensorBuilder + ) { try { return thresholdSensorBuilder .setSensorResourceId(R.string.proximity_sensor_secondary_type, true) @@ -64,4 +79,153 @@ public class SensorModule { return thresholdSensorBuilder.setSensor(null).setThresholdValue(0).build(); } } + + /** + * If postures are supported on the device, returns a posture dependent proximity sensor + * which switches proximity sensors based on the current posture. + * + * If postures are not supported the regular {@link ProximitySensorImpl} will be returned. + */ + @Provides + static ProximitySensor provideProximitySensor( + @Main Resources resources, + Lazy<PostureDependentProximitySensor> postureDependentProximitySensorProvider, + Lazy<ProximitySensorImpl> proximitySensorProvider + ) { + if (hasPostureSupport( + resources.getStringArray(R.array.proximity_sensor_posture_mapping))) { + return postureDependentProximitySensorProvider.get(); + } else { + return proximitySensorProvider.get(); + } + } + + @Provides + static ProximityCheck provideProximityCheck( + ProximitySensor proximitySensor, + @Main DelayableExecutor delayableExecutor + ) { + return new ProximityCheck( + proximitySensor, + delayableExecutor + ); + } + + @Provides + @PrimaryProxSensor + @NonNull + static ThresholdSensor[] providePostureToProximitySensorMapping( + ThresholdSensorImpl.BuilderFactory thresholdSensorImplBuilderFactory, + @Main Resources resources + ) { + return createPostureToSensorMapping( + thresholdSensorImplBuilderFactory, + resources.getStringArray(R.array.proximity_sensor_posture_mapping), + R.dimen.proximity_sensor_threshold, + R.dimen.proximity_sensor_threshold_latch + ); + } + + @Provides + @SecondaryProxSensor + @NonNull + static ThresholdSensor[] providePostureToSecondaryProximitySensorMapping( + ThresholdSensorImpl.BuilderFactory thresholdSensorImplBuilderFactory, + @Main Resources resources + ) { + return createPostureToSensorMapping( + thresholdSensorImplBuilderFactory, + resources.getStringArray(R.array.proximity_sensor_secondary_posture_mapping), + R.dimen.proximity_sensor_secondary_threshold, + R.dimen.proximity_sensor_secondary_threshold_latch + ); + } + + /** + * Builds sensors to use per posture. + * + * @param sensorTypes an array where the index represents + * {@link DevicePostureController.DevicePostureInt} and the value + * at the given index is the sensorType. Empty values represent + * no sensor desired. + * @param proximitySensorThresholdResourceId resource id for the threshold for all sensor + * postures. This currently only supports one value. + * This needs to be updated in the future if postures + * use different sensors with differing thresholds. + * @param proximitySensorThresholdLatchResourceId resource id for the latch for all sensor + * postures. This currently only supports one + * value. This needs to be updated in the future + * if postures use different sensors with + * differing latches. + * @return an array where the index represents the device posture + * {@link DevicePostureController.DevicePostureInt} and the value at the index is the sensor to + * use when the device is in that posture. + */ + @NonNull + private static ThresholdSensor[] createPostureToSensorMapping( + ThresholdSensorImpl.BuilderFactory thresholdSensorImplBuilderFactory, + String[] sensorTypes, + int proximitySensorThresholdResourceId, + int proximitySensorThresholdLatchResourceId + + ) { + ThresholdSensor noProxSensor = thresholdSensorImplBuilderFactory + .createBuilder() + .setSensor(null).setThresholdValue(0).build(); + + + // length and index of sensorMap correspond to DevicePostureController.DevicePostureInt: + final ThresholdSensor[] sensorMap = + new ThresholdSensor[DevicePostureController.SUPPORTED_POSTURES_SIZE]; + for (int i = 0; i < DevicePostureController.SUPPORTED_POSTURES_SIZE; i++) { + sensorMap[i] = noProxSensor; + } + + if (!hasPostureSupport(sensorTypes)) { + Log.e("SensorModule", "config doesn't support postures," + + " but attempting to retrieve proxSensorMapping"); + return sensorMap; + } + + // Map of sensorType => Sensor, so we reuse the same sensor if it's the same between + // postures + Map<String, ThresholdSensor> typeToSensorMap = new HashMap<>(); + for (int i = 0; i < sensorTypes.length; i++) { + try { + final String sensorType = sensorTypes[i]; + if (typeToSensorMap.containsKey(sensorType)) { + sensorMap[i] = typeToSensorMap.get(sensorType); + } else { + sensorMap[i] = thresholdSensorImplBuilderFactory + .createBuilder() + .setSensorType(sensorTypes[i], true) + .setThresholdResourceId(proximitySensorThresholdResourceId) + .setThresholdLatchResourceId(proximitySensorThresholdLatchResourceId) + .build(); + typeToSensorMap.put(sensorType, sensorMap[i]); + } + } catch (IllegalStateException e) { + // do nothing, sensor at this posture is already set to noProxSensor + } + } + + return sensorMap; + } + + /** + * Returns true if there's at least one non-empty sensor type in the given array. + */ + private static boolean hasPostureSupport(String[] postureToSensorTypeMapping) { + if (postureToSensorTypeMapping == null || postureToSensorTypeMapping.length == 0) { + return false; + } + + for (String sensorType : postureToSensorTypeMapping) { + if (!TextUtils.isEmpty(sensorType)) { + return true; + } + } + + return false; + } } diff --git a/packages/SystemUI/src/com/android/systemui/util/sensors/ThresholdSensor.java b/packages/SystemUI/src/com/android/systemui/util/sensors/ThresholdSensor.java index 363a734a6ae5..d81a8d5991d1 100644 --- a/packages/SystemUI/src/com/android/systemui/util/sensors/ThresholdSensor.java +++ b/packages/SystemUI/src/com/android/systemui/util/sensors/ThresholdSensor.java @@ -16,8 +16,6 @@ package com.android.systemui.util.sensors; -import java.util.Locale; - /** * A wrapper class for sensors that have a boolean state - above/below. */ @@ -77,6 +75,16 @@ public interface ThresholdSensor { void unregister(Listener listener); /** + * Name of the sensor. + */ + String getName(); + + /** + * Type of the sensor. + */ + String getType(); + + /** * Interface for listening to events on {@link ThresholdSensor} */ interface Listener { @@ -85,34 +93,4 @@ public interface ThresholdSensor { */ void onThresholdCrossed(ThresholdSensorEvent event); } - - /** - * Returned when the below/above state of a {@link ThresholdSensor} changes. - */ - class ThresholdSensorEvent { - private final boolean mBelow; - private final long mTimestampNs; - - public ThresholdSensorEvent(boolean below, long timestampNs) { - mBelow = below; - mTimestampNs = timestampNs; - } - - public boolean getBelow() { - return mBelow; - } - - public long getTimestampNs() { - return mTimestampNs; - } - - public long getTimestampMs() { - return mTimestampNs / 1000000; - } - - @Override - public String toString() { - return String.format((Locale) null, "{near=%s, timestamp_ns=%d}", mBelow, mTimestampNs); - } - } } diff --git a/packages/SystemUI/src/com/android/systemui/util/sensors/ThresholdSensorEvent.java b/packages/SystemUI/src/com/android/systemui/util/sensors/ThresholdSensorEvent.java new file mode 100644 index 000000000000..afce09fbe6d0 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/util/sensors/ThresholdSensorEvent.java @@ -0,0 +1,49 @@ +/* + * 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.util.sensors; + +import java.util.Locale; + +/** + * Returned when the below/above state of a {@link ThresholdSensor} changes. + */ +public class ThresholdSensorEvent { + private final boolean mBelow; + private final long mTimestampNs; + + public ThresholdSensorEvent(boolean below, long timestampNs) { + mBelow = below; + mTimestampNs = timestampNs; + } + + public boolean getBelow() { + return mBelow; + } + + public long getTimestampNs() { + return mTimestampNs; + } + + public long getTimestampMs() { + return mTimestampNs / 1000000; + } + + @Override + public String toString() { + return String.format((Locale) null, "{near=%s, timestamp_ns=%d}", mBelow, mTimestampNs); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/util/sensors/ThresholdSensorImpl.java b/packages/SystemUI/src/com/android/systemui/util/sensors/ThresholdSensorImpl.java index d10cf9b180c3..a9086b140a3c 100644 --- a/packages/SystemUI/src/com/android/systemui/util/sensors/ThresholdSensorImpl.java +++ b/packages/SystemUI/src/com/android/systemui/util/sensors/ThresholdSensorImpl.java @@ -21,6 +21,7 @@ import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; +import android.text.TextUtils; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; @@ -32,7 +33,10 @@ import java.util.List; import javax.inject.Inject; -class ThresholdSensorImpl implements ThresholdSensor { +/** + * Sensor that will only trigger beyond some lower and upper threshold. + */ +public class ThresholdSensorImpl implements ThresholdSensor { private static final String TAG = "ThresholdSensor"; private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); @@ -198,6 +202,15 @@ class ThresholdSensorImpl implements ThresholdSensor { alertListenersInternal(belowThreshold, timestampNs); } + @Override + public String getName() { + return mSensor != null ? mSensor.getName() : null; + } + + @Override + public String getType() { + return mSensor != null ? mSensor.getStringType() : null; + } @Override public String toString() { @@ -211,7 +224,12 @@ class ThresholdSensorImpl implements ThresholdSensor { } } - static class Builder { + /** + * Use to build a ThresholdSensor. Should only be used once per sensor built, since + * parameters are not reset after calls to build(). For ease of retrievingnew Builders, use + * {@link BuilderFactory}. + */ + public static class Builder { private final Resources mResources; private final AsyncSensorManager mSensorManager; private final Execution mExecution; @@ -318,7 +336,7 @@ class ThresholdSensorImpl implements ThresholdSensor { @VisibleForTesting Sensor findSensorByType(String sensorType, boolean requireWakeUp) { - if (sensorType.isEmpty()) { + if (TextUtils.isEmpty(sensorType)) { return null; } @@ -336,4 +354,29 @@ class ThresholdSensorImpl implements ThresholdSensor { return sensor; } } + + /** + * Factory that creates a new ThresholdSensorImpl.Builder. In general, Builders should not be + * reused after creating a ThresholdSensor or else there may be default threshold and sensor + * values set from the previous built sensor. + */ + public static class BuilderFactory { + private final Resources mResources; + private final AsyncSensorManager mSensorManager; + private final Execution mExecution; + + @Inject + BuilderFactory( + @Main Resources resources, + AsyncSensorManager sensorManager, + Execution execution) { + mResources = resources; + mSensorManager = sensorManager; + mExecution = execution; + } + + ThresholdSensorImpl.Builder createBuilder() { + return new Builder(mResources, mSensorManager, mExecution); + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java index f420a85c8bf6..ff263109d555 100644 --- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java +++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java @@ -28,7 +28,6 @@ import com.android.internal.logging.UiEventLogger; import com.android.internal.statusbar.IStatusBarService; import com.android.systemui.dagger.WMComponent; import com.android.systemui.dagger.WMSingleton; -import com.android.wm.shell.FullscreenTaskListener; import com.android.wm.shell.RootTaskDisplayAreaOrganizer; import com.android.wm.shell.ShellCommandHandler; import com.android.wm.shell.ShellCommandHandlerImpl; @@ -57,6 +56,8 @@ import com.android.wm.shell.common.annotations.ShellMainThread; import com.android.wm.shell.common.annotations.ShellSplashscreenThread; import com.android.wm.shell.draganddrop.DragAndDropController; import com.android.wm.shell.freeform.FreeformTaskListener; +import com.android.wm.shell.fullscreen.FullscreenTaskListener; +import com.android.wm.shell.fullscreen.FullscreenUnfoldController; import com.android.wm.shell.hidedisplaycutout.HideDisplayCutout; import com.android.wm.shell.hidedisplaycutout.HideDisplayCutoutController; import com.android.wm.shell.legacysplitscreen.LegacySplitScreen; @@ -79,6 +80,7 @@ import com.android.wm.shell.tasksurfacehelper.TaskSurfaceHelper; import com.android.wm.shell.tasksurfacehelper.TaskSurfaceHelperController; import com.android.wm.shell.transition.ShellTransitions; import com.android.wm.shell.transition.Transitions; +import com.android.wm.shell.unfold.ShellUnfoldProgressProvider; import java.util.Optional; @@ -218,8 +220,28 @@ public abstract class WMShellBaseModule { @WMSingleton @Provides - static FullscreenTaskListener provideFullscreenTaskListener(SyncTransactionQueue syncQueue) { - return new FullscreenTaskListener(syncQueue); + static FullscreenTaskListener provideFullscreenTaskListener( + SyncTransactionQueue syncQueue, Optional<FullscreenUnfoldController> controller) { + return new FullscreenTaskListener(syncQueue, controller); + } + + // + // Unfold transition + // + + @WMSingleton + @Provides + static Optional<FullscreenUnfoldController> provideFullscreenUnfoldController( + Context context, + Optional<ShellUnfoldProgressProvider> progressProvider, + RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer, + DisplayInsetsController displayInsetsController, + @ShellMainThread ShellExecutor mainExecutor + ) { + return progressProvider.map(shellUnfoldTransitionProgressProvider -> + new FullscreenUnfoldController(context, mainExecutor, + shellUnfoldTransitionProgressProvider, rootTaskDisplayAreaOrganizer, + displayInsetsController)); } // @@ -474,6 +496,7 @@ public abstract class WMShellBaseModule { Optional<AppPairsController> appPairsOptional, Optional<PipTouchHandler> pipTouchHandlerOptional, FullscreenTaskListener fullscreenTaskListener, + Optional<FullscreenUnfoldController> appUnfoldTransitionController, Optional<Optional<FreeformTaskListener>> freeformTaskListener, Transitions transitions, StartingWindowController startingWindow, @@ -489,6 +512,7 @@ public abstract class WMShellBaseModule { appPairsOptional, pipTouchHandlerOptional, fullscreenTaskListener, + appUnfoldTransitionController, freeformTaskListener, transitions, startingWindow, diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java index 83c2a9b1be33..a7c5ad2e3716 100644 --- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java +++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java @@ -126,9 +126,10 @@ public class WMShellModule { static AppPairsController provideAppPairs(ShellTaskOrganizer shellTaskOrganizer, SyncTransactionQueue syncQueue, DisplayController displayController, @ShellMainThread ShellExecutor mainExecutor, - DisplayImeController displayImeController) { + DisplayImeController displayImeController, + DisplayInsetsController displayInsetsController) { return new AppPairsController(shellTaskOrganizer, syncQueue, displayController, - mainExecutor, displayImeController); + mainExecutor, displayImeController, displayInsetsController); } // diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java index ce02b8339422..e4336fe07dbb 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java @@ -97,6 +97,7 @@ public class KeyguardClockSwitchTest extends SysuiTestCase { mLargeClockFrame = mKeyguardClockSwitch.findViewById(R.id.lockscreen_clock_view_large); mLargeClockView = mKeyguardClockSwitch.findViewById(R.id.animatable_clock_view_large); mBigClock = new TextClock(getContext()); + mKeyguardClockSwitch.mChildrenAreLaidOut = true; MockitoAnnotations.initMocks(this); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt index f2f0029708ed..2c4808a4b84f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt @@ -21,11 +21,12 @@ import android.hardware.biometrics.BiometricSourceType import android.testing.AndroidTestingRunner import android.testing.TestableLooper.RunWithLooper import androidx.test.filters.SmallTest +import com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession import com.android.keyguard.KeyguardUpdateMonitor import com.android.keyguard.KeyguardUpdateMonitorCallback import com.android.systemui.SysuiTestCase -import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.keyguard.WakefulnessLifecycle +import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.statusbar.LightRevealScrim import com.android.systemui.statusbar.NotificationShadeWindowController import com.android.systemui.statusbar.commandline.CommandRegistry @@ -34,6 +35,8 @@ import com.android.systemui.statusbar.phone.KeyguardBypassController import com.android.systemui.statusbar.phone.StatusBar import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.statusbar.policy.KeyguardStateController +import com.android.systemui.util.leak.RotationUtils +import org.junit.After import org.junit.Assert.assertFalse import org.junit.Assert.assertTrue import org.junit.Before @@ -48,12 +51,15 @@ import org.mockito.Mockito.never import org.mockito.Mockito.reset import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations - +import org.mockito.MockitoSession +import org.mockito.quality.Strictness import javax.inject.Provider @SmallTest @RunWith(AndroidTestingRunner::class) class AuthRippleControllerTest : SysuiTestCase() { + private lateinit var staticMockSession: MockitoSession + private lateinit var controller: AuthRippleController @Mock private lateinit var statusBar: StatusBar @Mock private lateinit var rippleView: AuthRippleView @@ -74,6 +80,12 @@ class AuthRippleControllerTest : SysuiTestCase() { @Before fun setUp() { MockitoAnnotations.initMocks(this) + staticMockSession = mockitoSession() + .mockStatic(RotationUtils::class.java) + .strictness(Strictness.LENIENT) + .startMocking() + + `when`(RotationUtils.getRotation(context)).thenReturn(RotationUtils.ROTATION_NONE) `when`(udfpsControllerProvider.get()).thenReturn(udfpsController) controller = AuthRippleController( @@ -96,6 +108,11 @@ class AuthRippleControllerTest : SysuiTestCase() { `when`(statusBar.lightRevealScrim).thenReturn(lightRevealScrim) } + @After + fun tearDown() { + staticMockSession.finishMocking() + } + @Test fun testFingerprintTrigger_Ripple() { // GIVEN fp exists, keyguard is visible, user doesn't need strong auth diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java index d6226aa53f67..866791cc24cb 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java @@ -40,7 +40,7 @@ public class DozeConfigurationUtil { when(params.doubleTapReportsTouchCoordinates()).thenReturn(false); when(params.getDisplayNeedsBlanking()).thenReturn(false); when(params.getSelectivelyRegisterSensorsUsingProx()).thenReturn(false); - when(params.singleTapUsesProx()).thenReturn(true); + when(params.singleTapUsesProx(anyInt())).thenReturn(true); when(params.longPressUsesProx()).thenReturn(true); when(params.getQuickPickupAodDuration()).thenReturn(500); @@ -61,14 +61,13 @@ public class DozeConfigurationUtil { when(config.getWakeLockScreenDebounce()).thenReturn(0L); when(config.doubleTapSensorType()).thenReturn(null); - when(config.tapSensorType()).thenReturn(null); when(config.longPressSensorType()).thenReturn(null); when(config.udfpsLongPressSensorType()).thenReturn(null); when(config.quickPickupSensorType()).thenReturn(null); when(config.tapGestureEnabled(anyInt())).thenReturn(true); when(config.tapSensorAvailable()).thenReturn(true); - when(config.tapSensorType()).thenReturn(FakeSensorManager.TAP_SENSOR_TYPE); + when(config.tapSensorType(anyInt())).thenReturn(FakeSensorManager.TAP_SENSOR_TYPE); when(config.dozePickupSensorAvailable()).thenReturn(false); when(config.wakeScreenGestureAvailable()).thenReturn(false); diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java index 5c4c27ccc4ca..42e34c81a790 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java @@ -19,6 +19,7 @@ package com.android.systemui.doze; import static com.android.systemui.doze.DozeLog.REASON_SENSOR_TAP; import static com.android.systemui.plugins.SensorManagerPlugin.Sensor.TYPE_WAKE_LOCK_SCREEN; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; @@ -47,6 +48,7 @@ import com.android.systemui.biometrics.AuthController; import com.android.systemui.doze.DozeSensors.TriggerSensor; import com.android.systemui.plugins.SensorManagerPlugin; import com.android.systemui.statusbar.phone.DozeParameters; +import com.android.systemui.statusbar.policy.DevicePostureController; import com.android.systemui.util.sensors.AsyncSensorManager; import com.android.systemui.util.sensors.ProximitySensor; import com.android.systemui.util.settings.FakeSettings; @@ -58,6 +60,11 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; import java.util.function.Consumer; @RunWith(AndroidTestingRunner.class) @@ -85,6 +92,8 @@ public class DozeSensorsTest extends SysuiTestCase { private AuthController mAuthController; @Mock private ProximitySensor mProximitySensor; + private @DevicePostureController.DevicePostureInt int mDevicePosture = + DevicePostureController.DEVICE_POSTURE_UNKNOWN; private FakeSettings mFakeSettings = new FakeSettings(); private SensorManagerPlugin.SensorEventListener mWakeLockScreenListener; private TestableLooper mTestableLooper; @@ -101,6 +110,7 @@ public class DozeSensorsTest extends SysuiTestCase { ((Runnable) invocation.getArgument(0)).run(); return null; }).when(mWakeLock).wrap(any(Runnable.class)); + mDevicePosture = DevicePostureController.DEVICE_POSTURE_UNKNOWN; mDozeSensors = new TestableDozeSensors(); } @@ -157,7 +167,7 @@ public class DozeSensorsTest extends SysuiTestCase { // GIVEN we only should register sensors using prox when not in low-powered mode / off // and the single tap sensor uses the proximity sensor when(mDozeParameters.getSelectivelyRegisterSensorsUsingProx()).thenReturn(true); - when(mDozeParameters.singleTapUsesProx()).thenReturn(true); + when(mDozeParameters.singleTapUsesProx(anyInt())).thenReturn(true); TestableDozeSensors dozeSensors = new TestableDozeSensors(); // THEN on initialization, the tap sensor isn't requested @@ -258,12 +268,55 @@ public class DozeSensorsTest extends SysuiTestCase { assertTrue(triggerSensor.mRegistered); } + @Test + public void testPostureOpen_registersCorrectTapGesture() { + // GIVEN device posture open + mDevicePosture = DevicePostureController.DEVICE_POSTURE_OPENED; + + // WHEN DozeSensors are initialized + new TestableDozeSensors(); + + // THEN we use the posture to determine which tap sensor to use + verify(mAmbientDisplayConfiguration).tapSensorType(eq(mDevicePosture)); + } + + @Test + public void testFindSensor() throws Exception { + // GIVEN a prox sensor + List<Sensor> sensors = new ArrayList<>(); + Sensor proxSensor = + createSensor(Sensor.TYPE_PROXIMITY, Sensor.STRING_TYPE_PROXIMITY); + sensors.add(proxSensor); + + when(mSensorManager.getSensorList(anyInt())).thenReturn(sensors); + + // WHEN we try to find the prox sensor with the same type and name + // THEN we find the added sensor + assertEquals( + proxSensor, + DozeSensors.findSensor( + mSensorManager, + Sensor.STRING_TYPE_PROXIMITY, + proxSensor.getName())); + + // WHEN we try to find a prox sensor with a different name + // THEN no sensor is found + assertEquals( + null, + DozeSensors.findSensor( + mSensorManager, + Sensor.STRING_TYPE_PROXIMITY, + "some other name")); + } + + private class TestableDozeSensors extends DozeSensors { TestableDozeSensors() { super(getContext(), mSensorManager, mDozeParameters, mAmbientDisplayConfiguration, mWakeLock, mCallback, mProxCallback, mDozeLog, - mProximitySensor, mFakeSettings, mAuthController); + mProximitySensor, mFakeSettings, mAuthController, + mDevicePosture); for (TriggerSensor sensor : mSensors) { if (sensor instanceof PluginSensor && ((PluginSensor) sensor).mPluginSensor.getType() @@ -288,4 +341,23 @@ public class DozeSensorsTest extends SysuiTestCase { mDozeLog); } } + + public static void setSensorType(Sensor sensor, int type, String strType) throws Exception { + Method setter = Sensor.class.getDeclaredMethod("setType", Integer.TYPE); + setter.setAccessible(true); + setter.invoke(sensor, type); + if (strType != null) { + Field f = sensor.getClass().getDeclaredField("mStringType"); + f.setAccessible(true); + f.set(sensor, strType); + } + } + + public static Sensor createSensor(int type, String strType) throws Exception { + Constructor<Sensor> constr = Sensor.class.getDeclaredConstructor(); + constr.setAccessible(true); + Sensor sensor = constr.newInstance(); + setSensorType(sensor, type, strType); + return sensor; + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java index 9577c7a2d6fa..31fa3f841b19 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java @@ -45,6 +45,7 @@ import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.dock.DockManager; import com.android.systemui.doze.DozeTriggers.DozingUpdateUiEvent; import com.android.systemui.statusbar.phone.DozeParameters; +import com.android.systemui.statusbar.policy.DevicePostureController; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.util.concurrency.FakeExecutor; import com.android.systemui.util.concurrency.FakeThreadFactory; @@ -52,7 +53,8 @@ import com.android.systemui.util.sensors.AsyncSensorManager; import com.android.systemui.util.sensors.FakeProximitySensor; import com.android.systemui.util.sensors.FakeSensorManager; import com.android.systemui.util.sensors.FakeThresholdSensor; -import com.android.systemui.util.sensors.ProximitySensor; +import com.android.systemui.util.sensors.ProximityCheck; +import com.android.systemui.util.sensors.ThresholdSensorEvent; import com.android.systemui.util.settings.FakeSettings; import com.android.systemui.util.time.FakeSystemClock; import com.android.systemui.util.wakelock.WakeLock; @@ -79,13 +81,15 @@ public class DozeTriggersTest extends SysuiTestCase { @Mock private DockManager mDockManager; @Mock - private ProximitySensor.ProximityCheck mProximityCheck; + private ProximityCheck mProximityCheck; @Mock private AuthController mAuthController; @Mock private UiEventLogger mUiEventLogger; @Mock private KeyguardStateController mKeyguardStateController; + @Mock + private DevicePostureController mDevicePostureController; private DozeTriggers mTriggers; private FakeSensorManager mSensors; @@ -117,7 +121,8 @@ public class DozeTriggersTest extends SysuiTestCase { mTriggers = new DozeTriggers(mContext, mHost, config, dozeParameters, asyncSensorManager, wakeLock, mDockManager, mProximitySensor, mProximityCheck, mock(DozeLog.class), mBroadcastDispatcher, new FakeSettings(), - mAuthController, mExecutor, mUiEventLogger, mKeyguardStateController); + mAuthController, mExecutor, mUiEventLogger, mKeyguardStateController, + mDevicePostureController); mTriggers.setDozeMachine(mMachine); waitForSensorManager(); } @@ -132,14 +137,14 @@ public class DozeTriggersTest extends SysuiTestCase { mTriggers.transitionTo(DozeMachine.State.INITIALIZED, DozeMachine.State.DOZE); clearInvocations(mMachine); - mProximitySensor.setLastEvent(new ProximitySensor.ThresholdSensorEvent(true, 1)); + mProximitySensor.setLastEvent(new ThresholdSensorEvent(true, 1)); captor.getValue().onNotificationAlerted(null /* pulseSuppressedListener */); mProximitySensor.alertListeners(); verify(mMachine, never()).requestState(any()); verify(mMachine, never()).requestPulse(anyInt()); - mProximitySensor.setLastEvent(new ProximitySensor.ThresholdSensorEvent(false, 2)); + mProximitySensor.setLastEvent(new ThresholdSensorEvent(false, 2)); mProximitySensor.alertListeners(); waitForSensorManager(); captor.getValue().onNotificationAlerted(null /* pulseSuppressedListener */); diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/carrier/QSCarrierGroupControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/carrier/QSCarrierGroupControllerTest.java index a1b72104509b..8ae7100e2e60 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/carrier/QSCarrierGroupControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/carrier/QSCarrierGroupControllerTest.java @@ -39,8 +39,8 @@ import androidx.test.filters.SmallTest; import com.android.keyguard.CarrierTextManager; import com.android.systemui.flags.FeatureFlags; import com.android.systemui.plugins.ActivityStarter; -import com.android.systemui.statusbar.policy.NetworkController; -import com.android.systemui.statusbar.policy.NetworkController.MobileDataIndicators; +import com.android.systemui.statusbar.connectivity.NetworkController; +import com.android.systemui.statusbar.connectivity.NetworkController.MobileDataIndicators; import com.android.systemui.util.CarrierConfigTracker; import com.android.systemui.utils.leaks.LeakCheckedTest; import com.android.systemui.utils.os.FakeHandler; 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 e939411e4a2a..f0bd06571eb9 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 @@ -43,12 +43,12 @@ import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSTileHost; import com.android.systemui.qs.logging.QSLogger; +import com.android.systemui.statusbar.connectivity.NetworkController; +import com.android.systemui.statusbar.connectivity.NetworkController.WifiIndicators; import com.android.systemui.statusbar.policy.CastController; import com.android.systemui.statusbar.policy.CastController.CastDevice; import com.android.systemui.statusbar.policy.HotspotController; import com.android.systemui.statusbar.policy.KeyguardStateController; -import com.android.systemui.statusbar.policy.NetworkController; -import com.android.systemui.statusbar.policy.NetworkController.WifiIndicators; import org.junit.Before; import org.junit.Test; diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java index f9d5be6c4807..fe328395b89f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java @@ -48,9 +48,9 @@ import com.android.systemui.SysuiTestCase; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.plugins.ActivityStarter; +import com.android.systemui.statusbar.connectivity.NetworkController; +import com.android.systemui.statusbar.connectivity.NetworkController.AccessPointController; import com.android.systemui.statusbar.policy.KeyguardStateController; -import com.android.systemui.statusbar.policy.NetworkController; -import com.android.systemui.statusbar.policy.NetworkController.AccessPointController; import com.android.systemui.toast.SystemUIToast; import com.android.systemui.toast.ToastFactory; import com.android.systemui.util.CarrierConfigTracker; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/AccessPointControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/AccessPointControllerImplTest.kt index 4068f93f5ee3..7896a26badbe 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/AccessPointControllerImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/AccessPointControllerImplTest.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.systemui.statusbar.policy +package com.android.systemui.statusbar.connectivity import android.os.UserManager import android.test.suitebuilder.annotation.SmallTest diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/CallbackHandlerTest.java index 3c55df934f76..11a53c55c024 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/CallbackHandlerTest.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.android.systemui.statusbar.policy; +package com.android.systemui.statusbar.connectivity; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertTrue; @@ -28,11 +28,11 @@ import androidx.test.runner.AndroidJUnit4; import com.android.settingslib.mobile.TelephonyIcons; import com.android.systemui.SysuiTestCase; -import com.android.systemui.statusbar.policy.NetworkController.EmergencyListener; -import com.android.systemui.statusbar.policy.NetworkController.IconState; -import com.android.systemui.statusbar.policy.NetworkController.MobileDataIndicators; -import com.android.systemui.statusbar.policy.NetworkController.SignalCallback; -import com.android.systemui.statusbar.policy.NetworkController.WifiIndicators; +import com.android.systemui.statusbar.connectivity.NetworkController.EmergencyListener; +import com.android.systemui.statusbar.connectivity.NetworkController.IconState; +import com.android.systemui.statusbar.connectivity.NetworkController.MobileDataIndicators; +import com.android.systemui.statusbar.connectivity.NetworkController.SignalCallback; +import com.android.systemui.statusbar.connectivity.NetworkController.WifiIndicators; import com.android.systemui.tests.R; import org.junit.Before; @@ -182,7 +182,8 @@ public class CallbackHandlerTest extends SysuiTestCase { @Test public void testSignalCallback_setIsAirplaneMode() { - IconState state = new IconState(true, R.drawable.stat_sys_airplane_mode, "Test Description"); + IconState state = + new IconState(true, R.drawable.stat_sys_airplane_mode, "Test Description"); mHandler.setIsAirplaneMode(state); waitForCallbacks(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java index c488ee95aa3c..67cab7413f1f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.systemui.statusbar.policy; +package com.android.systemui.statusbar.connectivity; import static android.telephony.AccessNetworkConstants.TRANSPORT_TYPE_WWAN; import static android.telephony.NetworkRegistrationInfo.DOMAIN_PS; @@ -72,10 +72,11 @@ import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.demomode.DemoModeController; import com.android.systemui.dump.DumpManager; import com.android.systemui.flags.FeatureFlags; +import com.android.systemui.statusbar.connectivity.NetworkController.IconState; +import com.android.systemui.statusbar.connectivity.NetworkController.MobileDataIndicators; +import com.android.systemui.statusbar.connectivity.NetworkController.SignalCallback; +import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener; -import com.android.systemui.statusbar.policy.NetworkController.IconState; -import com.android.systemui.statusbar.policy.NetworkController.MobileDataIndicators; -import com.android.systemui.statusbar.policy.NetworkController.SignalCallback; import com.android.systemui.telephony.TelephonyListenerManager; import com.android.systemui.util.CarrierConfigTracker; import com.android.systemui.util.concurrency.FakeExecutor; @@ -268,7 +269,7 @@ public class NetworkControllerBaseTest extends SysuiTestCase { setSubscriptions(mSubId); mMobileSignalController = mNetworkController.mMobileSignalControllers.get(mSubId); ArgumentCaptor<ConnectivityManager.NetworkCallback> callbackArg = - ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class); + ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class); verify(mMockCm, atLeastOnce()) .registerDefaultNetworkCallback(callbackArg.capture(), isA(Handler.class)); int captureSize = callbackArg.getAllValues().size(); @@ -404,7 +405,7 @@ public class NetworkControllerBaseTest extends SysuiTestCase { } private static void setConnectivityCommon(NetworkCapabilities.Builder builder, - int networkType, boolean validated, boolean isConnected){ + int networkType, boolean validated, boolean isConnected) { // TODO: Separate out into several NetworkCapabilities. if (isConnected) { builder.addTransportType(networkType); @@ -538,7 +539,7 @@ public class NetworkControllerBaseTest extends SysuiTestCase { } protected void verifyLastMobileDataIndicators(boolean visible, int icon, int typeIcon, - boolean roaming, boolean inet) { + boolean roaming, boolean inet) { ArgumentCaptor<MobileDataIndicators> indicatorsArg = ArgumentCaptor.forClass(MobileDataIndicators.class); @@ -646,7 +647,7 @@ public class NetworkControllerBaseTest extends SysuiTestCase { } protected void assertNetworkNameEquals(String expected) { - assertEquals("Network name", expected, mMobileSignalController.getState().networkName); + assertEquals("Network name", expected, mMobileSignalController.getState().networkName); } protected void assertDataNetworkNameEquals(String expected) { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerDataTest.java index 3433a14f54e7..00dedd961074 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerDataTest.java @@ -1,4 +1,20 @@ -package com.android.systemui.statusbar.policy; +/* + * 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.connectivity; import static android.telephony.AccessNetworkConstants.TRANSPORT_TYPE_WWAN; import static android.telephony.NetworkRegistrationInfo.DOMAIN_PS; @@ -22,6 +38,7 @@ import android.testing.TestableLooper.RunWithLooper; import com.android.settingslib.mobile.TelephonyIcons; import com.android.settingslib.net.DataUsageController; import com.android.systemui.dump.DumpManager; +import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.util.CarrierConfigTracker; import org.junit.Test; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerEthernetTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerEthernetTest.java index 6aab9c762a95..675d755ad3e3 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerEthernetTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerEthernetTest.java @@ -1,4 +1,20 @@ -package com.android.systemui.statusbar.policy; +/* + * 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.connectivity; import static junit.framework.Assert.assertEquals; @@ -7,7 +23,7 @@ import android.test.suitebuilder.annotation.SmallTest; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper.RunWithLooper; -import com.android.systemui.statusbar.policy.NetworkController.IconState; +import com.android.systemui.statusbar.connectivity.NetworkController.IconState; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerSignalTest.java index 4ff13011567b..73eddd166f88 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerSignalTest.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.android.systemui.statusbar.policy; +package com.android.systemui.statusbar.connectivity; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; @@ -42,6 +42,7 @@ import com.android.settingslib.mobile.TelephonyIcons; import com.android.settingslib.net.DataUsageController; import com.android.systemui.R; import com.android.systemui.dump.DumpManager; +import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.util.CarrierConfigTracker; import org.junit.Test; @@ -280,7 +281,7 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest { // TODO: Put this somewhere else, maybe in its own file. @Test public void testHasCorrectMobileControllers() { - int[] testSubscriptions = new int[] { 1, 5, 3 }; + int[] testSubscriptions = new int[]{1, 5, 3}; int notTestSubscription = 0; MobileSignalController mobileSignalController = Mockito.mock(MobileSignalController.class); @@ -312,8 +313,8 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest { // We will not add one subscription to make sure it's controller gets removed. int indexToSkipSubscription = 1; - int[] testSubscriptions = new int[] { 1, 5, 3 }; - MobileSignalController[] mobileSignalControllers = new MobileSignalController[] { + int[] testSubscriptions = new int[]{1, 5, 3}; + MobileSignalController[] mobileSignalControllers = new MobileSignalController[]{ Mockito.mock(MobileSignalController.class), Mockito.mock(MobileSignalController.class), Mockito.mock(MobileSignalController.class), @@ -401,24 +402,24 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest { @Test public void testOnReceive_stringsUpdatedAction_bothFalse() { Intent intent = createStringsUpdatedIntent(false /* showSpn */, - "Irrelevant" /* spn */, - false /* showPlmn */, - "Irrelevant" /* plmn */); + "Irrelevant" /* spn */, + false /* showPlmn */, + "Irrelevant" /* plmn */); mNetworkController.onReceive(mContext, intent); String defaultNetworkName = mMobileSignalController .getTextIfExists( - com.android.internal.R.string.lockscreen_carrier_default).toString(); + com.android.internal.R.string.lockscreen_carrier_default).toString(); assertNetworkNameEquals(defaultNetworkName); } @Test public void testOnReceive_stringsUpdatedAction_bothTrueAndNull() { Intent intent = createStringsUpdatedIntent(true /* showSpn */, - null /* spn */, - true /* showPlmn */, - null /* plmn */); + null /* spn */, + true /* showPlmn */, + null /* plmn */); mNetworkController.onReceive(mContext, intent); @@ -433,15 +434,15 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest { String plmn = "Test2"; Intent intent = createStringsUpdatedIntent(true /* showSpn */, - spn /* spn */, - true /* showPlmn */, - plmn /* plmn */); + spn /* spn */, + true /* showPlmn */, + plmn /* plmn */); mNetworkController.onReceive(mContext, intent); assertNetworkNameEquals(plmn + mMobileSignalController.getTextIfExists( - R.string.status_bar_network_name_separator).toString() + R.string.status_bar_network_name_separator).toString() + spn); } @@ -477,145 +478,149 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest { @Test public void testOnUpdateDataActivity_dataOut() { - setupDefaultSignal(); + setupDefaultSignal(); - updateDataActivity(TelephonyManager.DATA_ACTIVITY_OUT); + updateDataActivity(TelephonyManager.DATA_ACTIVITY_OUT); - verifyLastQsMobileDataIndicators(true /* visible */, - DEFAULT_LEVEL /* icon */, - DEFAULT_QS_ICON /* typeIcon */, - false /* dataIn */, - true /* dataOut */); + verifyLastQsMobileDataIndicators(true /* visible */, + DEFAULT_LEVEL /* icon */, + DEFAULT_QS_ICON /* typeIcon */, + false /* dataIn */, + true /* dataOut */); } @Test public void testOnUpdateDataActivity_dataInOut() { - setupDefaultSignal(); + setupDefaultSignal(); - updateDataActivity(TelephonyManager.DATA_ACTIVITY_INOUT); + updateDataActivity(TelephonyManager.DATA_ACTIVITY_INOUT); - verifyLastQsMobileDataIndicators(true /* visible */, - DEFAULT_LEVEL /* icon */, - DEFAULT_QS_ICON /* typeIcon */, - true /* dataIn */, - true /* dataOut */); + verifyLastQsMobileDataIndicators(true /* visible */, + DEFAULT_LEVEL /* icon */, + DEFAULT_QS_ICON /* typeIcon */, + true /* dataIn */, + true /* dataOut */); } @Test public void testOnUpdateDataActivity_dataActivityNone() { - setupDefaultSignal(); + setupDefaultSignal(); - updateDataActivity(TelephonyManager.DATA_ACTIVITY_NONE); + updateDataActivity(TelephonyManager.DATA_ACTIVITY_NONE); - verifyLastQsMobileDataIndicators(true /* visible */, - DEFAULT_LEVEL /* icon */, - DEFAULT_QS_ICON /* typeIcon */, - false /* dataIn */, - false /* dataOut */); + verifyLastQsMobileDataIndicators(true /* visible */, + DEFAULT_LEVEL /* icon */, + DEFAULT_QS_ICON /* typeIcon */, + false /* dataIn */, + false /* dataOut */); } @Test public void testCarrierNetworkChange_carrierNetworkChange() { - int strength = SignalStrength.SIGNAL_STRENGTH_GREAT; + int strength = SignalStrength.SIGNAL_STRENGTH_GREAT; - setupDefaultSignal(); - setLevel(strength); + setupDefaultSignal(); + setLevel(strength); - // Verify baseline - verifyLastMobileDataIndicators(true /* visible */, - strength /* strengthIcon */, - DEFAULT_ICON /* typeIcon */); + // Verify baseline + verifyLastMobileDataIndicators(true /* visible */, + strength /* strengthIcon */, + DEFAULT_ICON /* typeIcon */); - // API call is made - setCarrierNetworkChange(true /* enabled */); + // API call is made + setCarrierNetworkChange(true /* enabled */); - // Carrier network change is true, show special indicator - verifyLastMobileDataIndicators(true /* visible */, - SignalDrawable.getCarrierChangeState(CellSignalStrength.getNumSignalStrengthLevels()), - 0 /* typeIcon */); + // Carrier network change is true, show special indicator + verifyLastMobileDataIndicators(true /* visible */, + SignalDrawable.getCarrierChangeState( + CellSignalStrength.getNumSignalStrengthLevels()), + 0 /* typeIcon */); - // Revert back - setCarrierNetworkChange(false /* enabled */); + // Revert back + setCarrierNetworkChange(false /* enabled */); - // Verify back in previous state - verifyLastMobileDataIndicators(true /* visible */, - strength /* strengthIcon */, - DEFAULT_ICON /* typeIcon */); + // Verify back in previous state + verifyLastMobileDataIndicators(true /* visible */, + strength /* strengthIcon */, + DEFAULT_ICON /* typeIcon */); } @Test public void testCarrierNetworkChange_roamingBeforeNetworkChange() { - int strength = SignalStrength.SIGNAL_STRENGTH_GREAT; + int strength = SignalStrength.SIGNAL_STRENGTH_GREAT; - setupDefaultSignal(); - setLevel(strength); - setGsmRoaming(true); + setupDefaultSignal(); + setLevel(strength); + setGsmRoaming(true); - // Verify baseline - verifyLastMobileDataIndicators(true /* visible */, - strength /* strengthIcon */, - DEFAULT_ICON /* typeIcon */, - true /* roaming */); + // Verify baseline + verifyLastMobileDataIndicators(true /* visible */, + strength /* strengthIcon */, + DEFAULT_ICON /* typeIcon */, + true /* roaming */); - // API call is made - setCarrierNetworkChange(true /* enabled */); + // API call is made + setCarrierNetworkChange(true /* enabled */); - // Carrier network change is true, show special indicator, no roaming. - verifyLastMobileDataIndicators(true /* visible */, - SignalDrawable.getCarrierChangeState(CellSignalStrength.getNumSignalStrengthLevels()), - 0 /* typeIcon */, - false /* roaming */); + // Carrier network change is true, show special indicator, no roaming. + verifyLastMobileDataIndicators(true /* visible */, + SignalDrawable.getCarrierChangeState( + CellSignalStrength.getNumSignalStrengthLevels()), + 0 /* typeIcon */, + false /* roaming */); - // Revert back - setCarrierNetworkChange(false /* enabled */); + // Revert back + setCarrierNetworkChange(false /* enabled */); - // Verify back in previous state - verifyLastMobileDataIndicators(true /* visible */, - strength /* strengthIcon */, - DEFAULT_ICON /* typeIcon */, - true /* roaming */); + // Verify back in previous state + verifyLastMobileDataIndicators(true /* visible */, + strength /* strengthIcon */, + DEFAULT_ICON /* typeIcon */, + true /* roaming */); } @Test public void testCarrierNetworkChange_roamingAfterNetworkChange() { - int strength = SignalStrength.SIGNAL_STRENGTH_GREAT; - - setupDefaultSignal(); - setLevel(strength); - - // Verify baseline - verifyLastMobileDataIndicators(true /* visible */, - strength /* strengthIcon */, - DEFAULT_ICON /* typeIcon */, - false /* roaming */); - - // API call is made - setCarrierNetworkChange(true /* enabled */); - - // Carrier network change is true, show special indicator, no roaming. - verifyLastMobileDataIndicators(true /* visible */, - SignalDrawable.getCarrierChangeState(CellSignalStrength.getNumSignalStrengthLevels()), - 0 /* typeIcon */, - false /* roaming */); - - setGsmRoaming(true); - - // Roaming should not show. - verifyLastMobileDataIndicators(true /* visible */, - SignalDrawable.getCarrierChangeState(CellSignalStrength.getNumSignalStrengthLevels()), - 0 /* typeIcon */, - false /* roaming */); - - // Revert back - setCarrierNetworkChange(false /* enabled */); - - // Verify back in previous state - verifyLastMobileDataIndicators(true /* visible */, - strength /* strengthIcon */, - DEFAULT_ICON /* typeIcon */, - true /* roaming */); + int strength = SignalStrength.SIGNAL_STRENGTH_GREAT; + + setupDefaultSignal(); + setLevel(strength); + + // Verify baseline + verifyLastMobileDataIndicators(true /* visible */, + strength /* strengthIcon */, + DEFAULT_ICON /* typeIcon */, + false /* roaming */); + + // API call is made + setCarrierNetworkChange(true /* enabled */); + + // Carrier network change is true, show special indicator, no roaming. + verifyLastMobileDataIndicators(true /* visible */, + SignalDrawable.getCarrierChangeState( + CellSignalStrength.getNumSignalStrengthLevels()), + 0 /* typeIcon */, + false /* roaming */); + + setGsmRoaming(true); + + // Roaming should not show. + verifyLastMobileDataIndicators(true /* visible */, + SignalDrawable.getCarrierChangeState( + CellSignalStrength.getNumSignalStrengthLevels()), + 0 /* typeIcon */, + false /* roaming */); + + // Revert back + setCarrierNetworkChange(false /* enabled */); + + // Verify back in previous state + verifyLastMobileDataIndicators(true /* visible */, + strength /* strengthIcon */, + DEFAULT_ICON /* typeIcon */, + true /* roaming */); } private void verifyEmergencyOnly(boolean isEmergencyOnly) { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerWifiTest.java index 4a5770d12239..ffeaf207942b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerWifiTest.java @@ -1,10 +1,25 @@ -package com.android.systemui.statusbar.policy; +/* + * 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.connectivity; import static junit.framework.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.Matchers.anyLong; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -21,7 +36,7 @@ import android.testing.AndroidTestingRunner; import android.testing.TestableLooper.RunWithLooper; import com.android.settingslib.mobile.TelephonyIcons; -import com.android.systemui.statusbar.policy.NetworkController.WifiIndicators; +import com.android.systemui.statusbar.connectivity.NetworkController.WifiIndicators; import org.junit.Before; import org.junit.Test; @@ -165,7 +180,7 @@ public class NetworkControllerWifiTest extends NetworkControllerBaseTest { } @Test - public void testWifiIconDisconnectedViaCallback(){ + public void testWifiIconDisconnectedViaCallback() { // Setup normal connection String testSsid = "Test SSID"; int testLevel = 2; @@ -183,7 +198,7 @@ public class NetworkControllerWifiTest extends NetworkControllerBaseTest { } @Test - public void testVpnWithUnderlyingWifi(){ + public void testVpnWithUnderlyingWifi() { String testSsid = "Test SSID"; int testLevel = 2; setWifiEnabled(true); @@ -299,7 +314,7 @@ public class NetworkControllerWifiTest extends NetworkControllerBaseTest { protected void setWifiLevel(int level) { float amountPerLevel = (MAX_RSSI - MIN_RSSI) / (WifiIcons.WIFI_LEVEL_COUNT - 1); - int rssi = (int)(MIN_RSSI + level * amountPerLevel); + int rssi = (int) (MIN_RSSI + level * amountPerLevel); // Put RSSI in the middle of the range. rssi += amountPerLevel / 2; when(mWifiInfo.getRssi()).thenReturn(rssi); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt index fd932803ff37..ee9c2b82c283 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt @@ -199,8 +199,9 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() { `when`(deviceProvisionedController.isDeviceProvisioned()).thenReturn(false) `when`(deviceProvisionedController.isCurrentUserSetup()).thenReturn(false) - // WHEN a connection attempt is made - controller.buildAndConnectView(fakeParent) + // WHEN a connection attempt is made and view is attached + val view = controller.buildAndConnectView(fakeParent) + controller.stateChangeListener.onViewAttachedToWindow(view) // THEN no session is created verify(smartspaceManager, never()).createSmartspaceSession(any()) diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java index 07ebaea8bdda..baed694e6fa0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java @@ -75,6 +75,7 @@ import com.android.systemui.statusbar.phone.ScrimController; import com.android.systemui.statusbar.phone.ShadeController; import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.policy.ConfigurationController; +import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.ZenModeController; import com.android.systemui.tuner.TunerService; @@ -99,6 +100,7 @@ public class NotificationStackScrollLayoutControllerTest extends SysuiTestCase { @Mock private HeadsUpManagerPhone mHeadsUpManager; @Mock private NotificationRoundnessManager mNotificationRoundnessManager; @Mock private TunerService mTunerService; + @Mock private DeviceProvisionedController mDeviceProvisionedController; @Mock private DynamicPrivacyController mDynamicPrivacyController; @Mock private ConfigurationController mConfigurationController; @Mock private NotificationStackScrollLayout mNotificationStackScrollLayout; @@ -152,6 +154,7 @@ public class NotificationStackScrollLayoutControllerTest extends SysuiTestCase { mHeadsUpManager, mNotificationRoundnessManager, mTunerService, + mDeviceProvisionedController, mDynamicPrivacyController, mConfigurationController, mSysuiStatusBarStateController, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java index 4e76b1695f0b..9f42fa4d2ae7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java @@ -280,6 +280,8 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { @Test public void testUpdateFooter_noNotifications() { setBarStateForTest(StatusBarState.SHADE); + mStackScroller.setCurrentUserSetup(true); + FooterView view = mock(FooterView.class); mStackScroller.setFooterView(view); mStackScroller.updateFooter(); @@ -289,6 +291,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { @Test public void testUpdateFooter_remoteInput() { setBarStateForTest(StatusBarState.SHADE); + mStackScroller.setCurrentUserSetup(true); ExpandableNotificationRow row = mock(ExpandableNotificationRow.class); when(row.canViewBeDismissed()).thenReturn(true); @@ -308,6 +311,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { @Test public void testUpdateFooter_oneClearableNotification() { setBarStateForTest(StatusBarState.SHADE); + mStackScroller.setCurrentUserSetup(true); when(mEmptyShadeView.getVisibility()).thenReturn(GONE); when(mStackScrollLayoutController.hasActiveClearableNotifications(ROWS_ALL)) @@ -321,8 +325,25 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { } @Test + public void testUpdateFooter_oneClearableNotification_beforeUserSetup() { + setBarStateForTest(StatusBarState.SHADE); + mStackScroller.setCurrentUserSetup(false); + + when(mEmptyShadeView.getVisibility()).thenReturn(GONE); + when(mStackScrollLayoutController.hasActiveClearableNotifications(ROWS_ALL)) + .thenReturn(true); + when(mStackScrollLayoutController.hasActiveNotifications()).thenReturn(true); + + FooterView view = mock(FooterView.class); + mStackScroller.setFooterView(view); + mStackScroller.updateFooter(); + verify(mStackScroller).updateFooterView(false, true, true); + } + + @Test public void testUpdateFooter_oneNonClearableNotification() { setBarStateForTest(StatusBarState.SHADE); + mStackScroller.setCurrentUserSetup(true); ExpandableNotificationRow row = mock(ExpandableNotificationRow.class); when(row.canViewBeDismissed()).thenReturn(false); @@ -341,6 +362,8 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { @Test public void testUpdateFooter_atEnd() { + mStackScroller.setCurrentUserSetup(true); + // add footer mStackScroller.inflateFooterView(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java index b08dbee687e6..f23f14801484 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java @@ -45,10 +45,10 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.CommandQueue; 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.ongoingcall.OngoingCallController; import com.android.systemui.statusbar.policy.KeyguardStateController; -import com.android.systemui.statusbar.policy.NetworkController; import org.junit.Before; import org.junit.Ignore; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java index f5fb98b4c2c7..f7423bb7951d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java @@ -156,8 +156,6 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { private KeyguardBottomAreaView mQsFrame; private KeyguardStatusView mKeyguardStatusView; @Mock - private ViewGroup mBigClockContainer; - @Mock private NotificationIconAreaController mNotificationAreaController; @Mock private HeadsUpManagerPhone mHeadsUpManager; @@ -347,7 +345,6 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { when(mKeyguardBottomArea.getLeftView()).thenReturn(mock(KeyguardAffordanceView.class)); when(mKeyguardBottomArea.getRightView()).thenReturn(mock(KeyguardAffordanceView.class)); when(mKeyguardBottomArea.animate()).thenReturn(mock(ViewPropertyAnimator.class)); - when(mView.findViewById(R.id.big_clock_container)).thenReturn(mBigClockContainer); when(mView.findViewById(R.id.qs_frame)).thenReturn(mQsFrame); when(mView.findViewById(R.id.keyguard_status_view)) .thenReturn(mock(KeyguardStatusView.class)); 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 fdda76df64d7..6868e1855c65 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 @@ -112,6 +112,7 @@ import com.android.systemui.statusbar.OperatorNameViewController; import com.android.systemui.statusbar.PulseExpansionHandler; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.StatusBarStateControllerImpl; +import com.android.systemui.statusbar.connectivity.NetworkController; import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler; import com.android.systemui.statusbar.notification.DynamicPrivacyController; import com.android.systemui.statusbar.notification.NotificationEntryManager; @@ -137,7 +138,6 @@ import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.ExtensionController; import com.android.systemui.statusbar.policy.HeadsUpManager; import com.android.systemui.statusbar.policy.KeyguardStateController; -import com.android.systemui.statusbar.policy.NetworkController; import com.android.systemui.statusbar.policy.UserInfoControllerImpl; import com.android.systemui.statusbar.policy.UserSwitcherController; import com.android.systemui.tuner.TunerService; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt index efe2c1774b08..fe7ec68f77b8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt @@ -33,6 +33,7 @@ import androidx.test.filters.SmallTest import com.android.internal.logging.testing.UiEventLoggerFake import com.android.systemui.R import com.android.systemui.SysuiTestCase +import com.android.systemui.dump.DumpManager import com.android.systemui.plugins.ActivityStarter import com.android.systemui.flags.FeatureFlags import com.android.systemui.statusbar.notification.collection.NotificationEntry @@ -105,7 +106,9 @@ class OngoingCallControllerTest : SysuiTestCase() { mockActivityStarter, mainExecutor, mockIActivityManager, - OngoingCallLogger(uiEventLoggerFake)) + OngoingCallLogger(uiEventLoggerFake), + DumpManager(), + ) controller.init() controller.addCallback(mockOngoingCallListener) controller.setChipView(chipView) @@ -221,18 +224,6 @@ class OngoingCallControllerTest : SysuiTestCase() { verify(mockOngoingCallListener).onOngoingCallStateChanged(anyBoolean()) } - /** Regression test for b/201097913. */ - @Test - fun onEntryCleanUp_callNotifAddedThenRemoved_listenerNotified() { - val ongoingCallNotifEntry = createOngoingCallNotifEntry() - notifCollectionListener.onEntryAdded(ongoingCallNotifEntry) - reset(mockOngoingCallListener) - - notifCollectionListener.onEntryCleanUp(ongoingCallNotifEntry) - - verify(mockOngoingCallListener).onOngoingCallStateChanged(anyBoolean()) - } - /** Regression test for b/188491504. */ @Test fun onEntryRemoved_removedNotifHasSameKeyAsAddedNotif_listenerNotified() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/WallpaperControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/util/WallpaperControllerTest.kt index de86821c0535..b54aadb8228f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/util/WallpaperControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/util/WallpaperControllerTest.kt @@ -138,7 +138,7 @@ class WallpaperControllerTest : SysuiTestCase() { private fun createWallpaperInfo(useDefaultTransition: Boolean = true): WallpaperInfo { val info = mock(WallpaperInfo::class.java) - whenever(info.shouldUseDefaultDeviceStateChangeTransition()) + whenever(info.shouldUseDefaultDisplayStateChangeTransition()) .thenReturn(useDefaultTransition) return info } diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/FakeProximitySensor.java b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/FakeProximitySensor.java index 50947ab0ee86..22cf744c726b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/FakeProximitySensor.java +++ b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/FakeProximitySensor.java @@ -19,14 +19,21 @@ package com.android.systemui.util.sensors; import com.android.systemui.util.concurrency.DelayableExecutor; import com.android.systemui.util.concurrency.FakeExecution; -public class FakeProximitySensor extends ProximitySensor { +public class FakeProximitySensor extends ProximitySensorImpl { private boolean mAvailable; private boolean mRegistered; - public FakeProximitySensor(ThresholdSensor primary, ThresholdSensor secondary, - DelayableExecutor delayableExecutor) { - super(primary, secondary == null ? new FakeThresholdSensor() : secondary, - delayableExecutor, new FakeExecution()); + public FakeProximitySensor( + ThresholdSensor primary, + ThresholdSensor secondary, + DelayableExecutor delayableExecutor + ) { + super( + primary, + secondary == null ? new FakeThresholdSensor() : secondary, + delayableExecutor, + new FakeExecution() + ); mAvailable = true; } diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/FakeThresholdSensor.java b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/FakeThresholdSensor.java index d9f978944cde..0d4a6c7023fb 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/FakeThresholdSensor.java +++ b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/FakeThresholdSensor.java @@ -59,6 +59,16 @@ public class FakeThresholdSensor implements ThresholdSensor { mListeners.remove(listener); } + @Override + public String getName() { + return "FakeThresholdSensorName"; + } + + @Override + public String getType() { + return "FakeThresholdSensorType"; + } + public void setLoaded(boolean loaded) { mIsLoaded = loaded; } diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/PostureDependentProximitySensorTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/PostureDependentProximitySensorTest.java new file mode 100644 index 000000000000..075f393df15a --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/PostureDependentProximitySensorTest.java @@ -0,0 +1,114 @@ +/* + * 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.util.sensors; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.verify; + +import android.content.res.Resources; +import android.testing.AndroidTestingRunner; +import android.testing.TestableLooper; + +import androidx.test.filters.SmallTest; + +import com.android.systemui.SysuiTestCase; +import com.android.systemui.statusbar.policy.DevicePostureController; +import com.android.systemui.util.concurrency.FakeExecution; +import com.android.systemui.util.concurrency.FakeExecutor; +import com.android.systemui.util.time.FakeSystemClock; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +@SmallTest +@RunWith(AndroidTestingRunner.class) +@TestableLooper.RunWithLooper +public class PostureDependentProximitySensorTest extends SysuiTestCase { + @Mock private Resources mResources; + @Mock private DevicePostureController mDevicePostureController; + @Mock private AsyncSensorManager mSensorManager; + + @Captor private ArgumentCaptor<DevicePostureController.Callback> mPostureListenerCaptor = + ArgumentCaptor.forClass(DevicePostureController.Callback.class); + private DevicePostureController.Callback mPostureListener; + + private PostureDependentProximitySensor mProximitySensor; + private FakeExecutor mFakeExecutor = new FakeExecutor(new FakeSystemClock()); + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + allowTestableLooperAsMainThread(); + + mProximitySensor = new PostureDependentProximitySensor( + new ThresholdSensor[DevicePostureController.SUPPORTED_POSTURES_SIZE], + new ThresholdSensor[DevicePostureController.SUPPORTED_POSTURES_SIZE], + mFakeExecutor, + new FakeExecution(), + mDevicePostureController + ); + } + + @Test + public void testPostureChangeListenerAdded() { + capturePostureListener(); + } + + @Test + public void testPostureChangeListenerUpdatesPosture() { + // GIVEN posture listener is registered + capturePostureListener(); + + // WHEN the posture changes to DEVICE_POSTURE_OPENED + mPostureListener.onPostureChanged(DevicePostureController.DEVICE_POSTURE_OPENED); + + // THEN device posture is updated to DEVICE_POSTURE_OPENED + assertEquals(DevicePostureController.DEVICE_POSTURE_OPENED, + mProximitySensor.mDevicePosture); + + // WHEN the posture changes to DEVICE_POSTURE_CLOSED + mPostureListener.onPostureChanged(DevicePostureController.DEVICE_POSTURE_CLOSED); + + // THEN device posture is updated to DEVICE_POSTURE_CLOSED + assertEquals(DevicePostureController.DEVICE_POSTURE_CLOSED, + mProximitySensor.mDevicePosture); + + // WHEN the posture changes to DEVICE_POSTURE_FLIPPED + mPostureListener.onPostureChanged(DevicePostureController.DEVICE_POSTURE_FLIPPED); + + // THEN device posture is updated to DEVICE_POSTURE_FLIPPED + assertEquals(DevicePostureController.DEVICE_POSTURE_FLIPPED, + mProximitySensor.mDevicePosture); + + // WHEN the posture changes to DEVICE_POSTURE_HALF_OPENED + mPostureListener.onPostureChanged(DevicePostureController.DEVICE_POSTURE_HALF_OPENED); + + // THEN device posture is updated to DEVICE_POSTURE_HALF_OPENED + assertEquals(DevicePostureController.DEVICE_POSTURE_HALF_OPENED, + mProximitySensor.mDevicePosture); + } + + private void capturePostureListener() { + verify(mDevicePostureController).addCallback(mPostureListenerCaptor.capture()); + mPostureListener = mPostureListenerCaptor.getValue(); + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximityCheckTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximityCheckTest.java index 242fe9f5fffe..19dbf9aa3c13 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximityCheckTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximityCheckTest.java @@ -49,7 +49,7 @@ public class ProximityCheckTest extends SysuiTestCase { private TestableCallback mTestableCallback = new TestableCallback(); - private ProximitySensor.ProximityCheck mProximityCheck; + private ProximityCheck mProximityCheck; @Before public void setUp() throws Exception { @@ -58,7 +58,7 @@ public class ProximityCheckTest extends SysuiTestCase { thresholdSensor.setLoaded(true); mFakeProximitySensor = new FakeProximitySensor(thresholdSensor, null, mFakeExecutor); - mProximityCheck = new ProximitySensor.ProximityCheck(mFakeProximitySensor, mFakeExecutor); + mProximityCheck = new ProximityCheck(mFakeProximitySensor, mFakeExecutor); } @Test @@ -67,7 +67,7 @@ public class ProximityCheckTest extends SysuiTestCase { assertNull(mTestableCallback.mLastResult); - mFakeProximitySensor.setLastEvent(new ProximitySensor.ThresholdSensorEvent(true, 0)); + mFakeProximitySensor.setLastEvent(new ThresholdSensorEvent(true, 0)); mFakeProximitySensor.alertListeners(); assertTrue(mTestableCallback.mLastResult); @@ -103,7 +103,7 @@ public class ProximityCheckTest extends SysuiTestCase { mProximityCheck.check(100, mTestableCallback); - mFakeProximitySensor.setLastEvent(new ProximitySensor.ThresholdSensorEvent(true, 0)); + mFakeProximitySensor.setLastEvent(new ThresholdSensorEvent(true, 0)); mFakeProximitySensor.alertListeners(); assertThat(mTestableCallback.mLastResult).isNotNull(); @@ -123,7 +123,7 @@ public class ProximityCheckTest extends SysuiTestCase { assertNull(mTestableCallback.mLastResult); - mFakeProximitySensor.setLastEvent(new ProximitySensor.ThresholdSensorEvent(true, 0)); + mFakeProximitySensor.setLastEvent(new ThresholdSensorEvent(true, 0)); mFakeProximitySensor.alertListeners(); assertTrue(mTestableCallback.mLastResult); diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximitySensorDualTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximitySensorImplDualTest.java index 0e9d96c61e54..5e7557896145 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximitySensorDualTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximitySensorImplDualTest.java @@ -42,7 +42,7 @@ import org.mockito.MockitoAnnotations; @SmallTest @RunWith(AndroidTestingRunner.class) @TestableLooper.RunWithLooper -public class ProximitySensorDualTest extends SysuiTestCase { +public class ProximitySensorImplDualTest extends SysuiTestCase { private ProximitySensor mProximitySensor; private FakeExecutor mFakeExecutor = new FakeExecutor(new FakeSystemClock()); private FakeThresholdSensor mThresholdSensorPrimary; @@ -57,7 +57,7 @@ public class ProximitySensorDualTest extends SysuiTestCase { mThresholdSensorSecondary = new FakeThresholdSensor(); mThresholdSensorSecondary.setLoaded(true); - mProximitySensor = new ProximitySensor( + mProximitySensor = new ProximitySensorImpl( mThresholdSensorPrimary, mThresholdSensorSecondary, mFakeExecutor, new FakeExecution()); } @@ -430,11 +430,11 @@ public class ProximitySensorDualTest extends SysuiTestCase { } private static class TestableListener implements ThresholdSensor.Listener { - ThresholdSensor.ThresholdSensorEvent mLastEvent; + ThresholdSensorEvent mLastEvent; int mCallCount = 0; @Override - public void onThresholdCrossed(ThresholdSensor.ThresholdSensorEvent proximityEvent) { + public void onThresholdCrossed(ThresholdSensorEvent proximityEvent) { mLastEvent = proximityEvent; mCallCount++; } diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximitySensorSingleTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximitySensorImplSingleTest.java index 6c6d355d7866..752cd3211161 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximitySensorSingleTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximitySensorImplSingleTest.java @@ -42,7 +42,7 @@ import org.mockito.MockitoAnnotations; @SmallTest @RunWith(AndroidTestingRunner.class) @TestableLooper.RunWithLooper -public class ProximitySensorSingleTest extends SysuiTestCase { +public class ProximitySensorImplSingleTest extends SysuiTestCase { private ProximitySensor mProximitySensor; private FakeExecutor mFakeExecutor = new FakeExecutor(new FakeSystemClock()); private FakeThresholdSensor mThresholdSensor; @@ -54,7 +54,7 @@ public class ProximitySensorSingleTest extends SysuiTestCase { mThresholdSensor = new FakeThresholdSensor(); mThresholdSensor.setLoaded(true); - mProximitySensor = new ProximitySensor( + mProximitySensor = new ProximitySensorImpl( mThresholdSensor, new FakeThresholdSensor(), mFakeExecutor, new FakeExecution()); } @@ -215,7 +215,7 @@ public class ProximitySensorSingleTest extends SysuiTestCase { public void testPreventRecursiveAlert() { TestableListener listenerA = new TestableListener() { @Override - public void onThresholdCrossed(ProximitySensor.ThresholdSensorEvent proximityEvent) { + public void onThresholdCrossed(ThresholdSensorEvent proximityEvent) { super.onThresholdCrossed(proximityEvent); if (mCallCount < 2) { mProximitySensor.alertListeners(); @@ -231,11 +231,11 @@ public class ProximitySensorSingleTest extends SysuiTestCase { } private static class TestableListener implements ThresholdSensor.Listener { - ThresholdSensor.ThresholdSensorEvent mLastEvent; + ThresholdSensorEvent mLastEvent; int mCallCount = 0; @Override - public void onThresholdCrossed(ThresholdSensor.ThresholdSensorEvent proximityEvent) { + public void onThresholdCrossed(ThresholdSensorEvent proximityEvent) { mLastEvent = proximityEvent; mCallCount++; } diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ThresholdSensorImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ThresholdSensorImplTest.java index 125063a7adc4..b10f16c963ed 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ThresholdSensorImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ThresholdSensorImplTest.java @@ -380,7 +380,7 @@ public class ThresholdSensorImplTest extends SysuiTestCase { int mCallCount; @Override - public void onThresholdCrossed(ThresholdSensor.ThresholdSensorEvent event) { + public void onThresholdCrossed(ThresholdSensorEvent event) { mBelow = event.getBelow(); mTimestampNs = event.getTimestampNs(); mCallCount++; diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeNetworkController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeNetworkController.java index e7acfae24f30..8ea9da6f4d0e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeNetworkController.java +++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeNetworkController.java @@ -18,9 +18,9 @@ import android.os.Bundle; import android.testing.LeakCheck; import com.android.settingslib.net.DataUsageController; +import com.android.systemui.statusbar.connectivity.NetworkController; +import com.android.systemui.statusbar.connectivity.NetworkController.SignalCallback; import com.android.systemui.statusbar.policy.DataSaverController; -import com.android.systemui.statusbar.policy.NetworkController; -import com.android.systemui.statusbar.policy.NetworkController.SignalCallback; public class FakeNetworkController extends BaseLeakChecker<SignalCallback> implements NetworkController { diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/LeakCheckedTest.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/LeakCheckedTest.java index fedc08d93bc7..dc6a8fb9a4c4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/LeakCheckedTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/LeakCheckedTest.java @@ -19,6 +19,7 @@ import android.util.ArrayMap; import com.android.systemui.SysuiTestCase; import com.android.systemui.shared.plugins.PluginManager; +import com.android.systemui.statusbar.connectivity.NetworkController; import com.android.systemui.statusbar.phone.ManagedProfileController; import com.android.systemui.statusbar.phone.StatusBarIconController; import com.android.systemui.statusbar.policy.BatteryController; @@ -29,7 +30,6 @@ import com.android.systemui.statusbar.policy.FlashlightController; import com.android.systemui.statusbar.policy.HotspotController; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.statusbar.policy.LocationController; -import com.android.systemui.statusbar.policy.NetworkController; import com.android.systemui.statusbar.policy.NextAlarmController; import com.android.systemui.statusbar.policy.RotationLockController; import com.android.systemui.statusbar.policy.SecurityController; diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java index 904def0af2cf..6bd1fa6c335d 100644 --- a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java +++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java @@ -190,6 +190,9 @@ final class ContentCapturePerUserService Slog.w(TAG, "remote service died: " + service); synchronized (mLock) { mZombie = true; + writeServiceEvent( + FrameworkStatsLog.CONTENT_CAPTURE_SERVICE_EVENTS__EVENT__ON_REMOTE_SERVICE_DIED, + getServiceComponentName()); } } diff --git a/services/core/java/com/android/server/SensorPrivacyService.java b/services/core/java/com/android/server/SensorPrivacyService.java index 1176c506cf60..93a820cf1406 100644 --- a/services/core/java/com/android/server/SensorPrivacyService.java +++ b/services/core/java/com/android/server/SensorPrivacyService.java @@ -711,6 +711,16 @@ public final class SensorPrivacyService extends SystemService { @Override public void setIndividualSensorPrivacy(@UserIdInt int userId, @SensorPrivacyManager.Sources.Source int source, int sensor, boolean enable) { + if (DEBUG) { + Log.d(TAG, "callingUid=" + Binder.getCallingUid() + + " callingPid=" + Binder.getCallingPid() + + " setIndividualSensorPrivacy(" + + "userId=" + userId + + " source=" + source + + " sensor=" + sensor + + " enable=" + enable + + ")"); + } enforceManageSensorPrivacyPermission(); if (userId == UserHandle.USER_CURRENT) { userId = mCurrentUser; @@ -895,6 +905,14 @@ public final class SensorPrivacyService extends SystemService { @Override public boolean isIndividualSensorPrivacyEnabled(@UserIdInt int userId, int sensor) { + if (DEBUG) { + Log.d(TAG, "callingUid=" + Binder.getCallingUid() + + " callingPid=" + Binder.getCallingPid() + + " isIndividualSensorPrivacyEnabled(" + + "userId=" + userId + + " sensor=" + sensor + + ")"); + } enforceObserveSensorPrivacyPermission(); if (userId == UserHandle.USER_CURRENT) { userId = mCurrentUser; diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java index fcd049f1c494..d10ab8e2d0dd 100644 --- a/services/core/java/com/android/server/Watchdog.java +++ b/services/core/java/com/android/server/Watchdog.java @@ -142,6 +142,8 @@ public class Watchdog { ); public static final String[] AIDL_INTERFACE_PREFIXES_OF_INTEREST = new String[] { + "android.hardware.biometrics.face.IFace/", + "android.hardware.biometrics.fingerprint.IFingerprint/", "android.hardware.light.ILights/", "android.hardware.power.stats.IPowerStats/", }; diff --git a/services/core/java/com/android/server/display/DisplayModeDirector.java b/services/core/java/com/android/server/display/DisplayModeDirector.java index 5fc301e60b9d..0a22f2fdfdf8 100644 --- a/services/core/java/com/android/server/display/DisplayModeDirector.java +++ b/services/core/java/com/android/server/display/DisplayModeDirector.java @@ -17,6 +17,7 @@ package com.android.server.display; import static android.hardware.display.DisplayManagerInternal.REFRESH_RATE_LIMIT_HIGH_BRIGHTNESS_MODE; +import static android.os.PowerManager.BRIGHTNESS_INVALID; import android.annotation.NonNull; import android.annotation.Nullable; @@ -40,6 +41,7 @@ import android.os.IThermalEventListener; import android.os.IThermalService; import android.os.Looper; import android.os.Message; +import android.os.PowerManager; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; @@ -60,6 +62,7 @@ import android.view.DisplayInfo; import com.android.internal.R; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.display.BrightnessSynchronizer; import com.android.internal.os.BackgroundThread; import com.android.server.LocalServices; import com.android.server.display.utils.AmbientFilter; @@ -155,7 +158,7 @@ public class DisplayModeDirector { mAppRequestObserver = new AppRequestObserver(); mSettingsObserver = new SettingsObserver(context, handler); mDisplayObserver = new DisplayObserver(context, handler); - mBrightnessObserver = new BrightnessObserver(context, handler); + mBrightnessObserver = new BrightnessObserver(context, handler, injector); mUdfpsObserver = new UdfpsObserver(); final BallotBox ballotBox = (displayId, priority, vote) -> { synchronized (mLock) { @@ -1427,8 +1430,6 @@ public class DisplayModeDirector { @Override public void onDisplayChanged(int displayId) { updateDisplayModes(displayId); - // TODO: Break the coupling between DisplayObserver and BrightnessObserver. - mBrightnessObserver.onDisplayChanged(displayId); } private void updateDisplayModes(int displayId) { @@ -1465,7 +1466,7 @@ public class DisplayModeDirector { * {@link R.array#config_ambientThresholdsOfPeakRefreshRate}. */ @VisibleForTesting - public class BrightnessObserver extends ContentObserver { + public class BrightnessObserver implements DisplayManager.DisplayListener { private final static int LIGHT_SENSOR_RATE_MS = 250; private int[] mLowDisplayBrightnessThresholds; private int[] mLowAmbientBrightnessThresholds; @@ -1488,6 +1489,8 @@ public class DisplayModeDirector { private int mBrightness = -1; private final Context mContext; + private final Injector mInjector; + private final Handler mHandler; // Enable light sensor only when mShouldObserveAmbientLowChange is true or // mShouldObserveAmbientHighChange is true, screen is on, peak refresh rate @@ -1500,9 +1503,11 @@ public class DisplayModeDirector { private int mRefreshRateInLowZone; private int mRefreshRateInHighZone; - BrightnessObserver(Context context, Handler handler) { - super(handler); + BrightnessObserver(Context context, Handler handler, Injector injector) { mContext = context; + mHandler = handler; + mInjector = injector; + mLowDisplayBrightnessThresholds = context.getResources().getIntArray( R.array.config_brightnessThresholdsOfPeakRefreshRate); mLowAmbientBrightnessThresholds = context.getResources().getIntArray( @@ -1569,8 +1574,7 @@ public class DisplayModeDirector { public void observe(SensorManager sensorManager) { mSensorManager = sensorManager; final ContentResolver cr = mContext.getContentResolver(); - mBrightness = Settings.System.getIntForUser(cr, - Settings.System.SCREEN_BRIGHTNESS, -1 /*default*/, cr.getUserId()); + mBrightness = getBrightness(Display.DEFAULT_DISPLAY); // DeviceConfig is accessible after system ready. int[] lowDisplayBrightnessThresholds = @@ -1603,6 +1607,10 @@ public class DisplayModeDirector { restartObserver(); mDeviceConfigDisplaySettings.startListening(); + + mInjector.registerDisplayListener(this, mHandler, + DisplayManager.EVENT_FLAG_DISPLAY_CHANGED | + DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS); } public void setLoggingEnabled(boolean loggingEnabled) { @@ -1718,28 +1726,30 @@ public class DisplayModeDirector { } } + @Override + public void onDisplayAdded(int displayId) {} + + @Override + public void onDisplayRemoved(int displayId) {} + + @Override public void onDisplayChanged(int displayId) { if (displayId == Display.DEFAULT_DISPLAY) { updateDefaultDisplayState(); - } - } - @Override - public void onChange(boolean selfChange, Uri uri, int userId) { - synchronized (mLock) { - final ContentResolver cr = mContext.getContentResolver(); - int brightness = Settings.System.getIntForUser(cr, - Settings.System.SCREEN_BRIGHTNESS, -1 /*default*/, cr.getUserId()); - if (brightness != mBrightness) { - mBrightness = brightness; - onBrightnessChangedLocked(); + // We don't support multiple display blocking zones yet, so only handle + // brightness changes for the default display for now. + int brightness = getBrightness(displayId); + synchronized (mLock) { + if (brightness != mBrightness) { + mBrightness = brightness; + onBrightnessChangedLocked(); + } } } } private void restartObserver() { - final ContentResolver cr = mContext.getContentResolver(); - if (mRefreshRateInLowZone > 0) { mShouldObserveDisplayLowChange = hasValidThreshold( mLowDisplayBrightnessThresholds); @@ -1760,15 +1770,6 @@ public class DisplayModeDirector { mShouldObserveAmbientHighChange = false; } - if (mShouldObserveDisplayLowChange || mShouldObserveDisplayHighChange) { - // Content Service does not check if an listener has already been registered. - // To ensure only one listener is registered, force an unregistration first. - mInjector.unregisterBrightnessObserver(cr, this); - mInjector.registerBrightnessObserver(cr, this); - } else { - mInjector.unregisterBrightnessObserver(cr, this); - } - if (mShouldObserveAmbientLowChange || mShouldObserveAmbientHighChange) { Resources resources = mContext.getResources(); String lightSensorType = resources.getString( @@ -1968,6 +1969,15 @@ public class DisplayModeDirector { return mDefaultDisplayState == Display.STATE_ON; } + private int getBrightness(int displayId) { + final BrightnessInfo info = mInjector.getBrightnessInfo(displayId); + if (info != null) { + return BrightnessSynchronizer.brightnessFloatToInt(info.adjustedBrightness); + } + + return BRIGHTNESS_INVALID; + } + private final class LightSensorEventListener implements SensorEventListener { final private static int INJECT_EVENTS_INTERVAL_MS = LIGHT_SENSOR_RATE_MS; private float mLastSensorData; @@ -2283,6 +2293,7 @@ public class DisplayModeDirector { private final BallotBox mBallotBox; private final Handler mHandler; private final SparseIntArray mHbmMode = new SparseIntArray(); + private final SparseBooleanArray mHbmActive = new SparseBooleanArray(); private final Injector mInjector; private final DeviceConfigDisplaySettings mDeviceConfigDisplaySettings; private int mRefreshRateInHbmSunlight; @@ -2351,6 +2362,7 @@ public class DisplayModeDirector { public void onDisplayRemoved(int displayId) { mBallotBox.vote(displayId, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE, null); mHbmMode.delete(displayId); + mHbmActive.delete(displayId); } @Override @@ -2360,12 +2372,17 @@ public class DisplayModeDirector { // Display no longer there. Assume we'll get an onDisplayRemoved very soon. return; } + final int hbmMode = info.highBrightnessMode; - if (hbmMode == mHbmMode.get(displayId)) { + final boolean isHbmActive = hbmMode != BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF && + info.adjustedBrightness > info.highBrightnessTransitionPoint; + if (hbmMode == mHbmMode.get(displayId) && + isHbmActive == mHbmActive.get(displayId)) { // no change, ignore. return; } mHbmMode.put(displayId, hbmMode); + mHbmActive.put(displayId, isHbmActive); recalculateVotesForDisplay(displayId); } @@ -2379,28 +2396,36 @@ public class DisplayModeDirector { } private void recalculateVotesForDisplay(int displayId) { - final int hbmMode = mHbmMode.get(displayId, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF); Vote vote = null; - if (hbmMode == BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT) { - // Device resource properties take priority over DisplayDeviceConfig - if (mRefreshRateInHbmSunlight > 0) { - vote = Vote.forRefreshRates(mRefreshRateInHbmSunlight, - mRefreshRateInHbmSunlight); - } else { - final List<RefreshRateLimitation> limits = - mDisplayManagerInternal.getRefreshRateLimitations(displayId); - for (int i = 0; limits != null && i < limits.size(); i++) { - final RefreshRateLimitation limitation = limits.get(i); - if (limitation.type == REFRESH_RATE_LIMIT_HIGH_BRIGHTNESS_MODE) { - vote = Vote.forRefreshRates(limitation.range.min, limitation.range.max); - break; + if (mHbmActive.get(displayId, false)) { + final int hbmMode = + mHbmMode.get(displayId, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF); + if (hbmMode == BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT) { + // Device resource properties take priority over DisplayDeviceConfig + if (mRefreshRateInHbmSunlight > 0) { + vote = Vote.forRefreshRates(mRefreshRateInHbmSunlight, + mRefreshRateInHbmSunlight); + } else { + final List<RefreshRateLimitation> limits = + mDisplayManagerInternal.getRefreshRateLimitations(displayId); + for (int i = 0; limits != null && i < limits.size(); i++) { + final RefreshRateLimitation limitation = limits.get(i); + if (limitation.type == REFRESH_RATE_LIMIT_HIGH_BRIGHTNESS_MODE) { + vote = Vote.forRefreshRates(limitation.range.min, + limitation.range.max); + break; + } } } + } else if (hbmMode == BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR && + mRefreshRateInHbmHdr > 0) { + // HBM for HDR vote isn't supported through DisplayDeviceConfig yet, so look for + // a vote from Device properties + vote = Vote.forRefreshRates(mRefreshRateInHbmHdr, mRefreshRateInHbmHdr); + } else { + Slog.w(TAG, "Unexpected HBM mode " + hbmMode + " for display ID " + displayId); } - } - if (hbmMode == BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR - && mRefreshRateInHbmHdr > 0) { - vote = Vote.forRefreshRates(mRefreshRateInHbmHdr, mRefreshRateInHbmHdr); + } mBallotBox.vote(displayId, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE, vote); } @@ -2408,6 +2433,7 @@ public class DisplayModeDirector { void dumpLocked(PrintWriter pw) { pw.println(" HbmObserver"); pw.println(" mHbmMode: " + mHbmMode); + pw.println(" mHbmActive: " + mHbmActive); pw.println(" mRefreshRateInHbmSunlight: " + mRefreshRateInHbmSunlight); pw.println(" mRefreshRateInHbmHdr: " + mRefreshRateInHbmHdr); } @@ -2630,19 +2656,11 @@ public class DisplayModeDirector { } interface Injector { - // TODO: brightnessfloat: change this to the float setting - Uri DISPLAY_BRIGHTNESS_URI = Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS); Uri PEAK_REFRESH_RATE_URI = Settings.System.getUriFor(Settings.System.PEAK_REFRESH_RATE); @NonNull DeviceConfigInterface getDeviceConfig(); - void registerBrightnessObserver(@NonNull ContentResolver cr, - @NonNull ContentObserver observer); - - void unregisterBrightnessObserver(@NonNull ContentResolver cr, - @NonNull ContentObserver observer); - void registerPeakRefreshRateObserver(@NonNull ContentResolver cr, @NonNull ContentObserver observer); @@ -2672,19 +2690,6 @@ public class DisplayModeDirector { } @Override - public void registerBrightnessObserver(@NonNull ContentResolver cr, - @NonNull ContentObserver observer) { - cr.registerContentObserver(DISPLAY_BRIGHTNESS_URI, false /*notifyDescendants*/, - observer, UserHandle.USER_SYSTEM); - } - - @Override - public void unregisterBrightnessObserver(@NonNull ContentResolver cr, - @NonNull ContentObserver observer) { - cr.unregisterContentObserver(observer); - } - - @Override public void registerPeakRefreshRateObserver(@NonNull ContentResolver cr, @NonNull ContentObserver observer) { cr.registerContentObserver(PEAK_REFRESH_RATE_URI, false /*notifyDescendants*/, diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java index 1063481d6788..bf5208aed3f7 100644 --- a/services/core/java/com/android/server/display/DisplayPowerController.java +++ b/services/core/java/com/android/server/display/DisplayPowerController.java @@ -1259,10 +1259,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call putScreenBrightnessSetting(brightnessState, /* updateCurrent */ true); } - // We save the brightness info *after* the brightness setting has been changed so that - // the brightness info reflects the latest value. - saveBrightnessInfo(getScreenBrightnessSetting()); - // Apply dimming by at least some minimum amount when user activity // timeout is about to expire. if (mPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) { @@ -1393,6 +1389,11 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call hadUserBrightnessPoint); } + // We save the brightness info *after* the brightness setting has been changed and + // adjustments made so that the brightness info reflects the latest value. + saveBrightnessInfo(getScreenBrightnessSetting(), animateValue); + } else { + saveBrightnessInfo(getScreenBrightnessSetting()); } // Log any changes to what is currently driving the brightness setting. @@ -1509,18 +1510,27 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call synchronized (mCachedBrightnessInfo) { return new BrightnessInfo( mCachedBrightnessInfo.brightness, + mCachedBrightnessInfo.adjustedBrightness, mCachedBrightnessInfo.brightnessMin, mCachedBrightnessInfo.brightnessMax, - mCachedBrightnessInfo.hbmMode); + mCachedBrightnessInfo.hbmMode, + mCachedBrightnessInfo.highBrightnessTransitionPoint); } } private void saveBrightnessInfo(float brightness) { + saveBrightnessInfo(brightness, brightness); + } + + private void saveBrightnessInfo(float brightness, float adjustedBrightness) { synchronized (mCachedBrightnessInfo) { mCachedBrightnessInfo.brightness = brightness; + mCachedBrightnessInfo.adjustedBrightness = adjustedBrightness; mCachedBrightnessInfo.brightnessMin = mHbmController.getCurrentBrightnessMin(); mCachedBrightnessInfo.brightnessMax = mHbmController.getCurrentBrightnessMax(); mCachedBrightnessInfo.hbmMode = mHbmController.getHighBrightnessMode(); + mCachedBrightnessInfo.highBrightnessTransitionPoint = + mHbmController.getTransitionPoint(); } } @@ -2195,6 +2205,18 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call pw.println(" mSkipScreenOnBrightnessRamp=" + mSkipScreenOnBrightnessRamp); pw.println(" mColorFadeFadesConfig=" + mColorFadeFadesConfig); pw.println(" mColorFadeEnabled=" + mColorFadeEnabled); + synchronized (mCachedBrightnessInfo) { + pw.println(" mCachedBrightnessInfo.brightness=" + mCachedBrightnessInfo.brightness); + pw.println(" mCachedBrightnessInfo.adjustedBrightness=" + + mCachedBrightnessInfo.adjustedBrightness); + pw.println(" mCachedBrightnessInfo.brightnessMin=" + + mCachedBrightnessInfo.brightnessMin); + pw.println(" mCachedBrightnessInfo.brightnessMax=" + + mCachedBrightnessInfo.brightnessMax); + pw.println(" mCachedBrightnessInfo.hbmMode=" + mCachedBrightnessInfo.hbmMode); + pw.println(" mCachedBrightnessInfo.highBrightnessTransitionPoint=" + + mCachedBrightnessInfo.highBrightnessTransitionPoint); + } pw.println(" mDisplayBlanksAfterDozeConfig=" + mDisplayBlanksAfterDozeConfig); pw.println(" mBrightnessBucketsInDozeConfig=" + mBrightnessBucketsInDozeConfig); @@ -2606,8 +2628,10 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call static class CachedBrightnessInfo { public float brightness; + public float adjustedBrightness; public float brightnessMin; public float brightnessMax; public int hbmMode; + public float highBrightnessTransitionPoint; } } diff --git a/services/core/java/com/android/server/display/HighBrightnessModeController.java b/services/core/java/com/android/server/display/HighBrightnessModeController.java index 2791f6a409be..1e1cfeb5b9dd 100644 --- a/services/core/java/com/android/server/display/HighBrightnessModeController.java +++ b/services/core/java/com/android/server/display/HighBrightnessModeController.java @@ -59,6 +59,9 @@ class HighBrightnessModeController { private static final float HDR_PERCENT_OF_SCREEN_REQUIRED = 0.50f; + @VisibleForTesting + static final float HBM_TRANSITION_POINT_INVALID = Float.POSITIVE_INFINITY; + private final float mBrightnessMin; private final float mBrightnessMax; private final Handler mHandler; @@ -214,6 +217,14 @@ class HighBrightnessModeController { return mHbmMode; } + float getTransitionPoint() { + if (deviceSupportsHbm()) { + return mHbmData.transitionPoint; + } else { + return HBM_TRANSITION_POINT_INVALID; + } + } + void stop() { registerHdrListener(null /*displayToken*/); mSkinThermalStatusObserver.stopObserving(); diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index dd2583a0ce1a..5acff2b6c743 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -1816,7 +1816,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { @Override public int onAppTransitionStartingLocked(boolean keyguardGoingAway, long duration, long statusBarAnimationStartTime, long statusBarAnimationDuration) { - return handleStartTransitionForKeyguardLw(keyguardGoingAway, duration); + // When remote animation is enabled for KEYGUARD_GOING_AWAY transition, SysUI + // receives IRemoteAnimationRunner#onAnimationStart to start animation, so we don't + // need to call IKeyguardService#keyguardGoingAway here. + return handleStartTransitionForKeyguardLw(keyguardGoingAway + && !WindowManagerService.sEnableRemoteKeyguardGoingAwayAnimation, duration); } @Override @@ -3064,7 +3068,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { private int handleStartTransitionForKeyguardLw(boolean keyguardGoingAway, long duration) { final int res = applyKeyguardOcclusionChange(); if (res != 0) return res; - if (!WindowManagerService.sEnableRemoteKeyguardGoingAwayAnimation && keyguardGoingAway) { + if (keyguardGoingAway) { if (DEBUG_KEYGUARD) Slog.d(TAG, "Starting keyguard exit animation"); startKeyguardExitAnimation(SystemClock.uptimeMillis(), duration); } diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java index d1906785994a..86ff33e8cc42 100644 --- a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java +++ b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java @@ -410,8 +410,7 @@ public class KeyguardServiceDelegate { } public void startKeyguardExitAnimation(long startTime, long fadeoutDuration) { - if (!WindowManagerService.sEnableRemoteKeyguardGoingAwayAnimation - && mKeyguardService != null) { + if (mKeyguardService != null) { mKeyguardService.startKeyguardExitAnimation(startTime, fadeoutDuration); } } diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java index 61770ea1c1c2..106cff17dbef 100644 --- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java +++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java @@ -67,6 +67,7 @@ import static java.util.concurrent.TimeUnit.MICROSECONDS; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.UserIdInt; import android.app.ActivityManagerInternal; import android.app.AppOpsManager; import android.app.AppOpsManager.HistoricalOp; @@ -82,6 +83,7 @@ import android.app.StatsManager.PullAtomMetadata; import android.bluetooth.BluetoothActivityEnergyInfo; import android.bluetooth.BluetoothAdapter; import android.bluetooth.UidTraffic; +import android.content.ContentResolver; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; @@ -734,6 +736,10 @@ public class StatsPullAtomService extends SystemService { case FrameworkStatsLog.RKP_ERROR_STATS: case FrameworkStatsLog.KEYSTORE2_CRASH_STATS: return pullKeystoreAtoms(atomTag, data); + case FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_STATS: + return pullAccessibilityShortcutStatsLocked(atomTag, data); + case FrameworkStatsLog.ACCESSIBILITY_FLOATING_MENU_STATS: + return pullAccessibilityFloatingMenuStatsLocked(atomTag, data); default: throw new UnsupportedOperationException("Unknown tagId=" + atomTag); } @@ -930,6 +936,8 @@ public class StatsPullAtomService extends SystemService { registerKeystoreKeyOperationWithGeneralInfo(); registerRkpErrorStats(); registerKeystoreCrashStats(); + registerAccessibilityShortcutStats(); + registerAccessibilityFloatingMenuStats(); } private void initAndRegisterNetworkStatsPullers() { @@ -4150,6 +4158,26 @@ public class StatsPullAtomService extends SystemService { mStatsCallbackImpl); } + private void registerAccessibilityShortcutStats() { + int tagId = FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_STATS; + mStatsManager.setPullAtomCallback( + tagId, + null, // use default PullAtomMetadata values + DIRECT_EXECUTOR, + mStatsCallbackImpl + ); + } + + private void registerAccessibilityFloatingMenuStats() { + int tagId = FrameworkStatsLog.ACCESSIBILITY_FLOATING_MENU_STATS; + mStatsManager.setPullAtomCallback( + tagId, + null, // use default PullAtomMetadata values + DIRECT_EXECUTOR, + mStatsCallbackImpl + ); + } + int parseKeystoreStorageStats(KeystoreAtom[] atoms, List<StatsEvent> pulledData) { for (KeystoreAtom atomWrapper : atoms) { if (atomWrapper.payload.getTag() != KeystoreAtomPayload.storageStats) { @@ -4341,6 +4369,144 @@ public class StatsPullAtomService extends SystemService { } } + int pullAccessibilityShortcutStatsLocked(int atomTag, List<StatsEvent> pulledData) { + UserManager userManager = mContext.getSystemService(UserManager.class); + if (userManager == null) { + return StatsManager.PULL_SKIP; + } + final long token = Binder.clearCallingIdentity(); + try { + final ContentResolver resolver = mContext.getContentResolver(); + final int hardware_shortcut_type = + FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__VOLUME_KEY; + final int triple_tap_shortcut = + FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_REPORTED__SHORTCUT_TYPE__TRIPLE_TAP; + for (UserInfo userInfo : userManager.getUsers()) { + final int userId = userInfo.getUserHandle().getIdentifier(); + + if (isAccessibilityShortcutUser(mContext, userId)) { + final int software_shortcut_type = Settings.Secure.getIntForUser(resolver, + Settings.Secure.ACCESSIBILITY_BUTTON_MODE, 0, userId); + final String software_shortcut_list = Settings.Secure.getStringForUser(resolver, + Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, userId); + final int software_shortcut_service_num = countAccessibilityServices( + software_shortcut_list); + + final String hardware_shortcut_list = Settings.Secure.getStringForUser(resolver, + Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE, userId); + final int hardware_shortcut_service_num = countAccessibilityServices( + hardware_shortcut_list); + + // only allow magnification to use it for now + final int triple_tap_service_num = Settings.Secure.getIntForUser(resolver, + Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, 0, userId); + + pulledData.add( + FrameworkStatsLog.buildStatsEvent(atomTag, + software_shortcut_type, software_shortcut_service_num, + hardware_shortcut_type, hardware_shortcut_service_num, + triple_tap_shortcut, triple_tap_service_num)); + } + } + } catch (RuntimeException e) { + Slog.e(TAG, "pulling accessibility shortcuts stats failed at getUsers", e); + return StatsManager.PULL_SKIP; + } finally { + Binder.restoreCallingIdentity(token); + } + return StatsManager.PULL_SUCCESS; + } + + int pullAccessibilityFloatingMenuStatsLocked(int atomTag, List<StatsEvent> pulledData) { + UserManager userManager = mContext.getSystemService(UserManager.class); + if (userManager == null) { + return StatsManager.PULL_SKIP; + } + final long token = Binder.clearCallingIdentity(); + try { + final ContentResolver resolver = mContext.getContentResolver(); + final int defaultSize = 0; + final int defaultIconType = 0; + final int defaultFadeEnabled = 1; + final float defaultOpacity = 0.55f; + + for (UserInfo userInfo : userManager.getUsers()) { + final int userId = userInfo.getUserHandle().getIdentifier(); + + if (isAccessibilityFloatingMenuUser(mContext, userId)) { + final int size = Settings.Secure.getIntForUser(resolver, + Settings.Secure.ACCESSIBILITY_FLOATING_MENU_SIZE, defaultSize, userId); + final int type = Settings.Secure.getIntForUser(resolver, + Settings.Secure.ACCESSIBILITY_FLOATING_MENU_ICON_TYPE, + defaultIconType, userId); + final boolean fadeEnabled = (Settings.Secure.getIntForUser(resolver, + Settings.Secure.ACCESSIBILITY_FLOATING_MENU_FADE_ENABLED, + defaultFadeEnabled, userId)) == 1; + final float opacity = Settings.Secure.getFloatForUser(resolver, + Settings.Secure.ACCESSIBILITY_FLOATING_MENU_OPACITY, + defaultOpacity, userId); + + pulledData.add( + FrameworkStatsLog.buildStatsEvent(atomTag, size, type, fadeEnabled, + opacity)); + } + } + } catch (RuntimeException e) { + Slog.e(TAG, "pulling accessibility floating menu stats failed at getUsers", e); + return StatsManager.PULL_SKIP; + } finally { + Binder.restoreCallingIdentity(token); + } + return StatsManager.PULL_SUCCESS; + } + + /** + * Counts how many accessibility services (including features) there are in the colon-separated + * string list. + * + * @param semicolonList colon-separated string, it should be + * {@link Settings.Secure#ACCESSIBILITY_BUTTON_TARGETS} or + * {@link Settings.Secure#ACCESSIBILITY_SHORTCUT_TARGET_SERVICE}. + * @return The number of accessibility services + */ + private int countAccessibilityServices(String semicolonList) { + if (TextUtils.isEmpty(semicolonList)) { + return 0; + } + final int semiColonNums = (int) semicolonList.chars().filter(ch -> ch == ':').count(); + return TextUtils.isEmpty(semicolonList) ? 0 : semiColonNums + 1; + } + + private boolean isAccessibilityShortcutUser(Context context, @UserIdInt int userId) { + final ContentResolver resolver = context.getContentResolver(); + + final String software_shortcut_list = Settings.Secure.getStringForUser(resolver, + Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, userId); + final String hardware_shortcut_list = Settings.Secure.getStringForUser(resolver, + Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE, userId); + final boolean hardware_shortcut_dialog_shown = Settings.Secure.getIntForUser(resolver, + Settings.Secure.ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN, 0, userId) == 1; + final boolean software_shortcut_enabled = !TextUtils.isEmpty(software_shortcut_list); + final boolean hardware_shortcut_enabled = + hardware_shortcut_dialog_shown && !TextUtils.isEmpty(hardware_shortcut_list); + final boolean triple_tap_shortcut_enabled = Settings.Secure.getIntForUser(resolver, + Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, 0, userId) == 1; + + return software_shortcut_enabled || hardware_shortcut_enabled + || triple_tap_shortcut_enabled; + } + + private boolean isAccessibilityFloatingMenuUser(Context context, @UserIdInt int userId) { + final ContentResolver resolver = context.getContentResolver(); + final int mode = Settings.Secure.getIntForUser(resolver, + Settings.Secure.ACCESSIBILITY_BUTTON_MODE, 0, userId); + final String software_string = Settings.Secure.getStringForUser(resolver, + Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, userId); + + return (mode == Settings.Secure.ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU) + && !TextUtils.isEmpty(software_string); + } + // Thermal event received from vendor thermal management subsystem private static final class ThermalEventListener extends IThermalEventListener.Stub { @Override diff --git a/services/core/java/com/android/server/wm/ActivityClientController.java b/services/core/java/com/android/server/wm/ActivityClientController.java index cc0db1d12e7b..ee72fc8622a5 100644 --- a/services/core/java/com/android/server/wm/ActivityClientController.java +++ b/services/core/java/com/android/server/wm/ActivityClientController.java @@ -1072,7 +1072,7 @@ class ActivityClientController extends IActivityClientController.Stub { r.mDisplayContent.mAppTransition.overridePendingAppTransition( packageName, enterAnim, exitAnim, null, null, r.mOverrideTaskTransition); - mService.getTransitionController().setOverrideAnimation( + r.mTransitionController.setOverrideAnimation( TransitionInfo.AnimationOptions.makeCustomAnimOptions(packageName, enterAnim, exitAnim, r.mOverrideTaskTransition), null /* startCallback */, null /* finishCallback */); diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index db44dd8f70d1..352168c0691e 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -1411,9 +1411,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A this.task = newTask; if (shouldStartChangeTransition(newParent, oldParent)) { - // The new parent and old parent may be in different position. Need to offset the - // animation surface to keep it in its original position. - initializeChangeTransition(getBounds(), newParent.getBounds()); + // Animate change transition on TaskFragment level to get the correct window crop. + newParent.initializeChangeTransition(getBounds(), getSurfaceControl()); } super.onParentChanged(newParent, oldParent); @@ -1532,7 +1531,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } // TODO(b/169035022): move to a more-appropriate place. - mAtmService.getTransitionController().collect(this); + mTransitionController.collect(this); if (prevDc.mOpeningApps.remove(this)) { // Transfer opening transition to new display. mDisplayContent.mOpeningApps.add(this); @@ -3097,9 +3096,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A mAtmService.deferWindowLayout(); try { - final Transition newTransition = (!mAtmService.getTransitionController().isCollecting() - && mAtmService.getTransitionController().getTransitionPlayer() != null) - ? mAtmService.getTransitionController().createTransition(TRANSIT_CLOSE) : null; + final Transition newTransition = (!mTransitionController.isCollecting() + && mTransitionController.getTransitionPlayer() != null) + ? mTransitionController.createTransition(TRANSIT_CLOSE) : null; mTaskSupervisor.mNoHistoryActivities.remove(this); makeFinishingLocked(); // Make a local reference to its task since this.task could be set to null once this @@ -3132,7 +3131,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A final boolean endTask = task.getTopNonFinishingActivity() == null && !task.isClearingToReuseTask(); if (newTransition != null) { - mAtmService.getTransitionController().requestStartTransition(newTransition, + mTransitionController.requestStartTransition(newTransition, endTask ? task : null, null /* remote */); } if (isState(RESUMED)) { @@ -3560,12 +3559,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A if (stopped) { abortAndClearOptionsAnimation(); } - if (mAtmService.getTransitionController().isCollecting()) { + if (mTransitionController.isCollecting()) { // We don't want the finishing to change the transition ready state since there will not // be corresponding setReady for finishing. - mAtmService.getTransitionController().collectExistenceChange(this); + mTransitionController.collectExistenceChange(this); } else { - mAtmService.getTransitionController().requestTransitionIfNeeded(TRANSIT_CLOSE, this); + mTransitionController.requestTransitionIfNeeded(TRANSIT_CLOSE, this); } } @@ -3817,7 +3816,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } else if (getDisplayContent().mAppTransition.isTransitionSet()) { getDisplayContent().mClosingApps.add(this); delayed = true; - } else if (mAtmService.getTransitionController().inTransition()) { + } else if (mTransitionController.inTransition()) { delayed = true; } @@ -3829,7 +3828,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } // TODO(b/169035022): move to a more-appropriate place. - mAtmService.getTransitionController().collect(this); + mTransitionController.collect(this); ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "Removing app %s delayed=%b animation=%s animating=%b", this, delayed, @@ -4030,7 +4029,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A ProtoLog.v(WM_DEBUG_ADD_REMOVE, "Removing starting %s from %s", tStartingWindow, fromActivity); - mAtmService.getTransitionController().collect(tStartingWindow); + mTransitionController.collect(tStartingWindow); tStartingWindow.reparent(this, POSITION_TOP); // Propagate other interesting state between the tokens. If the old token is displayed, @@ -4056,7 +4055,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // the token we transfer the animation over. Thus, set this flag to indicate // we've transferred the animation. mUseTransferredAnimation = true; - } else if (mAtmService.getTransitionController().getTransitionPlayer() != null) { + } else if (mTransitionController.getTransitionPlayer() != null) { // In the new transit system, just set this every time we transfer the window mUseTransferredAnimation = true; } @@ -4553,8 +4552,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } if (options != null) { - mAtmService.getTransitionController().setOverrideAnimation(options, - startCallback, finishCallback); + mTransitionController.setOverrideAnimation(options, startCallback, finishCallback); } } @@ -4785,7 +4783,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A Debug.getCallers(6)); // Before setting mVisibleRequested so we can track changes. - mAtmService.getTransitionController().collect(this); + mTransitionController.collect(this); onChildVisibilityRequested(visible); @@ -4857,7 +4855,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } // If in a transition, defer commits for activities that are going invisible - if (!visible && mAtmService.getTransitionController().inTransition(this)) { + if (!visible && inTransition()) { return; } // If we are preparing an app transition, then delay changing @@ -4942,7 +4940,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } else { // If we are being set visible, and the starting window is not yet displayed, // then make sure it doesn't get displayed. - if (mStartingWindow != null && !mStartingWindow.isDrawn()) { + if (mStartingWindow != null && !mStartingWindow.isDrawn() + && (firstWindowDrawn || allDrawn)) { mStartingWindow.clearPolicyVisibilityFlag(LEGACY_POLICY_VISIBILITY); mStartingWindow.mLegacyPolicyVisibilityAfterAnim = false; } @@ -4984,8 +4983,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A * this has become invisible. */ private void postApplyAnimation(boolean visible) { - final boolean usingShellTransitions = - mAtmService.getTransitionController().getTransitionPlayer() != null; + final boolean usingShellTransitions = mTransitionController.isShellTransitionsEnabled(); final boolean delayed = isAnimating(TRANSITION | PARENTS | CHILDREN, ANIMATION_TYPE_APP_TRANSITION | ANIMATION_TYPE_WINDOW_ANIMATION | ANIMATION_TYPE_RECENTS); @@ -5435,7 +5433,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // returns. Just need to confirm this reasoning makes sense. final boolean deferHidingClient = canEnterPictureInPicture && !isState(STARTED, STOPPING, STOPPED, PAUSED); - if (!mAtmService.getTransitionController().isShellTransitionsEnabled() + if (!mTransitionController.isShellTransitionsEnabled() && deferHidingClient && pictureInPictureArgs.isAutoEnterEnabled()) { // Go ahead and just put the activity in pip if it supports auto-pip. mAtmService.enterPictureInPictureMode(this, pictureInPictureArgs); @@ -5957,7 +5955,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } void startFreezingScreen(int overrideOriginalDisplayRotation) { - if (mAtmService.getTransitionController().isShellTransitionsEnabled()) { + if (mTransitionController.isShellTransitionsEnabled()) { return; } ProtoLog.i(WM_DEBUG_ORIENTATION, @@ -7603,7 +7601,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } boolean isInTransition() { - return mAtmService.getTransitionController().inTransition() // Shell transitions. + return mTransitionController.inTransition() // Shell transitions. || isAnimating(PARENTS | TRANSITION); // Legacy transitions. } diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java index 980ebf0646e8..170789569b3f 100644 --- a/services/core/java/com/android/server/wm/ActivityStarter.java +++ b/services/core/java/com/android/server/wm/ActivityStarter.java @@ -1564,14 +1564,15 @@ class ActivityStarter { // startActivityInner. Otherwise, logic in startActivityInner could start a different // transition based on a sub-action. // Only do the create here (and defer requestStart) since startActivityInner might abort. - final Transition newTransition = (!mService.getTransitionController().isCollecting() - && mService.getTransitionController().getTransitionPlayer() != null) - ? mService.getTransitionController().createTransition(TRANSIT_OPEN) : null; + final TransitionController transitionController = r.mTransitionController; + final Transition newTransition = (!transitionController.isCollecting() + && transitionController.getTransitionPlayer() != null) + ? transitionController.createTransition(TRANSIT_OPEN) : null; RemoteTransition remoteTransition = r.takeRemoteTransition(); if (newTransition != null && remoteTransition != null) { newTransition.setRemoteTransition(remoteTransition); } - mService.getTransitionController().collect(r); + transitionController.collect(r); final boolean isTransient = r.getOptions() != null && r.getOptions().getTransientLaunch(); try { mService.deferWindowLayout(); @@ -1618,19 +1619,19 @@ class ActivityStarter { if (started) { // The activity is started new rather than just brought forward, so record // it as an existence change. - mService.getTransitionController().collectExistenceChange(r); + transitionController.collectExistenceChange(r); } if (isTransient) { // `r` isn't guaranteed to be the actual relevant activity, so we must wait // until after we launched to identify the relevant activity. - mService.getTransitionController().setTransientLaunch(mLastStartActivityRecord); + transitionController.setTransientLaunch(mLastStartActivityRecord); } if (newTransition != null) { - mService.getTransitionController().requestStartTransition(newTransition, + transitionController.requestStartTransition(newTransition, mTargetTask, remoteTransition); } else if (started) { // Make the collecting transition wait until this request is ready. - mService.getTransitionController().setReady(r, false); + transitionController.setReady(r, false); } } } @@ -2769,7 +2770,7 @@ class ActivityStarter { mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info, mNewTaskIntent != null ? mNewTaskIntent : mIntent, mVoiceSession, mVoiceInteractor, toTop, mStartActivity, mSourceRecord, mOptions); - mService.getTransitionController().collectExistenceChange(task); + task.mTransitionController.collectExistenceChange(task); addOrReparentStartingActivity(task, "setTaskFromReuseOrCreateNewTask - mReuseTask"); ProtoLog.v(WM_DEBUG_TASKS, "Starting new activity %s in new task %s", diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java index 11936b21bd4e..ba305929d808 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java +++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java @@ -853,10 +853,6 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { proc.getThread(), r.appToken); final boolean isTransitionForward = r.isTransitionForward(); - IBinder fragmentToken = null; - if (r.getTaskFragment().getTaskFragmentOrganizerPid() == r.getPid()) { - fragmentToken = r.getTaskFragment().getFragmentToken(); - } clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent), System.identityHashCode(r), r.info, // TODO: Have this take the merged configuration instead of separate global @@ -868,7 +864,7 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { results, newIntents, r.takeOptions(), isTransitionForward, proc.createProfilerInfoIfNeeded(), r.assistToken, activityClientController, r.createFixedRotationAdjustmentsIfNeeded(), r.shareableActivityToken, - r.getLaunchedFromBubble(), fragmentToken)); + r.getLaunchedFromBubble())); // Set desired final state. final ActivityLifecycleItem lifecycleItem; @@ -1391,7 +1387,7 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { mUserLeaving = true; } - mService.getTransitionController().requestTransitionIfNeeded(TRANSIT_TO_FRONT, + task.mTransitionController.requestTransitionIfNeeded(TRANSIT_TO_FRONT, 0 /* flags */, task, task /* readyGroupRef */, options != null ? options.getRemoteTransition() : null); reason = reason + " findTaskToMoveToFront"; @@ -1567,17 +1563,17 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { return; } if (task.isVisible()) { - if (mService.getTransitionController().isCollecting()) { + if (task.mTransitionController.isCollecting()) { // We don't want the finishing to change the transition ready state since there will // not be corresponding setReady for finishing. - mService.getTransitionController().collectExistenceChange(task); + task.mTransitionController.collectExistenceChange(task); } else { - mService.getTransitionController().requestTransitionIfNeeded(TRANSIT_CLOSE, task); + task.mTransitionController.requestTransitionIfNeeded(TRANSIT_CLOSE, task); } } else { // Removing a non-visible task doesn't require a transition, but if there is one // collecting, this should be a member just in case. - mService.getTransitionController().collect(task); + task.mTransitionController.collect(task); } task.mInRemoveTask = true; try { @@ -1891,7 +1887,7 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { final ActivityRecord s = mStoppingActivities.get(i); final boolean animating = s.isAnimating(TRANSITION | PARENTS, ANIMATION_TYPE_APP_TRANSITION | ANIMATION_TYPE_RECENTS) - || mService.getTransitionController().inTransition(s); + || s.inTransition(); ProtoLog.v(WM_DEBUG_STATES, "Stopping %s: nowVisible=%b animating=%b " + "finishing=%s", s, s.nowVisible, animating, s.finishing); if (!animating || mService.mShuttingDown) { @@ -2192,7 +2188,7 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { } if (!task.supportsSplitScreenWindowingMode() || forceNonResizable) { - if (mService.getTransitionController().getTransitionPlayer() != null) return; + if (task.mTransitionController.isShellTransitionsEnabled()) return; // Dismiss docked root task. If task appeared to be in docked root task but is not // resizable - we need to move it to top of fullscreen root task, otherwise it will // be covered. diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java index 929ac56f740e..e21a00b4aec6 100644 --- a/services/core/java/com/android/server/wm/AppTransition.java +++ b/services/core/java/com/android/server/wm/AppTransition.java @@ -1547,7 +1547,7 @@ public class AppTransition implements Dump { } boolean prepareAppTransition(@TransitionType int transit, @TransitionFlags int flags) { - if (mService.mAtmService.getTransitionController().getTransitionPlayer() != null) { + if (mDisplayContent.mTransitionController.isShellTransitionsEnabled()) { return false; } mNextAppTransitionRequests.add(transit); diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java index 10ed8dc3dcb6..0e04c426ce1e 100644 --- a/services/core/java/com/android/server/wm/AppTransitionController.java +++ b/services/core/java/com/android/server/wm/AppTransitionController.java @@ -343,9 +343,6 @@ public class AppTransitionController { switch (changingType) { case TYPE_TASK: return TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE; - case TYPE_ACTIVITY: - // ActivityRecord is put in a change transition only when it is reparented - // to an organized TaskFragment. See ActivityRecord#shouldStartChangeTransition. case TYPE_TASK_FRAGMENT: return TRANSIT_OLD_TASK_FRAGMENT_CHANGE; default: @@ -1111,6 +1108,11 @@ public class AppTransitionController { // the same transition. for (int i = rootTasks.size() - 1; i >= 0; i--) { final Task rootTask = rootTasks.valueAt(i); + if (rootTask == null) { + // It is possible that one activity may have been removed from the hierarchy. No + // need to check for this case. + continue; + } final boolean notReady = rootTask.forAllLeafTaskFragments(taskFragment -> { if (!taskFragment.isReadyToTransit()) { ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "Organized TaskFragment is not ready= %s", diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index f800f0e395de..1db4c1da2023 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -1064,7 +1064,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp mAppTransition = new AppTransition(mWmService.mContext, mWmService, this); mAppTransition.registerListenerLocked(mWmService.mActivityManagerAppTransitionNotifier); - mAtmService.getTransitionController().registerLegacyListener( + mTransitionController.registerLegacyListener( mWmService.mActivityManagerAppTransitionNotifier); mAppTransition.registerListenerLocked(mFixedRotationTransitionListener); mAppTransitionController = new AppTransitionController(mWmService, this); @@ -1395,7 +1395,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp if (configChanged) { mWaitingForConfig = true; - if (mAtmService.getTransitionController().isShellTransitionsEnabled()) { + if (mTransitionController.isShellTransitionsEnabled()) { requestChangeTransitionIfNeeded(changes); } else { mWmService.startFreezingDisplay(0 /* exitAnim */, 0 /* enterAnim */, this); @@ -1515,7 +1515,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp } else if (currentConfig != null // If waiting for a remote rotation, don't prematurely update configuration. && !(mDisplayRotation.isWaitingForRemoteRotation() - || mAtmService.getTransitionController().isCollecting(this))) { + || mTransitionController.isCollecting(this))) { // No obvious action we need to take, but if our current state mismatches the // activity manager's, update it, disregarding font scale, which should remain set // to the value of the previous configuration. @@ -1914,8 +1914,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp */ private void applyRotation(final int oldRotation, final int rotation) { mDisplayRotation.applyCurrentRotation(rotation); - final boolean shellTransitions = - mWmService.mAtmService.getTransitionController().getTransitionPlayer() != null; + final boolean shellTransitions = mTransitionController.getTransitionPlayer() != null; final boolean rotateSeamlessly = mDisplayRotation.isRotatingSeamlessly() && !shellTransitions; final Transaction transaction = @@ -3070,7 +3069,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp if (isAnimating(TRANSITION | PARENTS) // isAnimating is a legacy transition query and will be removed, so also add a // check for whether this is in a shell-transition when not using legacy. - || mAtmService.getTransitionController().inTransition()) { + || mTransitionController.inTransition()) { mDeferredRemoval = true; return; } @@ -3176,7 +3175,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp * be non-zero. This method is no-op if the display has been collected. */ void requestChangeTransitionIfNeeded(@ActivityInfo.Config int changes) { - final TransitionController controller = mAtmService.getTransitionController(); + final TransitionController controller = mTransitionController; if (controller.isCollecting()) { if (!controller.isCollecting(this)) { controller.collect(this); @@ -3215,8 +3214,8 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp screenRotationAnimation.dumpDebug(proto, SCREEN_ROTATION_ANIMATION); } mDisplayFrames.dumpDebug(proto, DISPLAY_FRAMES); - if (mAtmService.getTransitionController().isShellTransitionsEnabled()) { - mAtmService.getTransitionController().dumpDebugLegacy(proto, APP_TRANSITION); + if (mTransitionController.isShellTransitionsEnabled()) { + mTransitionController.dumpDebugLegacy(proto, APP_TRANSITION); } else { mAppTransition.dumpDebug(proto, APP_TRANSITION); } @@ -5109,7 +5108,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp void requestTransitionAndLegacyPrepare(@WindowManager.TransitionType int transit, @WindowManager.TransitionFlags int flags) { prepareAppTransition(transit, flags); - mAtmService.getTransitionController().requestTransitionIfNeeded(transit, flags, + mTransitionController.requestTransitionIfNeeded(transit, flags, null /* trigger */, this); } @@ -5117,12 +5116,12 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp void requestTransitionAndLegacyPrepare(@WindowManager.TransitionType int transit, @Nullable WindowContainer trigger) { prepareAppTransition(transit); - mAtmService.getTransitionController().requestTransitionIfNeeded(transit, 0 /* flags */, + mTransitionController.requestTransitionIfNeeded(transit, 0 /* flags */, trigger, this); } void executeAppTransition() { - mAtmService.getTransitionController().setReady(this); + mTransitionController.setReady(this); if (mAppTransition.isTransitionSet()) { ProtoLog.w(WM_DEBUG_APP_TRANSITIONS, "Execute app transition: %s, displayId: %d Callers=%s", @@ -5171,9 +5170,9 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp /** Check if pending app transition is for activity / task launch. */ boolean isNextTransitionForward() { // TODO(b/191375840): decouple "forwardness" from transition system. - if (mAtmService.getTransitionController().isShellTransitionsEnabled()) { + if (mTransitionController.isShellTransitionsEnabled()) { @WindowManager.TransitionType int type = - mAtmService.getTransitionController().getCollectingTransitionType(); + mTransitionController.getCollectingTransitionType(); return type == TRANSIT_OPEN || type == TRANSIT_TO_FRONT; } return mAppTransition.containsTransitRequest(TRANSIT_OPEN) @@ -5748,7 +5747,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp } mWmService.mDisplayNotificationController.dispatchDisplayChanged( this, getConfiguration()); - if (isReady() && mAtmService.getTransitionController().isShellTransitionsEnabled()) { + if (isReady() && mTransitionController.isShellTransitionsEnabled()) { requestChangeTransitionIfNeeded(changes); } } diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java index 3dff680c9497..ccfb174e3d16 100644 --- a/services/core/java/com/android/server/wm/DisplayPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayPolicy.java @@ -641,8 +641,7 @@ public class DisplayPolicy { } }; displayContent.mAppTransition.registerListenerLocked(mAppTransitionListener); - mService.mAtmService.getTransitionController().registerLegacyListener( - mAppTransitionListener); + displayContent.mTransitionController.registerLegacyListener(mAppTransitionListener); mImmersiveModeConfirmation = new ImmersiveModeConfirmation(mContext, looper, mService.mVrModeEnabled); @@ -3145,6 +3144,7 @@ public class DisplayPolicy { pw.print(" mAllowLockscreenWhenOn="); pw.println(mAllowLockscreenWhenOn); pw.print(prefix); pw.print("mRemoteInsetsControllerControlsSystemBars="); pw.println(mDisplayContent.getInsetsPolicy().getRemoteInsetsControllerControlsSystemBars()); + mSystemGestures.dump(pw, prefix); pw.print(prefix); pw.println("Looper state:"); mHandler.getLooper().dump(new PrintWriterPrinter(pw), prefix + " "); diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java index 225a6ea20f3d..34e81498b1c3 100644 --- a/services/core/java/com/android/server/wm/DisplayRotation.java +++ b/services/core/java/com/android/server/wm/DisplayRotation.java @@ -413,7 +413,7 @@ public class DisplayRotation { */ boolean updateRotationUnchecked(boolean forceUpdate) { final boolean useShellTransitions = - mService.mAtmService.getTransitionController().getTransitionPlayer() != null; + mDisplayContent.mTransitionController.isShellTransitionsEnabled(); final int displayId = mDisplayContent.getDisplayId(); if (!forceUpdate && !useShellTransitions) { @@ -586,17 +586,17 @@ public class DisplayRotation { mService.mH.removeCallbacks(mDisplayRotationHandlerTimeout); mIsWaitingForRemoteRotation = false; - if (mService.mAtmService.getTransitionController().getTransitionPlayer() != null) { - if (!mService.mAtmService.getTransitionController().isCollecting()) { + if (mDisplayContent.mTransitionController.isShellTransitionsEnabled()) { + if (!mDisplayContent.mTransitionController.isCollecting()) { throw new IllegalStateException("Trying to rotate outside a transition"); } - mService.mAtmService.getTransitionController().collect(mDisplayContent); + mDisplayContent.mTransitionController.collect(mDisplayContent); // Go through all tasks and collect them before the rotation // TODO(shell-transitions): move collect() to onConfigurationChange once wallpaper // handling is synchronized. mDisplayContent.forAllTasks(task -> { if (task.isVisible()) { - mService.mAtmService.getTransitionController().collect(task); + mDisplayContent.mTransitionController.collect(task); } }); mDisplayContent.getInsetsStateController().addProvidersToTransition(); diff --git a/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java b/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java index 6560d15ca744..cddb1e7edb3b 100644 --- a/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java +++ b/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java @@ -135,7 +135,7 @@ class EnsureActivitiesVisibleHelper { setActivityVisibilityState(child.asActivityRecord(), starting, resumeTopActivity); } } - if (mTaskFragment.mAtmService.getTransitionController().getTransitionPlayer() != null) { + if (mTaskFragment.mTransitionController.isShellTransitionsEnabled()) { mTaskFragment.getDisplayContent().mWallpaperController.adjustWallpaperWindows(); } } diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java index 2c4adcbf1404..c4ca8e364011 100644 --- a/services/core/java/com/android/server/wm/InsetsStateController.java +++ b/services/core/java/com/android/server/wm/InsetsStateController.java @@ -254,7 +254,7 @@ class InsetsStateController { if (p == null) continue; final WindowContainer wc = p.mWin; if (wc == null) continue; - mDisplayContent.mAtmService.getTransitionController().collect(wc); + mDisplayContent.mTransitionController.collect(wc); } } diff --git a/services/core/java/com/android/server/wm/Letterbox.java b/services/core/java/com/android/server/wm/Letterbox.java index 45411a946f55..4b98013a99cc 100644 --- a/services/core/java/com/android/server/wm/Letterbox.java +++ b/services/core/java/com/android/server/wm/Letterbox.java @@ -36,6 +36,7 @@ import android.view.WindowManager; import com.android.server.UiThread; +import java.util.function.IntConsumer; import java.util.function.Supplier; /** @@ -70,7 +71,7 @@ public class Letterbox { private final LetterboxSurface mFullWindowSurface = new LetterboxSurface("fullWindow"); private final LetterboxSurface[] mSurfaces = { mLeft, mTop, mRight, mBottom }; // Reachability gestures. - private final Runnable mDoubleTapCallback; + private final IntConsumer mDoubleTapCallback; /** * Constructs a Letterbox. @@ -84,7 +85,7 @@ public class Letterbox { Supplier<Boolean> hasWallpaperBackgroundSupplier, Supplier<Integer> blurRadiusSupplier, Supplier<Float> darkScrimAlphaSupplier, - Runnable doubleTapCallback) { + IntConsumer doubleTapCallback) { mSurfaceControlFactory = surfaceControlFactory; mTransactionFactory = transactionFactory; mAreCornersRounded = areCornersRounded; @@ -262,7 +263,7 @@ public class Letterbox { @Override public boolean onDoubleTapEvent(MotionEvent e) { if (e.getAction() == MotionEvent.ACTION_UP) { - mDoubleTapCallback.run(); + mDoubleTapCallback.accept((int) e.getX()); return true; } return false; diff --git a/services/core/java/com/android/server/wm/LetterboxConfiguration.java b/services/core/java/com/android/server/wm/LetterboxConfiguration.java index 72fbfcc2959e..cbb473c10c6d 100644 --- a/services/core/java/com/android/server/wm/LetterboxConfiguration.java +++ b/services/core/java/com/android/server/wm/LetterboxConfiguration.java @@ -54,6 +54,27 @@ final class LetterboxConfiguration { /** Using wallpaper as a background which can be blurred or dimmed with dark scrim. */ static final int LETTERBOX_BACKGROUND_WALLPAPER = 3; + /** + * Enum for Letterbox reachability position types. + * + * <p>Order from left to right is important since it's used in {@link + * #movePositionForReachabilityToNextRightStop} and {@link + * #movePositionForReachabilityToNextLeftStop}. + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef({LETTERBOX_REACHABILITY_POSITION_LEFT, LETTERBOX_REACHABILITY_POSITION_CENTER, + LETTERBOX_REACHABILITY_POSITION_RIGHT}) + @interface LetterboxReachabilityPosition {}; + + /** Letterboxed app window is aligned to the left side. */ + static final int LETTERBOX_REACHABILITY_POSITION_LEFT = 0; + + /** Letterboxed app window is positioned in the horizontal center. */ + static final int LETTERBOX_REACHABILITY_POSITION_CENTER = 1; + + /** Letterboxed app window is aligned to the right side. */ + static final int LETTERBOX_REACHABILITY_POSITION_RIGHT = 2; + final Context mContext; // Aspect ratio of letterbox for fixed orientation, values <= @@ -85,25 +106,25 @@ final class LetterboxConfiguration { // side of the screen and 1.0 to the right side. private float mLetterboxHorizontalPositionMultiplier; - // Default horizontal position of a center of the letterboxed app window when reachability is - // enabled and an app is fullscreen in landscape device orientatio. 0 corresponds to the left - // side of the screen and 1.0 to the right side. - // It is used as a starting point for mLetterboxHorizontalMultiplierForReachability. - private float mDefaultPositionMultiplierForReachability; + // Default horizontal position the letterboxed app window when reachability is enabled and + // an app is fullscreen in landscape device orientatio. + // It is used as a starting point for mLetterboxPositionForReachability. + @LetterboxReachabilityPosition + private int mDefaultPositionForReachability; // Whether reachability repositioning is allowed for letterboxed fullscreen apps in landscape // device orientation. private boolean mIsReachabilityEnabled; - // Horizontal position of a center of the letterboxed app window. 0 corresponds to - // the left side of the screen and 1 to the right side. Keep it global to prevent - // "jumps" when switching between letterboxed apps. It's updated to reposition the app - // window in response to a double tap gesture (see LetterboxUiController#handleDoubleTap). - // Used in LetterboxUiController#getHorizontalPositionMultiplier which is called from + // Horizontal position of a center of the letterboxed app window which is global to prevent + // "jumps" when switching between letterboxed apps. It's updated to reposition the app window + // in response to a double tap gesture (see LetterboxUiController#handleDoubleTap). Used in + // LetterboxUiController#getHorizontalPositionMultiplier which is called from // ActivityRecord#updateResolvedBoundsHorizontalPosition. // TODO(b/199426138): Global reachability setting causes a jump when resuming an app from // Overview after changing position in another app. - private volatile float mLetterboxHorizontalMultiplierForReachability; + @LetterboxReachabilityPosition + private volatile int mLetterboxPositionForReachability; LetterboxConfiguration(Context systemUiContext) { mContext = systemUiContext; @@ -120,9 +141,8 @@ final class LetterboxConfiguration { R.dimen.config_letterboxHorizontalPositionMultiplier); mIsReachabilityEnabled = mContext.getResources().getBoolean( R.bool.config_letterboxIsReachabilityEnabled); - mDefaultPositionMultiplierForReachability = mContext.getResources().getFloat( - R.dimen.config_letterboxDefaultPositionMultiplierForReachability); - mLetterboxHorizontalMultiplierForReachability = mDefaultPositionMultiplierForReachability; + mDefaultPositionForReachability = readLetterboxReachabilityPositionFromConfig(mContext); + mLetterboxPositionForReachability = mDefaultPositionForReachability; } /** @@ -395,58 +415,90 @@ final class LetterboxConfiguration { } /* - * Gets default horizontal position of a center of the letterboxed app window when reachability - * is enabled specified in {@link - * R.dimen.config_letterboxDefaultPositionMultiplierForReachability} or via an ADB command. - * 0 corresponds to the left side of the screen and 1 to the right side. The returned value is - * >= 0.0 and <= 1.0. + * Gets default horizontal position of the letterboxed app window when reachability is enabled. + * Specified in {@link R.integer.config_letterboxDefaultPositionForReachability} or via an ADB + * command. */ - float getDefaultPositionMultiplierForReachability() { - return (mDefaultPositionMultiplierForReachability < 0.0f - || mDefaultPositionMultiplierForReachability > 1.0f) - // Default to a right position if invalid value is provided. - ? 1.0f : mDefaultPositionMultiplierForReachability; + @LetterboxReachabilityPosition + int getDefaultPositionForReachability() { + return mDefaultPositionForReachability; } /** - * Overrides default horizontal position of a center of the letterboxed app window when - * reachability is enabled. If given value < 0.0 or > 1.0, then it and a value of {@link - * R.dimen.config_letterboxDefaultPositionMultiplierForReachability} are ignored and the right - * position (1.0) is used. + * Overrides default horizonal position of the letterboxed app window when reachability + * is enabled. */ - void setDefaultPositionMultiplierForReachability(float multiplier) { - mDefaultPositionMultiplierForReachability = multiplier; + void setDefaultPositionForReachability(@LetterboxReachabilityPosition int position) { + mDefaultPositionForReachability = position; } /** - * Resets default horizontal position of a center of the letterboxed app window when - * reachability is enabled to {@link - * R.dimen.config_letterboxDefaultPositionMultiplierForReachability}. + * Resets default horizontal position of the letterboxed app window when reachability is + * enabled to {@link R.integer.config_letterboxDefaultPositionForReachability}. */ - void resetDefaultPositionMultiplierForReachability() { - mDefaultPositionMultiplierForReachability = mContext.getResources().getFloat( - R.dimen.config_letterboxDefaultPositionMultiplierForReachability); + void resetDefaultPositionForReachability() { + mDefaultPositionForReachability = readLetterboxReachabilityPositionFromConfig(mContext); + } + + @LetterboxReachabilityPosition + private static int readLetterboxReachabilityPositionFromConfig(Context context) { + int position = context.getResources().getInteger( + R.integer.config_letterboxDefaultPositionForReachability); + return position == LETTERBOX_REACHABILITY_POSITION_LEFT + || position == LETTERBOX_REACHABILITY_POSITION_CENTER + || position == LETTERBOX_REACHABILITY_POSITION_RIGHT + ? position : LETTERBOX_REACHABILITY_POSITION_CENTER; } /* * Gets horizontal position of a center of the letterboxed app window when reachability * is enabled specified. 0 corresponds to the left side of the screen and 1 to the right side. * - * <p>The position multiplier is changed to a symmetrical value computed as (1 - current - * multiplier) after each double tap in the letterbox area. + * <p>The position multiplier is changed after each double tap in the letterbox area. */ float getHorizontalMultiplierForReachability() { - return mLetterboxHorizontalMultiplierForReachability; + switch (mLetterboxPositionForReachability) { + case LETTERBOX_REACHABILITY_POSITION_LEFT: + return 0.0f; + case LETTERBOX_REACHABILITY_POSITION_CENTER: + return 0.5f; + case LETTERBOX_REACHABILITY_POSITION_RIGHT: + return 1.0f; + default: + throw new AssertionError( + "Unexpected letterbox position type: " + mLetterboxPositionForReachability); + } + } + + /** Returns a string representing the given {@link LetterboxReachabilityPosition}. */ + static String letterboxReachabilityPositionToString( + @LetterboxReachabilityPosition int position) { + switch (position) { + case LETTERBOX_REACHABILITY_POSITION_LEFT: + return "LETTERBOX_REACHABILITY_POSITION_LEFT"; + case LETTERBOX_REACHABILITY_POSITION_CENTER: + return "LETTERBOX_REACHABILITY_POSITION_CENTER"; + case LETTERBOX_REACHABILITY_POSITION_RIGHT: + return "LETTERBOX_REACHABILITY_POSITION_RIGHT"; + default: + throw new AssertionError( + "Unexpected letterbox position type: " + position); + } + } + + /** + * Changes letterbox position for reachability to the next available one on the right side. + */ + void movePositionForReachabilityToNextRightStop() { + mLetterboxPositionForReachability = Math.min( + mLetterboxPositionForReachability + 1, LETTERBOX_REACHABILITY_POSITION_RIGHT); } /** - * Changes horizontal position of a center of the letterboxed app window to the opposite - * (1 - current multiplier) when reachability is enabled specified. 0 corresponds to the left - * side of the screen and 1 to the right side. + * Changes letterbox position for reachability to the next available one on the left side. */ - void flipHorizontalMultiplierForReachability() { - mLetterboxHorizontalMultiplierForReachability = - 1.0f - mLetterboxHorizontalMultiplierForReachability; + void movePositionForReachabilityToNextLeftStop() { + mLetterboxPositionForReachability = Math.max(mLetterboxPositionForReachability - 1, 0); } } diff --git a/services/core/java/com/android/server/wm/LetterboxUiController.java b/services/core/java/com/android/server/wm/LetterboxUiController.java index cf2afc93c419..7d073573835f 100644 --- a/services/core/java/com/android/server/wm/LetterboxUiController.java +++ b/services/core/java/com/android/server/wm/LetterboxUiController.java @@ -65,6 +65,10 @@ final class LetterboxUiController { private final LetterboxConfiguration mLetterboxConfiguration; private final ActivityRecord mActivityRecord; + // Taskbar expanded height. Used to determine whether to crop an app window to display rounded + // corners above the taskbar. + private float mExpandedTaskBarHeight; + private boolean mShowWallpaperForLetterboxBackground; @Nullable @@ -76,6 +80,8 @@ final class LetterboxUiController { // is created in its constructor. It shouldn't be used in this constructor but it's safe // to use it after since controller is only used in ActivityRecord. mActivityRecord = activityRecord; + mExpandedTaskBarHeight = + getResources().getDimensionPixelSize(R.dimen.taskbar_frame_height); } /** Cleans up {@link Letterbox} if it exists.*/ @@ -204,12 +210,23 @@ final class LetterboxUiController { return mActivityRecord.mWmService.mContext.getResources(); } - private void handleDoubleTap() { + private void handleDoubleTap(int x) { if (!isReachabilityEnabled() || mActivityRecord.isInTransition()) { return; } - mLetterboxConfiguration.flipHorizontalMultiplierForReachability(); + if (mLetterbox.getInnerFrame().left <= x && mLetterbox.getInnerFrame().right >= x) { + // Only react to clicks at the sides of the letterboxed app window. + return; + } + + if (mLetterbox.getInnerFrame().left > x) { + // Moving to the next stop on the left side of the app window: right > center > left. + mLetterboxConfiguration.movePositionForReachabilityToNextLeftStop(); + } else if (mLetterbox.getInnerFrame().right < x) { + // Moving to the next stop on the right side of the app window: left > center > right. + mLetterboxConfiguration.movePositionForReachabilityToNextRightStop(); + } // TODO(197549949): Add animation for transition. mActivityRecord.recomputeConfiguration(); @@ -314,12 +331,27 @@ final class LetterboxUiController { final InsetsSource taskbarInsetsSource = insetsState.getSource(InsetsState.ITYPE_EXTRA_NAVIGATION_BAR); - Rect cropBounds = new Rect(mActivityRecord.getBounds()); - // Activity bounds are in screen coordinates while (0,0) for activity's surface control - // is at the top left corner of an app window so offsetting bounds accordingly. - cropBounds.offsetTo(0, 0); - // Rounded cornerners should be displayed above the taskbar. - cropBounds.bottom = Math.min(cropBounds.bottom, taskbarInsetsSource.getFrame().top); + Rect cropBounds = null; + + // Rounded corners should be displayed above the taskbar. When taskbar is hidden, + // an insets frame is equal to a navigation bar which shouldn't affect position of + // rounded corners since apps are expected to handle navigation bar inset. + // This condition checks whether the taskbar is visible. + if (taskbarInsetsSource.getFrame().height() >= mExpandedTaskBarHeight) { + cropBounds = new Rect(mActivityRecord.getBounds()); + // Activity bounds are in screen coordinates while (0,0) for activity's surface + // control is at the top left corner of an app window so offsetting bounds + // accordingly. + cropBounds.offsetTo(0, 0); + // Rounded cornerners should be displayed above the taskbar. + cropBounds.bottom = + Math.min(cropBounds.bottom, taskbarInsetsSource.getFrame().top); + if (mActivityRecord.inSizeCompatMode() + && mActivityRecord.getSizeCompatScale() < 1.0f) { + cropBounds.scale(1.0f / mActivityRecord.getSizeCompatScale()); + } + } + transaction .setWindowCrop(windowSurface, cropBounds) .setCornerRadius(windowSurface, getRoundedCorners(insetsState)); diff --git a/services/core/java/com/android/server/wm/PinnedTaskController.java b/services/core/java/com/android/server/wm/PinnedTaskController.java index 6014a87ae8f7..b4963c5b9f1c 100644 --- a/services/core/java/com/android/server/wm/PinnedTaskController.java +++ b/services/core/java/com/android/server/wm/PinnedTaskController.java @@ -211,7 +211,7 @@ class PinnedTaskController { } mFreezingTaskConfig = true; mDestRotatedBounds = new Rect(bounds); - if (!mService.mAtmService.getTransitionController().isShellTransitionsEnabled()) { + if (!mDisplayContent.mTransitionController.isShellTransitionsEnabled()) { continueOrientationChange(); } } diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index 40207882d73c..97ea41c2f228 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -2211,7 +2211,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> // display area, so reparent. rootTask.reparent(taskDisplayArea, true /* onTop */); } - mService.getTransitionController().requestTransitionIfNeeded(TRANSIT_PIP, rootTask); + rootTask.mTransitionController.requestTransitionIfNeeded(TRANSIT_PIP, rootTask); // Defer the windowing mode change until after the transition to prevent the activity // from doing work and changing the activity visuals while animating diff --git a/services/core/java/com/android/server/wm/SurfaceFreezer.java b/services/core/java/com/android/server/wm/SurfaceFreezer.java index 9c4f6f574487..89986cefb207 100644 --- a/services/core/java/com/android/server/wm/SurfaceFreezer.java +++ b/services/core/java/com/android/server/wm/SurfaceFreezer.java @@ -72,8 +72,11 @@ class SurfaceFreezer { * * @param startBounds The original bounds (on screen) of the surface we are snapshotting. * @param relativePosition The related position of the snapshot surface to its parent. + * @param freezeTarget The surface to take snapshot from. If {@code null}, we will take a + * snapshot from the {@link #mAnimatable} surface. */ - void freeze(SurfaceControl.Transaction t, Rect startBounds, Point relativePosition) { + void freeze(SurfaceControl.Transaction t, Rect startBounds, Point relativePosition, + @Nullable SurfaceControl freezeTarget) { mFreezeBounds.set(startBounds); mLeash = SurfaceAnimator.createAnimationLeash(mAnimatable, mAnimatable.getSurfaceControl(), @@ -82,7 +85,7 @@ class SurfaceFreezer { mWmService.mTransactionFactory); mAnimatable.onAnimationLeashCreated(t, mLeash); - SurfaceControl freezeTarget = mAnimatable.getFreezeSnapshotTarget(); + freezeTarget = freezeTarget != null ? freezeTarget : mAnimatable.getFreezeSnapshotTarget(); if (freezeTarget != null) { SurfaceControl.ScreenshotHardwareBuffer screenshotBuffer = createSnapshotBuffer( freezeTarget, startBounds); diff --git a/services/core/java/com/android/server/wm/SystemGesturesPointerEventListener.java b/services/core/java/com/android/server/wm/SystemGesturesPointerEventListener.java index 513b1b715a27..658f4efbdb2f 100644 --- a/services/core/java/com/android/server/wm/SystemGesturesPointerEventListener.java +++ b/services/core/java/com/android/server/wm/SystemGesturesPointerEventListener.java @@ -16,6 +16,12 @@ package com.android.server.wm; +import static android.view.DisplayCutout.BOUNDS_POSITION_BOTTOM; +import static android.view.DisplayCutout.BOUNDS_POSITION_LEFT; +import static android.view.DisplayCutout.BOUNDS_POSITION_RIGHT; +import static android.view.DisplayCutout.BOUNDS_POSITION_TOP; + +import android.annotation.NonNull; import android.content.Context; import android.content.res.Resources; import android.graphics.Rect; @@ -33,6 +39,8 @@ import android.view.MotionEvent; import android.view.WindowManagerPolicyConstants.PointerEventListener; import android.widget.OverScroller; +import java.io.PrintWriter; + /** * Listens for system-wide input gestures, firing callbacks when detected. * @hide @@ -54,7 +62,8 @@ class SystemGesturesPointerEventListener implements PointerEventListener { private final Context mContext; private final Handler mHandler; private int mDisplayCutoutTouchableRegionSize; - private int mSwipeStartThreshold; + // The thresholds for each edge of the display + private final Rect mSwipeStartThreshold = new Rect(); private int mSwipeDistanceThreshold; private final Callbacks mCallbacks; private final int[] mDownPointerId = new int[MAX_TRACKED_POINTERS]; @@ -66,7 +75,6 @@ class SystemGesturesPointerEventListener implements PointerEventListener { int screenHeight; int screenWidth; - private DisplayInfo mTmpDisplayInfo = new DisplayInfo(); private int mDownPointers; private boolean mSwipeFireable; private boolean mDebugFireable; @@ -88,27 +96,41 @@ class SystemGesturesPointerEventListener implements PointerEventListener { void onConfigurationChanged() { final Resources r = mContext.getResources(); + final int defaultThreshold = r.getDimensionPixelSize( + com.android.internal.R.dimen.system_gestures_start_threshold); + mSwipeStartThreshold.set(defaultThreshold, defaultThreshold, defaultThreshold, + defaultThreshold); + mSwipeDistanceThreshold = defaultThreshold; + final Display display = DisplayManagerGlobal.getInstance() .getRealDisplay(Display.DEFAULT_DISPLAY); - display.getDisplayInfo(mTmpDisplayInfo); - mSwipeStartThreshold = mTmpDisplayInfo.logicalWidth > mTmpDisplayInfo.logicalHeight - ? r.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height_landscape) - : r.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height_portrait); - final DisplayCutout displayCutout = display.getCutout(); if (displayCutout != null) { - final Rect bounds = displayCutout.getBoundingRectTop(); - if (!bounds.isEmpty()) { - // Expand swipe start threshold such that we can catch touches that just start below - // the notch area - mDisplayCutoutTouchableRegionSize = r.getDimensionPixelSize( - com.android.internal.R.dimen.display_cutout_touchable_region_size); - mSwipeStartThreshold += mDisplayCutoutTouchableRegionSize; + // Expand swipe start threshold such that we can catch touches that just start beyond + // the notch area + mDisplayCutoutTouchableRegionSize = r.getDimensionPixelSize( + com.android.internal.R.dimen.display_cutout_touchable_region_size); + final Rect[] bounds = displayCutout.getBoundingRectsAll(); + if (bounds[BOUNDS_POSITION_LEFT] != null) { + mSwipeStartThreshold.left = Math.max(mSwipeStartThreshold.left, + bounds[BOUNDS_POSITION_LEFT].width() + mDisplayCutoutTouchableRegionSize); + } + if (bounds[BOUNDS_POSITION_TOP] != null) { + mSwipeStartThreshold.top = Math.max(mSwipeStartThreshold.top, + bounds[BOUNDS_POSITION_TOP].height() + mDisplayCutoutTouchableRegionSize); + } + if (bounds[BOUNDS_POSITION_RIGHT] != null) { + mSwipeStartThreshold.right = Math.max(mSwipeStartThreshold.right, + bounds[BOUNDS_POSITION_RIGHT].width() + mDisplayCutoutTouchableRegionSize); + } + if (bounds[BOUNDS_POSITION_BOTTOM] != null) { + mSwipeStartThreshold.bottom = Math.max(mSwipeStartThreshold.bottom, + bounds[BOUNDS_POSITION_BOTTOM].height() + + mDisplayCutoutTouchableRegionSize); } } - mSwipeDistanceThreshold = mSwipeStartThreshold; if (DEBUG) Slog.d(TAG, "mSwipeStartThreshold=" + mSwipeStartThreshold - + " mSwipeDistanceThreshold=" + mSwipeDistanceThreshold); + + " mSwipeDistanceThreshold=" + mSwipeDistanceThreshold); } private static <T> T checkNull(String name, T arg) { @@ -275,22 +297,22 @@ class SystemGesturesPointerEventListener implements PointerEventListener { final long elapsed = time - mDownTime[i]; if (DEBUG) Slog.d(TAG, "pointer " + mDownPointerId[i] + " moved (" + fromX + "->" + x + "," + fromY + "->" + y + ") in " + elapsed); - if (fromY <= mSwipeStartThreshold + if (fromY <= mSwipeStartThreshold.top && y > fromY + mSwipeDistanceThreshold && elapsed < SWIPE_TIMEOUT_MS) { return SWIPE_FROM_TOP; } - if (fromY >= screenHeight - mSwipeStartThreshold + if (fromY >= screenHeight - mSwipeStartThreshold.bottom && y < fromY - mSwipeDistanceThreshold && elapsed < SWIPE_TIMEOUT_MS) { return SWIPE_FROM_BOTTOM; } - if (fromX >= screenWidth - mSwipeStartThreshold + if (fromX >= screenWidth - mSwipeStartThreshold.right && x < fromX - mSwipeDistanceThreshold && elapsed < SWIPE_TIMEOUT_MS) { return SWIPE_FROM_RIGHT; } - if (fromX <= mSwipeStartThreshold + if (fromX <= mSwipeStartThreshold.left && x > fromX + mSwipeDistanceThreshold && elapsed < SWIPE_TIMEOUT_MS) { return SWIPE_FROM_LEFT; @@ -298,6 +320,15 @@ class SystemGesturesPointerEventListener implements PointerEventListener { return SWIPE_NONE; } + public void dump(@NonNull PrintWriter pw, @NonNull String prefix) { + final String inner = prefix + " "; + pw.println(prefix + TAG + ":"); + pw.print(inner); pw.print("mDisplayCutoutTouchableRegionSize="); + pw.println(mDisplayCutoutTouchableRegionSize); + pw.print(inner); pw.print("mSwipeStartThreshold="); pw.println(mSwipeStartThreshold); + pw.print(inner); pw.print("mSwipeDistanceThreshold="); pw.println(mSwipeDistanceThreshold); + } + private final class FlingGestureDetector extends GestureDetector.SimpleOnGestureListener { private OverScroller mOverscroller; diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index c5362d38c613..0819549ad8df 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -480,7 +480,6 @@ class Task extends TaskFragment { private Dimmer mDimmer = new Dimmer(this); private final Rect mTmpDimBoundsRect = new Rect(); - private final Point mLastSurfaceSize = new Point(); /** @see #setCanAffectSystemUiFlags */ private boolean mCanAffectSystemUiFlags = true; @@ -4583,7 +4582,7 @@ class Task extends TaskFragment { // From fullscreen to PiP. if (topActivity != null && currentMode == WINDOWING_MODE_FULLSCREEN && windowingMode == WINDOWING_MODE_PINNED - && !mAtmService.getTransitionController().isShellTransitionsEnabled()) { + && !mTransitionController.isShellTransitionsEnabled()) { mDisplayContent.mPinnedTaskController .deferOrientationChangeForEnteringPipFromFullScreenIfNeeded(); } diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java index fce279d8b805..44b22c643347 100644 --- a/services/core/java/com/android/server/wm/TaskFragment.java +++ b/services/core/java/com/android/server/wm/TaskFragment.java @@ -240,6 +240,8 @@ class TaskFragment extends WindowContainer<WindowContainer> { */ private int mTaskFragmentOrganizerPid = ActivityRecord.INVALID_PID; + final Point mLastSurfaceSize = new Point(); + private final Rect mTmpInsets = new Rect(); private final Rect mTmpBounds = new Rect(); private final Rect mTmpFullBounds = new Rect(); @@ -1392,7 +1394,8 @@ class TaskFragment extends WindowContainer<WindowContainer> { ProtoLog.v(WM_DEBUG_STATES, "Moving to PAUSING: %s", prev); mPausingActivity = prev; mLastPausedActivity = prev; - if (prev.isNoHistory() && !mTaskSupervisor.mNoHistoryActivities.contains(prev)) { + if (!prev.finishing && prev.isNoHistory() + && !mTaskSupervisor.mNoHistoryActivities.contains(prev)) { mTaskSupervisor.mNoHistoryActivities.add(prev); } prev.setState(PAUSING, "startPausingLocked"); @@ -1476,7 +1479,7 @@ class TaskFragment extends WindowContainer<WindowContainer> { } else { prev.schedulePauseTimeout(); // Unset readiness since we now need to wait until this pause is complete. - mAtmService.getTransitionController().setReady(this, false /* ready */); + mTransitionController.setReady(this, false /* ready */); return true; } @@ -1654,6 +1657,7 @@ class TaskFragment extends WindowContainer<WindowContainer> { } } + @Override void onChildPositionChanged(WindowContainer child) { super.onChildPositionChanged(child); @@ -2049,14 +2053,58 @@ class TaskFragment extends WindowContainer<WindowContainer> { if (shouldStartChangeTransition(mTmpPrevBounds)) { initializeChangeTransition(mTmpPrevBounds); } else if (mTaskFragmentOrganizer != null) { - // Update the surface position here instead of in the organizer so that we can make sure + // Update the surface here instead of in the organizer so that we can make sure // it can be synced with the surface freezer. - updateSurfacePosition(getSyncTransaction()); + final SurfaceControl.Transaction t = getSyncTransaction(); + updateSurfacePosition(t); + updateOrganizedTaskFragmentSurfaceSize(t, false /* forceUpdate */); } sendTaskFragmentInfoChanged(); } + /** Updates the surface size so that the sub windows cannot be shown out of bounds. */ + private void updateOrganizedTaskFragmentSurfaceSize(SurfaceControl.Transaction t, + boolean forceUpdate) { + if (mTaskFragmentOrganizer == null) { + // We only want to update for organized TaskFragment. Task will handle itself. + return; + } + if (mSurfaceControl == null || mSurfaceAnimator.hasLeash() || mSurfaceFreezer.hasLeash()) { + return; + } + + final Rect bounds = getBounds(); + final int width = bounds.width(); + final int height = bounds.height(); + if (!forceUpdate && width == mLastSurfaceSize.x && height == mLastSurfaceSize.y) { + return; + } + t.setWindowCrop(mSurfaceControl, width, height); + mLastSurfaceSize.set(width, height); + } + + @Override + public void onAnimationLeashCreated(SurfaceControl.Transaction t, SurfaceControl leash) { + super.onAnimationLeashCreated(t, leash); + // Reset surface bounds for animation. It will be taken care by the animation leash, and + // reset again onAnimationLeashLost. + if (mTaskFragmentOrganizer != null + && (mLastSurfaceSize.x != 0 || mLastSurfaceSize.y != 0)) { + t.setWindowCrop(mSurfaceControl, 0, 0); + mLastSurfaceSize.set(0, 0); + } + } + + @Override + public void onAnimationLeashLost(SurfaceControl.Transaction t) { + super.onAnimationLeashLost(t); + // Update the surface bounds after animation. + if (mTaskFragmentOrganizer != null) { + updateOrganizedTaskFragmentSurfaceSize(t, true /* forceUpdate */); + } + } + /** Whether we should prepare a transition for this {@link TaskFragment} bounds change. */ private boolean shouldStartChangeTransition(Rect startBounds) { if (mWmService.mDisableTransitionAnimation @@ -2075,9 +2123,14 @@ class TaskFragment extends WindowContainer<WindowContainer> { @Override void setSurfaceControl(SurfaceControl sc) { super.setSurfaceControl(sc); - // If the TaskFragmentOrganizer was set before we created the SurfaceControl, we need to - // emit the callbacks now. - sendTaskFragmentAppeared(); + if (mTaskFragmentOrganizer != null) { + final SurfaceControl.Transaction t = getSyncTransaction(); + updateSurfacePosition(t); + updateOrganizedTaskFragmentSurfaceSize(t, false /* forceUpdate */); + // If the TaskFragmentOrganizer was set before we created the SurfaceControl, we need to + // emit the callbacks now. + sendTaskFragmentAppeared(); + } } void sendTaskFragmentInfoChanged() { @@ -2099,10 +2152,6 @@ class TaskFragment extends WindowContainer<WindowContainer> { } } - int getTaskFragmentOrganizerPid() { - return mTaskFragmentOrganizerPid; - } - /** * Returns a {@link TaskFragmentInfo} with information from this TaskFragment. Should not be * called from {@link Task}. @@ -2234,7 +2283,7 @@ class TaskFragment extends WindowContainer<WindowContainer> { return false; } return isAnimating(TRANSITION | CHILDREN, WindowState.EXIT_ANIMATING_TYPES) - || mAtmService.getTransitionController().inTransition(this); + || inTransition(); } @Override diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java index 1909875565f6..e50e8ef56778 100644 --- a/services/core/java/com/android/server/wm/Transition.java +++ b/services/core/java/com/android/server/wm/Transition.java @@ -758,8 +758,13 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe (flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER) != 0, (flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE) != 0, (flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_SUBTLE_ANIMATION) != 0); - mController.mAtm.mWindowManager.mPolicy.startKeyguardExitAnimation( - SystemClock.uptimeMillis(), 0 /* duration */); + if (!WindowManagerService.sEnableRemoteKeyguardGoingAwayAnimation) { + // When remote animation is enabled for KEYGUARD_GOING_AWAY transition, SysUI + // receives IRemoteAnimationRunner#onAnimationStart to start animation, so we don't + // need to call IKeyguardService#keyguardGoingAway here. + mController.mAtm.mWindowManager.mPolicy.startKeyguardExitAnimation( + SystemClock.uptimeMillis(), 0 /* duration */); + } } if ((flags & TRANSIT_FLAG_KEYGUARD_LOCKED) != 0) { mController.mAtm.mWindowManager.mPolicy.applyKeyguardOcclusionChange(); diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java index 7893612b5725..0909462585af 100644 --- a/services/core/java/com/android/server/wm/WallpaperController.java +++ b/services/core/java/com/android/server/wm/WallpaperController.java @@ -128,7 +128,7 @@ class WallpaperController { } mFindResults.resetTopWallpaper = true; - if (mService.mAtmService.getTransitionController().getTransitionPlayer() == null) { + if (!w.mTransitionController.isShellTransitionsEnabled()) { if (w.mActivityRecord != null && !w.mActivityRecord.isVisible() && !w.mActivityRecord.isAnimating(TRANSITION | PARENTS)) { // If this window's app token is hidden and not animating, it is of no interest. diff --git a/services/core/java/com/android/server/wm/WallpaperWindowToken.java b/services/core/java/com/android/server/wm/WallpaperWindowToken.java index b54e8b7a7b4e..75c84c44c48e 100644 --- a/services/core/java/com/android/server/wm/WallpaperWindowToken.java +++ b/services/core/java/com/android/server/wm/WallpaperWindowToken.java @@ -112,7 +112,7 @@ class WallpaperWindowToken extends WindowToken { setVisibility(visible); } final WallpaperController wallpaperController = mDisplayContent.mWallpaperController; - if (mWmService.mAtmService.getTransitionController().getTransitionPlayer() != null) { + if (mTransitionController.isShellTransitionsEnabled()) { return; } @@ -157,12 +157,12 @@ class WallpaperWindowToken extends WindowToken { */ void setVisibility(boolean visible) { // Before setting mVisibleRequested so we can track changes. - mWmService.mAtmService.getTransitionController().collect(this); + mTransitionController.collect(this); setVisibleRequested(visible); // If in a transition, defer commits for activities that are going invisible - if (!visible && (mWmService.mAtmService.getTransitionController().inTransition() + if (!visible && (mTransitionController.inTransition() || getDisplayContent().mAppTransition.isRunning())) { return; } diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java index 2a8fa1086799..841783d6b8cd 100644 --- a/services/core/java/com/android/server/wm/WindowContainer.java +++ b/services/core/java/com/android/server/wm/WindowContainer.java @@ -197,10 +197,10 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< * Applied as part of the animation pass in "prepareSurfaces". */ protected final SurfaceAnimator mSurfaceAnimator; - private boolean mAnyParentAnimating; final SurfaceFreezer mSurfaceFreezer; protected final WindowManagerService mWmService; + final TransitionController mTransitionController; /** * Sources which triggered a surface animation on this container. An animation target can be @@ -331,6 +331,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< WindowContainer(WindowManagerService wms) { mWmService = wms; + mTransitionController = mWmService.mAtmService.getTransitionController(); mPendingTransaction = wms.mTransactionFactory.get(); mSyncTransaction = wms.mTransactionFactory.get(); mSurfaceAnimator = new SurfaceAnimator(this, this::onAnimationFinished, wms); @@ -1008,7 +1009,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< } boolean inTransition() { - return mWmService.mAtmService.getTransitionController().inTransition(this); + return mTransitionController.inTransition(this); } void sendAppVisibilityToClients() { @@ -2310,7 +2311,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< void assignLayer(Transaction t, int layer) { // Don't assign layers while a transition animation is playing // TODO(b/173528115): establish robust best-practices around z-order fighting. - if (mWmService.mAtmService.getTransitionController().isPlaying()) return; + if (mTransitionController.isPlaying()) return; final boolean changed = layer != mLastLayer || mLastRelativeToLayer != null; if (mSurfaceControl != null && changed) { setLayer(t, layer); @@ -2620,23 +2621,27 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< * For now, this will only be called for the following cases: * 1. {@link Task} is changing windowing mode between fullscreen and freeform. * 2. {@link TaskFragment} is organized and is changing window bounds. - * 3. {@link ActivityRecord} is reparented into an organized {@link TaskFragment}. + * 3. {@link ActivityRecord} is reparented into an organized {@link TaskFragment}. (The + * transition will happen on the {@link TaskFragment} for this case). * - * This shouldn't be called on other {@link WindowContainer} unless there is a valid use case. + * This shouldn't be called on other {@link WindowContainer} unless there is a valid + * use case. * * @param startBounds The original bounds (on screen) of the surface we are snapshotting. - * @param parentBounds The parent bounds (on screen) to calculate the animation surface - * position. + * @param freezeTarget The surface to take snapshot from. If {@code null}, we will take a + * snapshot from {@link #getFreezeSnapshotTarget()}. */ - void initializeChangeTransition(Rect startBounds, Rect parentBounds) { + void initializeChangeTransition(Rect startBounds, @Nullable SurfaceControl freezeTarget) { mDisplayContent.prepareAppTransition(TRANSIT_CHANGE); mDisplayContent.mChangingContainers.add(this); + // Calculate the relative position in parent container. + final Rect parentBounds = getParent().getBounds(); mTmpPoint.set(startBounds.left - parentBounds.left, startBounds.top - parentBounds.top); - mSurfaceFreezer.freeze(getSyncTransaction(), startBounds, mTmpPoint); + mSurfaceFreezer.freeze(getSyncTransaction(), startBounds, mTmpPoint, freezeTarget); } void initializeChangeTransition(Rect startBounds) { - initializeChangeTransition(startBounds, getParent().getBounds()); + initializeChangeTransition(startBounds, null /* freezeTarget */); } ArraySet<WindowContainer> getAnimationSources() { @@ -3159,7 +3164,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< */ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PROTECTED) void updateSurfacePosition(Transaction t) { - if (mSurfaceControl == null || mSurfaceAnimator.hasLeash()) { + if (mSurfaceControl == null || mSurfaceAnimator.hasLeash() || mSurfaceFreezer.hasLeash()) { return; } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 0e99c0f1bad0..c77cd509ca4f 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -1804,7 +1804,7 @@ public class WindowManagerService extends IWindowManager.Stub winAnimator.mEnterAnimationPending = true; winAnimator.mEnteringAnimation = true; // Check if we need to prepare a transition for replacing window first. - if (mAtmService.getTransitionController().getTransitionPlayer() == null + if (!win.mTransitionController.isShellTransitionsEnabled() && activity != null && activity.isVisible() && !prepareWindowReplacementTransition(activity)) { // If not, check if need to set up a dummy transition during display freeze @@ -2569,7 +2569,7 @@ public class WindowManagerService extends IWindowManager.Stub if (win.mAttrs.type == TYPE_APPLICATION_STARTING) { transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE; } - if (mAtmService.getTransitionController().inTransition(win)) { + if (win.inTransition()) { focusMayChange = true; win.mAnimatingExit = true; } else if (win.isWinVisibleLw() && winAnimator.applyAnimationLocked(transit, false)) { @@ -4051,7 +4051,7 @@ public class WindowManagerService extends IWindowManager.Stub final boolean pendingRemoteRotation = rotationChanged && (displayContent.getDisplayRotation().isWaitingForRemoteRotation() - || mAtmService.getTransitionController().isCollecting()); + || displayContent.mTransitionController.isCollecting()); // Even if alwaysSend, we are waiting for a transition or remote to provide // rotated configuration, so we can't update configuration yet. if (!pendingRemoteRotation) { diff --git a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java index 47d7f030bcaa..0f8587c99958 100644 --- a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java +++ b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java @@ -23,6 +23,9 @@ import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_BACKGROUND_ import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND_FLOATING; import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_BACKGROUND_SOLID_COLOR; import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_BACKGROUND_WALLPAPER; +import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_REACHABILITY_POSITION_CENTER; +import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_REACHABILITY_POSITION_LEFT; +import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_REACHABILITY_POSITION_RIGHT; import android.content.res.Resources.NotFoundException; import android.graphics.Color; @@ -44,6 +47,7 @@ import com.android.internal.protolog.ProtoLogImpl; import com.android.server.LocalServices; import com.android.server.statusbar.StatusBarManagerInternal; import com.android.server.wm.LetterboxConfiguration.LetterboxBackgroundType; +import com.android.server.wm.LetterboxConfiguration.LetterboxReachabilityPosition; import java.io.IOException; import java.io.PrintWriter; @@ -787,22 +791,33 @@ public class WindowManagerShellCommand extends ShellCommand { return 0; } - private int runSetLetterboxDefaultPositionMultiplierForReachability(PrintWriter pw) + private int runSetLetterboxDefaultPositionForReachability(PrintWriter pw) throws RemoteException { - final float multiplier; + @LetterboxReachabilityPosition final int position; try { String arg = getNextArgRequired(); - multiplier = Float.parseFloat(arg); - } catch (NumberFormatException e) { - getErrPrintWriter().println("Error: bad multiplier format " + e); - return -1; + switch (arg) { + case "left": + position = LETTERBOX_REACHABILITY_POSITION_LEFT; + break; + case "center": + position = LETTERBOX_REACHABILITY_POSITION_CENTER; + break; + case "right": + position = LETTERBOX_REACHABILITY_POSITION_RIGHT; + break; + default: + getErrPrintWriter().println( + "Error: 'left', 'center' or 'right' are expected as an argument"); + return -1; + } } catch (IllegalArgumentException e) { getErrPrintWriter().println( - "Error: multiplier should be provided as an argument " + e); + "Error: 'left', 'center' or 'right' are expected as an argument" + e); return -1; } synchronized (mInternal.mGlobalLock) { - mLetterboxConfiguration.setDefaultPositionMultiplierForReachability(multiplier); + mLetterboxConfiguration.setDefaultPositionForReachability(position); } return 0; } @@ -841,8 +856,8 @@ public class WindowManagerShellCommand extends ShellCommand { case "--isReachabilityEnabled": runSetLetterboxIsReachabilityEnabled(pw); break; - case "--defaultPositionMultiplierReachability": - runSetLetterboxDefaultPositionMultiplierForReachability(pw); + case "--defaultPositionForReachability": + runSetLetterboxDefaultPositionForReachability(pw); break; default: getErrPrintWriter().println( @@ -885,8 +900,8 @@ public class WindowManagerShellCommand extends ShellCommand { case "isReachabilityEnabled": mLetterboxConfiguration.getIsReachabilityEnabled(); break; - case "defaultPositionMultiplierForReachability": - mLetterboxConfiguration.getDefaultPositionMultiplierForReachability(); + case "defaultPositionForReachability": + mLetterboxConfiguration.getDefaultPositionForReachability(); break; default: getErrPrintWriter().println( @@ -982,7 +997,7 @@ public class WindowManagerShellCommand extends ShellCommand { mLetterboxConfiguration.resetLetterboxBackgroundWallpaperDarkScrimAlpha(); mLetterboxConfiguration.resetLetterboxHorizontalPositionMultiplier(); mLetterboxConfiguration.resetIsReachabilityEnabled(); - mLetterboxConfiguration.resetDefaultPositionMultiplierForReachability(); + mLetterboxConfiguration.resetDefaultPositionForReachability(); } } @@ -996,8 +1011,9 @@ public class WindowManagerShellCommand extends ShellCommand { + mLetterboxConfiguration.getFixedOrientationLetterboxAspectRatio()); pw.println("Is reachability enabled: " + mLetterboxConfiguration.getIsReachabilityEnabled()); - pw.println("Default position multiplier for reachability: " - + mLetterboxConfiguration.getDefaultPositionMultiplierForReachability()); + pw.println("Default position for reachability: " + + LetterboxConfiguration.letterboxReachabilityPositionToString( + mLetterboxConfiguration.getDefaultPositionForReachability())); pw.println("Background type: " + LetterboxConfiguration.letterboxBackgroundTypeToString( @@ -1135,11 +1151,9 @@ public class WindowManagerShellCommand extends ShellCommand { pw.println(" --isReachabilityEnabled [true|1|false|0]"); pw.println(" Whether reachability repositioning is allowed for letterboxed"); pw.println(" fullscreen apps in landscape device orientation."); - pw.println(" --defaultPositionMultiplierReachability multiplier"); - pw.println(" Default horizontal position of app window center when reachability is"); - pw.println(" enabled. If multiplier < 0.0 or > 1, both it and "); - pw.println(" R.dimen.config_letterboxDefaultPositionMultiplierForReachability"); - pw.println(" are ignored and right position (1.0) is used."); + pw.println(" --defaultPositionForReachability [left|center|right]"); + pw.println(" Default horizontal position of app window when reachability is."); + pw.println(" enabled."); pw.println(" reset-letterbox-style [aspectRatio|cornerRadius|backgroundType"); pw.println(" |backgroundColor|wallpaperBlurRadius|wallpaperDarkScrimAlpha"); pw.println(" |horizontalPositionMultiplier|isReachabilityEnabled"); diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 3adecf3474eb..5f9d4f5182bc 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -1175,8 +1175,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP if (WindowManager.LayoutParams.isSystemAlertWindowType(mAttrs.type)) { return TouchOcclusionMode.USE_OPACITY; } - if (isAnimating(PARENTS | TRANSITION, ANIMATION_TYPE_ALL) - || mWmService.mAtmService.getTransitionController().inTransition(this)) { + if (isAnimating(PARENTS | TRANSITION, ANIMATION_TYPE_ALL) || inTransition()) { return TouchOcclusionMode.USE_OPACITY; } return TouchOcclusionMode.BLOCK_UNTRUSTED; @@ -2326,7 +2325,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP && (mWindowFrames.mRelFrame.top != mWindowFrames.mLastRelFrame.top || mWindowFrames.mRelFrame.left != mWindowFrames.mLastRelFrame.left) && (!mIsChildWindow || !getParentWindow().hasMoved()) - && !mWmService.mAtmService.getTransitionController().isCollecting(); + && !mTransitionController.isCollecting(); } boolean isObscuringDisplay() { @@ -2712,8 +2711,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP // Don't allow transient-launch activities to take IME. if (rootTask != null && mActivityRecord != null - && mWmService.mAtmService.getTransitionController().isTransientLaunch( - mActivityRecord)) { + && mTransitionController.isTransientLaunch(mActivityRecord)) { return false; } @@ -5679,9 +5677,11 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP } boolean needsRelativeLayeringToIme() { - // We only use the relative layering mode in split screen, as part of elevating the IME - // and windows above it's target above the docked divider. - if (!inSplitScreenWindowingMode()) { + // We use the relative layering when IME isn't attached to the app. Such as part of + // elevating the IME and windows above it's target above the docked divider in + // split-screen, or make the popupMenu to be above the IME when the parent window is the + // IME layering target in bubble/freeform mode. + if (mDisplayContent.isImeAttachedToApp()) { return false; } @@ -6073,7 +6073,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP } if (mActivityRecord != null - && mWmService.mAtmService.getTransitionController().isShellTransitionsEnabled() + && mTransitionController.isShellTransitionsEnabled() && mAttrs.type == TYPE_APPLICATION_STARTING) { mWmService.mAtmService.mTaskSupervisor.getActivityMetricsLogger() .notifyStartingWindowDrawn(mActivityRecord); diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 147889db3177..14970ceb13d2 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -3618,6 +3618,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { final CallerIdentity caller = getCallerIdentity(); Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(caller, userHandle)); + Preconditions.checkCallAuthorization( + isCallingFromPackage(adminReceiver.getPackageName(), caller.getUid()) + || isSystemUid(caller)); synchronized (getLockObject()) { ActiveAdmin administrator = getActiveAdminUncheckedLocked(adminReceiver, userHandle); @@ -8353,7 +8356,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } @Override - public boolean setDeviceOwner(ComponentName admin, String ownerName, int userId) { + public boolean setDeviceOwner(ComponentName admin, String ownerName, int userId, + boolean setProfileOwnerOnCurrentUserIfNecessary) { if (!mHasFeature) { logMissingFeatureAction("Cannot set " + ComponentName.flattenToShortString(admin) + " as device owner for user " + userId); @@ -8414,19 +8418,18 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { mDeviceAdminServiceController.startServiceForOwner( admin.getPackageName(), userId, "set-device-owner"); - Slogf.i(LOG_TAG, "Device owner set: %s on user %d", admin.flattenToShortString(), - userId); + Slogf.i(LOG_TAG, "Device owner set: " + admin + " on user " + userId); - if (mInjector.userManagerIsHeadlessSystemUserMode()) { + if (setProfileOwnerOnCurrentUserIfNecessary + && mInjector.userManagerIsHeadlessSystemUserMode()) { int currentForegroundUser = getCurrentForegroundUserId(); - Slogf.i(LOG_TAG, "setDeviceOwner(): setting %s as profile owner on user %d", - admin.flattenToShortString(), currentForegroundUser); + Slogf.i(LOG_TAG, "setDeviceOwner(): setting " + admin + + " as profile owner on user " + currentForegroundUser); // Sets profile owner on current foreground user since // the human user will complete the DO setup workflow from there. - mInjector.binderWithCleanCallingIdentity(() -> manageUserUnchecked( - /* deviceOwner= */ admin, /* profileOwner= */ admin, + manageUserUnchecked(/* deviceOwner= */ admin, /* profileOwner= */ admin, /* managedUser= */ currentForegroundUser, /* adminExtras= */ null, - /* showDisclaimer= */ false)); + /* showDisclaimer= */ false); } return true; } @@ -10629,19 +10632,21 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } } final String adminPkg = admin.getPackageName(); - try { - // Install the profile owner if not present. - if (!mIPackageManager.isPackageAvailable(adminPkg, userId)) { - mIPackageManager.installExistingPackageAsUser(adminPkg, userId, - PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS, - PackageManager.INSTALL_REASON_POLICY, - /* allowlistedRestrictedPermissions= */ null); + mInjector.binderWithCleanCallingIdentity(() -> { + try { + // Install the profile owner if not present. + if (!mIPackageManager.isPackageAvailable(adminPkg, userId)) { + mIPackageManager.installExistingPackageAsUser(adminPkg, userId, + PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS, + PackageManager.INSTALL_REASON_POLICY, + /* allowlistedRestrictedPermissions= */ null); + } + } catch (RemoteException e) { + // Does not happen, same process + Slogf.wtf(LOG_TAG, e, "Failed to install admin package %s for user %d", + adminPkg, userId); } - } catch (RemoteException e) { - // Does not happen, same process - Slogf.wtf(LOG_TAG, e, "Failed to install admin package %s for user %d", - adminPkg, userId); - } + }); // Set admin. setActiveAdmin(profileOwner, /* refreshing= */ true, userId); @@ -12713,74 +12718,21 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { // This method is called from AM with its lock held, so don't take the DPMS lock. // b/29242568 - ComponentName profileOwner = mOwners.getProfileOwnerComponent(userId); - if (profileOwner != null) { - return DevicePolicyManagerService.this - .createShowAdminSupportIntent(profileOwner, userId); - } - - final Pair<Integer, ComponentName> deviceOwner = - mOwners.getDeviceOwnerUserIdAndComponent(); - if (deviceOwner != null && deviceOwner.first == userId) { - return DevicePolicyManagerService.this - .createShowAdminSupportIntent(deviceOwner.second, userId); - } - - // We're not specifying the device admin because there isn't one. - if (useDefaultIfNoAdmin) { - return DevicePolicyManagerService.this.createShowAdminSupportIntent(null, userId); + if (getEnforcingAdminAndUserDetailsInternal(userId, null) != null + || useDefaultIfNoAdmin) { + return DevicePolicyManagerService.this.createShowAdminSupportIntent(userId); } return null; } @Override public Intent createUserRestrictionSupportIntent(int userId, String userRestriction) { - final long ident = mInjector.binderClearCallingIdentity(); - try { - final List<UserManager.EnforcingUser> sources = mUserManager - .getUserRestrictionSources(userRestriction, UserHandle.of(userId)); - if (sources == null || sources.isEmpty()) { - // The restriction is not enforced. - return null; - } else if (sources.size() > 1) { - // In this case, we'll show an admin support dialog that does not - // specify the admin. - // TODO(b/128928355): if this restriction is enforced by multiple DPCs, return - // the admin for the calling user. - return DevicePolicyManagerService.this.createShowAdminSupportIntent( - null, userId); - } - final UserManager.EnforcingUser enforcingUser = sources.get(0); - final int sourceType = enforcingUser.getUserRestrictionSource(); - final int enforcingUserId = enforcingUser.getUserHandle().getIdentifier(); - if (sourceType == UserManager.RESTRICTION_SOURCE_PROFILE_OWNER) { - // Restriction was enforced by PO - final ComponentName profileOwner = mOwners.getProfileOwnerComponent( - enforcingUserId); - if (profileOwner != null) { - return DevicePolicyManagerService.this.createShowAdminSupportIntent( - profileOwner, enforcingUserId); - } - } else if (sourceType == UserManager.RESTRICTION_SOURCE_DEVICE_OWNER) { - // Restriction was enforced by DO - final Pair<Integer, ComponentName> deviceOwner = - mOwners.getDeviceOwnerUserIdAndComponent(); - if (deviceOwner != null) { - return DevicePolicyManagerService.this.createShowAdminSupportIntent( - deviceOwner.second, deviceOwner.first); - } - } else if (sourceType == UserManager.RESTRICTION_SOURCE_SYSTEM) { - /* - * In this case, the user restriction is enforced by the system. - * So we won't show an admin support intent, even if it is also - * enforced by a profile/device owner. - */ - return null; - } - } finally { - mInjector.binderRestoreCallingIdentity(ident); + Intent intent = null; + if (getEnforcingAdminAndUserDetailsInternal(userId, userRestriction) != null) { + intent = DevicePolicyManagerService.this.createShowAdminSupportIntent(userId); + intent.putExtra(DevicePolicyManager.EXTRA_RESTRICTION, userRestriction); } - return null; + return intent; } @Override @@ -13075,53 +13027,153 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } } - private Intent createShowAdminSupportIntent(ComponentName admin, int userId) { + private Intent createShowAdminSupportIntent(int userId) { // This method is called with AMS lock held, so don't take DPMS lock final Intent intent = new Intent(Settings.ACTION_SHOW_ADMIN_SUPPORT_DETAILS); intent.putExtra(Intent.EXTRA_USER_ID, userId); - intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, admin); intent.setFlags(FLAG_ACTIVITY_NEW_TASK); return intent; } - @Override - public Intent createAdminSupportIntent(String restriction) { - Objects.requireNonNull(restriction); - final CallerIdentity caller = getCallerIdentity(); - Intent intent = null; - if (DevicePolicyManager.POLICY_DISABLE_CAMERA.equals(restriction) || - DevicePolicyManager.POLICY_DISABLE_SCREEN_CAPTURE.equals(restriction)) { + /** + * @param restriction The restriction enforced by admin. It could be any user restriction or + * policy like {@link DevicePolicyManager#POLICY_DISABLE_CAMERA} and + * {@link DevicePolicyManager#POLICY_DISABLE_SCREEN_CAPTURE}. + */ + private Bundle getEnforcingAdminAndUserDetailsInternal(int userId, String restriction) { + Bundle result = null; + if (restriction == null) { + ComponentName profileOwner = mOwners.getProfileOwnerComponent(userId); + if (profileOwner != null) { + result = new Bundle(); + result.putInt(Intent.EXTRA_USER_ID, userId); + result.putParcelable(DevicePolicyManager.EXTRA_DEVICE_ADMIN, + profileOwner); + return result; + } + final Pair<Integer, ComponentName> deviceOwner = + mOwners.getDeviceOwnerUserIdAndComponent(); + if (deviceOwner != null && deviceOwner.first == userId) { + result = new Bundle(); + result.putInt(Intent.EXTRA_USER_ID, userId); + result.putParcelable(DevicePolicyManager.EXTRA_DEVICE_ADMIN, + deviceOwner.second); + return result; + } + } else if (DevicePolicyManager.POLICY_DISABLE_CAMERA.equals(restriction) + || DevicePolicyManager.POLICY_DISABLE_SCREEN_CAPTURE.equals(restriction)) { synchronized (getLockObject()) { - final DevicePolicyData policy = getUserData(caller.getUserId()); + final DevicePolicyData policy = getUserData(userId); final int N = policy.mAdminList.size(); for (int i = 0; i < N; i++) { final ActiveAdmin admin = policy.mAdminList.get(i); if ((admin.disableCamera && - DevicePolicyManager.POLICY_DISABLE_CAMERA.equals(restriction)) || - (admin.disableScreenCapture && DevicePolicyManager - .POLICY_DISABLE_SCREEN_CAPTURE.equals(restriction))) { - intent = createShowAdminSupportIntent(admin.info.getComponent(), - caller.getUserId()); - break; + DevicePolicyManager.POLICY_DISABLE_CAMERA.equals(restriction)) + || (admin.disableScreenCapture && DevicePolicyManager + .POLICY_DISABLE_SCREEN_CAPTURE.equals(restriction))) { + result = new Bundle(); + result.putInt(Intent.EXTRA_USER_ID, userId); + result.putParcelable(DevicePolicyManager.EXTRA_DEVICE_ADMIN, + admin.info.getComponent()); + return result; } } // For the camera, a device owner on a different user can disable it globally, // so we need an additional check. - if (intent == null + if (result == null && DevicePolicyManager.POLICY_DISABLE_CAMERA.equals(restriction)) { final ActiveAdmin admin = getDeviceOwnerAdminLocked(); if (admin != null && admin.disableCamera) { - intent = createShowAdminSupportIntent(admin.info.getComponent(), - mOwners.getDeviceOwnerUserId()); + result = new Bundle(); + result.putInt(Intent.EXTRA_USER_ID, mOwners.getDeviceOwnerUserId()); + result.putParcelable(DevicePolicyManager.EXTRA_DEVICE_ADMIN, + admin.info.getComponent()); + return result; } } } } else { - // if valid, |restriction| can only be a user restriction - intent = mLocalService.createUserRestrictionSupportIntent(caller.getUserId(), - restriction); + long ident = mInjector.binderClearCallingIdentity(); + try { + List<UserManager.EnforcingUser> sources = mUserManager + .getUserRestrictionSources(restriction, UserHandle.of(userId)); + if (sources == null || sources.isEmpty()) { + // The restriction is not enforced. + return null; + } else if (sources.size() > 1) { + // In this case, we'll show an admin support dialog that does not + // specify the admin. + // TODO(b/128928355): if this restriction is enforced by multiple DPCs, return + // the admin for the calling user. + result = new Bundle(); + result.putInt(Intent.EXTRA_USER_ID, userId); + return result; + } + final UserManager.EnforcingUser enforcingUser = sources.get(0); + final int sourceType = enforcingUser.getUserRestrictionSource(); + final int enforcingUserId = enforcingUser.getUserHandle().getIdentifier(); + if (sourceType == UserManager.RESTRICTION_SOURCE_PROFILE_OWNER) { + // Restriction was enforced by PO + final ComponentName profileOwner = mOwners.getProfileOwnerComponent( + enforcingUserId); + if (profileOwner != null) { + result = new Bundle(); + result.putInt(Intent.EXTRA_USER_ID, enforcingUserId); + result.putParcelable(DevicePolicyManager.EXTRA_DEVICE_ADMIN, + profileOwner); + return result; + } + } else if (sourceType == UserManager.RESTRICTION_SOURCE_DEVICE_OWNER) { + // Restriction was enforced by DO + final Pair<Integer, ComponentName> deviceOwner = + mOwners.getDeviceOwnerUserIdAndComponent(); + if (deviceOwner != null) { + result = new Bundle(); + result.putInt(Intent.EXTRA_USER_ID, deviceOwner.first); + result.putParcelable(DevicePolicyManager.EXTRA_DEVICE_ADMIN, + deviceOwner.second); + return result; + } + } else if (sourceType == UserManager.RESTRICTION_SOURCE_SYSTEM) { + /* + * In this case, the user restriction is enforced by the system. + * So we won't show an admin support intent, even if it is also + * enforced by a profile/device owner. + */ + return null; + } + } finally { + mInjector.binderRestoreCallingIdentity(ident); + } } - if (intent != null) { + return null; + } + + /** + * @param restriction The restriction enforced by admin. It could be any user restriction or + * policy like {@link DevicePolicyManager#POLICY_DISABLE_CAMERA} and + * {@link DevicePolicyManager#POLICY_DISABLE_SCREEN_CAPTURE}. + * @return Details of admin and user which enforced the restriction for the userId. + */ + @Override + public Bundle getEnforcingAdminAndUserDetails(int userId, String restriction) { + Preconditions.checkCallAuthorization(isSystemUid(getCallerIdentity())); + return getEnforcingAdminAndUserDetailsInternal(userId, restriction); + } + + /** + * @param restriction The restriction enforced by admin. It could be any user restriction or + * policy like {@link DevicePolicyManager#POLICY_DISABLE_CAMERA} and + * {@link DevicePolicyManager#POLICY_DISABLE_SCREEN_CAPTURE}. + */ + @Override + public Intent createAdminSupportIntent(String restriction) { + Objects.requireNonNull(restriction); + final CallerIdentity caller = getCallerIdentity(); + final int userId = caller.getUserId(); + Intent intent = null; + if (getEnforcingAdminAndUserDetailsInternal(userId, restriction) != null) { + intent = createShowAdminSupportIntent(userId); intent.putExtra(DevicePolicyManager.EXTRA_RESTRICTION, restriction); } return intent; @@ -17429,7 +17481,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { // TODO(b/178187130): Directly set DO and remove the check once silent provisioning is no // longer used. if (getDeviceOwnerComponent(/* callingUserOnly= */ true) == null) { - return setDeviceOwner(adminComponent, name, userId); + return setDeviceOwner(adminComponent, name, userId, + /* setProfileOwnerOnCurrentUserIfNecessary= */ true); } return true; } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerServiceShellCommand.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerServiceShellCommand.java index 85fe65ca5563..e1d720ca25c8 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerServiceShellCommand.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerServiceShellCommand.java @@ -46,11 +46,13 @@ final class DevicePolicyManagerServiceShellCommand extends ShellCommand { private static final String USER_OPTION = "--user"; private static final String NAME_OPTION = "--name"; + private static final String DO_ONLY_OPTION = "--device-owner-only"; private final DevicePolicyManagerService mService; private int mUserId = UserHandle.USER_SYSTEM; private String mName = ""; private ComponentName mComponent; + private boolean mSetDoOnly; DevicePolicyManagerServiceShellCommand(DevicePolicyManagerService service) { mService = Objects.requireNonNull(service); @@ -130,8 +132,8 @@ final class DevicePolicyManagerServiceShellCommand extends ShellCommand { pw.printf(" %s [ %s <USER_ID> | current ] <COMPONENT>\n", CMD_SET_ACTIVE_ADMIN, USER_OPTION); pw.printf(" Sets the given component as active admin for an existing user.\n\n"); - pw.printf(" %s [ %s <USER_ID> | current *EXPERIMENTAL* ] [ %s <NAME> ] " - + "<COMPONENT>\n", CMD_SET_DEVICE_OWNER, USER_OPTION, NAME_OPTION); + pw.printf(" %s [ %s <USER_ID> | current *EXPERIMENTAL* ] [ %s <NAME> ] [ %s ]" + + "<COMPONENT>\n", CMD_SET_DEVICE_OWNER, USER_OPTION, NAME_OPTION, DO_ONLY_OPTION); pw.printf(" Sets the given component as active admin, and its package as device owner." + "\n\n"); pw.printf(" %s [ %s <USER_ID> | current ] [ %s <NAME> ] <COMPONENT>\n", @@ -254,7 +256,8 @@ final class DevicePolicyManagerServiceShellCommand extends ShellCommand { mService.setActiveAdmin(mComponent, /* refreshing= */ true, mUserId); try { - if (!mService.setDeviceOwner(mComponent, mName, mUserId)) { + if (!mService.setDeviceOwner(mComponent, mName, mUserId, + /* setProfileOwnerOnCurrentUserIfNecessary= */ !mSetDoOnly)) { throw new RuntimeException( "Can't set package " + mComponent + " as device owner."); } @@ -351,6 +354,8 @@ final class DevicePolicyManagerServiceShellCommand extends ShellCommand { if (mUserId == UserHandle.USER_CURRENT) { mUserId = ActivityManager.getCurrentUser(); } + } else if (DO_ONLY_OPTION.equals(opt)) { + mSetDoOnly = true; } else if (canHaveName && NAME_OPTION.equals(opt)) { mName = getNextArgRequired(); } else { diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java index 63e4efc1cce0..3ac30d0258a5 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java @@ -2960,9 +2960,6 @@ public class DevicePolicyManagerTest extends DpmTestBase { assertThat(intent.getAction()).isEqualTo(Settings.ACTION_SHOW_ADMIN_SUPPORT_DETAILS); assertThat(intent.getIntExtra(Intent.EXTRA_USER_ID, -1)) .isEqualTo(UserHandle.getUserId(DpmMockContext.CALLER_SYSTEM_USER_UID)); - assertThat( - (ComponentName) intent.getParcelableExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN)) - .isEqualTo(admin1); assertThat(intent.getStringExtra(DevicePolicyManager.EXTRA_RESTRICTION)) .isEqualTo(UserManager.DISALLOW_ADJUST_VOLUME); @@ -2999,7 +2996,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { assertThat(intent.getStringExtra(DevicePolicyManager.EXTRA_RESTRICTION)) .isEqualTo(DevicePolicyManager.POLICY_DISABLE_CAMERA); assertThat(intent.getIntExtra(Intent.EXTRA_USER_ID, -1)) - .isEqualTo(UserHandle.getUserId(DpmMockContext.CALLER_SYSTEM_USER_UID)); + .isEqualTo(UserHandle.getUserId(DpmMockContext.CALLER_UID)); // ScreenCapture should not be disabled by device owner intent = dpm.createAdminSupportIntent(DevicePolicyManager.POLICY_DISABLE_SCREEN_CAPTURE); assertThat(intent).isNull(); diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java index 0dd5c61121db..418831f47c1a 100644 --- a/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java +++ b/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java @@ -26,6 +26,7 @@ import static android.hardware.display.DisplayManager.DeviceConfig.KEY_REFRESH_R import static android.hardware.display.DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_LOW_ZONE; import static com.android.server.display.DisplayModeDirector.Vote.INVALID_SIZE; +import static com.android.server.display.HighBrightnessModeController.HBM_TRANSITION_POINT_INVALID; import static com.google.common.truth.Truth.assertThat; @@ -74,6 +75,7 @@ import androidx.test.core.app.ApplicationProvider; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; +import com.android.internal.display.BrightnessSynchronizer; import com.android.internal.util.Preconditions; import com.android.internal.util.test.FakeSettingsProvider; import com.android.internal.util.test.FakeSettingsProviderRule; @@ -110,6 +112,7 @@ public class DisplayModeDirectorTest { private static final boolean DEBUG = false; private static final float FLOAT_TOLERANCE = 0.01f; private static final int DISPLAY_ID = 0; + private static final float TRANSITION_POINT = 0.763f; private Context mContext; private FakesInjector mInjector; @@ -751,19 +754,27 @@ public class DisplayModeDirectorTest { director.start(sensorManager); - ArgumentCaptor<SensorEventListener> listenerCaptor = + ArgumentCaptor<DisplayListener> displayListenerCaptor = + ArgumentCaptor.forClass(DisplayListener.class); + verify(mInjector).registerDisplayListener(displayListenerCaptor.capture(), + any(Handler.class), + eq(DisplayManager.EVENT_FLAG_DISPLAY_CHANGED + | DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS)); + DisplayListener displayListener = displayListenerCaptor.getValue(); + + ArgumentCaptor<SensorEventListener> sensorListenerCaptor = ArgumentCaptor.forClass(SensorEventListener.class); Mockito.verify(sensorManager, Mockito.timeout(TimeUnit.SECONDS.toMillis(1))) .registerListener( - listenerCaptor.capture(), + sensorListenerCaptor.capture(), eq(lightSensor), anyInt(), any(Handler.class)); - SensorEventListener listener = listenerCaptor.getValue(); + SensorEventListener sensorListener = sensorListenerCaptor.getValue(); - setBrightness(10); + setBrightness(10, 10, displayListener); // Sensor reads 20 lux, - listener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 20 /*lux*/)); + sensorListener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 20 /*lux*/)); Vote vote = director.getVote(Display.DEFAULT_DISPLAY, Vote.PRIORITY_FLICKER_REFRESH_RATE); assertVoteForRefreshRate(vote, 90 /*fps*/); @@ -771,9 +782,11 @@ public class DisplayModeDirectorTest { assertThat(vote).isNotNull(); assertThat(vote.disableRefreshRateSwitching).isTrue(); - setBrightness(125); + // We expect DisplayModeDirector to act on BrightnessInfo.adjustedBrightness; set only this + // parameter to the necessary threshold + setBrightness(10, 125, displayListener); // Sensor reads 1000 lux, - listener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 1000 /*lux*/)); + sensorListener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 1000 /*lux*/)); vote = director.getVote(Display.DEFAULT_DISPLAY, Vote.PRIORITY_FLICKER_REFRESH_RATE); assertThat(vote).isNull(); @@ -799,6 +812,14 @@ public class DisplayModeDirectorTest { director.start(sensorManager); + ArgumentCaptor<DisplayListener> displayListenerCaptor = + ArgumentCaptor.forClass(DisplayListener.class); + verify(mInjector).registerDisplayListener(displayListenerCaptor.capture(), + any(Handler.class), + eq(DisplayManager.EVENT_FLAG_DISPLAY_CHANGED + | DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS)); + DisplayListener displayListener = displayListenerCaptor.getValue(); + ArgumentCaptor<SensorEventListener> listenerCaptor = ArgumentCaptor.forClass(SensorEventListener.class); verify(sensorManager, Mockito.timeout(TimeUnit.SECONDS.toMillis(1))) @@ -807,20 +828,22 @@ public class DisplayModeDirectorTest { eq(lightSensor), anyInt(), any(Handler.class)); - SensorEventListener listener = listenerCaptor.getValue(); + SensorEventListener sensorListener = listenerCaptor.getValue(); - setBrightness(100); + setBrightness(100, 100, displayListener); // Sensor reads 2000 lux, - listener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 2000)); + sensorListener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 2000)); Vote vote = director.getVote(Display.DEFAULT_DISPLAY, Vote.PRIORITY_FLICKER_REFRESH_RATE); assertThat(vote).isNull(); vote = director.getVote(Display.DEFAULT_DISPLAY, Vote.PRIORITY_FLICKER_REFRESH_RATE_SWITCH); assertThat(vote).isNull(); - setBrightness(255); + // We expect DisplayModeDirector to act on BrightnessInfo.adjustedBrightness; set only this + // parameter to the necessary threshold + setBrightness(100, 255, displayListener); // Sensor reads 9000 lux, - listener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 9000)); + sensorListener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 9000)); vote = director.getVote(Display.DEFAULT_DISPLAY, Vote.PRIORITY_FLICKER_REFRESH_RATE); assertVoteForRefreshRate(vote, 60 /*fps*/); @@ -1435,16 +1458,58 @@ public class DisplayModeDirectorTest { Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); assertNull(vote); - // Turn on HBM + // Turn on HBM, with brightness in the HBM range when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( - new BrightnessInfo(0.45f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR)); + new BrightnessInfo(TRANSITION_POINT + FLOAT_TOLERANCE, 0.0f, 1.0f, + BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR, TRANSITION_POINT)); listener.onDisplayChanged(DISPLAY_ID); vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); assertVoteForRefreshRate(vote, hbmRefreshRate); + // Turn on HBM, with brightness below the HBM range + when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( + new BrightnessInfo(TRANSITION_POINT - FLOAT_TOLERANCE, 0.0f, 1.0f, + BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR, TRANSITION_POINT)); + listener.onDisplayChanged(DISPLAY_ID); + vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); + assertNull(vote); + // Turn off HBM when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( - new BrightnessInfo(0.45f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF)); + new BrightnessInfo(0.45f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF, + TRANSITION_POINT)); + listener.onDisplayChanged(DISPLAY_ID); + vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); + assertNull(vote); + + // Turn on HBM, with brightness in the HBM range + when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( + new BrightnessInfo(TRANSITION_POINT + FLOAT_TOLERANCE, 0.0f, 1.0f, + BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR, TRANSITION_POINT)); + listener.onDisplayChanged(DISPLAY_ID); + vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); + assertVoteForRefreshRate(vote, hbmRefreshRate); + + // Turn off HBM + when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( + new BrightnessInfo(0.45f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF, + TRANSITION_POINT)); + listener.onDisplayChanged(DISPLAY_ID); + vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); + assertNull(vote); + + // Turn on HBM, with brightness below the HBM range + when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( + new BrightnessInfo(TRANSITION_POINT - FLOAT_TOLERANCE, 0.0f, 1.0f, + BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR, TRANSITION_POINT)); + listener.onDisplayChanged(DISPLAY_ID); + vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); + assertNull(vote); + + // Turn off HBM + when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( + new BrightnessInfo(0.45f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF, + TRANSITION_POINT)); listener.onDisplayChanged(DISPLAY_ID); vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); assertNull(vote); @@ -1514,7 +1579,8 @@ public class DisplayModeDirectorTest { // Turn on HBM when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( - new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT)); + new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT, + TRANSITION_POINT)); listener.onDisplayChanged(DISPLAY_ID); vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); assertVoteForRefreshRate(vote, initialRefreshRate); @@ -1531,14 +1597,16 @@ public class DisplayModeDirectorTest { // Turn off HBM when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( - new BrightnessInfo(0.43f, 0.1f, 0.8f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF)); + new BrightnessInfo(0.43f, 0.1f, 0.8f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF, + TRANSITION_POINT)); listener.onDisplayChanged(DISPLAY_ID); vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); assertNull(vote); // Turn HBM on again and ensure the updated vote value stuck when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( - new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT)); + new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT, + TRANSITION_POINT)); listener.onDisplayChanged(DISPLAY_ID); vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); assertVoteForRefreshRate(vote, updatedRefreshRate); @@ -1553,7 +1621,8 @@ public class DisplayModeDirectorTest { // Turn off HBM when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( - new BrightnessInfo(0.43f, 0.1f, 0.8f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF)); + new BrightnessInfo(0.43f, 0.1f, 0.8f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF, + TRANSITION_POINT)); listener.onDisplayChanged(DISPLAY_ID); vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); assertNull(vote); @@ -1584,14 +1653,82 @@ public class DisplayModeDirectorTest { // Turn on HBM when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( - new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT)); + new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT, + TRANSITION_POINT)); + listener.onDisplayChanged(DISPLAY_ID); + vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); + assertNull(vote); + + // Turn off HBM + when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( + new BrightnessInfo(0.43f, 0.1f, 0.8f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF, + TRANSITION_POINT)); + listener.onDisplayChanged(DISPLAY_ID); + vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); + assertNull(vote); + } + + @Test + public void testHbmVoting_HbmUnsupported() { + DisplayModeDirector director = + createDirectorFromRefreshRateArray(new float[] {60.0f, 90.0f}, 0); + director.start(createMockSensorManager()); + + ArgumentCaptor<DisplayListener> captor = + ArgumentCaptor.forClass(DisplayListener.class); + verify(mInjector).registerDisplayListener(captor.capture(), any(Handler.class), + eq(DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS + | DisplayManager.EVENT_FLAG_DISPLAY_REMOVED)); + DisplayListener listener = captor.getValue(); + + // Specify Limitation + when(mDisplayManagerInternalMock.getRefreshRateLimitations(DISPLAY_ID)).thenReturn( + List.of(new RefreshRateLimitation( + DisplayManagerInternal.REFRESH_RATE_LIMIT_HIGH_BRIGHTNESS_MODE, + 60.0f, 60.0f))); + + // Verify that there is no HBM vote initially + Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); + assertNull(vote); + + // Turn on HBM when HBM is supported; expect a valid transition point and a vote. + when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( + new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT, + TRANSITION_POINT)); + listener.onDisplayChanged(DISPLAY_ID); + vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); + assertVoteForRefreshRate(vote, 60.0f); + + // Turn off HBM + when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( + new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF, + TRANSITION_POINT)); + listener.onDisplayChanged(DISPLAY_ID); + vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); + assertNull(vote); + + // Turn on Sunlight HBM when HBM is unsupported; expect an invalid transition point and + // no vote. + when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( + new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT, + HBM_TRANSITION_POINT_INVALID)); + listener.onDisplayChanged(DISPLAY_ID); + vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); + assertNull(vote); + + // Turn on HDR HBM when HBM is unsupported; expect an invalid transition point and + // no vote. + when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( + new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR, + HBM_TRANSITION_POINT_INVALID)); listener.onDisplayChanged(DISPLAY_ID); vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); assertNull(vote); // Turn off HBM when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( - new BrightnessInfo(0.43f, 0.1f, 0.8f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF)); + new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF, + TRANSITION_POINT)); listener.onDisplayChanged(DISPLAY_ID); vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); assertNull(vote); @@ -1600,7 +1737,7 @@ public class DisplayModeDirectorTest { private void setHbmAndAssertRefreshRate( DisplayModeDirector director, DisplayListener listener, int mode, float rr) { when(mInjector.getBrightnessInfo(DISPLAY_ID)) - .thenReturn(new BrightnessInfo(1.0f, 0.0f, 1.0f, mode)); + .thenReturn(new BrightnessInfo(1.0f, 0.0f, 1.0f, mode, TRANSITION_POINT)); listener.onDisplayChanged(DISPLAY_ID); final Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); @@ -1679,7 +1816,8 @@ public class DisplayModeDirectorTest { // Turn on HBM when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( - new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT)); + new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT, + TRANSITION_POINT)); listener.onDisplayChanged(DISPLAY_ID); vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE); assertVoteForRefreshRate(vote, 60.f); @@ -1834,11 +1972,14 @@ public class DisplayModeDirectorTest { } } - private void setBrightness(int brightness) { - Settings.System.putInt(mContext.getContentResolver(), Settings.System.SCREEN_BRIGHTNESS, - brightness); - mInjector.notifyBrightnessChanged(); - waitForIdleSync(); + private void setBrightness(int brightness, int adjustedBrightness, DisplayListener listener) { + float floatBri = BrightnessSynchronizer.brightnessIntToFloat(brightness); + float floatAdjBri = BrightnessSynchronizer.brightnessIntToFloat(adjustedBrightness); + + when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn( + new BrightnessInfo(floatBri, floatAdjBri, 0.0f, 1.0f, + BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF, TRANSITION_POINT)); + listener.onDisplayChanged(DISPLAY_ID); } private void setPeakRefreshRate(float fps) { @@ -1902,27 +2043,6 @@ public class DisplayModeDirectorTest { } @Override - public void registerBrightnessObserver(@NonNull ContentResolver cr, - @NonNull ContentObserver observer) { - if (mBrightnessObserver != null) { - throw new IllegalStateException("Tried to register a second brightness observer"); - } - mBrightnessObserver = observer; - } - - @Override - public void unregisterBrightnessObserver(@NonNull ContentResolver cr, - @NonNull ContentObserver observer) { - mBrightnessObserver = null; - } - - void notifyBrightnessChanged() { - if (mBrightnessObserver != null) { - mBrightnessObserver.dispatchChange(false /*selfChange*/, DISPLAY_BRIGHTNESS_URI); - } - } - - @Override public void registerPeakRefreshRateObserver(@NonNull ContentResolver cr, @NonNull ContentObserver observer) { mPeakRefreshRateObserver = observer; diff --git a/services/tests/servicestests/src/com/android/server/display/HighBrightnessModeControllerTest.java b/services/tests/servicestests/src/com/android/server/display/HighBrightnessModeControllerTest.java index cc3591c89560..aca863299b33 100644 --- a/services/tests/servicestests/src/com/android/server/display/HighBrightnessModeControllerTest.java +++ b/services/tests/servicestests/src/com/android/server/display/HighBrightnessModeControllerTest.java @@ -20,6 +20,8 @@ import static android.hardware.display.BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR; import static android.hardware.display.BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF; import static android.hardware.display.BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT; +import static com.android.server.display.HighBrightnessModeController.HBM_TRANSITION_POINT_INVALID; + import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.spy; @@ -124,6 +126,7 @@ public class HighBrightnessModeControllerTest { mInjectorMock, mHandler, DISPLAY_WIDTH, DISPLAY_HEIGHT, mDisplayToken, DEFAULT_MIN, DEFAULT_MAX, null, () -> {}, mContextSpy); assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_OFF); + assertEquals(hbmc.getTransitionPoint(), HBM_TRANSITION_POINT_INVALID, 0.0f); } @Test @@ -135,6 +138,7 @@ public class HighBrightnessModeControllerTest { hbmc.setAutoBrightnessEnabled(true); hbmc.onAmbientLuxChange(MINIMUM_LUX - 1); // below allowed range assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_OFF); + assertEquals(hbmc.getTransitionPoint(), HBM_TRANSITION_POINT_INVALID, 0.0f); } @Test 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 5fa76bb2e25b..82140f4d965c 100644 --- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java @@ -922,6 +922,40 @@ public class AppTransitionControllerTest extends WindowTestsBase { verify(mDisplayContent.mAppTransition).goodToGo(anyInt(), any()); } + @Test + public void testTransitionGoodToGoForTaskFragments_detachedApp() { + final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run); + final Task task = createTask(mDisplayContent); + final TaskFragment changeTaskFragment = + createTaskFragmentWithEmbeddedActivity(task, organizer); + final TaskFragment emptyTaskFragment = new TaskFragmentBuilder(mAtm) + .setParentTask(task) + .setOrganizer(organizer) + .build(); + changeTaskFragment.getTopMostActivity().allDrawn = true; + // To make sure that having a detached activity won't cause any issue. + final ActivityRecord detachedActivity = createActivityRecord(task); + detachedActivity.removeImmediately(); + assertNull(detachedActivity.getRootTask()); + spyOn(mDisplayContent.mAppTransition); + spyOn(emptyTaskFragment); + + prepareAndTriggerAppTransition( + null /* openingActivity */, detachedActivity, changeTaskFragment); + + // Transition not ready because there is an empty non-finishing TaskFragment. + verify(mDisplayContent.mAppTransition, never()).goodToGo(anyInt(), any()); + + doReturn(true).when(emptyTaskFragment).hasChild(); + emptyTaskFragment.remove(false /* withTransition */, "test"); + + mDisplayContent.mAppTransitionController.handleAppTransitionReady(); + + // Transition ready because the empty (no running activity) TaskFragment is requested to be + // removed. + verify(mDisplayContent.mAppTransition).goodToGo(anyInt(), any()); + } + /** Registers remote animation for the organizer. */ private void setupTaskFragmentRemoteAnimation(TaskFragmentOrganizer organizer, RemoteAnimationAdapter adapter) { diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java index 405d714256ab..fb8bc7be38ce 100644 --- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java @@ -35,6 +35,8 @@ import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentat import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; import static com.android.server.wm.WindowContainer.POSITION_TOP; import static org.junit.Assert.assertEquals; @@ -42,6 +44,7 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; import android.graphics.Rect; import android.os.Binder; @@ -54,6 +57,7 @@ import android.view.IRemoteAnimationFinishedCallback; import android.view.IRemoteAnimationRunner; import android.view.RemoteAnimationAdapter; import android.view.RemoteAnimationTarget; +import android.view.SurfaceControl; import android.view.WindowManager; import android.window.ITaskFragmentOrganizer; import android.window.TaskFragmentOrganizer; @@ -397,7 +401,9 @@ public class AppTransitionTests extends WindowTestsBase { @Test public void testActivityRecordReparentToTaskFragment() { final ActivityRecord activity = createActivityRecord(mDc); + final SurfaceControl activityLeash = mock(SurfaceControl.class); activity.setVisibility(true); + activity.setSurfaceControl(activityLeash); final Task task = activity.getTask(); // Add a TaskFragment of half of the Task size. @@ -412,15 +418,20 @@ public class AppTransitionTests extends WindowTestsBase { final Rect taskBounds = new Rect(); task.getBounds(taskBounds); taskFragment.setBounds(0, 0, taskBounds.right / 2, taskBounds.bottom); + spyOn(taskFragment); assertTrue(mDc.mChangingContainers.isEmpty()); assertFalse(mDc.mAppTransition.isTransitionSet()); // Schedule app transition when reparent activity to a TaskFragment of different size. + final Rect startBounds = new Rect(activity.getBounds()); activity.reparent(taskFragment, POSITION_TOP); - assertTrue(mDc.mChangingContainers.contains(activity)); + // It should transit at TaskFragment level with snapshot on the activity surface. + verify(taskFragment).initializeChangeTransition(activity.getBounds(), activityLeash); + assertTrue(mDc.mChangingContainers.contains(taskFragment)); assertTrue(mDc.mAppTransition.containsTransitRequest(TRANSIT_CHANGE)); + assertEquals(startBounds, taskFragment.mSurfaceFreezer.mFreezeBounds); } private class TestRemoteAnimationRunner implements IRemoteAnimationRunner { diff --git a/services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java b/services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java index 78946fca7e8b..1e86522a2307 100644 --- a/services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java @@ -63,7 +63,7 @@ public class LetterboxTest { mLetterbox = new Letterbox(mSurfaces, StubTransaction::new, () -> mAreCornersRounded, () -> Color.valueOf(mColor), () -> mHasWallpaperBackground, () -> mBlurRadius, () -> mDarkScrimAlpha, - /* doubleTapCallback= */ () -> {}); + /* doubleTapCallback= */ x -> {}); mTransaction = spy(StubTransaction.class); } diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java new file mode 100644 index 000000000000..cb209abf6aa9 --- /dev/null +++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java @@ -0,0 +1,105 @@ +/* + * 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 com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; + +import static org.mockito.Mockito.clearInvocations; + +import android.graphics.Rect; +import android.platform.test.annotations.Presubmit; +import android.view.SurfaceControl; +import android.window.ITaskFragmentOrganizer; +import android.window.TaskFragmentOrganizer; + +import androidx.test.filters.MediumTest; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +/** + * Test class for {@link TaskFragment}. + * + * Build/Install/Run: + * atest WmTests:TaskFragmentTest + */ +@MediumTest +@Presubmit +@RunWith(WindowTestRunner.class) +public class TaskFragmentTest extends WindowTestsBase { + + private TaskFragmentOrganizer mOrganizer; + private TaskFragment mTaskFragment; + private SurfaceControl mLeash; + @Mock + private SurfaceControl.Transaction mTransaction; + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + mOrganizer = new TaskFragmentOrganizer(Runnable::run); + final ITaskFragmentOrganizer iOrganizer = + ITaskFragmentOrganizer.Stub.asInterface(mOrganizer.getOrganizerToken().asBinder()); + mAtm.mWindowOrganizerController.mTaskFragmentOrganizerController + .registerOrganizer(iOrganizer); + mTaskFragment = new TaskFragmentBuilder(mAtm) + .setCreateParentTask() + .setOrganizer(mOrganizer) + .build(); + mLeash = mTaskFragment.getSurfaceControl(); + spyOn(mTaskFragment); + doReturn(mTransaction).when(mTaskFragment).getSyncTransaction(); + doReturn(mTransaction).when(mTaskFragment).getPendingTransaction(); + } + + @Test + public void testOnConfigurationChanged_updateSurface() { + final Rect bounds = new Rect(100, 100, 1100, 1100); + mTaskFragment.setBounds(bounds); + + verify(mTransaction).setPosition(mLeash, 100, 100); + verify(mTransaction).setWindowCrop(mLeash, 1000, 1000); + } + + @Test + public void testStartChangeTransition_resetSurface() { + 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(); + + clearInvocations(mTransaction); + mTaskFragment.setBounds(endBounds); + + // Surface reset when prepare transition. + verify(mTaskFragment).initializeChangeTransition(startBounds); + verify(mTransaction).setPosition(mLeash, 0, 0); + verify(mTransaction).setWindowCrop(mLeash, 0, 0); + + clearInvocations(mTransaction); + mTaskFragment.mSurfaceFreezer.unfreeze(mTransaction); + + // Update surface after animation. + verify(mTransaction).setPosition(mLeash, 500, 500); + verify(mTransaction).setWindowCrop(mLeash, 500, 500); + } +} diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java index b17ea5e48db5..e6ad68aafaec 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java @@ -18,6 +18,7 @@ package com.android.server.wm; import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; 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.view.InsetsState.ITYPE_IME; @@ -835,8 +836,7 @@ public class WindowStateTests extends WindowTestsBase { WindowState sameTokenWindow = createWindow(null, TYPE_BASE_APPLICATION, mAppWindow.mToken, "SameTokenWindow"); mDisplayContent.setImeLayeringTarget(mAppWindow); - sameTokenWindow.mActivityRecord.getRootTask().setWindowingMode( - WINDOWING_MODE_SPLIT_SCREEN_PRIMARY); + sameTokenWindow.mActivityRecord.getRootTask().setWindowingMode(WINDOWING_MODE_MULTI_WINDOW); assertTrue(sameTokenWindow.needsRelativeLayeringToIme()); sameTokenWindow.removeImmediately(); assertFalse(sameTokenWindow.needsRelativeLayeringToIme()); @@ -848,8 +848,7 @@ public class WindowStateTests extends WindowTestsBase { WindowState sameTokenWindow = createWindow(null, TYPE_APPLICATION_STARTING, mAppWindow.mToken, "SameTokenWindow"); mDisplayContent.setImeLayeringTarget(mAppWindow); - sameTokenWindow.mActivityRecord.getRootTask().setWindowingMode( - WINDOWING_MODE_SPLIT_SCREEN_PRIMARY); + sameTokenWindow.mActivityRecord.getRootTask().setWindowingMode(WINDOWING_MODE_MULTI_WINDOW); assertFalse(sameTokenWindow.needsRelativeLayeringToIme()); } 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 d967891fdb76..22ea3d5be71b 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java @@ -20,6 +20,7 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT; import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; 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; @@ -37,6 +38,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; import static com.android.server.wm.WindowStateAnimator.PRESERVED_SURFACE_LAYER; import static com.google.common.truth.Truth.assertThat; @@ -493,4 +495,27 @@ public class ZOrderingTests extends WindowTestsBase { assertZOrderGreaterThan(mTransaction, mNavBarWindow.mToken.getSurfaceControl(), mDisplayContent.getImeContainer().getSurfaceControl()); } + + @Test + public void testPopupWindowAndParentIsImeTarget_expectHigherThanIme_inMultiWindow() { + // Simulate the app window is in multi windowing mode and being IME target + mAppWindow.getConfiguration().windowConfiguration.setWindowingMode( + WINDOWING_MODE_MULTI_WINDOW); + mDisplayContent.setImeLayeringTarget(mAppWindow); + mDisplayContent.setImeInputTarget(mAppWindow); + + // Create a popupWindow + assertWindowHigher(mImeWindow, mAppWindow); + final WindowState popupWindow = createWindow(mAppWindow, TYPE_APPLICATION_PANEL, + mDisplayContent, "PopupWindow"); + spyOn(popupWindow); + + mDisplayContent.assignChildLayers(mTransaction); + + // Verify the surface layer of the popupWindow should higher than IME + verify(popupWindow).needsRelativeLayeringToIme(); + assertThat(popupWindow.needsRelativeLayeringToIme()).isTrue(); + assertZOrderGreaterThan(mTransaction, popupWindow.getSurfaceControl(), + mDisplayContent.getImeContainer().getSurfaceControl()); + } } |