diff options
49 files changed, 853 insertions, 210 deletions
diff --git a/apex/jobscheduler/framework/java/android/app/job/JobInfo.java b/apex/jobscheduler/framework/java/android/app/job/JobInfo.java index b9052734b65f..ae8976a2972e 100644 --- a/apex/jobscheduler/framework/java/android/app/job/JobInfo.java +++ b/apex/jobscheduler/framework/java/android/app/job/JobInfo.java @@ -53,9 +53,8 @@ import java.util.Objects; * Container of data passed to the {@link android.app.job.JobScheduler} fully encapsulating the * parameters required to schedule work against the calling application. These are constructed * using the {@link JobInfo.Builder}. - * You must specify at least one sort of constraint on the JobInfo object that you are creating. * The goal here is to provide the scheduler with high-level semantics about the work you want to - * accomplish. Doing otherwise with throw an exception in your app. + * accomplish. */ public class JobInfo implements Parcelable { private static String TAG = "JobInfo"; @@ -147,7 +146,7 @@ public class JobInfo implements Parcelable { /** * Query the minimum interval allowed for periodic scheduled jobs. Attempting - * to declare a smaller period that this when scheduling a job will result in a + * to declare a smaller period than this when scheduling a job will result in a * job that is still periodic, but will run with this effective period. * * @return The minimum available interval for scheduling periodic jobs, in milliseconds. diff --git a/api/current.txt b/api/current.txt index 6632546bf99d..a85d632e0f31 100644 --- a/api/current.txt +++ b/api/current.txt @@ -11572,6 +11572,7 @@ package android.content.pm { method @NonNull public CharSequence getProfileSwitchingLabel(@NonNull android.os.UserHandle); method @NonNull public java.util.List<android.os.UserHandle> getTargetUserProfiles(); method @RequiresPermission(anyOf={android.Manifest.permission.INTERACT_ACROSS_PROFILES, "android.permission.INTERACT_ACROSS_USERS"}) public void startActivity(@NonNull android.content.Intent, @NonNull android.os.UserHandle, @Nullable android.app.Activity); + method @RequiresPermission(anyOf={android.Manifest.permission.INTERACT_ACROSS_PROFILES, "android.permission.INTERACT_ACROSS_USERS"}) public void startActivity(@NonNull android.content.Intent, @NonNull android.os.UserHandle, @Nullable android.app.Activity, @Nullable android.os.Bundle); method public void startMainActivity(@NonNull android.content.ComponentName, @NonNull android.os.UserHandle); field public static final String ACTION_CAN_INTERACT_ACROSS_PROFILES_CHANGED = "android.content.pm.action.CAN_INTERACT_ACROSS_PROFILES_CHANGED"; } diff --git a/api/system-current.txt b/api/system-current.txt index ab87a5dbdc1b..b7aa9da83c6a 100755 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -11306,7 +11306,6 @@ package android.telephony { public class ServiceState implements android.os.Parcelable { method public void fillInNotifierBundle(@NonNull android.os.Bundle); method public int getDataNetworkType(); - method public int getDataRegistrationState(); method @Nullable public android.telephony.NetworkRegistrationInfo getNetworkRegistrationInfo(int, int); method @NonNull public java.util.List<android.telephony.NetworkRegistrationInfo> getNetworkRegistrationInfoListForDomain(int); method @NonNull public java.util.List<android.telephony.NetworkRegistrationInfo> getNetworkRegistrationInfoListForTransportType(int); diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto index b7d1135e0315..56f2340933d3 100644 --- a/cmds/statsd/src/atoms.proto +++ b/cmds/statsd/src/atoms.proto @@ -402,7 +402,7 @@ message Atom { } // Pulled events will start at field 10000. - // Next: 10076 + // Next: 10080 oneof pulled { WifiBytesTransfer wifi_bytes_transfer = 10000 [(module) = "framework"]; WifiBytesTransferByFgBg wifi_bytes_transfer_by_fg_bg = 10001 [(module) = "framework"]; @@ -486,6 +486,10 @@ message Atom { 10073 [(module) = "framework"]; GnssStats gnss_stats = 10074 [(module) = "framework"]; AppFeaturesOps app_features_ops = 10075 [(module) = "framework"]; + VoiceCallSession voice_call_session = 10076 [(module) = "telephony"]; + VoiceCallRatUsage voice_call_rat_usage = 10077 [(module) = "telephony"]; + SimSlotState sim_slot_state = 10078 [(module) = "telephony"]; + SupportedRadioAccessFamily supported_radio_access_family = 10079 [(module) = "telephony"]; } // DO NOT USE field numbers above 100,000 in AOSP. @@ -8671,6 +8675,154 @@ message AppFreezeChanged { } /** + * Pulls information for a single voice call. + * + * Each pull creates multiple atoms, one for each call. The sequence is randomized when pulled. + * + * Pulled from: + * frameworks/opt/telephony/src/java/com/android/internal/telephony/metrics/PersistPullers.java + */ +message VoiceCallSession { + // Bearer (IMS or CS) when the call started. + optional android.telephony.CallBearerEnum bearer_at_start = 1; + + // Bearer (IMS or CS) when the call ended. + // The bearer may change during the call, e.g. due to SRVCC. + optional android.telephony.CallBearerEnum bearer_at_end = 2; + + // Direction of the call (incoming or outgoing). + optional android.telephony.CallDirectionEnum direction = 3; + + // Time spent setting up the call. + optional android.telephony.CallSetupDurationEnum setup_duration = 4; + + // Whether the call ended before the setup was completed. + optional bool setup_failed = 5; + + // IMS reason code or CS disconnect cause. + // For IMS, see: frameworks/base/telephony/java/android/telephony/ims/ImsReasonInfo.java + // For CS, see: frameworks/base/telephony/java/android/telephony/DisconnectCause.java + optional int32 disconnect_reason_code = 6; + + // IMS extra code or CS precise disconnect cause. + // For IMS, this code is vendor-specific + // For CS, see: frameworks/base/telephony/java/android/telephony/PreciseDisconnectCause.java + optional int32 disconnect_extra_code = 7; + + // IMS extra message or CS vendor cause. + optional string disconnect_extra_message = 8; + + // Radio access technology (RAT) used when call started. + optional android.telephony.NetworkTypeEnum rat_at_start = 9; + + // Radio access technology (RAT) used when call terminated. + optional android.telephony.NetworkTypeEnum rat_at_end = 10; + + // Number of times RAT changed during the call. + optional int64 rat_switch_count = 11; + + // A bitmask of all codecs used during the call. + // See: frameworks/opt/telephony/src/java/com/android/internal/telephony/metrics/VoiceCallSessionStats.java + optional int64 codec_bitmask = 12; + + // Number of other calls going on during call setup, for the same SIM slot. + optional int32 concurrent_call_count_at_start = 13; + + // Number of other calls going on during call termination, for the same SIM slot. + optional int32 concurrent_call_count_at_end = 14; + + // Index of the SIM is used, 0 for single-SIM devices. + optional int32 sim_slot_index = 15; + + // Whether the device was in multi-SIM mode (with multiple active SIM profiles). + optional bool is_multi_sim = 16; + + // Whether the call was made with an eSIM profile. + optional bool is_esim = 17; + + // Carrier ID of the SIM card. + // See https://source.android.com/devices/tech/config/carrierid. + optional int32 carrier_id = 18; + + // Whether an SRVCC has been completed successfully. + // SRVCC (CS fallback) should be recorded in the IMS call since there will be no more SRVCC + // events once the call is switched to CS. + optional bool srvcc_completed = 19; + + // Number of SRVCC failures. + optional int64 srvcc_failure_count = 20; + + // Number of SRVCC cancellations. + optional int64 srvcc_cancellation_count = 21; + + // Whether the Real-Time Text (RTT) was ever used in the call. + optional bool rtt_enabled = 22; + + // Whether this was an emergency call. + optional bool is_emergency = 23; + + // Whether the call was performed while roaming. + optional bool is_roaming = 24; +} + +/** + * Pulls voice call radio access technology (RAT) usage. + * + * Each pull creates multiple atoms, one for each carrier/RAT, the order of which is irrelevant to + * time. The atom will be skipped if not enough data is available. + * + * Pulled from: + * frameworks/opt/telephony/src/java/com/android/internal/telephony/metrics/PersistPullers.java + */ +message VoiceCallRatUsage { + // Carrier ID (https://source.android.com/devices/tech/config/carrierid). + optional int32 carrier_id = 1; + + // Radio access technology. + optional android.telephony.NetworkTypeEnum rat = 2; + + // Total duration that voice calls spent on this carrier and RAT. + optional int64 total_duration_seconds = 3; + + // Total number of calls using this carrier and RAT. + // A call is counted once even if it used the RAT multiple times. + optional int64 call_count = 4; +} + +/** + * Pulls the number of active SIM slots and SIMs/eSIM profiles. + * + * Pulled from: + * frameworks/opt/telephony/src/java/com/android/internal/telephony/metrics/NonPersistPullers.java + */ +message SimSlotState { + // Number of active SIM slots (both physical and eSIM profiles) in the device. + optional int32 active_slot_count = 1; + + // Number of SIM cards (both physical and active eSIM profiles). + // This number is always equal to or less than the number of active SIM slots. + optional int32 sim_count = 2; + + // Number of active eSIM profiles. + // This number is always equal to or less than the number of SIMs. + optional int32 esim_count = 3; +} + +/** + * Pulls supported cellular radio access technologies. + * + * This atom reports the capabilities of the device, rather than the network it has access to. + * + * Pulled from: + * frameworks/opt/telephony/src/java/com/android/internal/telephony/metrics/NonPersistPullers.java + */ +message SupportedRadioAccessFamily { + // A bitmask of supported radio technologies. + // See android.telephony.TelephonyManager.NetworkTypeBitMask. + optional int64 network_type_bitmask = 1; +} + +/** * Logs gnss stats from location service provider * * Pulled from: diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index 6564dc9b0840..9925d69b9ce0 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java @@ -27,6 +27,7 @@ import android.annotation.SystemApi; import android.annotation.SystemService; import android.annotation.TestApi; import android.app.usage.UsageStatsManager; +import android.compat.Compatibility; import android.compat.annotation.ChangeId; import android.compat.annotation.EnabledAfter; import android.compat.annotation.UnsupportedAppUsage; @@ -385,6 +386,13 @@ public class AppOpsManager { */ public static final int WATCH_FOREGROUND_CHANGES = 1 << 0; + /** + * Flag for {@link #startWatchingMode} that causes the callback to happen on the switch-op + * instead the op the callback was registered. (This simulates pre-R behavior). + * + * @hide + */ + public static final int CALL_BACK_ON_SWITCHED_OP = 1 << 1; /** * Flag to determine whether we should log noteOp/startOp calls to make sure they @@ -6712,6 +6720,13 @@ public class AppOpsManager { }; mModeWatchers.put(callback, cb); } + + // See CALL_BACK_ON_CHANGED_LISTENER_WITH_SWITCHED_OP_CHANGE + if (!Compatibility.isChangeEnabled( + CALL_BACK_ON_CHANGED_LISTENER_WITH_SWITCHED_OP_CHANGE)) { + flags |= CALL_BACK_ON_SWITCHED_OP; + } + try { mService.startWatchingModeWithFlags(op, packageName, flags, cb); } catch (RemoteException e) { diff --git a/core/java/android/content/pm/CrossProfileApps.java b/core/java/android/content/pm/CrossProfileApps.java index 3261cb124e00..5e7e0c8a2d6a 100644 --- a/core/java/android/content/pm/CrossProfileApps.java +++ b/core/java/android/content/pm/CrossProfileApps.java @@ -27,6 +27,7 @@ import android.content.Intent; import android.content.res.Resources; import android.graphics.drawable.Drawable; import android.net.Uri; +import android.os.Bundle; import android.os.RemoteException; import android.os.UserHandle; import android.os.UserManager; @@ -128,6 +129,35 @@ public class CrossProfileApps { @NonNull Intent intent, @NonNull UserHandle targetUser, @Nullable Activity callingActivity) { + startActivity(intent, targetUser, callingActivity, /* options= */ null); + } + + /** + * Starts the specified activity of the caller package in the specified profile. + * + * <p>The caller must have the {@link android.Manifest.permission#INTERACT_ACROSS_PROFILES}, + * {@code android.Manifest.permission#INTERACT_ACROSS_USERS}, or {@code + * android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} permission. Both the caller and + * target user profiles must be in the same profile group. The target user must be a valid user + * returned from {@link #getTargetUserProfiles()}. + * + * @param intent The intent to launch. A component in the caller package must be specified. + * @param targetUser The {@link UserHandle} of the profile; must be one of the users returned by + * {@link #getTargetUserProfiles()} if different to the calling user, otherwise a + * {@link SecurityException} will be thrown. + * @param callingActivity The activity to start the new activity from for the purposes of + * deciding which task the new activity should belong to. If {@code null}, the activity + * will always be started in a new task. + * @param options The activity options or {@code null}. See {@link android.app.ActivityOptions}. + */ + @RequiresPermission(anyOf = { + android.Manifest.permission.INTERACT_ACROSS_PROFILES, + android.Manifest.permission.INTERACT_ACROSS_USERS}) + public void startActivity( + @NonNull Intent intent, + @NonNull UserHandle targetUser, + @Nullable Activity callingActivity, + @Nullable Bundle options) { try { mService.startActivityAsUserByIntent( mContext.getIApplicationThread(), @@ -135,7 +165,8 @@ public class CrossProfileApps { mContext.getFeatureId(), intent, targetUser.getIdentifier(), - callingActivity != null ? callingActivity.getActivityToken() : null); + callingActivity != null ? callingActivity.getActivityToken() : null, + options); } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } diff --git a/core/java/android/content/pm/ICrossProfileApps.aidl b/core/java/android/content/pm/ICrossProfileApps.aidl index 5a6e008608f3..4cecb30990e6 100644 --- a/core/java/android/content/pm/ICrossProfileApps.aidl +++ b/core/java/android/content/pm/ICrossProfileApps.aidl @@ -31,7 +31,8 @@ interface ICrossProfileApps { in String callingFeatureId, in ComponentName component, int userId, boolean launchMainActivity); void startActivityAsUserByIntent(in IApplicationThread caller, in String callingPackage, - in String callingFeatureId, in Intent intent, int userId, in IBinder callingActivity); + in String callingFeatureId, in Intent intent, int userId, in IBinder callingActivity, + in Bundle options); List<UserHandle> getTargetUserProfiles(in String callingPackage); boolean canInteractAcrossProfiles(in String callingPackage); boolean canRequestInteractAcrossProfiles(in String callingPackage); diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java index 1f5317679bd2..ec3590fd23cf 100644 --- a/core/java/android/content/pm/PackageInstaller.java +++ b/core/java/android/content/pm/PackageInstaller.java @@ -2323,6 +2323,7 @@ public class PackageInstaller { /** * Get the value set in {@link SessionParams#setOriginatingUri(Uri)}. + * Note: This value will only be non-null for the owner of the session. */ public @Nullable Uri getOriginatingUri() { return originatingUri; @@ -2337,6 +2338,7 @@ public class PackageInstaller { /** * Get the value set in {@link SessionParams#setReferrerUri(Uri)} + * Note: This value will only be non-null for the owner of the session. */ public @Nullable Uri getReferrerUri() { return referrerUri; diff --git a/core/java/android/view/WindowContainerTransaction.java b/core/java/android/view/WindowContainerTransaction.java index e05c3743565c..9c16e1334e00 100644 --- a/core/java/android/view/WindowContainerTransaction.java +++ b/core/java/android/view/WindowContainerTransaction.java @@ -131,6 +131,31 @@ public class WindowContainerTransaction implements Parcelable { } /** + * Set the windowing mode of children of a given root task, without changing + * the windowing mode of the Task itself. This can be used during transitions + * for example to make the activity render it's fullscreen configuration + * while the Task is still in PIP, so you can complete the animation. + * + * TODO(b/134365562): Can be removed once TaskOrg drives full-screen + */ + public WindowContainerTransaction setActivityWindowingMode(IWindowContainer container, + int windowingMode) { + Change chg = getOrCreateChange(container.asBinder()); + chg.mActivityWindowingMode = windowingMode; + return this; + } + + /** + * Sets the windowing mode of the given container. + */ + public WindowContainerTransaction setWindowingMode(IWindowContainer container, + int windowingMode) { + Change chg = getOrCreateChange(container.asBinder()); + chg.mWindowingMode = windowingMode; + return this; + } + + /** * Sets whether a container or any of its children can be focusable. When {@code false}, no * child can be focused; however, when {@code true}, it is still possible for children to be * non-focusable due to WM policy. @@ -235,6 +260,9 @@ public class WindowContainerTransaction implements Parcelable { private Rect mPinnedBounds = null; private SurfaceControl.Transaction mBoundsChangeTransaction = null; + private int mActivityWindowingMode = -1; + private int mWindowingMode = -1; + public Change() {} protected Change(Parcel in) { @@ -251,6 +279,17 @@ public class WindowContainerTransaction implements Parcelable { mBoundsChangeTransaction = SurfaceControl.Transaction.CREATOR.createFromParcel(in); } + + mWindowingMode = in.readInt(); + mActivityWindowingMode = in.readInt(); + } + + public int getWindowingMode() { + return mWindowingMode; + } + + public int getActivityWindowingMode() { + return mActivityWindowingMode; } public Configuration getConfiguration() { @@ -340,6 +379,9 @@ public class WindowContainerTransaction implements Parcelable { if (mBoundsChangeTransaction != null) { mBoundsChangeTransaction.writeToParcel(dest, flags); } + + dest.writeInt(mWindowingMode); + dest.writeInt(mActivityWindowingMode); } @Override diff --git a/core/java/com/android/internal/app/AbstractMultiProfilePagerAdapter.java b/core/java/com/android/internal/app/AbstractMultiProfilePagerAdapter.java index d50826f815a0..fa567f235c94 100644 --- a/core/java/com/android/internal/app/AbstractMultiProfilePagerAdapter.java +++ b/core/java/com/android/internal/app/AbstractMultiProfilePagerAdapter.java @@ -452,7 +452,7 @@ public abstract class AbstractMultiProfilePagerAdapter extends PagerAdapter { mEmptyStateView = rootView.findViewById(R.id.resolver_empty_state); } - private ViewGroup getEmptyStateView() { + protected ViewGroup getEmptyStateView() { return mEmptyStateView; } } diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java index c099301d2043..5620bff5142b 100644 --- a/core/java/com/android/internal/app/ChooserActivity.java +++ b/core/java/com/android/internal/app/ChooserActivity.java @@ -2411,6 +2411,8 @@ public class ChooserActivity extends ResolverActivity implements mChooserMultiProfilePagerAdapter.getActiveAdapterView() .setAdapter(mChooserMultiProfilePagerAdapter.getCurrentRootAdapter()); return; + } else if (mChooserMultiProfilePagerAdapter.getCurrentUserHandle() != getUser()) { + return; } getMainThreadHandler().post(() -> { @@ -2455,39 +2457,46 @@ public class ChooserActivity extends ResolverActivity implements offset += tabDivider.getHeight(); } - int directShareHeight = 0; - rowsToShow = Math.min(4, rowsToShow); - mLastNumberOfChildren = recyclerView.getChildCount(); - for (int i = 0, childCount = recyclerView.getChildCount(); - i < childCount && rowsToShow > 0; i++) { - View child = recyclerView.getChildAt(i); - if (((GridLayoutManager.LayoutParams) - child.getLayoutParams()).getSpanIndex() != 0) { - continue; - } - int height = child.getHeight(); - offset += height; + if (recyclerView.getVisibility() == View.VISIBLE) { + int directShareHeight = 0; + rowsToShow = Math.min(4, rowsToShow); + mLastNumberOfChildren = recyclerView.getChildCount(); + for (int i = 0, childCount = recyclerView.getChildCount(); + i < childCount && rowsToShow > 0; i++) { + View child = recyclerView.getChildAt(i); + if (((GridLayoutManager.LayoutParams) + child.getLayoutParams()).getSpanIndex() != 0) { + continue; + } + int height = child.getHeight(); + offset += height; - if (gridAdapter.getTargetType( - recyclerView.getChildAdapterPosition(child)) - == ChooserListAdapter.TARGET_SERVICE) { - directShareHeight = height; + if (gridAdapter.getTargetType( + recyclerView.getChildAdapterPosition(child)) + == ChooserListAdapter.TARGET_SERVICE) { + directShareHeight = height; + } + rowsToShow--; } - rowsToShow--; - } - boolean isExpandable = getResources().getConfiguration().orientation - == Configuration.ORIENTATION_PORTRAIT && !isInMultiWindowMode(); - if (directShareHeight != 0 && isSendAction(getTargetIntent()) - && isExpandable) { - // make sure to leave room for direct share 4->8 expansion - int requiredExpansionHeight = - (int) (directShareHeight / DIRECT_SHARE_EXPANSION_RATE); - int topInset = mSystemWindowInsets != null ? mSystemWindowInsets.top : 0; - int minHeight = bottom - top - mResolverDrawerLayout.getAlwaysShowHeight() - - requiredExpansionHeight - topInset - bottomInset; - - offset = Math.min(offset, minHeight); + boolean isExpandable = getResources().getConfiguration().orientation + == Configuration.ORIENTATION_PORTRAIT && !isInMultiWindowMode(); + if (directShareHeight != 0 && isSendAction(getTargetIntent()) + && isExpandable) { + // make sure to leave room for direct share 4->8 expansion + int requiredExpansionHeight = + (int) (directShareHeight / DIRECT_SHARE_EXPANSION_RATE); + int topInset = mSystemWindowInsets != null ? mSystemWindowInsets.top : 0; + int minHeight = bottom - top - mResolverDrawerLayout.getAlwaysShowHeight() + - requiredExpansionHeight - topInset - bottomInset; + + offset = Math.min(offset, minHeight); + } + } else { + ViewGroup currentEmptyStateView = getCurrentEmptyStateView(); + if (currentEmptyStateView.getVisibility() == View.VISIBLE) { + offset += currentEmptyStateView.getHeight(); + } } mResolverDrawerLayout.setCollapsibleHeightReserved(Math.min(offset, bottom - top)); @@ -2495,6 +2504,11 @@ public class ChooserActivity extends ResolverActivity implements } } + private ViewGroup getCurrentEmptyStateView() { + int currentPage = mChooserMultiProfilePagerAdapter.getCurrentPage(); + return mChooserMultiProfilePagerAdapter.getItem(currentPage).getEmptyStateView(); + } + static class BaseChooserTargetComparator implements Comparator<ChooserTarget> { @Override public int compare(ChooserTarget lhs, ChooserTarget rhs) { diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp index 0d0dc3ede754..f7c6dbd1a65d 100644 --- a/core/jni/android_os_Debug.cpp +++ b/core/jni/android_os_Debug.cpp @@ -853,8 +853,11 @@ static jboolean android_os_Debug_isVmapStack(JNIEnv *env, jobject clazz) } cfg_state = CONFIG_UNKNOWN; if (cfg_state == CONFIG_UNKNOWN) { - const std::map<std::string, std::string> configs = - vintf::VintfObject::GetInstance()->getRuntimeInfo()->kernelConfigs(); + auto runtime_info = vintf::VintfObject::GetInstance() + ->getRuntimeInfo(false /* skip cache */, + vintf::RuntimeInfo::FetchFlag::CONFIG_GZ); + CHECK(runtime_info != nullptr) << "Kernel configs cannot be fetched. b/151092221"; + const std::map<std::string, std::string>& configs = runtime_info->kernelConfigs(); std::map<std::string, std::string>::const_iterator it = configs.find("CONFIG_VMAP_STACK"); cfg_state = (it != configs.end() && it->second == "y") ? CONFIG_SET : CONFIG_UNSET; } diff --git a/core/proto/android/app/settings_enums.proto b/core/proto/android/app/settings_enums.proto index 030483bc4c33..ef6eb38043f6 100644 --- a/core/proto/android/app/settings_enums.proto +++ b/core/proto/android/app/settings_enums.proto @@ -724,6 +724,16 @@ enum Action { // CATEGORY: SETTINGS // OS: R ACTION_ADB_WIRELESS_OFF = 1735; + + // ACTION: Change Wi-Fi hotspot name + // CATEGORY: SETTINGS + // OS: R + ACTION_SETTINGS_CHANGE_WIFI_HOTSPOT_NAME = 1736; + + // ACTION: Change Wi-Fi hotspot password + // CATEGORY: SETTINGS + // OS: R + ACTION_SETTINGS_CHANGE_WIFI_HOTSPOT_PASSWORD = 1737; } /** diff --git a/core/proto/android/telephony/enums.proto b/core/proto/android/telephony/enums.proto index 477716982008..f14e3ed1872d 100644 --- a/core/proto/android/telephony/enums.proto +++ b/core/proto/android/telephony/enums.proto @@ -20,6 +20,43 @@ package android.telephony; option java_outer_classname = "TelephonyProtoEnums"; option java_multiple_files = true; +enum CallBearerEnum { + /** Call bearer is unknown or invalid */ + CALL_BEARER_UNKNOWN = 0; + + /** Call bearer is legacy CS */ + CALL_BEARER_CS = 1; + + /** Call bearer is IMS */ + CALL_BEARER_IMS = 2; +} + +enum CallDirectionEnum { + /** Call direction: unknown or invalid */ + CALL_DIRECTION_UNKNOWN = 0; + + /** Call direction: mobile originated (outgoing for this device) */ + CALL_DIRECTION_MO = 1; + + /** Call direction: mobile terminated (incoming for this device) */ + CALL_DIRECTION_MT = 2; +} + +// Call setup duration buckets. +// See com.android.internal.telephony.metrics.VoiceCallSessionStats for definition. +enum CallSetupDurationEnum { + CALL_SETUP_DURATION_UNKNOWN = 0; + CALL_SETUP_DURATION_EXTREMELY_FAST = 1; + CALL_SETUP_DURATION_ULTRA_FAST = 2; + CALL_SETUP_DURATION_VERY_FAST = 3; + CALL_SETUP_DURATION_FAST = 4; + CALL_SETUP_DURATION_NORMAL = 5; + CALL_SETUP_DURATION_SLOW = 6; + CALL_SETUP_DURATION_VERY_SLOW = 7; + CALL_SETUP_DURATION_ULTRA_SLOW = 8; + CALL_SETUP_DURATION_EXTREMELY_SLOW = 9; +} + // Data conn. power states, primarily used by android/telephony/DataConnectionRealTimeInfo.java. enum DataConnectionPowerStateEnum { DATA_CONNECTION_POWER_STATE_LOW = 1; @@ -63,7 +100,6 @@ enum SignalStrengthEnum { SIGNAL_STRENGTH_GREAT = 4; } - enum ServiceStateEnum { /** * Normal operation condition, the phone is registered diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 0dd3ad639aa1..071bb11d7738 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -5200,6 +5200,7 @@ <activity android:name="com.android.internal.app.BlockedAppActivity" android:theme="@style/Theme.Dialog.Confirmation" android:excludeFromRecents="true" + android:lockTaskMode="always" android:process=":ui"> </activity> diff --git a/core/res/res/layout-car/car_resolver_different_item_header.xml b/core/res/res/layout-car/car_resolver_different_item_header.xml deleted file mode 100644 index 222ecc689792..000000000000 --- a/core/res/res/layout-car/car_resolver_different_item_header.xml +++ /dev/null @@ -1,33 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* - * Copyright 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. - */ ---> -<TextView - xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_alwaysShow="true" - android:text="@*android:string/use_a_different_app" - android:minHeight="56dp" - android:textAppearance="?android:attr/textAppearanceLarge" - android:gravity="start|center_vertical" - android:paddingStart="16dp" - android:paddingEnd="16dp" - android:paddingTop="8dp" - android:paddingBottom="8dp" - android:elevation="8dp" -/>
\ No newline at end of file diff --git a/core/res/res/layout-car/car_resolver_list.xml b/core/res/res/layout-car/car_resolver_list.xml index 15a864505d3f..755cbfe1b419 100644 --- a/core/res/res/layout-car/car_resolver_list.xml +++ b/core/res/res/layout-car/car_resolver_list.xml @@ -23,90 +23,142 @@ android:id="@id/contentPanel"> <LinearLayout - android:id="@+id/button_bar" - android:visibility="gone" - style="?attr/buttonBarStyle" android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_ignoreOffset="true" + android:layout_height="match_parent" + android:weightSum="5" android:layout_alwaysShow="true" - android:layout_hasNestedScrollIndicator="true" + android:orientation="vertical" android:background="?attr/colorBackgroundFloating" - android:orientation="horizontal" - android:paddingTop="8dp" - android:paddingBottom="8dp" - android:paddingStart="12dp" - android:weightSum="5" - android:paddingEnd="12dp" android:elevation="8dp"> - <TextView - android:id="@+id/profile_button" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginEnd="8dp" - android:paddingStart="8dp" - android:paddingEnd="8dp" - android:textSize="40sp" - android:layout_weight="5" - android:layout_gravity = "left" + <LinearLayout + android:id="@+id/button_bar" android:visibility="gone" - android:textColor="?attr/colorAccent" - android:singleLine="true"/> - - <TextView - android:id="@+id/title" - android:layout_width="wrap_content" + style="?attr/buttonBarStyle" + android:layout_width="match_parent" android:layout_height="wrap_content" - android:minHeight="56dp" - android:layout_gravity = "left" - android:layout_weight="3" + android:layout_ignoreOffset="true" + android:layout_alwaysShow="true" + android:layout_hasNestedScrollIndicator="true" + android:background="?attr/colorBackgroundFloating" + android:orientation="horizontal" android:paddingTop="8dp" - android:layout_below="@id/profile_button" - android:paddingBottom="8dp"/> + android:paddingStart="12dp" + android:weightSum="4" + android:paddingEnd="12dp" + android:elevation="8dp"> + + <TextView + android:id="@+id/profile_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginEnd="8dp" + android:paddingStart="8dp" + android:paddingEnd="8dp" + android:textSize="40sp" + android:layout_weight="4" + android:layout_gravity="left" + android:visibility="gone" + android:textColor="?attr/colorAccent" + android:singleLine="true"/> + + <TextView + android:id="@+id/title" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="left" + android:layout_weight="3" + android:paddingTop="8dp" + android:layout_below="@id/profile_button" + android:textAppearance="?android:attr/textAppearanceLarge" + android:paddingBottom="8dp"/> + + <Button + android:id="@+id/button_once" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:enabled="false" + android:layout_gravity="right" + style="?attr/buttonBarButtonStyle" + android:text="@string/activity_resolver_use_once" + android:layout_weight="0.5" + android:onClick="onButtonClick"/> - <Button - android:id="@+id/button_once" - android:layout_width="wrap_content" + <Button + android:id="@+id/button_always" + android:layout_marginLeft="2dp" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:enabled="false" + android:layout_gravity="right" + style="?attr/buttonBarButtonStyle" + android:text="@string/activity_resolver_use_always" + android:layout_weight="0.5" + android:onClick="onButtonClick"/> + </LinearLayout> + + <FrameLayout + android:id="@+id/stub" + android:visibility="gone" + android:layout_width="match_parent" android:layout_height="wrap_content" - android:enabled="false" - android:layout_gravity = "right" - android:text="@string/activity_resolver_use_once" - android:layout_weight="1" - android:onClick="onButtonClick"/> + android:background="?attr/colorBackgroundFloating"/> - <Button - android:id="@+id/button_always" - android:layout_marginLeft="10dp" - android:layout_width="wrap_content" + <TabHost + android:id="@+id/profile_tabhost" + android:layout_width="match_parent" android:layout_height="wrap_content" - android:enabled="false" - android:layout_gravity = "right" - android:text="@string/activity_resolver_use_always" - android:layout_weight="1" - android:onClick="onButtonClick"/> - </LinearLayout> + android:layout_alignParentTop="true" + android:layout_centerHorizontal="true" + android:background="?attr/colorBackgroundFloating"> + <LinearLayout + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="wrap_content"> + <TabWidget + android:id="@android:id/tabs" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:visibility="gone"> + </TabWidget> + <View + android:id="@+id/resolver_tab_divider" + android:visibility="gone" + android:layout_width="match_parent" + android:layout_height="1dp" + android:background="?attr/colorBackgroundFloating" + android:foreground="?attr/dividerVertical" + android:layout_marginBottom="8dp"/> + <FrameLayout + android:id="@android:id/tabcontent" + android:layout_width="match_parent" + android:layout_height="wrap_content"> + <com.android.internal.app.ResolverViewPager + android:id="@+id/profile_pager" + android:layout_width="match_parent" + android:layout_height="wrap_content"/> + </FrameLayout> + </LinearLayout> + </TabHost> - <ListView - android:layout_width="match_parent" - android:layout_height="500dp" - android:id="@+id/resolver_list" - android:clipToPadding="false" - android:scrollbarStyle="outsideOverlay" - android:background="?attr/colorBackgroundFloating" - android:elevation="8dp" - android:nestedScrollingEnabled="true" - android:scrollIndicators="top|bottom"/> + <View + android:layout_alwaysShow="true" + android:layout_width="match_parent" + android:layout_height="1dp" + android:background="?attr/colorBackgroundFloating" + android:foreground="?attr/dividerVertical"/> + + <TextView android:id="@+id/empty" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:background="?attr/colorBackgroundFloating" + android:elevation="8dp" + android:layout_alwaysShow="true" + android:text="@string/noApplications" + android:padding="32dp" + android:gravity="center" + android:visibility="gone"/> - <TextView android:id="@+id/empty" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:background="?attr/colorBackgroundFloating" - android:elevation="8dp" - android:layout_alwaysShow="true" - android:text="@string/noApplications" - android:padding="32dp" - android:gravity="center" - android:visibility="gone"/> + </LinearLayout> </com.android.internal.widget.ResolverDrawerLayout> diff --git a/core/res/res/layout-car/car_resolver_list_with_default.xml b/core/res/res/layout-car/car_resolver_list_with_default.xml index 2aed00bea14e..5e450b221959 100644 --- a/core/res/res/layout-car/car_resolver_list_with_default.xml +++ b/core/res/res/layout-car/car_resolver_list_with_default.xml @@ -40,12 +40,12 @@ <ImageView android:id="@+id/icon" - android:layout_width="24dp" - android:layout_height="24dp" + android:layout_width="60dp" + android:layout_height="60dp" android:layout_gravity="start|top" - android:layout_marginStart="16dp" - android:layout_marginEnd="16dp" - android:layout_marginTop="20dp" + android:layout_marginStart="10dp" + android:layout_marginEnd="5dp" + android:layout_marginTop="10dp" android:src="@drawable/resolver_icon_placeholder" android:scaleType="fitCenter"/> @@ -55,7 +55,7 @@ android:layout_weight="1" android:layout_height="?attr/listPreferredItemHeight" android:layout_marginStart="16dp" - android:textAppearance="?attr/textAppearanceMedium" + android:textAppearance="?android:attr/textAppearanceLarge" android:gravity="start|center_vertical" android:paddingEnd="16dp"/> @@ -120,7 +120,7 @@ android:layout_width="wrap_content" android:layout_gravity="start" android:maxLines="2" - style="?attr/buttonBarNegativeButtonStyle" + style="?attr/buttonBarButtonStyle" android:minHeight="@dimen/alert_dialog_button_bar_height" android:layout_height="wrap_content" android:enabled="false" @@ -133,29 +133,64 @@ android:layout_gravity="end" android:maxLines="2" android:minHeight="@dimen/alert_dialog_button_bar_height" - style="?attr/buttonBarPositiveButtonStyle" + style="?attr/buttonBarButtonStyle" android:layout_height="wrap_content" android:enabled="false" android:text="@string/activity_resolver_use_always" android:onClick="onButtonClick"/> </LinearLayout> - <View + <FrameLayout + android:id="@+id/stub" + android:layout_alwaysShow="true" + android:visibility="gone" android:layout_width="match_parent" - android:layout_height="1dp" - android:background="?attr/dividerVertical"/> + android:layout_height="wrap_content" + android:background="?attr/colorBackgroundFloating"/> - <ListView + <TabHost + android:layout_alwaysShow="true" + android:id="@+id/profile_tabhost" android:layout_width="match_parent" android:layout_height="wrap_content" - android:id="@+id/resolver_list" - android:layout_weight="4" - android:clipToPadding="false" - android:scrollbarStyle="outsideOverlay" - android:background="?attr/colorBackgroundFloating" - android:elevation="8dp" - android:nestedScrollingEnabled="true" - android:divider="@null"/> + android:layout_alignParentTop="true" + android:layout_centerHorizontal="true" + android:background="?attr/colorBackgroundFloating"> + <LinearLayout + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="wrap_content"> + <TabWidget + android:id="@android:id/tabs" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:visibility="gone"> + </TabWidget> + <View + android:id="@+id/resolver_tab_divider" + android:visibility="gone" + android:layout_width="match_parent" + android:layout_height="1dp" + android:background="?attr/colorBackgroundFloating" + android:foreground="?attr/dividerVertical" + android:layout_marginBottom="8dp"/> + <FrameLayout + android:id="@android:id/tabcontent" + android:layout_width="match_parent" + android:layout_height="wrap_content"> + <com.android.internal.app.ResolverViewPager + android:id="@+id/profile_pager" + android:layout_width="match_parent" + android:layout_height="wrap_content"> + </com.android.internal.app.ResolverViewPager> + </FrameLayout> + </LinearLayout> + </TabHost> + + <View + android:layout_width="match_parent" + android:layout_height="1dp" + android:background="?attr/dividerVertical"/> </LinearLayout> </com.android.internal.widget.ResolverDrawerLayout> diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml index 49edcf7aa347..487a6e912238 100644 --- a/data/etc/privapp-permissions-platform.xml +++ b/data/etc/privapp-permissions-platform.xml @@ -164,6 +164,7 @@ applications that come with the platform <permission name="android.permission.REBOOT"/> <permission name="android.permission.REGISTER_CALL_PROVIDER"/> <permission name="android.permission.REGISTER_SIM_SUBSCRIPTION"/> + <permission name="android.permission.REGISTER_STATS_PULL_ATOM"/> <permission name="android.permission.SEND_RESPOND_VIA_MESSAGE"/> <permission name="android.permission.SET_TIME_ZONE"/> <permission name="android.permission.SHUTDOWN"/> diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java index 8fa98c85fc33..d350d9df37b8 100644 --- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java +++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java @@ -141,6 +141,8 @@ public class SecureSettings { Settings.Secure.NOTIFICATION_NEW_INTERRUPTION_MODEL, Settings.Secure.TRUST_AGENTS_EXTEND_UNLOCK, Settings.Secure.UI_NIGHT_MODE, + Settings.Secure.DARK_THEME_CUSTOM_START_TIME, + Settings.Secure.DARK_THEME_CUSTOM_END_TIME, Settings.Secure.LOCK_SCREEN_WHEN_TRUST_LOST, Settings.Secure.SKIP_DIRECTION, Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES, diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java index 75c5f9581820..4d33b627f4e2 100644 --- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java +++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java @@ -28,6 +28,7 @@ import static android.provider.settings.validators.SettingsValidators.LOCALE_VAL import static android.provider.settings.validators.SettingsValidators.NON_NEGATIVE_INTEGER_VALIDATOR; import static android.provider.settings.validators.SettingsValidators.NULLABLE_COMPONENT_NAME_VALIDATOR; import static android.provider.settings.validators.SettingsValidators.PACKAGE_NAME_VALIDATOR; +import static android.provider.settings.validators.SettingsValidators.NONE_NEGATIVE_LONG_VALIDATOR; import static android.provider.settings.validators.SettingsValidators.TILE_LIST_VALIDATOR; import static android.provider.settings.validators.SettingsValidators.TTS_LIST_VALIDATOR; @@ -235,7 +236,9 @@ public class SecureSettingsValidators { VALIDATORS.put(Secure.AWARE_TAP_PAUSE_TOUCH_COUNT, NON_NEGATIVE_INTEGER_VALIDATOR); VALIDATORS.put(Secure.ODI_CAPTIONS_ENABLED, BOOLEAN_VALIDATOR); VALIDATORS.put(Secure.DARK_MODE_DIALOG_SEEN, BOOLEAN_VALIDATOR); - VALIDATORS.put(Secure.UI_NIGHT_MODE, new InclusiveIntegerRangeValidator(0, 2)); + VALIDATORS.put(Secure.UI_NIGHT_MODE, NON_NEGATIVE_INTEGER_VALIDATOR); + VALIDATORS.put(Secure.DARK_THEME_CUSTOM_START_TIME, NONE_NEGATIVE_LONG_VALIDATOR); + VALIDATORS.put(Secure.DARK_THEME_CUSTOM_END_TIME, NONE_NEGATIVE_LONG_VALIDATOR); VALIDATORS.put(Secure.GLOBAL_ACTIONS_PANEL_ENABLED, BOOLEAN_VALIDATOR); VALIDATORS.put(Secure.AWARE_LOCK_ENABLED, BOOLEAN_VALIDATOR); VALIDATORS.put(Secure.DISPLAY_DENSITY_FORCED, NON_NEGATIVE_INTEGER_VALIDATOR); diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SettingsValidators.java index 71c7544a3a4c..8d5c6e69b850 100644 --- a/packages/SettingsProvider/src/android/provider/settings/validators/SettingsValidators.java +++ b/packages/SettingsProvider/src/android/provider/settings/validators/SettingsValidators.java @@ -207,4 +207,15 @@ public class SettingsValidators { static final Validator ACCESSIBILITY_SHORTCUT_TARGET_LIST_VALIDATOR = new AccessibilityShortcutTargetListValidator(); + + static final Validator NONE_NEGATIVE_LONG_VALIDATOR = new Validator() { + @Override + public boolean validate(String value) { + try { + return Long.parseLong(value) >= 0; + } catch (NumberFormatException e) { + return false; + } + } + }; } diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java index 36bb8ef62320..b6e31d26a088 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java @@ -75,6 +75,9 @@ public class SettingsHelper { sBroadcastOnRestore.add(Settings.Secure.ENABLED_VR_LISTENERS); sBroadcastOnRestore.add(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES); sBroadcastOnRestore.add(Settings.Global.BLUETOOTH_ON); + sBroadcastOnRestore.add(Settings.Secure.UI_NIGHT_MODE); + sBroadcastOnRestore.add(Settings.Secure.DARK_THEME_CUSTOM_START_TIME); + sBroadcastOnRestore.add(Settings.Secure.DARK_THEME_CUSTOM_END_TIME); } private interface SettingsLookup { diff --git a/packages/SettingsProvider/test/src/android/provider/settings/validators/SettingsValidatorsTest.java b/packages/SettingsProvider/test/src/android/provider/settings/validators/SettingsValidatorsTest.java index bb9e6f6fe885..9134d875097e 100644 --- a/packages/SettingsProvider/test/src/android/provider/settings/validators/SettingsValidatorsTest.java +++ b/packages/SettingsProvider/test/src/android/provider/settings/validators/SettingsValidatorsTest.java @@ -277,6 +277,27 @@ public class SettingsValidatorsTest { } @Test + public void testPositiveLongValidator_zero() { + assertTrue(SettingsValidators.NONE_NEGATIVE_LONG_VALIDATOR.validate("0")); + } + + @Test + public void testPositiveLongValidator_negative() { + assertFalse(SettingsValidators.NONE_NEGATIVE_LONG_VALIDATOR.validate("-5")); + } + + + @Test + public void testPositiveLongValidator_positive() { + assertTrue(SettingsValidators.NONE_NEGATIVE_LONG_VALIDATOR.validate("5")); + } + + @Test + public void testPositiveLongValidator_floatFormat() { + assertFalse(SettingsValidators.NONE_NEGATIVE_LONG_VALIDATOR.validate("4.4756")); + } + + @Test public void testTTSListValidator_withNullInput_returnsFalse() { assertFalse(SettingsValidators.TTS_LIST_VALIDATOR.validate(null)); } diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingControllerImpl.kt index d109d4a16152..f8d4a39a98fe 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingControllerImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingControllerImpl.kt @@ -255,12 +255,14 @@ open class ControlsBindingControllerImpl @Inject constructor( override fun onError(token: IBinder, s: String) { hasError = true _loadCancelInternal = {} + currentProvider?.cancelLoadTimeout() backgroundExecutor.execute(OnLoadErrorRunnable(token, s, callback)) } override fun onComplete(token: IBinder) { _loadCancelInternal = {} if (!hasError) { + currentProvider?.cancelLoadTimeout() backgroundExecutor.execute(OnLoadRunnable(token, loadedControls, callback)) } } diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt index 50f7d76b14ab..4918bd7b3349 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt @@ -228,6 +228,11 @@ class ControlsProviderLifecycleManager( invokeOrQueue({ load(subscriber) }, Message.Load(subscriber)) } + fun cancelLoadTimeout() { + onLoadCanceller?.run() + onLoadCanceller = null + } + /** * Request a subscription to the [Publisher] returned by [ControlsProviderService.publisherFor] * diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java index 00b977e1d558..51113acd0e82 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java +++ b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java @@ -415,11 +415,16 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub { } mLastReportedBounds.set(destinationBounds); try { + // If we are animating to fullscreen, then we need to reset the override bounds on the + // task to ensure that the task "matches" the parent's bounds + Rect taskBounds = direction == TRANSITION_DIRECTION_TO_FULLSCREEN + ? null + : destinationBounds; final WindowContainerTransaction wct = new WindowContainerTransaction(); if (direction == TRANSITION_DIRECTION_TO_PIP) { - wct.scheduleFinishEnterPip(mToken, destinationBounds); + wct.scheduleFinishEnterPip(mToken, taskBounds); } else { - wct.setBounds(mToken, destinationBounds); + wct.setBounds(mToken, taskBounds); } wct.setBoundsChangeTransaction(mToken, tx); mTaskOrganizerController.applyContainerTransaction(wct, null /* ITaskOrganizer */); diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipAppOpsListener.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipAppOpsListener.java index b09d6e163b77..7dfd99c2110d 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipAppOpsListener.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipAppOpsListener.java @@ -44,7 +44,7 @@ public class PipAppOpsListener { try { // Dismiss the PiP once the user disables the app ops setting for that package final Pair<ComponentName, Integer> topPipActivityInfo = - PipUtils.getTopPinnedActivity(mContext, mActivityManager); + PipUtils.getTopPipActivity(mContext, mActivityManager); if (topPipActivityInfo.first != null) { final ApplicationInfo appInfo = mContext.getPackageManager() .getApplicationInfoAsUser(packageName, 0, topPipActivityInfo.second); diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java index 1fdf92ee3832..32e9a03dfac9 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java @@ -115,7 +115,7 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio @Override public void onActivityUnpinned() { - final Pair<ComponentName, Integer> topPipActivityInfo = PipUtils.getTopPinnedActivity( + final Pair<ComponentName, Integer> topPipActivityInfo = PipUtils.getTopPipActivity( mContext, mActivityManager); final ComponentName topActivity = topPipActivityInfo.first; mMenuController.onActivityUnpinned(); diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMediaController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMediaController.java index e57b4166937f..849a62add80f 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMediaController.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMediaController.java @@ -231,7 +231,7 @@ public class PipMediaController { */ private void resolveActiveMediaController(List<MediaController> controllers) { if (controllers != null) { - final ComponentName topActivity = PipUtils.getTopPinnedActivity(mContext, + final ComponentName topActivity = PipUtils.getTopPipActivity(mContext, mActivityManager).first; if (topActivity != null) { for (int i = 0; i < controllers.size(); i++) { diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java index fc04f795c056..2b9b1716cb18 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java @@ -569,7 +569,7 @@ public class PipMenuActivity extends Activity { private void showSettings() { final Pair<ComponentName, Integer> topPipActivityInfo = - PipUtils.getTopPinnedActivity(this, ActivityManager.getService()); + PipUtils.getTopPipActivity(this, ActivityManager.getService()); if (topPipActivityInfo.first != null) { final UserHandle user = UserHandle.of(topPipActivityInfo.second); final Intent settingsIntent = new Intent(ACTION_PICTURE_IN_PICTURE_SETTINGS, diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java index 90db91a7a29e..b5fb1a9dba9a 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java @@ -31,6 +31,7 @@ import android.graphics.Rect; import android.os.Handler; import android.os.RemoteException; import android.util.Log; +import android.util.Pair; import android.util.Size; import android.view.IPinnedStackController; import android.view.InputEvent; @@ -148,8 +149,11 @@ public class PipTouchHandler { @Override public void onPipDismiss() { - MetricsLoggerWrapper.logPictureInPictureDismissByTap(mContext, - PipUtils.getTopPinnedActivity(mContext, mActivityManager)); + Pair<ComponentName, Integer> topPipActivity = PipUtils.getTopPipActivity(mContext, + mActivityManager); + if (topPipActivity.first != null) { + MetricsLoggerWrapper.logPictureInPictureDismissByTap(mContext, topPipActivity); + } mMotionHelper.dismissPip(); } @@ -653,7 +657,7 @@ public class PipTouchHandler { // Check if the user dragged or flung the PiP offscreen to dismiss it if (mMotionHelper.shouldDismissPip() || isFlingToBot) { MetricsLoggerWrapper.logPictureInPictureDismissByDrag(mContext, - PipUtils.getTopPinnedActivity(mContext, mActivityManager)); + PipUtils.getTopPipActivity(mContext, mActivityManager)); mMotionHelper.animateDismiss( vel.x, vel.y, PipTouchHandler.this::updateDismissFraction /* updateAction */); diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipUtils.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipUtils.java index 1ed1904d30fb..4cfec0193b54 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipUtils.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipUtils.java @@ -36,7 +36,7 @@ public class PipUtils { * @return the ComponentName and user id of the top non-SystemUI activity in the pinned stack. * The component name may be null if no such activity exists. */ - public static Pair<ComponentName, Integer> getTopPinnedActivity(Context context, + public static Pair<ComponentName, Integer> getTopPipActivity(Context context, IActivityManager activityManager) { try { final String sysUiPackageName = context.getPackageName(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java index c5c3fff7d1af..c54fa2928a90 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java @@ -27,6 +27,8 @@ import android.widget.TextView; */ public class KeyguardIndicationTextView extends TextView { + private CharSequence mText = ""; + public KeyguardIndicationTextView(Context context) { super(context); } @@ -53,10 +55,12 @@ public class KeyguardIndicationTextView extends TextView { // TODO: Animation, make sure that we will show one indication long enough. if (TextUtils.isEmpty(text)) { + mText = ""; setVisibility(View.INVISIBLE); - } else { + } else if (!TextUtils.equals(text, mText)) { + mText = text; setVisibility(View.VISIBLE); - setText(text); + setText(mText); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsBindingControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsBindingControllerImplTest.kt index f5ad40b8d06d..c25d4e2d4b30 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsBindingControllerImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsBindingControllerImplTest.kt @@ -63,7 +63,7 @@ class ControlsBindingControllerImplTest : SysuiTestCase() { private lateinit var mockControlsController: ControlsController @Captor - private lateinit var subscriberCaptor: ArgumentCaptor<IControlsSubscriber> + private lateinit var subscriberCaptor: ArgumentCaptor<IControlsSubscriber.Stub> @Captor private lateinit var loadSubscriberCaptor: ArgumentCaptor<IControlsSubscriber.Stub> @@ -149,6 +149,44 @@ class ControlsBindingControllerImplTest : SysuiTestCase() { } @Test + fun testLoad_onCompleteRemovesTimeout() { + val callback = object : ControlsBindingController.LoadCallback { + override fun error(message: String) {} + + override fun accept(t: List<Control>) {} + } + val subscription = mock(IControlsSubscription::class.java) + + val canceller = controller.bindAndLoad(TEST_COMPONENT_NAME_1, callback) + + verify(providers[0]).maybeBindAndLoad(capture(subscriberCaptor)) + val b = Binder() + subscriberCaptor.value.onSubscribe(b, subscription) + + subscriberCaptor.value.onComplete(b) + verify(providers[0]).cancelLoadTimeout() + } + + @Test + fun testLoad_onErrorRemovesTimeout() { + val callback = object : ControlsBindingController.LoadCallback { + override fun error(message: String) {} + + override fun accept(t: List<Control>) {} + } + val subscription = mock(IControlsSubscription::class.java) + + val canceller = controller.bindAndLoad(TEST_COMPONENT_NAME_1, callback) + + verify(providers[0]).maybeBindAndLoad(capture(subscriberCaptor)) + val b = Binder() + subscriberCaptor.value.onSubscribe(b, subscription) + + subscriberCaptor.value.onError(b, "") + verify(providers[0]).cancelLoadTimeout() + } + + @Test fun testBindAndLoad_noCancelAfterOnError() { val callback = object : ControlsBindingController.LoadCallback { override fun error(message: String) {} diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt index 64a961539d20..2d3757c29ebf 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt @@ -43,6 +43,7 @@ import org.mockito.ArgumentMatchers.eq import org.mockito.Captor import org.mockito.Mock import org.mockito.Mockito.`when` +import org.mockito.Mockito.never import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations @@ -143,6 +144,19 @@ class ControlsProviderLifecycleManagerTest : SysuiTestCase() { } @Test + fun testMaybeBindAndLoad_timeoutCancelled() { + manager.maybeBindAndLoad(subscriberService) + executor.runAllReady() + + manager.cancelLoadTimeout() + + executor.advanceClockToLast() + executor.runAllReady() + + verify(subscriberService, never()).onError(any(), anyString()) + } + + @Test fun testMaybeBindAndSubscribe() { val list = listOf("TEST_ID") manager.maybeBindAndSubscribe(list, subscriberService) diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextViewTest.java new file mode 100644 index 000000000000..291c0393a9b9 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextViewTest.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.phone; + +import static com.google.common.truth.Truth.assertThat; + +import android.testing.AndroidTestingRunner; +import android.testing.TestableLooper; +import android.view.View; + +import androidx.test.filters.SmallTest; + +import com.android.systemui.SysuiTestCase; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +@SmallTest +@RunWith(AndroidTestingRunner.class) +@TestableLooper.RunWithLooper +public class KeyguardIndicationTextViewTest extends SysuiTestCase { + + private KeyguardIndicationTextView mKeyguardIndicationTextView; + + @Before + public void setup() { + mKeyguardIndicationTextView = new KeyguardIndicationTextView(mContext); + } + + @Test + public void switchIndication_null_hideIndication() { + mKeyguardIndicationTextView.switchIndication(null /* text */); + + assertThat(mKeyguardIndicationTextView.getVisibility()).isEqualTo(View.INVISIBLE); + assertThat(mKeyguardIndicationTextView.getText()).isEqualTo(""); + } + + @Test + public void switchIndication_emptyText_hideIndication() { + mKeyguardIndicationTextView.switchIndication("" /* text */); + + assertThat(mKeyguardIndicationTextView.getVisibility()).isEqualTo(View.INVISIBLE); + assertThat(mKeyguardIndicationTextView.getText()).isEqualTo(""); + } + + @Test + public void switchIndication_newText_updateProperly() { + mKeyguardIndicationTextView.switchIndication("test_indication" /* text */); + + assertThat(mKeyguardIndicationTextView.getVisibility()).isEqualTo(View.VISIBLE); + assertThat(mKeyguardIndicationTextView.getText()).isEqualTo("test_indication"); + } +} diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java index 7c833faee1bd..eace86b7b976 100644 --- a/services/core/java/com/android/server/UiModeManagerService.java +++ b/services/core/java/com/android/server/UiModeManagerService.java @@ -75,7 +75,9 @@ import java.time.DateTimeException; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.ZoneId; +import java.util.Arrays; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Set; @@ -293,7 +295,7 @@ final class UiModeManagerService extends SystemService { public void onChange(boolean selfChange, Uri uri) { synchronized (mLock) { // setup wizard is done now so we can unblock - if (setupWizardCompleteForCurrentUser()) { + if (setupWizardCompleteForCurrentUser() && !selfChange) { mSetupWizardComplete = true; getContext().getContentResolver() .unregisterContentObserver(mSetupWizardObserver); @@ -348,6 +350,9 @@ final class UiModeManagerService extends SystemService { IntentFilter batteryFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED); context.registerReceiver(mBatteryReceiver, batteryFilter); + context.registerReceiver(mSettingsRestored, + new IntentFilter(Intent.ACTION_SETTING_RESTORED), null, mHandler); + mLocalPowerManager = LocalServices.getService(PowerManagerInternal.class); initPowerSave(); @@ -395,6 +400,22 @@ final class UiModeManagerService extends SystemService { mHandler.post(() -> updateSystemProperties()); } + private final BroadcastReceiver mSettingsRestored = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + List<String> settings = Arrays.asList( + Secure.UI_NIGHT_MODE, Secure.DARK_THEME_CUSTOM_START_TIME, + Secure.DARK_THEME_CUSTOM_END_TIME); + if (settings.contains(intent.getExtras().getCharSequence(Intent.EXTRA_SETTING_NAME))) { + synchronized (mLock) { + updateNightModeFromSettingsLocked(context, context.getResources(), + UserHandle.getCallingUserId()); + updateConfigurationLocked(); + } + } + } + }; + private void initPowerSave() { mPowerSave = mLocalPowerManager.getLowPowerState(ServiceType.NIGHT_MODE) diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java index 471c97b0e7c6..87e1dbc2391c 100644 --- a/services/core/java/com/android/server/appop/AppOpsService.java +++ b/services/core/java/com/android/server/appop/AppOpsService.java @@ -19,7 +19,7 @@ package com.android.server.appop; import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_CAMERA; import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION; import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_MICROPHONE; -import static android.app.AppOpsManager.CALL_BACK_ON_CHANGED_LISTENER_WITH_SWITCHED_OP_CHANGE; +import static android.app.AppOpsManager.CALL_BACK_ON_SWITCHED_OP; import static android.app.AppOpsManager.FILTER_BY_FEATURE_ID; import static android.app.AppOpsManager.FILTER_BY_OP_NAMES; import static android.app.AppOpsManager.FILTER_BY_PACKAGE_NAME; @@ -87,7 +87,6 @@ import android.app.AppOpsManagerInternal.CheckOpsDelegate; import android.app.AsyncNotedAppOp; import android.app.RuntimeAppOpAccessMessage; import android.app.SyncNotedAppOp; -import android.compat.Compatibility; import android.content.BroadcastReceiver; import android.content.ContentResolver; import android.content.Context; @@ -2679,10 +2678,8 @@ public class AppOpsService extends IAppOpsService.Stub { synchronized (this) { int switchOp = (op != AppOpsManager.OP_NONE) ? AppOpsManager.opToSwitch(op) : op; - // See CALL_BACK_ON_CHANGED_LISTENER_WITH_SWITCHED_OP_CHANGE int notifiedOps; - if (Compatibility.isChangeEnabled( - CALL_BACK_ON_CHANGED_LISTENER_WITH_SWITCHED_OP_CHANGE)) { + if ((flags & CALL_BACK_ON_SWITCHED_OP) == 0) { if (op == OP_NONE) { notifiedOps = ALL_OPS; } else { diff --git a/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java index ec9b37db3137..83da38195053 100644 --- a/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java +++ b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java @@ -45,6 +45,7 @@ import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; import android.content.pm.ResolveInfo; import android.os.Binder; +import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import android.os.UserHandle; @@ -183,7 +184,8 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub { String callingFeatureId, Intent intent, @UserIdInt int userId, - IBinder callingActivity) throws RemoteException { + IBinder callingActivity, + Bundle options) throws RemoteException { Objects.requireNonNull(callingPackage); Objects.requireNonNull(intent); Objects.requireNonNull(intent.getComponent(), "The intent must have a Component set"); @@ -226,7 +228,7 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub { launchIntent, callingActivity, /* startFlags= */ 0, - /* options= */ null, + options, userId); logStartActivityByIntent(callingPackage); } diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java index 33ef2d43d720..cdc37364ca79 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerService.java +++ b/services/core/java/com/android/server/pm/PackageInstallerService.java @@ -805,26 +805,30 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements public SessionInfo getSessionInfo(int sessionId) { synchronized (mSessions) { final PackageInstallerSession session = mSessions.get(sessionId); - return session != null ? session.generateInfo() : null; + + return session != null + ? session.generateInfoForCaller(true /*withIcon*/, Binder.getCallingUid()) + : null; } } @Override public ParceledListSlice<SessionInfo> getStagedSessions() { - return mStagingManager.getSessions(); + return mStagingManager.getSessions(Binder.getCallingUid()); } @Override public ParceledListSlice<SessionInfo> getAllSessions(int userId) { + final int callingUid = Binder.getCallingUid(); mPermissionManager.enforceCrossUserPermission( - Binder.getCallingUid(), userId, true, false, "getAllSessions"); + callingUid, userId, true, false, "getAllSessions"); final List<SessionInfo> result = new ArrayList<>(); synchronized (mSessions) { for (int i = 0; i < mSessions.size(); i++) { final PackageInstallerSession session = mSessions.valueAt(i); if (session.userId == userId && !session.hasParentSessionId()) { - result.add(session.generateInfo(false)); + result.add(session.generateInfoForCaller(false, callingUid)); } } } @@ -842,7 +846,8 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements for (int i = 0; i < mSessions.size(); i++) { final PackageInstallerSession session = mSessions.valueAt(i); - SessionInfo info = session.generateInfo(false); + SessionInfo info = + session.generateInfoForCaller(false /*withIcon*/, Process.SYSTEM_UID); if (Objects.equals(info.getInstallerPackageName(), installerPackageName) && session.userId == userId && !session.hasParentSessionId()) { result.add(info); @@ -1302,7 +1307,10 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements session.markUpdated(); writeSessionsAsync(); if (mOkToSendBroadcasts) { - mPm.sendSessionUpdatedBroadcast(session.generateInfo(false), + // we don't scrub the data here as this is sent only to the installer several + // privileged system packages + mPm.sendSessionUpdatedBroadcast( + session.generateInfoForCaller(false/*icon*/, Process.SYSTEM_UID), session.userId); } } diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java index 97aa79de5e8d..483f83efd508 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerSession.java +++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java @@ -557,11 +557,41 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } } - public SessionInfo generateInfo() { - return generateInfo(true); + /** + * Returns {@code true} if the {@link SessionInfo} object should be produced with potentially + * sensitive data scrubbed from its fields. + * + * @param callingUid the uid of the caller; the recipient of the {@link SessionInfo} that may + * need to be scrubbed + */ + private boolean shouldScrubData(int callingUid) { + return !(callingUid < Process.FIRST_APPLICATION_UID || getInstallerUid() == callingUid); + } + + /** + * Generates a {@link SessionInfo} object for the provided uid. This may result in some fields + * that may contain sensitive info being filtered. + * + * @param includeIcon true if the icon should be included in the object + * @param callingUid the uid of the caller; the recipient of the {@link SessionInfo} that may + * need to be scrubbed + * @see #shouldScrubData(int) + */ + public SessionInfo generateInfoForCaller(boolean includeIcon, int callingUid) { + return generateInfoInternal(includeIcon, shouldScrubData(callingUid)); } - public SessionInfo generateInfo(boolean includeIcon) { + /** + * Generates a {@link SessionInfo} object to ensure proper hiding of sensitive fields. + * + * @param includeIcon true if the icon should be included in the object + * @see #generateInfoForCaller(boolean, int) + */ + public SessionInfo generateInfoScrubbed(boolean includeIcon) { + return generateInfoInternal(includeIcon, true /*scrubData*/); + } + + private SessionInfo generateInfoInternal(boolean includeIcon, boolean scrubData) { final SessionInfo info = new SessionInfo(); synchronized (mLock) { info.sessionId = sessionId; @@ -584,9 +614,13 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { info.appLabel = params.appLabel; info.installLocation = params.installLocation; - info.originatingUri = params.originatingUri; + if (!scrubData) { + info.originatingUri = params.originatingUri; + } info.originatingUid = params.originatingUid; - info.referrerUri = params.referrerUri; + if (!scrubData) { + info.referrerUri = params.referrerUri; + } info.grantedRuntimePermissions = params.grantedRuntimePermissions; info.whitelistedRestrictedPermissions = params.whitelistedRestrictedPermissions; info.installFlags = params.installFlags; @@ -2664,7 +2698,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { final boolean isNewInstall = extras == null || !extras.getBoolean(Intent.EXTRA_REPLACING); if (success && isNewInstall && mPm.mInstallerService.okToSendBroadcasts() && (params.installFlags & PackageManager.INSTALL_DRY_RUN) == 0) { - mPm.sendSessionCommitBroadcast(generateInfo(), userId); + mPm.sendSessionCommitBroadcast(generateInfoScrubbed(true /*icon*/), userId); } mCallback.onSessionFinished(this, success); diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java index 83fe5562324f..342c90719916 100644 --- a/services/core/java/com/android/server/pm/StagingManager.java +++ b/services/core/java/com/android/server/pm/StagingManager.java @@ -128,11 +128,12 @@ public class StagingManager { } } - ParceledListSlice<PackageInstaller.SessionInfo> getSessions() { + ParceledListSlice<PackageInstaller.SessionInfo> getSessions(int callingUid) { final List<PackageInstaller.SessionInfo> result = new ArrayList<>(); synchronized (mStagedSessions) { for (int i = 0; i < mStagedSessions.size(); i++) { - result.add(mStagedSessions.valueAt(i).generateInfo(false)); + final PackageInstallerSession stagedSession = mStagedSessions.valueAt(i); + result.add(stagedSession.generateInfoForCaller(false /*icon*/, callingUid)); } } return new ParceledListSlice<>(result); diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 36fdb2d1a180..98e3d07fc2e4 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -2224,9 +2224,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo .addTaggedData(MetricsEvent.FIELD_DISPLAY_ID, getDisplayId())); } - // If there was no pinned stack, we still need to notify the controller of the display info - // update as a result of the config change. - if (mPinnedStackControllerLocked != null && !hasPinnedTask()) { + if (mPinnedStackControllerLocked != null) { mPinnedStackControllerLocked.onDisplayInfoChanged(getDisplayInfo()); } } diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index b2db99b06cde..5ed903e875c2 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -4123,8 +4123,16 @@ class Task extends WindowContainer<WindowContainer> { return mMainWindowSizeChangeTransaction; } + void setActivityWindowingMode(int windowingMode) { + PooledConsumer c = PooledLambda.obtainConsumer(ActivityRecord::setWindowingMode, + PooledLambda.__(ActivityRecord.class), windowingMode); + forAllActivities(c); + c.recycle(); + } + @Override long getProtoFieldId() { return TASK; } + } diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java index 4093fe5cb288..cfb570678e5b 100644 --- a/services/core/java/com/android/server/wm/TaskOrganizerController.java +++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java @@ -553,18 +553,28 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub WindowContainerTransaction.Change c) { int effects = sanitizeAndApplyChange(wc, c); + final Task tr = wc.asTask(); + final SurfaceControl.Transaction t = c.getBoundsChangeTransaction(); if (t != null) { - Task tr = (Task) wc; tr.setMainWindowSizeChangeTransaction(t); } Rect enterPipBounds = c.getEnterPipBounds(); if (enterPipBounds != null) { - Task tr = (Task) wc; mService.mStackSupervisor.updatePictureInPictureMode(tr, enterPipBounds, true); } + + final int windowingMode = c.getWindowingMode(); + if (windowingMode > -1) { + tr.setWindowingMode(windowingMode); + } + final int childWindowingMode = c.getActivityWindowingMode(); + if (childWindowingMode > -1) { + tr.setActivityWindowingMode(childWindowingMode); + } + return effects; } diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java index 53a3682a1efa..251886ac309c 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java @@ -241,6 +241,32 @@ public class TaskOrganizerTests extends WindowTestsBase { } @Test + public void testSetWindowingMode() { + final ActivityStack stack = new ActivityTestsBase.StackBuilder(mWm.mRoot) + .setWindowingMode(WINDOWING_MODE_FREEFORM).build(); + final WindowContainerTransaction t = new WindowContainerTransaction(); + + t.setWindowingMode(stack.mRemoteToken, WINDOWING_MODE_FULLSCREEN); + mWm.mAtmService.mTaskOrganizerController.applyContainerTransaction(t, null); + + assertEquals(WINDOWING_MODE_FULLSCREEN, stack.getWindowingMode()); + } + + @Test + public void testSetActivityWindowingMode() { + final ActivityRecord record = makePipableActivity(); + final ActivityStack stack = record.getStack(); + final WindowContainerTransaction t = new WindowContainerTransaction(); + + t.setWindowingMode(stack.mRemoteToken, WINDOWING_MODE_PINNED); + t.setActivityWindowingMode(stack.mRemoteToken, WINDOWING_MODE_FULLSCREEN); + mWm.mAtmService.mTaskOrganizerController.applyContainerTransaction(t, null); + + assertEquals(WINDOWING_MODE_FULLSCREEN, record.getWindowingMode()); + assertEquals(WINDOWING_MODE_PINNED, stack.getWindowingMode()); + } + + @Test public void testContainerChanges() { removeGlobalMinSizeRestriction(); final ActivityStack stack = new ActivityTestsBase.StackBuilder(mWm.mRoot) diff --git a/telecomm/java/android/telecom/CallRedirectionService.java b/telecomm/java/android/telecom/CallRedirectionService.java index 36c637723c0a..c832f53ae073 100644 --- a/telecomm/java/android/telecom/CallRedirectionService.java +++ b/telecomm/java/android/telecom/CallRedirectionService.java @@ -38,16 +38,14 @@ import com.android.internal.telecom.ICallRedirectionService; * * <p> * Below is an example manifest registration for a {@code CallRedirectionService}. - * <pre> * {@code * <service android:name="your.package.YourCallRedirectionServiceImplementation" - * android:permission="android.permission.BIND_REDIRECTION_SERVICE"> + * android:permission="android.permission.BIND_CALL_REDIRECTION_SERVICE"> * <intent-filter> * <action android:name="android.telecom.CallRedirectionService"/> * </intent-filter> * </service> * } - * </pre> */ public abstract class CallRedirectionService extends Service { /** diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java index 45cba518f933..dd20d065fc83 100644 --- a/telephony/java/android/telephony/ServiceState.java +++ b/telephony/java/android/telephony/ServiceState.java @@ -580,7 +580,6 @@ public class ServiceState implements Parcelable { * * @hide */ - @SystemApi public @RegState int getDataRegistrationState() { return getDataRegState(); } |