diff options
56 files changed, 675 insertions, 288 deletions
diff --git a/api/test-current.txt b/api/test-current.txt index ee6fb51705a4..1a912a1c69b1 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -1917,6 +1917,10 @@ package android.os { method public boolean hasSingleFileDescriptor(); } + public final class Parcel { + method public int readExceptionCode(); + } + public class ParcelFileDescriptor implements java.io.Closeable android.os.Parcelable { method public static java.io.File getFile(java.io.FileDescriptor) throws java.io.IOException; } @@ -1986,6 +1990,7 @@ package android.os { public class SystemProperties { method @NonNull public static String get(@NonNull String); method @NonNull public static String get(@NonNull String, @Nullable String); + method public static boolean getBoolean(@NonNull String, boolean); } public final class UserHandle implements android.os.Parcelable { @@ -2140,6 +2145,36 @@ package android.os.health { } +package android.os.image { + + public class DynamicSystemClient { + ctor public DynamicSystemClient(@NonNull android.content.Context); + method @RequiresPermission("android.permission.INSTALL_DYNAMIC_SYSTEM") public void bind(); + method public void setOnStatusChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.os.image.DynamicSystemClient.OnStatusChangedListener); + method public void setOnStatusChangedListener(@NonNull android.os.image.DynamicSystemClient.OnStatusChangedListener); + method @RequiresPermission("android.permission.INSTALL_DYNAMIC_SYSTEM") public void start(@NonNull android.net.Uri, long); + method @RequiresPermission("android.permission.INSTALL_DYNAMIC_SYSTEM") public void start(@NonNull android.net.Uri, long, long); + method @RequiresPermission("android.permission.INSTALL_DYNAMIC_SYSTEM") public void unbind(); + field public static final int CAUSE_ERROR_EXCEPTION = 6; // 0x6 + field public static final int CAUSE_ERROR_INVALID_URL = 4; // 0x4 + field public static final int CAUSE_ERROR_IO = 3; // 0x3 + field public static final int CAUSE_ERROR_IPC = 5; // 0x5 + field public static final int CAUSE_INSTALL_CANCELLED = 2; // 0x2 + field public static final int CAUSE_INSTALL_COMPLETED = 1; // 0x1 + field public static final int CAUSE_NOT_SPECIFIED = 0; // 0x0 + field public static final int STATUS_IN_PROGRESS = 2; // 0x2 + field public static final int STATUS_IN_USE = 4; // 0x4 + field public static final int STATUS_NOT_STARTED = 1; // 0x1 + field public static final int STATUS_READY = 3; // 0x3 + field public static final int STATUS_UNKNOWN = 0; // 0x0 + } + + public static interface DynamicSystemClient.OnStatusChangedListener { + method public void onStatusChanged(int, int, long, @Nullable Throwable); + } + +} + package android.os.storage { public class StorageManager { @@ -2946,6 +2981,21 @@ package android.util { method public E valueAtUnchecked(int); } + public class FeatureFlagUtils { + ctor public FeatureFlagUtils(); + method public static java.util.Map<java.lang.String,java.lang.String> getAllFeatureFlags(); + method public static boolean isEnabled(android.content.Context, String); + method public static void setEnabled(android.content.Context, String, boolean); + field public static final String DYNAMIC_SYSTEM = "settings_dynamic_system"; + field public static final String FFLAG_OVERRIDE_PREFIX = "sys.fflag.override."; + field public static final String FFLAG_PREFIX = "sys.fflag."; + field public static final String HEARING_AID_SETTINGS = "settings_bluetooth_hearing_aid"; + field public static final String PERSIST_PREFIX = "persist.sys.fflag.override."; + field public static final String PIXEL_WALLPAPER_CATEGORY_SWITCH = "settings_pixel_wallpaper_category_switch"; + field public static final String SCREENRECORD_LONG_PRESS = "settings_screenrecord_long_press"; + field public static final String SEAMLESS_TRANSFER = "settings_seamless_transfer"; + } + public class TimeUtils { method public static String formatDuration(long); } diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index b09eada27ce4..cb939f05ffc5 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -807,7 +807,7 @@ public abstract class PackageManager { * * @hide */ - public static final int INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS = 0x00000200; + public static final int INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS = 0x00400000; /** {@hide} */ public static final int INSTALL_FORCE_VOLUME_UUID = 0x00000200; diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java index 41be38a6e8dd..58aacc2c36c7 100644 --- a/core/java/android/content/pm/ShortcutInfo.java +++ b/core/java/android/content/pm/ShortcutInfo.java @@ -153,14 +153,21 @@ public final class ShortcutInfo implements Parcelable { public static final int CLONE_REMOVE_RES_NAMES = 1 << 3; /** @hide */ + public static final int CLONE_REMOVE_PERSON = 1 << 4; + + /** @hide */ public static final int CLONE_REMOVE_FOR_CREATOR = CLONE_REMOVE_ICON | CLONE_REMOVE_RES_NAMES; /** @hide */ public static final int CLONE_REMOVE_FOR_LAUNCHER = CLONE_REMOVE_ICON | CLONE_REMOVE_INTENT - | CLONE_REMOVE_RES_NAMES; + | CLONE_REMOVE_RES_NAMES | CLONE_REMOVE_PERSON; /** @hide */ public static final int CLONE_REMOVE_FOR_LAUNCHER_APPROVAL = CLONE_REMOVE_INTENT + | CLONE_REMOVE_RES_NAMES | CLONE_REMOVE_PERSON; + + /** @hide */ + public static final int CLONE_REMOVE_FOR_APP_PREDICTION = CLONE_REMOVE_ICON | CLONE_REMOVE_RES_NAMES; /** @hide */ @@ -169,8 +176,11 @@ public final class ShortcutInfo implements Parcelable { CLONE_REMOVE_INTENT, CLONE_REMOVE_NON_KEY_INFO, CLONE_REMOVE_RES_NAMES, + CLONE_REMOVE_PERSON, CLONE_REMOVE_FOR_CREATOR, - CLONE_REMOVE_FOR_LAUNCHER + CLONE_REMOVE_FOR_LAUNCHER, + CLONE_REMOVE_FOR_LAUNCHER_APPROVAL, + CLONE_REMOVE_FOR_APP_PREDICTION }) @Retention(RetentionPolicy.SOURCE) public @interface CloneFlags {} @@ -548,7 +558,9 @@ public final class ShortcutInfo implements Parcelable { mDisabledMessage = source.mDisabledMessage; mDisabledMessageResId = source.mDisabledMessageResId; mCategories = cloneCategories(source.mCategories); - mPersons = clonePersons(source.mPersons); + if ((cloneFlags & CLONE_REMOVE_PERSON) == 0) { + mPersons = clonePersons(source.mPersons); + } if ((cloneFlags & CLONE_REMOVE_INTENT) == 0) { mIntents = cloneIntents(source.mIntents); mIntentPersistableExtrases = diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java index de963c9927c2..fe2e948bfcd9 100644 --- a/core/java/android/os/Parcel.java +++ b/core/java/android/os/Parcel.java @@ -18,6 +18,7 @@ package android.os; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.TestApi; import android.annotation.UnsupportedAppUsage; import android.text.TextUtils; import android.util.ArrayMap; @@ -2001,6 +2002,7 @@ public final class Parcel { * @hide */ @UnsupportedAppUsage + @TestApi public final int readExceptionCode() { int code = readInt(); if (code == EX_HAS_REPLY_HEADER) { diff --git a/core/java/android/os/SystemProperties.java b/core/java/android/os/SystemProperties.java index edfdda8bb760..45384105cc8f 100644 --- a/core/java/android/os/SystemProperties.java +++ b/core/java/android/os/SystemProperties.java @@ -174,6 +174,7 @@ public class SystemProperties { * @hide */ @SystemApi + @TestApi public static boolean getBoolean(@NonNull String key, boolean def) { if (TRACK_KEY_ACCESS) onKeyAccess(key); return native_get_boolean(key, def); diff --git a/core/java/android/os/image/DynamicSystemClient.java b/core/java/android/os/image/DynamicSystemClient.java index f1f24fb4dd89..921f0f2ab1e2 100644 --- a/core/java/android/os/image/DynamicSystemClient.java +++ b/core/java/android/os/image/DynamicSystemClient.java @@ -22,6 +22,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -67,6 +68,7 @@ import java.util.concurrent.Executor; * @hide */ @SystemApi +@TestApi public class DynamicSystemClient { /** @hide */ @IntDef(prefix = { "STATUS_" }, value = { @@ -283,6 +285,7 @@ public class DynamicSystemClient { * @hide */ @SystemApi + @TestApi public DynamicSystemClient(@NonNull Context context) { mContext = context; mConnection = new DynSystemServiceConnection(); @@ -314,8 +317,11 @@ public class DynamicSystemClient { * Bind to {@code DynamicSystem} installation service. Binding to the installation service * allows it to send status updates to {@link #OnStatusChangedListener}. It is recommanded * to bind before calling {@link #start} and get status updates. + * @hide */ @RequiresPermission(android.Manifest.permission.INSTALL_DYNAMIC_SYSTEM) + @SystemApi + @TestApi public void bind() { if (!featureFlagEnabled()) { Slog.w(TAG, FeatureFlagUtils.DYNAMIC_SYSTEM + " not enabled; bind() aborted."); @@ -334,8 +340,11 @@ public class DynamicSystemClient { /** * Unbind from {@code DynamicSystem} installation service. Unbinding from the installation * service stops it from sending following status updates. + * @hide */ @RequiresPermission(android.Manifest.permission.INSTALL_DYNAMIC_SYSTEM) + @SystemApi + @TestApi public void unbind() { if (!mBound) { return; @@ -367,8 +376,11 @@ public class DynamicSystemClient { * * @param systemUrl a network Uri, a file Uri or a content Uri pointing to a system image file. * @param systemSize size of system image. + * @hide */ @RequiresPermission(android.Manifest.permission.INSTALL_DYNAMIC_SYSTEM) + @SystemApi + @TestApi public void start(@NonNull Uri systemUrl, @BytesLong long systemSize) { start(systemUrl, systemSize, DEFAULT_USERDATA_SIZE); } diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java index c42dc817bec4..324e02ceb1d5 100644 --- a/core/java/android/util/FeatureFlagUtils.java +++ b/core/java/android/util/FeatureFlagUtils.java @@ -16,6 +16,7 @@ package android.util; +import android.annotation.TestApi; import android.content.Context; import android.os.SystemProperties; import android.provider.Settings; @@ -29,6 +30,7 @@ import java.util.Map; * * @hide */ +@TestApi public class FeatureFlagUtils { public static final String FFLAG_PREFIX = "sys.fflag."; diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java index a88c51a28229..fca97fee603e 100644 --- a/core/java/com/android/internal/app/ChooserActivity.java +++ b/core/java/com/android/internal/app/ChooserActivity.java @@ -185,7 +185,7 @@ public class ChooserActivity extends ResolverActivity { private static final int SHARE_TARGET_QUERY_PACKAGE_LIMIT = 20; private static final int QUERY_TARGET_SERVICE_LIMIT = 5; - private static final int WATCHDOG_TIMEOUT_MILLIS = 3000; + private static final int WATCHDOG_TIMEOUT_MILLIS = 5000; private static final int DEFAULT_SALT_EXPIRATION_DAYS = 7; private int mMaxHashSaltDays = DeviceConfig.getInt(DeviceConfig.NAMESPACE_SYSTEMUI, @@ -252,6 +252,123 @@ public class ChooserActivity extends ResolverActivity { // Sorted list of DisplayResolveInfos for the alphabetical app section. private List<ResolverActivity.DisplayResolveInfo> mSortedList = new ArrayList<>(); + private ContentPreviewCoordinator mPreviewCoord; + + private class ContentPreviewCoordinator { + private static final int IMAGE_LOAD_TIMEOUT_MILLIS = 300; + private static final int IMAGE_FADE_IN_MILLIS = 150; + private static final int IMAGE_LOAD_TIMEOUT = 1; + private static final int IMAGE_LOAD_INTO_VIEW = 2; + + private final View mParentView; + private boolean mHideParentOnFail; + private boolean mAtLeastOneLoaded = false; + + class LoadUriTask { + public final Uri mUri; + public final int mImageResourceId; + public final int mExtraCount; + public final Bitmap mBmp; + + LoadUriTask(int imageResourceId, Uri uri, int extraCount, Bitmap bmp) { + this.mImageResourceId = imageResourceId; + this.mUri = uri; + this.mExtraCount = extraCount; + this.mBmp = bmp; + } + } + + // If at least one image loads within the timeout period, allow other + // loads to continue. Otherwise terminate and optionally hide + // the parent area + private final Handler mHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case IMAGE_LOAD_TIMEOUT: + maybeHideContentPreview(); + break; + + case IMAGE_LOAD_INTO_VIEW: + if (isFinishing()) break; + + LoadUriTask task = (LoadUriTask) msg.obj; + RoundedRectImageView imageView = mParentView.findViewById( + task.mImageResourceId); + if (task.mBmp == null) { + imageView.setVisibility(View.GONE); + maybeHideContentPreview(); + return; + } + + mAtLeastOneLoaded = true; + imageView.setVisibility(View.VISIBLE); + imageView.setAlpha(0.0f); + imageView.setImageBitmap(task.mBmp); + + ValueAnimator fadeAnim = ObjectAnimator.ofFloat(imageView, "alpha", 0.0f, + 1.0f); + fadeAnim.setInterpolator(new DecelerateInterpolator(1.0f)); + fadeAnim.setDuration(IMAGE_FADE_IN_MILLIS); + fadeAnim.start(); + + if (task.mExtraCount > 0) { + imageView.setExtraImageCount(task.mExtraCount); + } + } + } + }; + + ContentPreviewCoordinator(View parentView, boolean hideParentOnFail) { + super(); + + this.mParentView = parentView; + this.mHideParentOnFail = hideParentOnFail; + } + + private void loadUriIntoView(final int imageResourceId, final Uri uri, + final int extraImages) { + mHandler.sendEmptyMessageDelayed(IMAGE_LOAD_TIMEOUT, IMAGE_LOAD_TIMEOUT_MILLIS); + + AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> { + final Bitmap bmp = loadThumbnail(uri, new Size(200, 200)); + final Message msg = Message.obtain(); + msg.what = IMAGE_LOAD_INTO_VIEW; + msg.obj = new LoadUriTask(imageResourceId, uri, extraImages, bmp); + mHandler.sendMessage(msg); + }); + } + + private void cancelLoads() { + mHandler.removeMessages(IMAGE_LOAD_INTO_VIEW); + mHandler.removeMessages(IMAGE_LOAD_TIMEOUT); + } + + private void maybeHideContentPreview() { + if (!mAtLeastOneLoaded && mHideParentOnFail) { + Log.i(TAG, "Hiding image preview area. Timed out waiting for preview to load" + + " within " + IMAGE_LOAD_TIMEOUT_MILLIS + "ms."); + collapseParentView(); + if (mChooserRowAdapter != null) { + mChooserRowAdapter.hideContentPreview(); + } + mHideParentOnFail = false; + } + } + + private void collapseParentView() { + // This will effectively hide the content preview row by forcing the height + // to zero. It is faster than forcing a relayout of the listview + final View v = mParentView; + int widthSpec = MeasureSpec.makeMeasureSpec(v.getWidth(), MeasureSpec.EXACTLY); + int heightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.EXACTLY); + v.measure(widthSpec, heightSpec); + v.getLayoutParams().height = 0; + v.layout(v.getLeft(), v.getTop(), v.getRight(), v.getTop()); + v.invalidate(); + } + } + private final Handler mChooserHandler = new Handler() { @Override public void handleMessage(Message msg) { @@ -621,14 +738,15 @@ public class ChooserActivity extends ResolverActivity { private ViewGroup displayContentPreview(@ContentPreviewType int previewType, Intent targetIntent, LayoutInflater layoutInflater, ViewGroup convertView, ViewGroup parent) { + if (convertView != null) return convertView; + switch (previewType) { case CONTENT_PREVIEW_TEXT: - return displayTextContentPreview(targetIntent, layoutInflater, convertView, parent); + return displayTextContentPreview(targetIntent, layoutInflater, parent); case CONTENT_PREVIEW_IMAGE: - return displayImageContentPreview(targetIntent, layoutInflater, convertView, - parent); + return displayImageContentPreview(targetIntent, layoutInflater, parent); case CONTENT_PREVIEW_FILE: - return displayFileContentPreview(targetIntent, layoutInflater, convertView, parent); + return displayFileContentPreview(targetIntent, layoutInflater, parent); default: Log.e(TAG, "Unexpected content preview type: " + previewType); } @@ -637,10 +755,9 @@ public class ChooserActivity extends ResolverActivity { } private ViewGroup displayTextContentPreview(Intent targetIntent, LayoutInflater layoutInflater, - ViewGroup convertView, ViewGroup parent) { - ViewGroup contentPreviewLayout = - convertView != null ? convertView : (ViewGroup) layoutInflater.inflate( - R.layout.chooser_grid_preview_text, parent, false); + ViewGroup parent) { + ViewGroup contentPreviewLayout = (ViewGroup) layoutInflater.inflate( + R.layout.chooser_grid_preview_text, parent, false); contentPreviewLayout.findViewById(R.id.copy_button).setOnClickListener( this::onCopyButtonClicked); @@ -677,12 +794,8 @@ public class ChooserActivity extends ResolverActivity { if (previewThumbnail == null) { previewThumbnailView.setVisibility(View.GONE); } else { - Bitmap bmp = loadThumbnail(previewThumbnail, new Size(100, 100)); - if (bmp == null) { - previewThumbnailView.setVisibility(View.GONE); - } else { - previewThumbnailView.setImageBitmap(bmp); - } + mPreviewCoord = new ContentPreviewCoordinator(contentPreviewLayout, false); + mPreviewCoord.loadUriIntoView(R.id.content_preview_thumbnail, previewThumbnail, 0); } } @@ -690,15 +803,15 @@ public class ChooserActivity extends ResolverActivity { } private ViewGroup displayImageContentPreview(Intent targetIntent, LayoutInflater layoutInflater, - ViewGroup convertView, ViewGroup parent) { - ViewGroup contentPreviewLayout = - convertView != null ? convertView : (ViewGroup) layoutInflater.inflate( - R.layout.chooser_grid_preview_image, parent, false); + ViewGroup parent) { + ViewGroup contentPreviewLayout = (ViewGroup) layoutInflater.inflate( + R.layout.chooser_grid_preview_image, parent, false); + mPreviewCoord = new ContentPreviewCoordinator(contentPreviewLayout, true); String action = targetIntent.getAction(); if (Intent.ACTION_SEND.equals(action)) { Uri uri = targetIntent.getParcelableExtra(Intent.EXTRA_STREAM); - loadUriIntoView(R.id.content_preview_image_1_large, uri, contentPreviewLayout); + mPreviewCoord.loadUriIntoView(R.id.content_preview_image_1_large, uri, 0); } else { ContentResolver resolver = getContentResolver(); @@ -717,21 +830,16 @@ public class ChooserActivity extends ResolverActivity { return contentPreviewLayout; } - loadUriIntoView(R.id.content_preview_image_1_large, imageUris.get(0), - contentPreviewLayout); + mPreviewCoord.loadUriIntoView(R.id.content_preview_image_1_large, imageUris.get(0), 0); if (imageUris.size() == 2) { - loadUriIntoView(R.id.content_preview_image_2_large, imageUris.get(1), - contentPreviewLayout); + mPreviewCoord.loadUriIntoView(R.id.content_preview_image_2_large, + imageUris.get(1), 0); } else if (imageUris.size() > 2) { - loadUriIntoView(R.id.content_preview_image_2_small, imageUris.get(1), - contentPreviewLayout); - RoundedRectImageView imageView = loadUriIntoView( - R.id.content_preview_image_3_small, imageUris.get(2), contentPreviewLayout); - - if (imageUris.size() > 3) { - imageView.setExtraImageCount(imageUris.size() - 3); - } + mPreviewCoord.loadUriIntoView(R.id.content_preview_image_2_small, + imageUris.get(1), 0); + mPreviewCoord.loadUriIntoView(R.id.content_preview_image_3_small, + imageUris.get(2), imageUris.size() - 3); } } @@ -803,11 +911,10 @@ public class ChooserActivity extends ResolverActivity { } private ViewGroup displayFileContentPreview(Intent targetIntent, LayoutInflater layoutInflater, - ViewGroup convertView, ViewGroup parent) { + ViewGroup parent) { - ViewGroup contentPreviewLayout = - convertView != null ? convertView : (ViewGroup) layoutInflater.inflate( - R.layout.chooser_grid_preview_file, parent, false); + ViewGroup contentPreviewLayout = (ViewGroup) layoutInflater.inflate( + R.layout.chooser_grid_preview_file, parent, false); // TODO(b/120417119): Disable file copy until after moving to sysui, // due to permissions issues @@ -839,6 +946,10 @@ public class ChooserActivity extends ResolverActivity { R.id.content_preview_filename); fileNameView.setText(fileName); + View thumbnailView = contentPreviewLayout.findViewById( + R.id.content_preview_file_thumbnail); + thumbnailView.setVisibility(View.GONE); + ImageView fileIconView = contentPreviewLayout.findViewById( R.id.content_preview_file_icon); fileIconView.setVisibility(View.VISIBLE); @@ -849,32 +960,25 @@ public class ChooserActivity extends ResolverActivity { return contentPreviewLayout; } - private void loadFileUriIntoView(Uri uri, View parent) { + private void loadFileUriIntoView(final Uri uri, final View parent) { FileInfo fileInfo = extractFileInfo(uri, getContentResolver()); TextView fileNameView = parent.findViewById(R.id.content_preview_filename); fileNameView.setText(fileInfo.name); if (fileInfo.hasThumbnail) { - loadUriIntoView(R.id.content_preview_file_thumbnail, uri, parent); + mPreviewCoord = new ContentPreviewCoordinator(parent, false); + mPreviewCoord.loadUriIntoView(R.id.content_preview_file_thumbnail, uri, 0); } else { + View thumbnailView = parent.findViewById(R.id.content_preview_file_thumbnail); + thumbnailView.setVisibility(View.GONE); + ImageView fileIconView = parent.findViewById(R.id.content_preview_file_icon); fileIconView.setVisibility(View.VISIBLE); fileIconView.setImageResource(R.drawable.chooser_file_generic); } } - private RoundedRectImageView loadUriIntoView(int imageResourceId, Uri uri, View parent) { - RoundedRectImageView imageView = parent.findViewById(imageResourceId); - Bitmap bmp = loadThumbnail(uri, new Size(200, 200)); - if (bmp != null) { - imageView.setVisibility(View.VISIBLE); - imageView.setImageBitmap(bmp); - } - - return imageView; - } - @VisibleForTesting protected boolean isImageType(String mimeType) { return mimeType != null && mimeType.startsWith("image/"); @@ -944,6 +1048,9 @@ public class ChooserActivity extends ResolverActivity { mChooserHandler.removeMessages(CHOOSER_TARGET_SERVICE_RESULT); mChooserHandler.removeMessages(SHORTCUT_MANAGER_SHARE_TARGET_RESULT); mChooserHandler.removeMessages(SHORTCUT_MANAGER_SHARE_TARGET_RESULT_COMPLETED); + + if (mPreviewCoord != null) mPreviewCoord.cancelLoads(); + if (mAppPredictor != null) { mAppPredictor.unregisterPredictionUpdates(mAppPredictorCallback); mAppPredictor.destroy(); @@ -2036,9 +2143,12 @@ public class ChooserActivity extends ResolverActivity { } int availableWidth = right - left - v.getPaddingLeft() - v.getPaddingRight(); - if (mChooserRowAdapter.calculateChooserTargetWidth(availableWidth) + if (mChooserRowAdapter.consumeLayoutRequest() + || mChooserRowAdapter.calculateChooserTargetWidth(availableWidth) || mAdapterView.getAdapter() == null) { - mAdapterView.setAdapter(mChooserRowAdapter); + if (mAdapterView.getAdapter() == null) { + mAdapterView.setAdapter(mChooserRowAdapter); + } getMainThreadHandler().post(() -> { if (mResolverDrawerLayout == null || mChooserRowAdapter == null) { @@ -2589,6 +2699,9 @@ public class ChooserActivity extends ResolverActivity { private int mChooserTargetWidth = 0; private boolean mShowAzLabelIfPoss; + private boolean mHideContentPreview = false; + private boolean mLayoutRequested = false; + private static final int VIEW_TYPE_DIRECT_SHARE = 0; private static final int VIEW_TYPE_NORMAL = 1; private static final int VIEW_TYPE_CONTENT_PREVIEW = 2; @@ -2651,6 +2764,18 @@ public class ChooserActivity extends ResolverActivity { return maxTargets; } + public void hideContentPreview() { + mHideContentPreview = true; + mLayoutRequested = true; + notifyDataSetChanged(); + } + + public boolean consumeLayoutRequest() { + boolean oldValue = mLayoutRequested; + mLayoutRequested = false; + return oldValue; + } + @Override public boolean areAllItemsEnabled() { return false; @@ -2684,7 +2809,8 @@ public class ChooserActivity extends ResolverActivity { return 0; } - if (mChooserListAdapter == null || mChooserListAdapter.getCount() == 0) { + if (mHideContentPreview || mChooserListAdapter == null + || mChooserListAdapter.getCount() == 0) { return 0; } diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp index f9f28dabc694..daa63475f706 100644 --- a/core/jni/android_media_AudioTrack.cpp +++ b/core/jni/android_media_AudioTrack.cpp @@ -1301,18 +1301,6 @@ static void android_media_AudioTrack_set_delay_padding(JNIEnv *env, jobject thi lpTrack->setParameters(param.toString()); } -static void android_media_AudioTrack_set_eos(JNIEnv *env, jobject thiz) { - sp<AudioTrack> lpTrack = getAudioTrack(env, thiz); - if (lpTrack == NULL) { - jniThrowException(env, "java/lang/IllegalStateException", - "AudioTrack not initialized"); - return; - } - AudioParameter param = AudioParameter(); - param.addInt(String8("EOS"), 1); - lpTrack->setParameters(param.toString()); -} - // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- static const JNINativeMethod gMethods[] = { @@ -1389,7 +1377,6 @@ static const JNINativeMethod gMethods[] = { {"native_setPresentation", "(II)I", (void *)android_media_AudioTrack_setPresentation}, {"native_getPortId", "()I", (void *)android_media_AudioTrack_get_port_id}, {"native_set_delay_padding", "(II)V", (void *)android_media_AudioTrack_set_delay_padding}, - {"native_set_eos", "()V", (void *)android_media_AudioTrack_set_eos}, }; diff --git a/core/res/res/layout/chooser_grid_preview_file.xml b/core/res/res/layout/chooser_grid_preview_file.xml index 27c6041ba257..f7d60c91052d 100644 --- a/core/res/res/layout/chooser_grid_preview_file.xml +++ b/core/res/res/layout/chooser_grid_preview_file.xml @@ -44,8 +44,7 @@ android:adjustViewBounds="true" android:layout_gravity="center_vertical" android:gravity="center" - android:scaleType="centerCrop" - android:visibility="gone"/> + android:scaleType="centerCrop"/> <ImageView android:id="@+id/content_preview_file_icon" android:layout_width="36dp" diff --git a/core/res/res/layout/chooser_grid_preview_image.xml b/core/res/res/layout/chooser_grid_preview_image.xml index ad31e0d0c194..79a0de4b271f 100644 --- a/core/res/res/layout/chooser_grid_preview_image.xml +++ b/core/res/res/layout/chooser_grid_preview_image.xml @@ -33,7 +33,6 @@ <view class="com.android.internal.app.ChooserActivity$RoundedRectImageView" android:id="@+id/content_preview_image_1_large" - android:visibility="gone" android:layout_width="120dp" android:layout_height="140dp" android:layout_alignParentTop="true" diff --git a/packages/SystemUI/res/values-mcc310-mnc030/config.xml b/core/res/res/values-mcc310-mnc030/config.xml index 26b9192e0cc3..26b9192e0cc3 100644 --- a/packages/SystemUI/res/values-mcc310-mnc030/config.xml +++ b/core/res/res/values-mcc310-mnc030/config.xml diff --git a/packages/SystemUI/res/values-mcc310-mnc070/config.xml b/core/res/res/values-mcc310-mnc070/config.xml index 26b9192e0cc3..26b9192e0cc3 100644 --- a/packages/SystemUI/res/values-mcc310-mnc070/config.xml +++ b/core/res/res/values-mcc310-mnc070/config.xml diff --git a/packages/SystemUI/res/values-mcc310-mnc170/config.xml b/core/res/res/values-mcc310-mnc170/config.xml index 26b9192e0cc3..26b9192e0cc3 100644 --- a/packages/SystemUI/res/values-mcc310-mnc170/config.xml +++ b/core/res/res/values-mcc310-mnc170/config.xml diff --git a/packages/SystemUI/res/values-mcc310-mnc280/config.xml b/core/res/res/values-mcc310-mnc280/config.xml index 26b9192e0cc3..26b9192e0cc3 100644 --- a/packages/SystemUI/res/values-mcc310-mnc280/config.xml +++ b/core/res/res/values-mcc310-mnc280/config.xml diff --git a/packages/SystemUI/res/values-mcc310-mnc380/config.xml b/core/res/res/values-mcc310-mnc380/config.xml index 26b9192e0cc3..26b9192e0cc3 100644 --- a/packages/SystemUI/res/values-mcc310-mnc380/config.xml +++ b/core/res/res/values-mcc310-mnc380/config.xml diff --git a/core/res/res/values-mcc310-mnc410/config.xml b/core/res/res/values-mcc310-mnc410/config.xml index 00ab7127c331..3fb3f0f7e9ff 100644 --- a/core/res/res/values-mcc310-mnc410/config.xml +++ b/core/res/res/values-mcc310-mnc410/config.xml @@ -48,4 +48,8 @@ <item>"#8"</item> <item>"#9"</item> </string-array> + + <!-- Enable 5 bar signal strength icon --> + <bool name="config_inflateSignalStrength">true</bool> + </resources> diff --git a/packages/SystemUI/res/values-mcc310-mnc410/config.xml b/core/res/res/values-mcc310-mnc560/config.xml index 26b9192e0cc3..26b9192e0cc3 100644 --- a/packages/SystemUI/res/values-mcc310-mnc410/config.xml +++ b/core/res/res/values-mcc310-mnc560/config.xml diff --git a/packages/SystemUI/res/values-mcc310-mnc560/config.xml b/core/res/res/values-mcc310-mnc950/config.xml index 26b9192e0cc3..26b9192e0cc3 100644 --- a/packages/SystemUI/res/values-mcc310-mnc560/config.xml +++ b/core/res/res/values-mcc310-mnc950/config.xml diff --git a/packages/SystemUI/res/values-mcc310-mnc950/config.xml b/core/res/res/values-mcc311-mnc180/config.xml index 26b9192e0cc3..26b9192e0cc3 100644 --- a/packages/SystemUI/res/values-mcc310-mnc950/config.xml +++ b/core/res/res/values-mcc311-mnc180/config.xml diff --git a/core/res/res/values-mcc311-mnc480/config.xml b/core/res/res/values-mcc311-mnc480/config.xml index db2f8d01f93a..336e30e45b00 100755 --- a/core/res/res/values-mcc311-mnc480/config.xml +++ b/core/res/res/values-mcc311-mnc480/config.xml @@ -40,4 +40,7 @@ <bool name="config_use_sim_language_file">true</bool> + <!-- Enable 5 bar signal strength icon --> + <bool name="config_inflateSignalStrength">true</bool> + </resources> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 2de539721195..fb585693c8a5 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -4121,4 +4121,9 @@ even after user setup is complete. The defined component should be used for supervision purposes only. The component must be part of a system app. --> <string name="config_defaultSupervisionProfileOwnerComponent" translatable="false"></string> + + <!-- Whether to artificially interpret all signal strengths as + one bar higher than they actually are --> + <bool name="config_inflateSignalStrength">false</bool> + </resources> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 6cdb3d67192c..3d2d9693d62b 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -3797,4 +3797,5 @@ <java-symbol type="style" name="Animation.DeviceDefault.Activity.Resolver" /> <java-symbol type="string" name="config_defaultSupervisionProfileOwnerComponent" /> + <java-symbol type="bool" name="config_inflateSignalStrength" /> </resources> diff --git a/keystore/java/android/security/keystore/KeyStoreCryptoOperationChunkedStreamer.java b/keystore/java/android/security/keystore/KeyStoreCryptoOperationChunkedStreamer.java index dbb79bcd5aea..e0304787142d 100644 --- a/keystore/java/android/security/keystore/KeyStoreCryptoOperationChunkedStreamer.java +++ b/keystore/java/android/security/keystore/KeyStoreCryptoOperationChunkedStreamer.java @@ -162,15 +162,15 @@ class KeyStoreCryptoOperationChunkedStreamer implements KeyStoreCryptoOperationS } if ((opResult.output != null) && (opResult.output.length > 0)) { - if (inputLength > 0) { + if (inputLength + mBufferedLength > 0) { // More output might be produced in this loop -- buffer the current output if (bufferedOutput == null) { bufferedOutput = new ByteArrayOutputStream(); - try { - bufferedOutput.write(opResult.output); - } catch (IOException e) { - throw new ProviderException("Failed to buffer output", e); - } + } + try { + bufferedOutput.write(opResult.output); + } catch (IOException e) { + throw new ProviderException("Failed to buffer output", e); } } else { // No more output will be produced in this loop diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java index d9d614f7ead4..e29e5698439d 100644 --- a/media/java/android/media/AudioTrack.java +++ b/media/java/android/media/AudioTrack.java @@ -101,6 +101,20 @@ public class AudioTrack extends PlayerBase public static final int PLAYSTATE_PAUSED = 2; // matches SL_PLAYSTATE_PAUSED /** indicates AudioTrack state is playing */ public static final int PLAYSTATE_PLAYING = 3; // matches SL_PLAYSTATE_PLAYING + /** + * @hide + * indicates AudioTrack state is stopping waiting for NATIVE_EVENT_STREAM_END to + * transition to PLAYSTATE_STOPPED. + * Only valid for offload mode. + */ + private static final int PLAYSTATE_STOPPING = 4; + /** + * @hide + * indicates AudioTrack state is paused from stopping state. Will transition to + * PLAYSTATE_STOPPING if play() is called. + * Only valid for offload mode. + */ + private static final int PLAYSTATE_PAUSED_STOPPING = 5; // keep these values in sync with android_media_AudioTrack.cpp /** @@ -303,6 +317,14 @@ public class AudioTrack extends PlayerBase * One of PLAYSTATE_STOPPED, PLAYSTATE_PAUSED, or PLAYSTATE_PLAYING. */ private int mPlayState = PLAYSTATE_STOPPED; + + /** + * Indicates that we are expecting an end of stream callback following a call + * to setOffloadEndOfStream() in a gapless track transition context. The native track + * will be restarted automatically. + */ + private boolean mOffloadEosPending = false; + /** * Lock to ensure mPlayState updates reflect the actual state of the object. */ @@ -1073,6 +1095,10 @@ public class AudioTrack extends PlayerBase * Declares that the last write() operation on this track provided the last buffer of this * stream. * After the end of stream, previously set padding and delay values are ignored. + * Can only be called only if the AudioTrack is opened in offload mode + * {@see Builder#setOffloadedPlayback(boolean)}. + * Can only be called only if the AudioTrack is in state {@link #PLAYSTATE_PLAYING} + * {@see #getPlaystate()}. * Use this method in the same thread as any write() operation. */ public void setOffloadEndOfStream() { @@ -1082,7 +1108,20 @@ public class AudioTrack extends PlayerBase if (mState == STATE_UNINITIALIZED) { throw new IllegalStateException("Uninitialized track"); } - native_set_eos(); + if (mPlayState != PLAYSTATE_PLAYING) { + throw new IllegalStateException("EOS not supported if not playing"); + } + synchronized (mStreamEventCbLock) { + if (mStreamEventCbInfoList.size() == 0) { + throw new IllegalStateException("EOS not supported without StreamEventCallback"); + } + } + + synchronized (mPlayStateLock) { + native_stop(); + mOffloadEosPending = true; + mPlayState = PLAYSTATE_STOPPING; + } } /** @@ -1366,7 +1405,11 @@ public class AudioTrack extends PlayerBase } baseRelease(); native_release(); - mState = STATE_UNINITIALIZED; + synchronized (mPlayStateLock) { + mState = STATE_UNINITIALIZED; + mPlayState = PLAYSTATE_STOPPED; + mPlayStateLock.notify(); + } } @Override @@ -1525,7 +1568,14 @@ public class AudioTrack extends PlayerBase */ public int getPlayState() { synchronized (mPlayStateLock) { - return mPlayState; + switch (mPlayState) { + case PLAYSTATE_STOPPING: + return PLAYSTATE_PLAYING; + case PLAYSTATE_PAUSED_STOPPING: + return PLAYSTATE_PAUSED; + default: + return mPlayState; + } } } @@ -2260,7 +2310,12 @@ public class AudioTrack extends PlayerBase synchronized(mPlayStateLock) { baseStart(); native_start(); - mPlayState = PLAYSTATE_PLAYING; + if (mPlayState == PLAYSTATE_PAUSED_STOPPING) { + mPlayState = PLAYSTATE_STOPPING; + } else { + mPlayState = PLAYSTATE_PLAYING; + mOffloadEosPending = false; + } } } @@ -2282,9 +2337,15 @@ public class AudioTrack extends PlayerBase synchronized(mPlayStateLock) { native_stop(); baseStop(); - mPlayState = PLAYSTATE_STOPPED; - mAvSyncHeader = null; - mAvSyncBytesRemaining = 0; + if (mOffloaded && mPlayState != PLAYSTATE_PAUSED_STOPPING) { + mPlayState = PLAYSTATE_STOPPING; + } else { + mPlayState = PLAYSTATE_STOPPED; + mOffloadEosPending = false; + mAvSyncHeader = null; + mAvSyncBytesRemaining = 0; + mPlayStateLock.notify(); + } } } @@ -2305,7 +2366,11 @@ public class AudioTrack extends PlayerBase synchronized(mPlayStateLock) { native_pause(); basePause(); - mPlayState = PLAYSTATE_PAUSED; + if (mPlayState == PLAYSTATE_STOPPING) { + mPlayState = PLAYSTATE_PAUSED_STOPPING; + } else { + mPlayState = PLAYSTATE_PAUSED; + } } } @@ -2434,6 +2499,9 @@ public class AudioTrack extends PlayerBase return ERROR_BAD_VALUE; } + if (!blockUntilOffloadDrain(writeMode)) { + return 0; + } final int ret = native_write_byte(audioData, offsetInBytes, sizeInBytes, mAudioFormat, writeMode == WRITE_BLOCKING); @@ -2544,6 +2612,10 @@ public class AudioTrack extends PlayerBase return ERROR_BAD_VALUE; } + if (!blockUntilOffloadDrain(writeMode)) { + return 0; + } + final int ret = native_write_short(audioData, offsetInShorts, sizeInShorts, mAudioFormat, writeMode == WRITE_BLOCKING); @@ -2632,6 +2704,10 @@ public class AudioTrack extends PlayerBase return ERROR_BAD_VALUE; } + if (!blockUntilOffloadDrain(writeMode)) { + return 0; + } + final int ret = native_write_float(audioData, offsetInFloats, sizeInFloats, mAudioFormat, writeMode == WRITE_BLOCKING); @@ -2706,6 +2782,10 @@ public class AudioTrack extends PlayerBase return ERROR_BAD_VALUE; } + if (!blockUntilOffloadDrain(writeMode)) { + return 0; + } + int ret = 0; if (audioData.isDirect()) { ret = native_write_native_bytes(audioData, @@ -2790,6 +2870,10 @@ public class AudioTrack extends PlayerBase return ERROR_BAD_VALUE; } + if (!blockUntilOffloadDrain(writeMode)) { + return 0; + } + // create timestamp header if none exists if (mAvSyncHeader == null) { mAvSyncHeader = ByteBuffer.allocate(mOffset); @@ -2859,6 +2943,25 @@ public class AudioTrack extends PlayerBase return native_reload_static(); } + /** + * When an AudioTrack in offload mode is in STOPPING play state, wait until event STREAM_END is + * received if blocking write or return with 0 frames written if non blocking mode. + */ + private boolean blockUntilOffloadDrain(int writeMode) { + synchronized (mPlayStateLock) { + while (mPlayState == PLAYSTATE_STOPPING || mPlayState == PLAYSTATE_PAUSED_STOPPING) { + if (writeMode == WRITE_NON_BLOCKING) { + return false; + } + try { + mPlayStateLock.wait(); + } catch (InterruptedException e) { + } + } + return true; + } + } + //-------------------------------------------------------------------------- // Audio effects management //-------------------- @@ -3293,6 +3396,22 @@ public class AudioTrack extends PlayerBase public void handleMessage(Message msg) { final LinkedList<StreamEventCbInfo> cbInfoList; synchronized (mStreamEventCbLock) { + if (msg.what == NATIVE_EVENT_STREAM_END) { + synchronized (mPlayStateLock) { + if (mPlayState == PLAYSTATE_STOPPING) { + if (mOffloadEosPending) { + native_start(); + mPlayState = PLAYSTATE_PLAYING; + } else { + mAvSyncHeader = null; + mAvSyncBytesRemaining = 0; + mPlayState = PLAYSTATE_STOPPED; + } + mOffloadEosPending = false; + mPlayStateLock.notify(); + } + } + } if (mStreamEventCbInfoList.size() == 0) { return; } @@ -3560,7 +3679,6 @@ public class AudioTrack extends PlayerBase private native int native_getPortId(); private native void native_set_delay_padding(int delayInFrames, int paddingInFrames); - private native void native_set_eos(); //--------------------------------------------------------- // Utility methods diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml index 4c72f48da87f..0e9183940f22 100644 --- a/packages/SettingsLib/res/values/strings.xml +++ b/packages/SettingsLib/res/values/strings.xml @@ -578,6 +578,8 @@ <string name="wifi_display_certification">Wireless display certification</string> <!-- Setting Checkbox title whether to enable WiFi Verbose Logging. [CHAR LIMIT=40] --> <string name="wifi_verbose_logging">Enable Wi\u2011Fi Verbose Logging</string> + <!-- Setting Checkbox title whether to disable WiFi Scan Throttling. [CHAR LIMIT=40] --> + <string name="wifi_scan_throttling">Wi\u2011Fi scan throttling</string> <!-- Setting Checkbox title whether to always keep mobile data active. [CHAR LIMIT=80] --> <string name="mobile_data_always_on">Mobile data always active</string> <!-- Setting Checkbox title whether to enable hardware acceleration for tethering. [CHAR LIMIT=80] --> @@ -633,6 +635,8 @@ <string name="wifi_display_certification_summary">Show options for wireless display certification</string> <!-- Setting Checkbox summary whether to enable Wifi verbose Logging [CHAR LIMIT=80] --> <string name="wifi_verbose_logging_summary">Increase Wi\u2011Fi logging level, show per SSID RSSI in Wi\u2011Fi Picker</string> + <!-- Setting Checkbox summary whether to disable Wifi scan throttling [CHAR LIMIT=NONE] --> + <string name="wifi_scan_throttling_summary">Reduces battery drain & improves network performance</string> <!-- Label indicating network has been manually marked as metered --> <string name="wifi_metered_label">Metered</string> <!-- Label indicating network has been manually marked as unmetered --> diff --git a/packages/SettingsLib/src/com/android/settingslib/net/SignalStrengthUtil.java b/packages/SettingsLib/src/com/android/settingslib/net/SignalStrengthUtil.java new file mode 100644 index 000000000000..246f2ceac87c --- /dev/null +++ b/packages/SettingsLib/src/com/android/settingslib/net/SignalStrengthUtil.java @@ -0,0 +1,34 @@ +/* + * 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.settingslib.net; + +import android.content.Context; +import android.telephony.SubscriptionManager; + +/** + * Utilities for dealing with signal strength. + */ +public class SignalStrengthUtil { + /** + * @return whether we should artificially inflate the signal strength and number of levels by 1 + * bar for the subscription with the given id + */ + public static boolean shouldInflateSignalStrength(Context context, int subscriptionId) { + return SubscriptionManager.getResourcesForSubId(context, subscriptionId) + .getBoolean(com.android.internal.R.bool.config_inflateSignalStrength); + } +} diff --git a/packages/SystemUI/res/drawable/ic_volume_media.xml b/packages/SystemUI/res/drawable/ic_volume_media.xml index c8fa3fbdd50b..99be7b6e8fea 100644 --- a/packages/SystemUI/res/drawable/ic_volume_media.xml +++ b/packages/SystemUI/res/drawable/ic_volume_media.xml @@ -22,6 +22,6 @@ <path android:fillColor="#FFFFFFFF" - android:pathData="M12,3l0.01,10.55c-0.59,-0.34 -1.27,-0.55 -2,-0.55C7.79,13 6,14.79 6,17c0,2.21 1.79,4 4.01,4S14,19.21 14,17V7h4V3H12zM10.01,19c-1.1,0 -2,-0.9 -2,-2c0,-1.1 0.9,-2 2,-2s2,0.9 2,2C12.01,18.1 11.11,19 10.01,19z"/> + android:pathData="M12 3l0.01 10.55c-0.59-0.34-1.27-0.55-2-0.55C7.79 13 6 14.79 6 17s1.79 4 4.01 4S14 19.21 14 17V7h4V3h-6z" /> </vector> diff --git a/packages/SystemUI/res/drawable/ic_volume_media_mute.xml b/packages/SystemUI/res/drawable/ic_volume_media_mute.xml index 45b5b87e8ab5..3a495963fc76 100644 --- a/packages/SystemUI/res/drawable/ic_volume_media_mute.xml +++ b/packages/SystemUI/res/drawable/ic_volume_media_mute.xml @@ -22,9 +22,6 @@ <path android:fillColor="#FFFFFFFF" - android:pathData="M21.19,21.19L14,14l-2,-2l-9.2,-9.2L1.39,4.22l8.79,8.79c-0.06,0 -0.12,-0.01 -0.18,-0.01C7.79,13 6,14.79 6,17c0,2.21 1.79,4 4.01,4S14,19.21 14,17v-0.17l5.78,5.78L21.19,21.19zM10.01,19c-1.1,0 -2,-0.9 -2,-2c0,-1.1 0.9,-2 2,-2s2,0.9 2,2C12.01,18.1 11.11,19 10.01,19z"/> - <path - android:fillColor="#FFffffff" - android:pathData="M14,11.17l0,-4.17l4,0l0,-4l-6,0l0,6.17z"/> + android:pathData="M21.19 21.19L14 14l-2-2-9.2-9.2-1.41 1.42 8.79 8.79c-0.06 0-0.12-0.01-0.18-0.01-2.21 0-4 1.79-4 4s1.79 4 4.01 4S14 19.21 14 17v-0.17l5.78 5.78 1.41-1.42zM14 11.17V7h4V3h-6v6.17z" /> </vector> diff --git a/packages/SystemUI/res/values-mcc311-mnc180/config.xml b/packages/SystemUI/res/values-mcc311-mnc180/config.xml deleted file mode 100644 index 26b9192e0cc3..000000000000 --- a/packages/SystemUI/res/values-mcc311-mnc180/config.xml +++ /dev/null @@ -1,26 +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. -*/ ---> - -<!-- These resources are around just to allow their values to be customized - for different hardware and product builds. --> -<resources> - <!-- Enable 5 bar signal strength icon --> - <bool name="config_inflateSignalStrength">true</bool> -</resources> - diff --git a/packages/SystemUI/res/values-mcc311-mnc480/config.xml b/packages/SystemUI/res/values-mcc311-mnc480/config.xml deleted file mode 100644 index 7dadae7f9107..000000000000 --- a/packages/SystemUI/res/values-mcc311-mnc480/config.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** Copyright 2017, 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. -*/ ---> - -<!-- These resources are around just to allow their values to be customized - for different hardware and product builds. --> -<resources> - <!-- Enable 5 bar signal strength icon --> - <bool name="config_inflateSignalStrength">true</bool> -</resources> - diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index 27431f7257f2..19e7b734912a 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -417,10 +417,6 @@ it has been expanded to reveal its children. --> <bool name="config_showGroupNotificationBgWhenExpanded">false</bool> - <!-- Whether to artificially interpret all signal strengths as - one bar higher than they actually are --> - <bool name="config_inflateSignalStrength">false</bool> - <!-- Should we vibrate on an icon animation of the shelf. This should only be active if the vibrator is capable of subtle vibrations --> <bool name="config_vibrateOnIconAnimation">false</bool> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 19874948cb54..c04d28a6cda8 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -38,7 +38,6 @@ <dimen name="navigation_handle_sample_horizontal_margin">10dp</dimen> <dimen name="navigation_home_handle_width">72dp</dimen> - <!-- Size of the nav bar edge panels, should be greater to the edge sensitivity + the drag threshold --> <dimen name="navigation_edge_panel_width">70dp</dimen> @@ -57,6 +56,9 @@ <!-- Luminance change threshold that allows applying new value if difference was exceeded --> <item name="navigation_luminance_change_threshold" type="dimen" format="float">0.05</item> + <dimen name="floating_rotation_button_diameter">40dp</dimen> + <dimen name="floating_rotation_button_margin">4dp</dimen> + <!-- Height of notification icons in the status bar --> <dimen name="status_bar_icon_size">@*android:dimen/status_bar_icon_size</dimen> diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java index 4ec79a64b2a3..392183b554a9 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java @@ -16,6 +16,7 @@ package com.android.systemui.bubbles; +import static android.app.Notification.FLAG_BUBBLE; import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_BADGE; import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST; import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK; @@ -40,8 +41,6 @@ import static java.lang.annotation.RetentionPolicy.SOURCE; import android.app.ActivityManager; import android.app.ActivityManager.RunningTaskInfo; -import android.app.ActivityTaskManager; -import android.app.IActivityTaskManager; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; @@ -53,6 +52,7 @@ import android.graphics.Rect; import android.os.RemoteException; import android.os.ServiceManager; import android.provider.Settings; +import android.service.notification.NotificationListenerService.RankingMap; import android.service.notification.StatusBarNotification; import android.service.notification.ZenModeConfig; import android.util.Log; @@ -138,7 +138,6 @@ public class BubbleController implements ConfigurationController.ConfigurationLi private final Context mContext; private final NotificationEntryManager mNotificationEntryManager; - private final IActivityTaskManager mActivityTaskManager; private final BubbleTaskStackListener mTaskStackListener; private BubbleStateChangeListener mStateChangeListener; private BubbleExpandListener mExpandListener; @@ -250,7 +249,6 @@ public class BubbleController implements ConfigurationController.ConfigurationLi mStatusBarStateListener = new StatusBarStateListener(); Dependency.get(StatusBarStateController.class).addCallback(mStatusBarStateListener); - mActivityTaskManager = ActivityTaskManager.getService(); mTaskStackListener = new BubbleTaskStackListener(); ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener); @@ -509,6 +507,12 @@ public class BubbleController implements ConfigurationController.ConfigurationLi updateBubble(entry); } } + + @Override + public void onNotificationRankingUpdated(RankingMap rankingMap) { + // Forward to BubbleData to block any bubbles which should no longer be shown + mBubbleData.notificationRankingUpdated(rankingMap); + } }; @SuppressWarnings("FieldCanBeLocal") @@ -547,8 +551,11 @@ public class BubbleController implements ConfigurationController.ConfigurationLi mNotificationEntryManager.performRemoveNotification(bubble.entry.notification, UNDEFINED_DISMISS_REASON); } else { - // The notification is still in the shade but we've removed the bubble so - // lets make sure NoMan knows it's not a bubble anymore + // Update the flag for SysUI + bubble.entry.notification.getNotification().flags &= ~FLAG_BUBBLE; + + // Make sure NoMan knows it's not a bubble anymore so anyone querying it will + // get right result back try { mBarService.onNotificationBubbleChanged(bubble.getKey(), false /* isBubble */); diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java index 6ab973eb3065..5575b35a12ae 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java @@ -22,6 +22,8 @@ import static java.util.stream.Collectors.toList; import android.app.Notification; import android.app.PendingIntent; import android.content.Context; +import android.service.notification.NotificationListenerService; +import android.service.notification.NotificationListenerService.RankingMap; import android.util.Log; import android.util.Pair; @@ -114,6 +116,8 @@ public class BubbleData { // State tracked during an operation -- keeps track of what listener events to dispatch. private Update mStateChange; + private NotificationListenerService.Ranking mTmpRanking; + private TimeSource mTimeSource = System::currentTimeMillis; @Nullable @@ -193,6 +197,31 @@ public class BubbleData { dispatchPendingChanges(); } + /** + * Called when NotificationListener has received adjusted notification rank and reapplied + * filtering and sorting. This is used to dismiss any bubbles which should no longer be shown + * due to changes in permissions on the notification channel or the global setting. + * + * @param rankingMap the updated ranking map from NotificationListenerService + */ + public void notificationRankingUpdated(RankingMap rankingMap) { + if (mTmpRanking == null) { + mTmpRanking = new NotificationListenerService.Ranking(); + } + + String[] orderedKeys = rankingMap.getOrderedKeys(); + for (int i = 0; i < orderedKeys.length; i++) { + String key = orderedKeys[i]; + if (hasBubbleWithKey(key)) { + rankingMap.getRanking(key, mTmpRanking); + if (!mTmpRanking.canBubble()) { + doRemove(key, BubbleController.DISMISS_BLOCKED); + } + } + } + dispatchPendingChanges(); + } + private void doAdd(Bubble bubble) { if (DEBUG) { Log.d(TAG, "doAdd: " + bubble); diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java index 6de0fb581e90..c63389a47d2d 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java @@ -732,7 +732,6 @@ public class BubbleStackView extends FrameLayout { } } - /** * Changes the currently selected bubble. If the stack is already expanded, the newly selected * bubble will be shown immediately. This does not change the expanded state or change the diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java index 9d5871eb595c..c375574f023d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java @@ -169,6 +169,5 @@ public class NotificationListener extends NotificationListenerWithPlugins { public interface NotificationSettingsListener { default void onStatusBarIconsBehaviorChanged(boolean hideSilentStatusIcons) { } - } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java index a5a6d87c2030..1aa6bc9ae5f9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java @@ -16,6 +16,8 @@ package com.android.systemui.statusbar.notification; import android.annotation.Nullable; +import android.service.notification.NotificationListenerService; +import android.service.notification.NotificationListenerService.RankingMap; import android.service.notification.StatusBarNotification; import com.android.internal.statusbar.NotificationVisibility; @@ -98,4 +100,14 @@ public interface NotificationEntryListener { @Nullable NotificationVisibility visibility, boolean removedByUser) { } + + /** + * Called whenever notification ranking changes, in response to + * {@link NotificationListenerService#onNotificationRankingUpdate}. This is called after + * NotificationData has processed the update and notifications have been re-sorted and filtered. + * + * @param rankingMap provides access to ranking information on currently active notifications + */ + default void onNotificationRankingUpdated(RankingMap rankingMap) { + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java index 3ac5768f091a..e8388ceded04 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java @@ -483,6 +483,10 @@ public class NotificationEntryManager implements } updateNotifications(); + + for (NotificationEntryListener listener : mNotificationEntryListeners) { + listener.onNotificationRankingUpdated(rankingMap); + } } private void updateRankingOfPendingNotifications( diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt index c65e90ea7bea..35cc960bb6f0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt @@ -65,7 +65,7 @@ class NotificationWakeUpCoordinator @Inject constructor( private val mDozeParameters: DozeParameters; var willWakeUp = false set(value) { - if (value && mDozeAmount != 0.0f) { + if (!value || mDozeAmount != 0.0f) { field = value } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FloatingRotationButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FloatingRotationButton.java index 215aa77920d9..6286d4d7febf 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FloatingRotationButton.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FloatingRotationButton.java @@ -17,6 +17,7 @@ package com.android.systemui.statusbar.phone; import android.content.Context; +import android.content.res.Resources; import android.graphics.PixelFormat; import android.view.ContextThemeWrapper; import android.view.Gravity; @@ -35,6 +36,8 @@ public class FloatingRotationButton implements RotationButton { private final Context mContext; private final WindowManager mWindowManager; private final KeyButtonView mKeyButtonView; + private final int mDiameter; + private final int mMargin; private KeyButtonDrawable mKeyButtonDrawable; private boolean mIsShowing; private boolean mCanShow = true; @@ -46,6 +49,11 @@ public class FloatingRotationButton implements RotationButton { mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); mKeyButtonView = (KeyButtonView) LayoutInflater.from(mContext).inflate( R.layout.rotate_suggestion, null); + mKeyButtonView.setVisibility(View.VISIBLE); + + Resources resources = mContext.getResources(); + mDiameter = resources.getDimensionPixelSize(R.dimen.floating_rotation_button_diameter); + mMargin = resources.getDimensionPixelSize(R.dimen.floating_rotation_button_margin); } @Override @@ -66,11 +74,8 @@ public class FloatingRotationButton implements RotationButton { mIsShowing = true; int flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; - float density = mContext.getResources().getDisplayMetrics().density; - int diameter = (int) density * 48; - int margin = (int) density * 4; - final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(diameter, diameter, - margin, margin, WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL, flags, + final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(mDiameter, mDiameter, + mMargin, mMargin, WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL, flags, PixelFormat.TRANSLUCENT); lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS; lp.setTitle("FloatingRotationButton"); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java index c08390fa53a2..2afe485eff8e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java @@ -38,6 +38,7 @@ import com.android.internal.telephony.TelephonyIntents; import com.android.internal.telephony.cdma.EriInfo; import com.android.settingslib.Utils; import com.android.settingslib.graph.SignalDrawable; +import com.android.settingslib.net.SignalStrengthUtil; import com.android.systemui.R; import com.android.systemui.statusbar.policy.NetworkController.IconState; import com.android.systemui.statusbar.policy.NetworkController.SignalCallback; @@ -248,9 +249,8 @@ public class MobileSignalController extends SignalController< } private void updateInflateSignalStrength() { - mInflateSignalStrengths = SubscriptionManager.getResourcesForSubId(mContext, - mSubscriptionInfo.getSubscriptionId()) - .getBoolean(R.bool.config_inflateSignalStrength); + mInflateSignalStrengths = SignalStrengthUtil.shouldInflateSignalStrength(mContext, + mSubscriptionInfo.getSubscriptionId()); } private int getNumLevels() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java index b8a14efa4935..b2972fcd1286 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java @@ -1140,7 +1140,8 @@ public class NetworkControllerImpl extends BroadcastReceiver res.getBoolean(com.android.internal.R.bool.config_alwaysUseCdmaRssi); config.hspaDataDistinguishable = res.getBoolean(R.bool.config_hspa_data_distinguishable); - config.inflateSignalStrengths = res.getBoolean(R.bool.config_inflateSignalStrength); + config.inflateSignalStrengths = res.getBoolean( + com.android.internal.R.bool.config_inflateSignalStrength); CarrierConfigManager configMgr = (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java index 4d593c101706..72f3a62f30a7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java @@ -402,6 +402,7 @@ public class NotificationEntryManagerTest extends SysuiTestCase { verify(mRow).setEntry(eq(mEntry)); assertEquals(1, mEntry.systemGeneratedSmartActions.size()); assertEquals("action", mEntry.systemGeneratedSmartActions.get(0).title); + verify(mEntryListener).onNotificationRankingUpdated(mRankingMap); } @Test diff --git a/services/core/java/com/android/server/adb/AdbDebuggingManager.java b/services/core/java/com/android/server/adb/AdbDebuggingManager.java index bdbff3db943d..4b48ef917744 100644 --- a/services/core/java/com/android/server/adb/AdbDebuggingManager.java +++ b/services/core/java/com/android/server/adb/AdbDebuggingManager.java @@ -661,12 +661,6 @@ public class AdbDebuggingManager { return mTestUserKeyFile == null ? getAdbFile(ADB_KEYS_FILE) : mTestUserKeyFile; } - private void createKeyFile(File keyFile) throws IOException { - keyFile.createNewFile(); - FileUtils.setPermissions(keyFile.toString(), - FileUtils.S_IRUSR | FileUtils.S_IWUSR | FileUtils.S_IRGRP, -1, -1); - } - private void writeKey(String key) { try { File keyFile = getUserKeyFile(); @@ -675,14 +669,13 @@ public class AdbDebuggingManager { return; } - if (!keyFile.exists()) { - createKeyFile(keyFile); - } - FileOutputStream fo = new FileOutputStream(keyFile, true); fo.write(key.getBytes()); fo.write('\n'); fo.close(); + + FileUtils.setPermissions(keyFile.toString(), + FileUtils.S_IRUSR | FileUtils.S_IWUSR | FileUtils.S_IRGRP, -1, -1); } catch (IOException ex) { Slog.e(TAG, "Error writing key:" + ex); } @@ -698,10 +691,6 @@ public class AdbDebuggingManager { return; } - if (!keyFile.exists()) { - createKeyFile(keyFile); - } - atomicKeyFile = new AtomicFile(keyFile); fo = atomicKeyFile.startWrite(); for (String key : keys) { @@ -709,6 +698,9 @@ public class AdbDebuggingManager { fo.write('\n'); } atomicKeyFile.finishWrite(fo); + + FileUtils.setPermissions(keyFile.toString(), + FileUtils.S_IRUSR | FileUtils.S_IWUSR | FileUtils.S_IRGRP, -1, -1); } catch (IOException ex) { Slog.e(TAG, "Error writing keys: " + ex); if (atomicKeyFile != null) { diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 1160e33aca25..c4eb661c55d8 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -1036,19 +1036,12 @@ public class NotificationManagerService extends SystemService { final StatusBarNotification n = r.sbn; final int callingUid = n.getUid(); final String pkg = n.getPackageName(); - final boolean wasBubble = r.getNotification().isBubbleNotification(); if (isBubble && isNotificationAppropriateToBubble(r, pkg, callingUid, null /* oldEntry */)) { r.getNotification().flags |= FLAG_BUBBLE; } else { r.getNotification().flags &= ~FLAG_BUBBLE; } - if (wasBubble != r.getNotification().isBubbleNotification()) { - // Add the "alert only once" flag so that the notification won't HUN - // unnecessarily just because the bubble flag was changed. - r.getNotification().flags |= FLAG_ONLY_ALERT_ONCE; - mListeners.notifyPostedLocked(r, r); - } } } } @@ -2643,18 +2636,25 @@ public class NotificationManagerService extends SystemService { ParceledListSlice channelsList) { List<NotificationChannel> channels = channelsList.getList(); final int channelsSize = channels.size(); + boolean needsPolicyFileChange = false; for (int i = 0; i < channelsSize; i++) { final NotificationChannel channel = channels.get(i); Preconditions.checkNotNull(channel, "channel in list is null"); - mPreferencesHelper.createNotificationChannel(pkg, uid, channel, - true /* fromTargetApp */, mConditionProviders.isPackageOrComponentAllowed( + needsPolicyFileChange = mPreferencesHelper.createNotificationChannel(pkg, uid, + channel, true /* fromTargetApp */, + mConditionProviders.isPackageOrComponentAllowed( pkg, UserHandle.getUserId(uid))); - mListeners.notifyNotificationChannelChanged(pkg, - UserHandle.getUserHandleForUid(uid), - mPreferencesHelper.getNotificationChannel(pkg, uid, channel.getId(), false), - NOTIFICATION_CHANNEL_OR_GROUP_ADDED); + if (needsPolicyFileChange) { + mListeners.notifyNotificationChannelChanged(pkg, + UserHandle.getUserHandleForUid(uid), + mPreferencesHelper.getNotificationChannel(pkg, uid, channel.getId(), + false), + NOTIFICATION_CHANNEL_OR_GROUP_ADDED); + } + } + if (needsPolicyFileChange) { + handleSavePolicyFile(); } - handleSavePolicyFile(); } @Override diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java index 5956c65defef..1c0ac167c26b 100644 --- a/services/core/java/com/android/server/notification/PreferencesHelper.java +++ b/services/core/java/com/android/server/notification/PreferencesHelper.java @@ -615,12 +615,13 @@ public class PreferencesHelper implements RankingConfig { } @Override - public void createNotificationChannel(String pkg, int uid, NotificationChannel channel, + public boolean createNotificationChannel(String pkg, int uid, NotificationChannel channel, boolean fromTargetApp, boolean hasDndAccess) { Preconditions.checkNotNull(pkg); Preconditions.checkNotNull(channel); Preconditions.checkNotNull(channel.getId()); Preconditions.checkArgument(!TextUtils.isEmpty(channel.getName())); + boolean needsPolicyFileChange = false; synchronized (mPackagePreferences) { PackagePreferences r = getOrCreatePackagePreferencesLocked(pkg, uid); if (r == null) { @@ -637,17 +638,28 @@ public class PreferencesHelper implements RankingConfig { if (existing != null && fromTargetApp) { if (existing.isDeleted()) { existing.setDeleted(false); + needsPolicyFileChange = true; // log a resurrected channel as if it's new again MetricsLogger.action(getChannelLog(channel, pkg).setType( com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_OPEN)); } - existing.setName(channel.getName().toString()); - existing.setDescription(channel.getDescription()); - existing.setBlockableSystem(channel.isBlockableSystem()); - if (existing.getGroup() == null) { + if (!Objects.equals(channel.getName().toString(), existing.getName().toString())) { + existing.setName(channel.getName().toString()); + needsPolicyFileChange = true; + } + if (!Objects.equals(channel.getDescription(), existing.getDescription())) { + existing.setDescription(channel.getDescription()); + needsPolicyFileChange = true; + } + if (channel.isBlockableSystem() != existing.isBlockableSystem()) { + existing.setBlockableSystem(channel.isBlockableSystem()); + needsPolicyFileChange = true; + } + if (channel.getGroup() != null && existing.getGroup() == null) { existing.setGroup(channel.getGroup()); + needsPolicyFileChange = true; } // Apps are allowed to downgrade channel importance if the user has not changed any @@ -656,23 +668,30 @@ public class PreferencesHelper implements RankingConfig { if (existing.getUserLockedFields() == 0 && channel.getImportance() < existing.getImportance()) { existing.setImportance(channel.getImportance()); + needsPolicyFileChange = true; } // system apps and dnd access apps can bypass dnd if the user hasn't changed any // fields on the channel yet if (existing.getUserLockedFields() == 0 && hasDndAccess) { boolean bypassDnd = channel.canBypassDnd(); - existing.setBypassDnd(bypassDnd); + if (bypassDnd != existing.canBypassDnd()) { + existing.setBypassDnd(bypassDnd); + needsPolicyFileChange = true; - if (bypassDnd != mAreChannelsBypassingDnd - || previousExistingImportance != existing.getImportance()) { - updateChannelsBypassingDnd(mContext.getUserId()); + if (bypassDnd != mAreChannelsBypassingDnd + || previousExistingImportance != existing.getImportance()) { + updateChannelsBypassingDnd(mContext.getUserId()); + } } } updateConfig(); - return; + return needsPolicyFileChange; } + + needsPolicyFileChange = true; + if (channel.getImportance() < IMPORTANCE_NONE || channel.getImportance() > NotificationManager.IMPORTANCE_MAX) { throw new IllegalArgumentException("Invalid importance level"); @@ -708,6 +727,8 @@ public class PreferencesHelper implements RankingConfig { MetricsLogger.action(getChannelLog(channel, pkg).setType( com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_OPEN)); } + + return needsPolicyFileChange; } void clearLockedFieldsLocked(NotificationChannel channel) { diff --git a/services/core/java/com/android/server/notification/RankingConfig.java b/services/core/java/com/android/server/notification/RankingConfig.java index 72502acd6560..5de00e43a05d 100644 --- a/services/core/java/com/android/server/notification/RankingConfig.java +++ b/services/core/java/com/android/server/notification/RankingConfig.java @@ -39,7 +39,7 @@ public interface RankingConfig { boolean fromTargetApp); ParceledListSlice<NotificationChannelGroup> getNotificationChannelGroups(String pkg, int uid, boolean includeDeleted, boolean includeNonGrouped, boolean includeEmpty); - void createNotificationChannel(String pkg, int uid, NotificationChannel channel, + boolean createNotificationChannel(String pkg, int uid, NotificationChannel channel, boolean fromTargetApp, boolean hasDndAccess); void updateNotificationChannel(String pkg, int uid, NotificationChannel channel, boolean fromUser); NotificationChannel getNotificationChannel(String pkg, int uid, String channelId, boolean includeDeleted); diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java index eec4b70880a5..d6e87aab35fe 100644 --- a/services/core/java/com/android/server/pm/ShortcutPackage.java +++ b/services/core/java/com/android/server/pm/ShortcutPackage.java @@ -674,9 +674,10 @@ class ShortcutPackage extends ShortcutPackageItem { return new ArrayList<>(); } - // Get the list of all dynamic shortcuts in this package + // Get the list of all dynamic shortcuts in this package. final ArrayList<ShortcutInfo> shortcuts = new ArrayList<>(); - findAll(shortcuts, ShortcutInfo::isDynamicVisible, ShortcutInfo.CLONE_REMOVE_FOR_LAUNCHER); + findAll(shortcuts, ShortcutInfo::isDynamicVisible, + ShortcutInfo.CLONE_REMOVE_FOR_APP_PREDICTION); final List<ShortcutManager.ShareShortcutInfo> result = new ArrayList<>(); for (int i = 0; i < shortcuts.size(); i++) { diff --git a/services/core/java/com/android/server/telecom/TelecomLoaderService.java b/services/core/java/com/android/server/telecom/TelecomLoaderService.java index e65eae0ab156..54369ca5c367 100644 --- a/services/core/java/com/android/server/telecom/TelecomLoaderService.java +++ b/services/core/java/com/android/server/telecom/TelecomLoaderService.java @@ -16,21 +16,17 @@ package com.android.server.telecom; +import android.app.role.RoleManager; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; -import android.database.ContentObserver; -import android.net.Uri; -import android.os.Handler; import android.os.IBinder; -import android.os.Looper; import android.os.RemoteException; import android.os.ServiceManager; import android.os.UserHandle; -import android.provider.Settings; import android.telecom.DefaultDialerManager; import android.telecom.PhoneAccountHandle; import android.telecom.TelecomManager; @@ -221,19 +217,10 @@ public class TelecomLoaderService extends SystemService { private void registerDefaultAppNotifier() { final DefaultPermissionGrantPolicy permissionPolicy = getDefaultPermissionGrantPolicy(); // Notify the package manager on default app changes - final Uri defaultDialerAppUri = Settings.Secure.getUriFor( - Settings.Secure.DIALER_DEFAULT_APPLICATION); - ContentObserver contentObserver = new ContentObserver( - new Handler(Looper.getMainLooper())) { - @Override - public void onChange(boolean selfChange, Uri uri, int userId) { - if (defaultDialerAppUri.equals(uri)) { - updateSimCallManagerPermissions(permissionPolicy, userId); - } - } - }; - mContext.getContentResolver().registerContentObserver(defaultDialerAppUri, - false, contentObserver, UserHandle.USER_ALL); + final RoleManager roleManager = mContext.getSystemService(RoleManager.class); + roleManager.addOnRoleHoldersChangedListenerAsUser(mContext.getMainExecutor(), + (roleName, user) -> updateSimCallManagerPermissions(permissionPolicy, + user.getIdentifier()), UserHandle.ALL); } diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java index 3a390536b438..a2eb40b0c6fa 100644 --- a/services/core/java/com/android/server/trust/TrustManagerService.java +++ b/services/core/java/com/android/server/trust/TrustManagerService.java @@ -518,8 +518,11 @@ public class TrustManagerService extends SystemService { agentInfo = mActiveAgents.valueAt(index); } - boolean directUnlock = resolveInfo.serviceInfo.directBootAware - && agentInfo.settings.canUnlockProfile; + boolean directUnlock = false; + if (agentInfo.settings != null) { + directUnlock = resolveInfo.serviceInfo.directBootAware + && agentInfo.settings.canUnlockProfile; + } if (directUnlock) { if (DEBUG) Slog.d(TAG, "refreshAgentList: trustagent " + name diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java index fa1bcaccd786..fd3678dae0c4 100644 --- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java +++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java @@ -423,9 +423,7 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest { assertEquals(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"), si.getCategories()); assertEquals(null, si.getIntent()); assertEquals(123, si.getRank()); - assertEquals("person", si.getPersons()[0].getName()); - assertEquals("personKey", si.getPersons()[0].getKey()); - assertEquals("personUri", si.getPersons()[0].getUri()); + assertEquals(null, si.getPersons()); assertEquals(1, si.getExtras().getInt("k")); assertEquals(ShortcutInfo.FLAG_PINNED | ShortcutInfo.FLAG_LONG_LIVED, si.getFlags()); @@ -455,6 +453,30 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest { assertEquals(456, si.getIconResourceId()); assertEquals(null, si.getIconResName()); + + si = sorig.clone(ShortcutInfo.CLONE_REMOVE_FOR_APP_PREDICTION); + + assertEquals(mClientContext.getPackageName(), si.getPackage()); + assertEquals("id", si.getId()); + assertEquals(new ComponentName("a", "b"), si.getActivity()); + assertEquals(null, si.getIcon()); + assertEquals("title", si.getTitle()); + assertEquals("text", si.getText()); + assertEquals("dismes", si.getDisabledMessage()); + assertEquals(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"), si.getCategories()); + assertEquals("action", si.getIntent().getAction()); + assertEquals("val", si.getIntent().getStringExtra("key")); + assertEquals(123, si.getRank()); + assertEquals("person", si.getPersons()[0].getName()); + assertEquals("personKey", si.getPersons()[0].getKey()); + assertEquals("personUri", si.getPersons()[0].getUri()); + assertEquals(1, si.getExtras().getInt("k")); + + assertEquals(ShortcutInfo.FLAG_PINNED | ShortcutInfo.FLAG_LONG_LIVED, si.getFlags()); + assertEquals(null, si.getBitmapPath()); + + assertEquals(456, si.getIconResourceId()); + assertEquals(null, si.getIconResName()); } public void testShortcutInfoClone_resId() { diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java index 87f221a18161..e75a30b12f68 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java @@ -22,7 +22,6 @@ import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIB import static android.app.Notification.CATEGORY_CALL; import static android.app.Notification.FLAG_BUBBLE; import static android.app.Notification.FLAG_FOREGROUND_SERVICE; -import static android.app.Notification.FLAG_ONLY_ALERT_ONCE; import static android.app.NotificationManager.EXTRA_BLOCKED_STATE; import static android.app.NotificationManager.IMPORTANCE_DEFAULT; import static android.app.NotificationManager.IMPORTANCE_HIGH; @@ -1660,11 +1659,14 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(), eq(channel2.getId()), anyBoolean())) .thenReturn(channel2); + when(mPreferencesHelper.createNotificationChannel(eq(PKG), anyInt(), + eq(channel2), anyBoolean(), anyBoolean())) + .thenReturn(true); reset(mListeners); mBinderService.createNotificationChannels(PKG, new ParceledListSlice(Arrays.asList(mTestNotificationChannel, channel2))); - verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG), + verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG), eq(Process.myUserHandle()), eq(mTestNotificationChannel), eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED)); verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG), @@ -4963,13 +4965,10 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), false); waitForIdle(); - // Make sure we are not a bubble / reported as such to listeners - ArgumentCaptor<NotificationRecord> captor = - ArgumentCaptor.forClass(NotificationRecord.class); - verify(mListeners, times(1)).notifyPostedLocked(captor.capture(), any()); - - assertEquals((captor.getValue().getNotification().flags & FLAG_BUBBLE), 0); - assertTrue((captor.getValue().getNotification().flags & FLAG_ONLY_ALERT_ONCE) != 0); + // Make sure we are not a bubble + StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG); + assertEquals(1, notifsAfter.length); + assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0); } @Test @@ -5000,13 +4999,10 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), true); waitForIdle(); - // Make sure we are a bubble / reported as such to listeners - ArgumentCaptor<NotificationRecord> captor = - ArgumentCaptor.forClass(NotificationRecord.class); - verify(mListeners, times(1)).notifyPostedLocked(captor.capture(), any()); - - assertTrue((captor.getValue().getNotification().flags & FLAG_BUBBLE) != 0); - assertTrue((captor.getValue().getNotification().flags & FLAG_ONLY_ALERT_ONCE) != 0); + // Make sure we are a bubble + StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG); + assertEquals(1, notifsAfter.length); + assertTrue((notifsAfter[0].getNotification().flags & FLAG_BUBBLE) != 0); } @Test @@ -5037,7 +5033,6 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG); assertEquals(1, notifsAfter.length); assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0); - verify(mListeners, times(0)).notifyPostedLocked(any(), any()); } @Test diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java index a0660c493605..8f8b746b59d4 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java @@ -262,13 +262,13 @@ public class PreferencesHelperTest extends UiServiceTestCase { int uid0 = 1001; setUpPackageWithUid(package0, uid0); NotificationChannel channel0 = new NotificationChannel("id0", "name0", IMPORTANCE_HIGH); - mHelper.createNotificationChannel(package0, uid0, channel0, true, false); + assertTrue(mHelper.createNotificationChannel(package0, uid0, channel0, true, false)); String package10 = "test.package.user10"; int uid10 = 1001001; setUpPackageWithUid(package10, uid10); NotificationChannel channel10 = new NotificationChannel("id10", "name10", IMPORTANCE_HIGH); - mHelper.createNotificationChannel(package10, uid10, channel10, true, false); + assertTrue(mHelper.createNotificationChannel(package10, uid10, channel10, true, false)); ByteArrayOutputStream baos = writeXmlAndPurge(package10, uid10, true, 10); @@ -293,7 +293,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { int uid0 = 1001; setUpPackageWithUid(package0, uid0); NotificationChannel channel0 = new NotificationChannel("id0", "name0", IMPORTANCE_HIGH); - mHelper.createNotificationChannel(package0, uid0, channel0, true, false); + assertTrue(mHelper.createNotificationChannel(package0, uid0, channel0, true, false)); ByteArrayOutputStream baos = writeXmlAndPurge(package0, uid0, true, 0); @@ -334,8 +334,8 @@ public class PreferencesHelperTest extends UiServiceTestCase { mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg, true); mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg2, true); - mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1, true, false); - mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2, false, false); + assertTrue(mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1, true, false)); + assertTrue(mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2, false, false)); mHelper.setShowBadge(PKG_N_MR1, UID_N_MR1, true); mHelper.setAppImportanceLocked(PKG_N_MR1, UID_N_MR1); @@ -716,8 +716,8 @@ public class PreferencesHelperTest extends UiServiceTestCase { public void testCreateChannel_blocked() throws Exception { mHelper.setImportance(PKG_N_MR1, UID_N_MR1, IMPORTANCE_NONE); - mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, - new NotificationChannel("bananas", "bananas", IMPORTANCE_LOW), true, false); + assertTrue(mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, + new NotificationChannel("bananas", "bananas", IMPORTANCE_LOW), true, false)); } @Test @@ -746,10 +746,10 @@ public class PreferencesHelperTest extends UiServiceTestCase { } catch (IllegalArgumentException e) { // yay } - mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, - new NotificationChannel("bananas", "bananas", IMPORTANCE_NONE), true, false); - mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, - new NotificationChannel("bananas", "bananas", IMPORTANCE_MAX), true, false); + assertTrue(mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, + new NotificationChannel("bananas", "bananas", IMPORTANCE_NONE), true, false)); + assertFalse(mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, + new NotificationChannel("bananas", "bananas", IMPORTANCE_MAX), true, false)); } @@ -763,7 +763,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { channel.setBypassDnd(true); channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET); - mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, false, false); + assertTrue(mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, false, false)); // same id, try to update all fields final NotificationChannel channel2 = @@ -776,7 +776,8 @@ public class PreferencesHelperTest extends UiServiceTestCase { mHelper.updateNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2, true); // all fields should be changed - assertEquals(channel2, mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel.getId(), false)); + assertEquals(channel2, + mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel.getId(), false)); verify(mHandler, times(1)).requestSort(); } @@ -894,7 +895,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { } channel.lockFields(lockMask); - mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false); + assertTrue(mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false)); NotificationChannel savedChannel = mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel.getId(), false); @@ -1469,13 +1470,18 @@ public class PreferencesHelperTest extends UiServiceTestCase { new NotificationChannel("id2", "name2", IMPORTANCE_LOW); channel.setVibrationPattern(vibration); - mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false); + assertTrue(mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false)); NotificationChannel newChannel = new NotificationChannel( channel.getId(), channel.getName(), NotificationManager.IMPORTANCE_HIGH); newChannel.setVibrationPattern(new long[]{100}); + newChannel.setAllowBubbles(!channel.canBubble()); + newChannel.setLightColor(Color.BLUE); + newChannel.setSound(Uri.EMPTY, null); + newChannel.setShowBadge(!channel.canShowBadge()); - mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, newChannel, true, false); + assertFalse(mHelper.createNotificationChannel( + PKG_N_MR1, UID_N_MR1, newChannel, true, false)); // Old settings not overridden compareChannels(channel, @@ -1588,16 +1594,17 @@ public class PreferencesHelperTest extends UiServiceTestCase { new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1, true, false); - mHelper.onPackagesChanged(true, UserHandle.USER_SYSTEM, new String[]{PKG_N_MR1}, new int[]{ - UID_N_MR1}); + assertTrue(mHelper.onPackagesChanged(true, UserHandle.USER_SYSTEM, new String[]{PKG_N_MR1}, + new int[]{UID_N_MR1})); - assertEquals(0, mHelper.getNotificationChannels(PKG_N_MR1, UID_N_MR1, true).getList().size()); + assertEquals(0, mHelper.getNotificationChannels( + PKG_N_MR1, UID_N_MR1, true).getList().size()); // Not deleted mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1, true, false); - mHelper.onPackagesChanged(false, UserHandle.USER_SYSTEM, new String[]{PKG_N_MR1}, new int[]{ - UID_N_MR1}); + assertFalse(mHelper.onPackagesChanged(false, UserHandle.USER_SYSTEM, + new String[]{PKG_N_MR1}, new int[]{UID_N_MR1})); assertEquals(2, mHelper.getNotificationChannels(PKG_N_MR1, UID_N_MR1, false).getList().size()); } @@ -1825,13 +1832,13 @@ public class PreferencesHelperTest extends UiServiceTestCase { @Test public void testCreateChannel_updateName() { NotificationChannel nc = new NotificationChannel("id", "hello", IMPORTANCE_DEFAULT); - mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, nc, true, false); + assertTrue(mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, nc, true, false)); NotificationChannel actual = mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, "id", false); assertEquals("hello", actual.getName()); nc = new NotificationChannel("id", "goodbye", IMPORTANCE_HIGH); - mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, nc, true, false); + assertTrue(mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, nc, true, false)); actual = mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, "id", false); assertEquals("goodbye", actual.getName()); @@ -1845,14 +1852,14 @@ public class PreferencesHelperTest extends UiServiceTestCase { NotificationChannelGroup group = new NotificationChannelGroup("group", ""); mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, group, true); NotificationChannel nc = new NotificationChannel("id", "hello", IMPORTANCE_DEFAULT); - mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, nc, true, false); + assertTrue(mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, nc, true, false)); NotificationChannel actual = mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, "id", false); assertNull(actual.getGroup()); nc = new NotificationChannel("id", "hello", IMPORTANCE_HIGH); nc.setGroup(group.getId()); - mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, nc, true, false); + assertTrue(mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, nc, true, false)); actual = mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, "id", false); assertNotNull(actual.getGroup()); @@ -2109,7 +2116,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { NotificationChannel update = new NotificationChannel("A", "a", IMPORTANCE_LOW); update.setBypassDnd(true); - mHelper.createNotificationChannel(SYSTEM_PKG, SYSTEM_UID, update, true, false); + assertFalse(mHelper.createNotificationChannel(SYSTEM_PKG, SYSTEM_UID, update, true, false)); assertFalse(mHelper.getNotificationChannel(SYSTEM_PKG, SYSTEM_UID, "A", false) .canBypassDnd()); @@ -2122,7 +2129,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { NotificationChannel update = new NotificationChannel("A", "a", IMPORTANCE_LOW); update.setBypassDnd(true); - mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, update, true, true); + assertTrue(mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, update, true, true)); assertTrue(mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, "A", false).canBypassDnd()); } diff --git a/services/usb/java/com/android/server/usb/UsbSerialReader.java b/services/usb/java/com/android/server/usb/UsbSerialReader.java index 32fc796e7e05..8ca77f0c63dc 100644 --- a/services/usb/java/com/android/server/usb/UsbSerialReader.java +++ b/services/usb/java/com/android/server/usb/UsbSerialReader.java @@ -85,22 +85,22 @@ class UsbSerialReader extends IUsbSerialReader.Stub { throw new RemoteException("package " + packageName + " cannot be found"); } packageTargetSdkVersion = pkg.applicationInfo.targetSdkVersion; - } finally { - Binder.restoreCallingIdentity(token); - } - if (packageTargetSdkVersion >= Build.VERSION_CODES.Q) { - if (mContext.checkPermission(android.Manifest.permission.MANAGE_USB, pid, uid) - == PackageManager.PERMISSION_DENIED) { - UsbUserSettingsManager settings = mSettingsManager.getSettingsForUser( - UserHandle.getUserId(uid)); + if (packageTargetSdkVersion >= Build.VERSION_CODES.Q) { + if (mContext.checkPermission(android.Manifest.permission.MANAGE_USB, pid, uid) + == PackageManager.PERMISSION_DENIED) { + UsbUserSettingsManager settings = mSettingsManager.getSettingsForUser( + UserHandle.getUserId(uid)); - if (mDevice instanceof UsbDevice) { - settings.checkPermission((UsbDevice) mDevice, packageName, uid); - } else { - settings.checkPermission((UsbAccessory) mDevice, uid); + if (mDevice instanceof UsbDevice) { + settings.checkPermission((UsbDevice) mDevice, packageName, uid); + } else { + settings.checkPermission((UsbAccessory) mDevice, uid); + } } } + } finally { + Binder.restoreCallingIdentity(token); } } diff --git a/telephony/java/android/telephony/emergency/EmergencyNumber.java b/telephony/java/android/telephony/emergency/EmergencyNumber.java index 7b5145740b08..511adf6ad65b 100644 --- a/telephony/java/android/telephony/emergency/EmergencyNumber.java +++ b/telephony/java/android/telephony/emergency/EmergencyNumber.java @@ -299,7 +299,7 @@ public final class EmergencyNumber implements Parcelable, Comparable<EmergencyNu * Get the dialing number of the emergency number. * * The character in the number string is only the dial pad - * character('0'-'9', '*', or '#'). For example: 911. + * character('0'-'9', '*', '+', or '#'). For example: 911. * * @return the dialing number. */ |