diff options
49 files changed, 661 insertions, 220 deletions
diff --git a/api/system-current.txt b/api/system-current.txt index 6112b545e1e4..4bf1d6bad600 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -33595,6 +33595,7 @@ package android.os { field public static final java.lang.String ACTION_UPDATE_INTENT_FIREWALL = "android.intent.action.UPDATE_INTENT_FIREWALL"; field public static final java.lang.String ACTION_UPDATE_PINS = "android.intent.action.UPDATE_PINS"; field public static final java.lang.String ACTION_UPDATE_SMS_SHORT_CODES = "android.intent.action.UPDATE_SMS_SHORT_CODES"; + field public static final java.lang.String ACTION_UPDATE_TZDATA = "android.intent.action.UPDATE_TZDATA"; } public abstract class CountDownTimer { @@ -35609,8 +35610,23 @@ package android.print { } public final class PrintManager { + method public void addPrintServiceRecommendationsChangeListener(android.print.PrintManager.PrintServiceRecommendationsChangeListener, android.os.Handler); + method public void addPrintServicesChangeListener(android.print.PrintManager.PrintServicesChangeListener, android.os.Handler); method public java.util.List<android.print.PrintJob> getPrintJobs(); + method public java.util.List<android.printservice.recommendation.RecommendationInfo> getPrintServiceRecommendations(); + method public java.util.List<android.printservice.PrintServiceInfo> getPrintServices(int); method public android.print.PrintJob print(java.lang.String, android.print.PrintDocumentAdapter, android.print.PrintAttributes); + method public void removePrintServiceRecommendationsChangeListener(android.print.PrintManager.PrintServiceRecommendationsChangeListener); + method public void removePrintServicesChangeListener(android.print.PrintManager.PrintServicesChangeListener); + field public static final int ENABLED_SERVICES = 1; // 0x1 + } + + public static abstract interface PrintManager.PrintServiceRecommendationsChangeListener { + method public abstract void onPrintServiceRecommendationsChanged(); + } + + public static abstract interface PrintManager.PrintServicesChangeListener { + method public abstract void onPrintServicesChanged(); } public final class PrinterCapabilitiesInfo implements android.os.Parcelable { @@ -35739,6 +35755,13 @@ package android.printservice { field public static final java.lang.String SERVICE_META_DATA = "android.printservice"; } + public final class PrintServiceInfo implements android.os.Parcelable { + method public int describeContents(); + method public android.content.ComponentName getComponentName(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.printservice.PrintServiceInfo> CREATOR; + } + public abstract class PrinterDiscoverySession { ctor public PrinterDiscoverySession(); method public final void addPrinters(java.util.List<android.print.PrinterInfo>); @@ -35761,8 +35784,10 @@ package android.printservice { package android.printservice.recommendation { public final class RecommendationInfo implements android.os.Parcelable { - ctor public RecommendationInfo(java.lang.CharSequence, java.lang.CharSequence, int, boolean); + ctor public RecommendationInfo(java.lang.CharSequence, java.lang.CharSequence, java.util.List<java.net.InetAddress>, boolean); + ctor public deprecated RecommendationInfo(java.lang.CharSequence, java.lang.CharSequence, int, boolean); method public int describeContents(); + method public java.util.List<java.net.InetAddress> getDiscoveredPrinters(); method public java.lang.CharSequence getName(); method public int getNumDiscoveredPrinters(); method public java.lang.CharSequence getPackageName(); @@ -52944,6 +52969,7 @@ package android.webkit { method public abstract boolean onKeyMultiple(int, int, android.view.KeyEvent); method public abstract boolean onKeyUp(int, android.view.KeyEvent); method public abstract void onMeasure(int, int); + method public default void onMovedToDisplay(int, android.content.res.Configuration); method public abstract void onOverScrolled(int, int, boolean, boolean); method public default void onProvideAutofillVirtualStructure(android.view.ViewStructure, int); method public abstract void onProvideVirtualStructure(android.view.ViewStructure); diff --git a/core/java/android/os/ConfigUpdate.java b/core/java/android/os/ConfigUpdate.java index 304ee292182d..793a90e1ece7 100644 --- a/core/java/android/os/ConfigUpdate.java +++ b/core/java/android/os/ConfigUpdate.java @@ -67,6 +67,13 @@ public final class ConfigUpdate { public static final String ACTION_UPDATE_CT_LOGS = "android.intent.action.UPDATE_CT_LOGS"; + /** + * Update system wide timezone data. + * @hide + */ + @SystemApi + public static final String ACTION_UPDATE_TZDATA = "android.intent.action.UPDATE_TZDATA"; + private ConfigUpdate() { } } diff --git a/core/java/android/os/RemoteCallbackList.java b/core/java/android/os/RemoteCallbackList.java index 6656b00d457c..2281fb6d5cc2 100644 --- a/core/java/android/os/RemoteCallbackList.java +++ b/core/java/android/os/RemoteCallbackList.java @@ -17,6 +17,7 @@ package android.os; import android.util.ArrayMap; +import android.util.Slog; import java.util.function.Consumer; @@ -49,16 +50,19 @@ import java.util.function.Consumer; * implements the {@link #onCallbackDied} method. */ public class RemoteCallbackList<E extends IInterface> { + private static final String TAG = "RemoteCallbackList"; + /*package*/ ArrayMap<IBinder, Callback> mCallbacks = new ArrayMap<IBinder, Callback>(); private Object[] mActiveBroadcast; private int mBroadcastCount = -1; private boolean mKilled = false; + private StringBuilder mRecentCallers; private final class Callback implements IBinder.DeathRecipient { final E mCallback; final Object mCookie; - + Callback(E callback, Object cookie) { mCallback = callback; mCookie = cookie; @@ -111,6 +115,8 @@ public class RemoteCallbackList<E extends IInterface> { if (mKilled) { return false; } + // Flag unusual case that could be caused by a leak. b/36778087 + logExcessiveCallbacks(); IBinder binder = callback.asBinder(); try { Callback cb = new Callback(callback, cookie); @@ -392,4 +398,25 @@ public class RemoteCallbackList<E extends IInterface> { return mCallbacks.valueAt(index).mCookie; } } + + private void logExcessiveCallbacks() { + final long size = mCallbacks.size(); + final long TOO_MANY = 3000; + final long MAX_CHARS = 1000; + if (size >= TOO_MANY) { + if (size == TOO_MANY && mRecentCallers == null) { + mRecentCallers = new StringBuilder(); + } + if (mRecentCallers != null && mRecentCallers.length() < MAX_CHARS) { + mRecentCallers.append(Debug.getCallers(5)); + mRecentCallers.append('\n'); + if (mRecentCallers.length() >= MAX_CHARS) { + Slog.wtf(TAG, "More than " + + TOO_MANY + " remote callbacks registered. Recent callers:\n" + + mRecentCallers.toString()); + mRecentCallers = null; + } + } + } + } } diff --git a/core/java/android/print/PrintManager.java b/core/java/android/print/PrintManager.java index 5d0ad5568173..8ee05177f186 100644 --- a/core/java/android/print/PrintManager.java +++ b/core/java/android/print/PrintManager.java @@ -18,6 +18,7 @@ package android.print; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SystemApi; import android.app.Activity; import android.app.Application.ActivityLifecycleCallbacks; import android.content.ComponentName; @@ -43,8 +44,8 @@ import android.util.ArrayMap; import android.util.Log; import com.android.internal.os.SomeArgs; - import com.android.internal.util.Preconditions; + import libcore.io.IoUtils; import java.lang.ref.WeakReference; @@ -115,8 +116,6 @@ public final class PrintManager { private static final boolean DEBUG = false; private static final int MSG_NOTIFY_PRINT_JOB_STATE_CHANGED = 1; - private static final int MSG_NOTIFY_PRINT_SERVICES_CHANGED = 2; - private static final int MSG_NOTIFY_PRINT_SERVICE_RECOMMENDATIONS_CHANGED = 3; /** * Package name of print spooler. @@ -131,6 +130,7 @@ public final class PrintManager { * @see #getPrintServices * @hide */ + @SystemApi public static final int ENABLED_SERVICES = 1 << 0; /** @@ -221,16 +221,26 @@ public final class PrintManager { public void onPrintJobStateChanged(PrintJobId printJobId); } - /** @hide */ + /** + * Listen for changes to {@link #getPrintServices(int)}. + * + * @hide + */ + @SystemApi public interface PrintServicesChangeListener { /** * Callback notifying that the print services changed. */ - public void onPrintServicesChanged(); + void onPrintServicesChanged(); } - /** @hide */ + /** + * Listen for changes to {@link #getPrintServiceRecommendations()}. + * + * @hide + */ + @SystemApi public interface PrintServiceRecommendationsChangeListener { /** @@ -268,22 +278,6 @@ public final class PrintManager { } args.recycle(); } break; - case MSG_NOTIFY_PRINT_SERVICES_CHANGED: { - PrintServicesChangeListenerWrapper wrapper = - (PrintServicesChangeListenerWrapper) message.obj; - PrintServicesChangeListener listener = wrapper.getListener(); - if (listener != null) { - listener.onPrintServicesChanged(); - } - } break; - case MSG_NOTIFY_PRINT_SERVICE_RECOMMENDATIONS_CHANGED: { - PrintServiceRecommendationsChangeListenerWrapper wrapper = - (PrintServiceRecommendationsChangeListenerWrapper) message.obj; - PrintServiceRecommendationsChangeListener listener = wrapper.getListener(); - if (listener != null) { - listener.onPrintServiceRecommendationsChanged(); - } - } break; } } }; @@ -325,8 +319,7 @@ public final class PrintManager { return; } if (mPrintJobStateChangeListeners == null) { - mPrintJobStateChangeListeners = new ArrayMap<PrintJobStateChangeListener, - PrintJobStateChangeListenerWrapper>(); + mPrintJobStateChangeListeners = new ArrayMap<>(); } PrintJobStateChangeListenerWrapper wrappedListener = new PrintJobStateChangeListenerWrapper(listener, mHandler); @@ -399,7 +392,7 @@ public final class PrintManager { * @param printerId the id of the printer the icon should be loaded for * @return the custom icon to be used for the printer or null if the icon is * not yet available - * @see android.print.PrinterInfo.Builder#setHasCustomPrinterIcon() + * @see android.print.PrinterInfo.Builder#setHasCustomPrinterIcon(boolean) * @hide */ public Icon getCustomPrinterIcon(PrinterId printerId) { @@ -558,12 +551,21 @@ public final class PrintManager { * Listen for changes to the installed and enabled print services. * * @param listener the listener to add + * @param handler the handler the listener is called back on * * @see android.print.PrintManager#getPrintServices + * + * @hide */ - void addPrintServicesChangeListener(@NonNull PrintServicesChangeListener listener) { + @SystemApi + public void addPrintServicesChangeListener(@NonNull PrintServicesChangeListener listener, + @Nullable Handler handler) { Preconditions.checkNotNull(listener); + if (handler == null) { + handler = mHandler; + } + if (mService == null) { Log.w(LOG_TAG, "Feature android.software.print not available"); return; @@ -572,7 +574,7 @@ public final class PrintManager { mPrintServicesChangeListeners = new ArrayMap<>(); } PrintServicesChangeListenerWrapper wrappedListener = - new PrintServicesChangeListenerWrapper(listener, mHandler); + new PrintServicesChangeListenerWrapper(listener, handler); try { mService.addPrintServicesChangeListener(wrappedListener, mUserId); mPrintServicesChangeListeners.put(listener, wrappedListener); @@ -587,8 +589,11 @@ public final class PrintManager { * @param listener the listener to remove * * @see android.print.PrintManager#getPrintServices + * + * @hide */ - void removePrintServicesChangeListener(@NonNull PrintServicesChangeListener listener) { + @SystemApi + public void removePrintServicesChangeListener(@NonNull PrintServicesChangeListener listener) { Preconditions.checkNotNull(listener); if (mService == null) { @@ -623,11 +628,12 @@ public final class PrintManager { * * @return The print service list or an empty list. * - * @see #addPrintServicesChangeListener(PrintServicesChangeListener) + * @see #addPrintServicesChangeListener(PrintServicesChangeListener, Handler) * @see #removePrintServicesChangeListener(PrintServicesChangeListener) * * @hide */ + @SystemApi public @NonNull List<PrintServiceInfo> getPrintServices(int selectionFlags) { Preconditions.checkFlagsArgument(selectionFlags, ALL_SERVICES); @@ -646,13 +652,22 @@ public final class PrintManager { * Listen for changes to the print service recommendations. * * @param listener the listener to add + * @param handler the handler the listener is called back on * * @see android.print.PrintManager#getPrintServiceRecommendations + * + * @hide */ - void addPrintServiceRecommendationsChangeListener( - @NonNull PrintServiceRecommendationsChangeListener listener) { + @SystemApi + public void addPrintServiceRecommendationsChangeListener( + @NonNull PrintServiceRecommendationsChangeListener listener, + @Nullable Handler handler) { Preconditions.checkNotNull(listener); + if (handler == null) { + handler = mHandler; + } + if (mService == null) { Log.w(LOG_TAG, "Feature android.software.print not available"); return; @@ -661,7 +676,7 @@ public final class PrintManager { mPrintServiceRecommendationsChangeListeners = new ArrayMap<>(); } PrintServiceRecommendationsChangeListenerWrapper wrappedListener = - new PrintServiceRecommendationsChangeListenerWrapper(listener, mHandler); + new PrintServiceRecommendationsChangeListenerWrapper(listener, handler); try { mService.addPrintServiceRecommendationsChangeListener(wrappedListener, mUserId); mPrintServiceRecommendationsChangeListeners.put(listener, wrappedListener); @@ -676,8 +691,11 @@ public final class PrintManager { * @param listener the listener to remove * * @see android.print.PrintManager#getPrintServiceRecommendations + * + * @hide */ - void removePrintServiceRecommendationsChangeListener( + @SystemApi + public void removePrintServiceRecommendationsChangeListener( @NonNull PrintServiceRecommendationsChangeListener listener) { Preconditions.checkNotNull(listener); @@ -715,6 +733,7 @@ public final class PrintManager { * * @hide */ + @SystemApi public @NonNull List<RecommendationInfo> getPrintServiceRecommendations() { try { List<RecommendationInfo> recommendations = @@ -1349,17 +1368,13 @@ public final class PrintManager { Handler handler = mWeakHandler.get(); PrintServicesChangeListener listener = mWeakListener.get(); if (handler != null && listener != null) { - handler.obtainMessage(MSG_NOTIFY_PRINT_SERVICES_CHANGED, this).sendToTarget(); + handler.post(listener::onPrintServicesChanged); } } public void destroy() { mWeakListener.clear(); } - - public PrintServicesChangeListener getListener() { - return mWeakListener.get(); - } } /** @@ -1381,17 +1396,12 @@ public final class PrintManager { Handler handler = mWeakHandler.get(); PrintServiceRecommendationsChangeListener listener = mWeakListener.get(); if (handler != null && listener != null) { - handler.obtainMessage(MSG_NOTIFY_PRINT_SERVICE_RECOMMENDATIONS_CHANGED, - this).sendToTarget(); + handler.post(listener::onPrintServiceRecommendationsChanged); } } public void destroy() { mWeakListener.clear(); } - - public PrintServiceRecommendationsChangeListener getListener() { - return mWeakListener.get(); - } } } diff --git a/core/java/android/print/PrintServiceRecommendationsLoader.java b/core/java/android/print/PrintServiceRecommendationsLoader.java index c6a4d5103a47..dbd219750758 100644 --- a/core/java/android/print/PrintServiceRecommendationsLoader.java +++ b/core/java/android/print/PrintServiceRecommendationsLoader.java @@ -22,6 +22,7 @@ import android.content.Loader; import android.os.Handler; import android.os.Message; import android.printservice.recommendation.RecommendationInfo; + import com.android.internal.util.Preconditions; import java.util.List; @@ -77,7 +78,7 @@ public class PrintServiceRecommendationsLoader extends Loader<List<Recommendatio } }; - mPrintManager.addPrintServiceRecommendationsChangeListener(mListener); + mPrintManager.addPrintServiceRecommendationsChangeListener(mListener, null); // Immediately deliver a result deliverResult(mPrintManager.getPrintServiceRecommendations()); diff --git a/core/java/android/print/PrintServicesLoader.java b/core/java/android/print/PrintServicesLoader.java index 4c9a69ab5e97..f686a6d8ef5a 100644 --- a/core/java/android/print/PrintServicesLoader.java +++ b/core/java/android/print/PrintServicesLoader.java @@ -22,6 +22,7 @@ import android.content.Loader; import android.os.Handler; import android.os.Message; import android.printservice.PrintServiceInfo; + import com.android.internal.util.Preconditions; import java.util.List; @@ -82,7 +83,7 @@ public class PrintServicesLoader extends Loader<List<PrintServiceInfo>> { } }; - mPrintManager.addPrintServicesChangeListener(mListener); + mPrintManager.addPrintServicesChangeListener(mListener, null); // Immediately deliver a result deliverResult(mPrintManager.getPrintServices(mSelectionFlags)); diff --git a/core/java/android/printservice/PrintServiceInfo.java b/core/java/android/printservice/PrintServiceInfo.java index 45e3d47c39de..57f122923c69 100644 --- a/core/java/android/printservice/PrintServiceInfo.java +++ b/core/java/android/printservice/PrintServiceInfo.java @@ -17,6 +17,7 @@ package android.printservice; import android.annotation.NonNull; +import android.annotation.SystemApi; import android.content.ComponentName; import android.content.Context; import android.content.pm.PackageManager; @@ -47,6 +48,7 @@ import java.io.IOException; * * @hide */ +@SystemApi public final class PrintServiceInfo implements Parcelable { private static final String LOG_TAG = PrintServiceInfo.class.getSimpleName(); @@ -86,6 +88,8 @@ public final class PrintServiceInfo implements Parcelable { * @param settingsActivityName Optional settings activity name. * @param addPrintersActivityName Optional add printers activity name. * @param advancedPrintOptionsActivityName Optional advanced print options activity. + * + * @hide */ public PrintServiceInfo(ResolveInfo resolveInfo, String settingsActivityName, String addPrintersActivityName, String advancedPrintOptionsActivityName) { @@ -110,11 +114,13 @@ public final class PrintServiceInfo implements Parcelable { /** * Creates a new instance. * - * @param resolveInfo The service resolve info. * @param context Context for accessing resources. + * @param resolveInfo The service resolve info. * @return The created instance. + * + * @hide */ - public static PrintServiceInfo create(ResolveInfo resolveInfo, Context context) { + public static PrintServiceInfo create(Context context, ResolveInfo resolveInfo) { String settingsActivityName = null; String addPrintersActivityName = null; String advancedPrintOptionsActivityName = null; @@ -177,6 +183,8 @@ public final class PrintServiceInfo implements Parcelable { * </p> * * @return The id. + * + * @hide */ public String getId() { return mId; @@ -186,6 +194,8 @@ public final class PrintServiceInfo implements Parcelable { * If the service was enabled when it was read from the system. * * @return The id. + * + * @hide */ public boolean isEnabled() { return mIsEnabled; @@ -195,6 +205,8 @@ public final class PrintServiceInfo implements Parcelable { * Mark a service as enabled or not * * @param isEnabled If the service should be marked as enabled. + * + * @hide */ public void setIsEnabled(boolean isEnabled) { mIsEnabled = isEnabled; @@ -204,6 +216,8 @@ public final class PrintServiceInfo implements Parcelable { * The service {@link ResolveInfo}. * * @return The info. + * + * @hide */ public ResolveInfo getResolveInfo() { return mResolveInfo; @@ -217,6 +231,8 @@ public final class PrintServiceInfo implements Parcelable { * </p> * * @return The settings activity name. + * + * @hide */ public String getSettingsActivityName() { return mSettingsActivityName; @@ -230,6 +246,8 @@ public final class PrintServiceInfo implements Parcelable { * </p> * * @return The add printers activity name. + * + * @hide */ public String getAddPrintersActivityName() { return mAddPrintersActivityName; @@ -243,6 +261,8 @@ public final class PrintServiceInfo implements Parcelable { * </p> * * @return The advanced print options activity name. + * + * @hide */ public String getAdvancedOptionsActivityName() { return mAdvancedPrintOptionsActivityName; diff --git a/core/java/android/printservice/recommendation/RecommendationInfo.java b/core/java/android/printservice/recommendation/RecommendationInfo.java index 65d534e45e1c..a32795631227 100644 --- a/core/java/android/printservice/recommendation/RecommendationInfo.java +++ b/core/java/android/printservice/recommendation/RecommendationInfo.java @@ -22,8 +22,14 @@ import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; import android.printservice.PrintService; + import com.android.internal.util.Preconditions; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.List; + /** * A recommendation to install a {@link PrintService print service}. * @@ -37,8 +43,8 @@ public final class RecommendationInfo implements Parcelable { /** Display name of the print service. */ private @NonNull final CharSequence mName; - /** Number of printers the print service would discover if installed. */ - private @IntRange(from = 0) final int mNumDiscoveredPrinters; + /** Printers the print service would discover if installed. */ + @NonNull private final List<InetAddress> mDiscoveredPrinters; /** If the service detects printer from multiple vendors. */ private final boolean mRecommendsMultiVendorService; @@ -48,19 +54,63 @@ public final class RecommendationInfo implements Parcelable { * * @param packageName Package name of the print service * @param name Display name of the print service - * @param numDiscoveredPrinters Number of printers the print service would discover if - * installed + * @param discoveredPrinters The {@link InetAddress addresses} of the discovered + * printers. Cannot be null or empty. * @param recommendsMultiVendorService If the service detects printer from multiple vendor */ public RecommendationInfo(@NonNull CharSequence packageName, @NonNull CharSequence name, - @IntRange(from = 0) int numDiscoveredPrinters, boolean recommendsMultiVendorService) { + @NonNull List<InetAddress> discoveredPrinters, boolean recommendsMultiVendorService) { mPackageName = Preconditions.checkStringNotEmpty(packageName); mName = Preconditions.checkStringNotEmpty(name); - mNumDiscoveredPrinters = Preconditions.checkArgumentNonnegative(numDiscoveredPrinters); + mDiscoveredPrinters = Preconditions.checkCollectionElementsNotNull(discoveredPrinters, + "discoveredPrinters"); mRecommendsMultiVendorService = recommendsMultiVendorService; } /** + * Create a new recommendation. + * + * @param packageName Package name of the print service + * @param name Display name of the print service + * @param numDiscoveredPrinters Number of printers the print service would discover if + * installed + * @param recommendsMultiVendorService If the service detects printer from multiple vendor + * + * @deprecated Use {@link RecommendationInfo(String, String, List<InetAddress>, boolean)} + * instead + */ + @Deprecated + public RecommendationInfo(@NonNull CharSequence packageName, @NonNull CharSequence name, + @IntRange(from = 0) int numDiscoveredPrinters, boolean recommendsMultiVendorService) { + throw new IllegalArgumentException("This constructor has been deprecated"); + } + + /** + * Read a list of blobs from the parcel and return it as a list of {@link InetAddress + * addresses}. + * + * @param parcel the parcel to read the blobs from + * + * @return The list of {@link InetAddress addresses} or null if no printers were found. + * + * @see #writeToParcel(Parcel, int) + */ + @NonNull private static ArrayList<InetAddress> readDiscoveredPrinters(@NonNull Parcel parcel) { + int numDiscoveredPrinters = parcel.readInt(); + ArrayList<InetAddress> discoveredPrinters = new ArrayList<>(numDiscoveredPrinters); + + for (int i = 0; i < numDiscoveredPrinters; i++) { + try { + discoveredPrinters.add(InetAddress.getByAddress(parcel.readBlob())); + } catch (UnknownHostException e) { + throw new IllegalArgumentException(e); + } + } + + return discoveredPrinters; + } + + /** * Create a new recommendation from a parcel. * * @param parcel The parcel containing the data @@ -68,7 +118,7 @@ public final class RecommendationInfo implements Parcelable { * @see #CREATOR */ private RecommendationInfo(@NonNull Parcel parcel) { - this(parcel.readCharSequence(), parcel.readCharSequence(), parcel.readInt(), + this(parcel.readCharSequence(), parcel.readCharSequence(), readDiscoveredPrinters(parcel), parcel.readByte() != 0); } @@ -87,10 +137,17 @@ public final class RecommendationInfo implements Parcelable { } /** + * @return The {@link InetAddress address} of the printers the print service would detect. + */ + @NonNull public List<InetAddress> getDiscoveredPrinters() { + return mDiscoveredPrinters; + } + + /** * @return The number of printer the print service would detect. */ public int getNumDiscoveredPrinters() { - return mNumDiscoveredPrinters; + return mDiscoveredPrinters.size(); } /** @@ -109,7 +166,14 @@ public final class RecommendationInfo implements Parcelable { public void writeToParcel(Parcel dest, int flags) { dest.writeCharSequence(mPackageName); dest.writeCharSequence(mName); - dest.writeInt(mNumDiscoveredPrinters); + + int numDiscoveredPrinters = mDiscoveredPrinters.size(); + dest.writeInt(numDiscoveredPrinters); + + for (InetAddress printer : mDiscoveredPrinters) { + dest.writeBlob(printer.getAddress()); + } + dest.writeByte((byte) (mRecommendsMultiVendorService ? 1 : 0)); } diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java index 5e6ace785dc3..41f1df719de2 100644 --- a/core/java/android/view/accessibility/AccessibilityManager.java +++ b/core/java/android/view/accessibility/AccessibilityManager.java @@ -113,7 +113,7 @@ public final class AccessibilityManager { */ @SdkConstant(SdkConstant.SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_CHOOSE_ACCESSIBILITY_BUTTON = - "android.intent.action.CHOOSE_ACCESSIBILITY_BUTTON"; + "com.android.internal.intent.action.CHOOSE_ACCESSIBILITY_BUTTON"; static final Object sInstanceSync = new Object(); diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index 3f72fde73b9d..6213a63e108a 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -2507,6 +2507,11 @@ public class WebView extends AbsoluteLayout } @Override + public void onMovedToDisplay(int displayId, Configuration config) { + mProvider.getViewDelegate().onMovedToDisplay(displayId, config); + } + + @Override public void setLayoutParams(ViewGroup.LayoutParams params) { mProvider.getViewDelegate().setLayoutParams(params); } diff --git a/core/java/android/webkit/WebViewProvider.java b/core/java/android/webkit/WebViewProvider.java index f01b349a746d..820b49accb65 100644 --- a/core/java/android/webkit/WebViewProvider.java +++ b/core/java/android/webkit/WebViewProvider.java @@ -378,6 +378,8 @@ public interface WebViewProvider { public void onDetachedFromWindow(); + public default void onMovedToDisplay(int displayId, Configuration config) {} + public void onVisibilityChanged(View changedView, int visibility); public void onWindowFocusChanged(boolean hasWindowFocus); diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java index b2a2fec879e6..67bce8c59309 100644 --- a/core/java/com/android/internal/os/ZygoteInit.java +++ b/core/java/com/android/internal/os/ZygoteInit.java @@ -548,10 +548,11 @@ public class ZygoteInit { final int dexFlags = 0; final String compilerFilter = "speed"; final String uuid = StorageManager.UUID_PRIVATE_INTERNAL; + final String seInfo = null; try { installd.dexopt(classPathElement, Process.SYSTEM_UID, packageName, instructionSet, dexoptNeeded, outputPath, dexFlags, compilerFilter, - uuid, sharedLibraries); + uuid, sharedLibraries, seInfo); } catch (RemoteException | ServiceSpecificException e) { // Ignore (but log), we need this on the classpath for fallback mode. Log.w(TAG, "Failed compiling classpath element for system server: " diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index cf6f37fc7972..bfb1356a03e3 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -3365,6 +3365,7 @@ </intent-filter> </activity> <activity android:name="com.android.internal.app.AccessibilityButtonChooserActivity" + android:exported="false" android:theme="@style/Theme.DeviceDefault.Resolver" android:finishOnCloseSystemDialogs="true" android:excludeFromRecents="true" @@ -3374,7 +3375,7 @@ android:process=":ui" android:visibleToInstantApps="true"> <intent-filter> - <action android:name="android.intent.action.CHOOSE_ACCESSIBILITY_BUTTON" /> + <action android:name="com.android.internal.intent.action.CHOOSE_ACCESSIBILITY_BUTTON" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity> diff --git a/core/res/res/values-watch/config.xml b/core/res/res/values-watch/config.xml index ac7b236ba981..98dc4cfeaa89 100644 --- a/core/res/res/values-watch/config.xml +++ b/core/res/res/values-watch/config.xml @@ -66,4 +66,8 @@ <!-- The small screens of watch devices makes multi-window support undesireable. --> <bool name="config_supportsMultiWindow">false</bool> <bool name="config_supportsSplitScreenMultiWindow">false</bool> + + <!-- Disable Multi-Display because of small screen space and lack of external display connection + options. --> + <bool name="config_supportsMultiDisplay">false</bool> </resources> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 221e30874367..3dd7ad415baf 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -2651,6 +2651,9 @@ <!-- True if the device supports split screen as a form of multi-window. --> <bool name="config_supportsSplitScreenMultiWindow">true</bool> + <!-- True if the device supports running activities on secondary displays. --> + <bool name="config_supportsMultiDisplay">true</bool> + <!-- True if the device has no home screen. That is a launcher activity where the user can launch other applications from. --> <bool name="config_noHomeScreen">false</bool> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index d0057d45f453..379c376bf2ff 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -313,6 +313,7 @@ <java-symbol type="bool" name="config_freeformWindowManagement" /> <java-symbol type="bool" name="config_supportsMultiWindow" /> <java-symbol type="bool" name="config_supportsSplitScreenMultiWindow" /> + <java-symbol type="bool" name="config_supportsMultiDisplay" /> <java-symbol type="bool" name="config_noHomeScreen" /> <java-symbol type="bool" name="config_guestUserEphemeral" /> <java-symbol type="bool" name="config_localDisplaysMirrorContent" /> diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/PrintServicePlugin.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/PrintServicePlugin.java index d604ef8a49ea..d723d2fd19f7 100644 --- a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/PrintServicePlugin.java +++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/PrintServicePlugin.java @@ -16,10 +16,13 @@ package com.android.printservice.recommendation; -import android.annotation.IntRange; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.StringRes; +import java.net.InetAddress; +import java.util.List; + /** * Interface to be implemented by each print service plugin. * <p/> @@ -35,9 +38,9 @@ public interface PrintServicePlugin { /** * Announce that something changed and the UI for this plugin should be updated. * - * @param numDiscoveredPrinters The number of printers discovered. + * @param discoveredPrinters The printers discovered. */ - void onChanged(@IntRange(from = 0) int numDiscoveredPrinters); + void onChanged(@Nullable List<InetAddress> discoveredPrinters); } /** diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/RecommendationServiceImpl.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/RecommendationServiceImpl.java index d0483962eae3..e18ee90d39d7 100644 --- a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/RecommendationServiceImpl.java +++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/RecommendationServiceImpl.java @@ -17,20 +17,24 @@ package com.android.printservice.recommendation; import android.content.res.Configuration; +import android.printservice.PrintService; import android.printservice.recommendation.RecommendationInfo; import android.printservice.recommendation.RecommendationService; -import android.printservice.PrintService; import android.util.Log; + import com.android.printservice.recommendation.plugin.hp.HPRecommendationPlugin; import com.android.printservice.recommendation.plugin.mdnsFilter.MDNSFilterPlugin; import com.android.printservice.recommendation.plugin.mdnsFilter.VendorConfig; import com.android.printservice.recommendation.plugin.mopria.MopriaRecommendationPlugin; import com.android.printservice.recommendation.plugin.samsung.SamsungRecommendationPlugin; import com.android.printservice.recommendation.plugin.xerox.XeroxPrintServiceRecommendationPlugin; + import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; +import java.net.InetAddress; import java.util.ArrayList; +import java.util.List; /** * Service that recommends {@link PrintService print services} that might be a good idea to install. @@ -129,12 +133,11 @@ public class RecommendationServiceImpl extends RecommendationService RemotePrintServicePlugin plugin = mPlugins.get(i); try { - int numPrinters = plugin.getNumPrinters(); + List<InetAddress> printers = plugin.getPrinters(); - if (numPrinters > 0) { + if (!printers.isEmpty()) { recommendations.add(new RecommendationInfo(plugin.packageName, - getString(plugin.name), numPrinters, - plugin.recommendsMultiVendorService)); + getString(plugin.name), printers, plugin.recommendsMultiVendorService)); } } catch (Exception e) { Log.e(LOG_TAG, "Could not read state of plugin for " + plugin.packageName, e); diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/RemotePrintServicePlugin.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/RemotePrintServicePlugin.java index dbd164946dfb..fd929a7c8233 100644 --- a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/RemotePrintServicePlugin.java +++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/RemotePrintServicePlugin.java @@ -16,11 +16,16 @@ package com.android.printservice.recommendation; -import android.annotation.IntRange; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.StringRes; + import com.android.internal.util.Preconditions; +import java.net.InetAddress; +import java.util.Collections; +import java.util.List; + /** * Wrapper for a {@link PrintServicePlugin}, isolating issues with the plugin as good as possible * from the {@link RecommendationServiceImpl service}. @@ -41,13 +46,13 @@ class RemotePrintServicePlugin implements PrintServicePlugin.PrinterDiscoveryCal /** Wrapped plugin */ private final @NonNull PrintServicePlugin mPlugin; - /** The number of printers discovered by the plugin */ - private @IntRange(from = 0) int mNumPrinters; + /** The printers discovered by the plugin */ + private @NonNull List<InetAddress> mPrinters; /** If the plugin is started by not yet stopped */ private boolean isRunning; - /** Listener for changes to {@link #mNumPrinters}. */ + /** Listener for changes to {@link #mPrinters}. */ private @NonNull OnChangedListener mListener; /** @@ -65,6 +70,8 @@ class RemotePrintServicePlugin implements PrintServicePlugin.PrinterDiscoveryCal throws PluginException { mListener = listener; mPlugin = plugin; + mPrinters = Collections.emptyList(); + this.recommendsMultiVendorService = recommendsMultiVendorService; // We handle any throwable to isolate our self from bugs in the plugin code. @@ -116,26 +123,28 @@ class RemotePrintServicePlugin implements PrintServicePlugin.PrinterDiscoveryCal * * @return The number of printers reported by the stub. */ - public @IntRange(from = 0) int getNumPrinters() { - return mNumPrinters; + public @NonNull List<InetAddress> getPrinters() { + return mPrinters; } @Override - public void onChanged(@IntRange(from = 0) int numDiscoveredPrinters) { + public void onChanged(@Nullable List<InetAddress> discoveredPrinters) { synchronized (mLock) { Preconditions.checkState(isRunning); - mNumPrinters = Preconditions.checkArgumentNonnegative(numDiscoveredPrinters, - "numDiscoveredPrinters"); - - if (mNumPrinters > 0) { - mListener.onChanged(); + if (discoveredPrinters == null) { + mPrinters = Collections.emptyList(); + } else { + mPrinters = Preconditions.checkCollectionElementsNotNull(discoveredPrinters, + "discoveredPrinters"); } + + mListener.onChanged(); } } /** - * Listener to listen for changes to {@link #getNumPrinters} + * Listener to listen for changes to {@link #getPrinters} */ public interface OnChangedListener { void onChanged(); diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/hp/ServiceListener.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/hp/ServiceListener.java index e34247a66fb6..600af1ff6da4 100644 --- a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/hp/ServiceListener.java +++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/hp/ServiceListener.java @@ -21,17 +21,17 @@ import android.content.res.TypedArray; import android.net.nsd.NsdManager; import android.net.nsd.NsdServiceInfo; import android.text.TextUtils; -import android.util.Pair; +import com.android.printservice.recommendation.R; +import com.android.printservice.recommendation.util.DiscoveryListenerMultiplexer; + +import java.net.InetAddress; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; -import com.android.printservice.recommendation.R; -import com.android.printservice.recommendation.util.DiscoveryListenerMultiplexer; - public class ServiceListener implements ServiceResolveQueue.ResolveCallback { private final NsdManager mNSDManager; @@ -176,11 +176,18 @@ public class ServiceListener implements ServiceResolveQueue.ResolveCallback { mListeners.clear(); } - public Pair<Integer, Integer> getCount() { - int count = 0; - for (PrinterHashMap map : mVendorHashMap.values()) { - count += map.size(); + /** + * @return The {@link InetAddress addresses} of the discovered printers + */ + public ArrayList<InetAddress> getPrinters() { + ArrayList<InetAddress> printerAddressess = new ArrayList<>(); + + for (PrinterHashMap oneVendorPrinters : mVendorHashMap.values()) { + for (NsdServiceInfo printer : oneVendorPrinters.values()) { + printerAddressess.add(printer.getHost()); + } } - return Pair.create(mVendorHashMap.size(), count); + + return printerAddressess; } } diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/hp/ServiceRecommendationPlugin.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/hp/ServiceRecommendationPlugin.java index 7ea530dda9d8..4e3bf933a524 100644 --- a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/hp/ServiceRecommendationPlugin.java +++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/hp/ServiceRecommendationPlugin.java @@ -16,13 +16,17 @@ package com.android.printservice.recommendation.plugin.hp; +import android.annotation.NonNull; import android.content.Context; import android.net.nsd.NsdManager; import android.net.nsd.NsdServiceInfo; -import android.annotation.NonNull; import android.text.TextUtils; + import com.android.printservice.recommendation.PrintServicePlugin; +import java.net.InetAddress; +import java.util.ArrayList; + public abstract class ServiceRecommendationPlugin implements PrintServicePlugin, ServiceListener.Observer { protected static final String PDL_ATTRIBUTE = "pdl"; @@ -71,7 +75,7 @@ public abstract class ServiceRecommendationPlugin implements PrintServicePlugin, @Override public void dataSetChanged() { synchronized (mLock) { - if (mCallback != null) mCallback.onChanged(getCount()); + if (mCallback != null) mCallback.onChanged(getPrinters()); } } @@ -80,7 +84,7 @@ public abstract class ServiceRecommendationPlugin implements PrintServicePlugin, return TextUtils.equals(vendor, mVendorInfo.mVendorID); } - public int getCount() { - return mListener.getCount().second; + public ArrayList<InetAddress> getPrinters() { + return mListener.getPrinters(); } } diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/mopria/MopriaRecommendationPlugin.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/mopria/MopriaRecommendationPlugin.java index 18c9da51865a..a9e1aed0d624 100644 --- a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/mopria/MopriaRecommendationPlugin.java +++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/mopria/MopriaRecommendationPlugin.java @@ -20,12 +20,14 @@ package com.android.printservice.recommendation.plugin.mopria; import android.content.Context; import android.net.nsd.NsdServiceInfo; import android.text.TextUtils; -import android.util.Pair; +import com.android.printservice.recommendation.R; import com.android.printservice.recommendation.plugin.hp.MDnsUtils; import com.android.printservice.recommendation.plugin.hp.ServiceRecommendationPlugin; import com.android.printservice.recommendation.plugin.hp.VendorInfo; -import com.android.printservice.recommendation.R; + +import java.net.InetAddress; +import java.util.ArrayList; public class MopriaRecommendationPlugin extends ServiceRecommendationPlugin { @@ -47,8 +49,7 @@ public class MopriaRecommendationPlugin extends ServiceRecommendationPlugin { } @Override - public int getCount() { - Pair<Integer, Integer> count = mListener.getCount(); - return ((count.first > 1) ? count.second : 0); + public ArrayList<InetAddress> getPrinters() { + return mListener.getPrinters(); } } diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/xerox/ServiceResolver.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/xerox/ServiceResolver.java index f64eed47f785..4d0efd8be23d 100755 --- a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/xerox/ServiceResolver.java +++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/xerox/ServiceResolver.java @@ -19,9 +19,11 @@ import android.content.Context; import android.net.nsd.NsdManager; import android.net.nsd.NsdServiceInfo; import android.text.TextUtils; + import com.android.printservice.recommendation.util.DiscoveryListenerMultiplexer; import com.android.printservice.recommendation.util.NsdResolveQueue; +import java.net.InetAddress; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; @@ -192,8 +194,13 @@ class ServiceResolver { } } - public int getCount() { - return mPrinterHashMap.size(); + public ArrayList<InetAddress> getPrinters() { + ArrayList<InetAddress> printerAddresses = new ArrayList<>(); + for (NsdServiceInfo printer : mPrinterHashMap.values()) { + printerAddresses.add(printer.getHost()); + } + + return printerAddresses; } } diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/xerox/XeroxPrintServiceRecommendationPlugin.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/xerox/XeroxPrintServiceRecommendationPlugin.java index 3fb9ca239716..e0942b7e91a4 100755 --- a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/xerox/XeroxPrintServiceRecommendationPlugin.java +++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/xerox/XeroxPrintServiceRecommendationPlugin.java @@ -15,11 +15,11 @@ */ package com.android.printservice.recommendation.plugin.xerox; +import android.annotation.NonNull; import android.content.Context; import android.net.nsd.NsdManager; -import android.annotation.NonNull; -import com.android.printservice.recommendation.PrintServicePlugin; +import com.android.printservice.recommendation.PrintServicePlugin; import com.android.printservice.recommendation.R; public class XeroxPrintServiceRecommendationPlugin implements PrintServicePlugin, ServiceResolver.Observer { @@ -69,11 +69,9 @@ public class XeroxPrintServiceRecommendationPlugin implements PrintServicePlugin @Override public void dataSetChanged() { synchronized (mLock) { - if (mDiscoveryCallback != null) mDiscoveryCallback.onChanged(getCount()); + if (mDiscoveryCallback != null) { + mDiscoveryCallback.onChanged(mServiceResolver.getPrinters()); + } } } - - public int getCount() { - return mServiceResolver.getCount(); - } } diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/util/MDNSFilteredDiscovery.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/util/MDNSFilteredDiscovery.java index c5dbc8c32e91..87ab2d3fcf22 100644 --- a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/util/MDNSFilteredDiscovery.java +++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/util/MDNSFilteredDiscovery.java @@ -15,17 +15,19 @@ */ package com.android.printservice.recommendation.util; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.content.Context; import android.net.nsd.NsdManager; import android.net.nsd.NsdServiceInfo; -import android.annotation.NonNull; -import android.annotation.Nullable; import android.util.Log; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.Preconditions; import com.android.printservice.recommendation.PrintServicePlugin; +import java.net.InetAddress; +import java.util.ArrayList; import java.util.HashSet; import java.util.Set; @@ -54,7 +56,7 @@ public class MDNSFilteredDiscovery implements NsdManager.DiscoveryListener { /** Printer identifiers of the mPrinters found. */ @GuardedBy("mLock") - private final @NonNull HashSet<String> mPrinters; + private final @NonNull HashSet<InetAddress> mPrinters; /** Service types discovered by this plugin */ private final @NonNull HashSet<String> mServiceTypes; @@ -111,7 +113,7 @@ public class MDNSFilteredDiscovery implements NsdManager.DiscoveryListener { */ public void start(@NonNull PrintServicePlugin.PrinterDiscoveryCallback callback) { mCallback = callback; - mCallback.onChanged(mPrinters.size()); + mCallback.onChanged(new ArrayList<>(mPrinters)); for (String serviceType : mServiceTypes) { DiscoveryListenerMultiplexer.addListener(getNDSManager(), serviceType, this); @@ -122,7 +124,7 @@ public class MDNSFilteredDiscovery implements NsdManager.DiscoveryListener { * Stop the discovery. This can only return once the plugin is completely finished and cleaned up. */ public void stop() { - mCallback.onChanged(0); + mCallback.onChanged(null); mCallback = null; for (int i = 0; i < mServiceTypes.size(); ++i) { @@ -130,14 +132,6 @@ public class MDNSFilteredDiscovery implements NsdManager.DiscoveryListener { } } - /** - * - * @return The number of discovered printers - */ - public int getCount() { - return mPrinters.size(); - } - @Override public void onStartDiscoveryFailed(String serviceType, int errorCode) { Log.w(LOG_TAG, "Failed to start network discovery for type " + serviceType + ": " @@ -174,9 +168,9 @@ public class MDNSFilteredDiscovery implements NsdManager.DiscoveryListener { public void onServiceResolved(NsdServiceInfo serviceInfo) { if (mPrinterFilter.matchesCriteria(serviceInfo)) { if (mCallback != null) { - boolean added = mPrinters.add(serviceInfo.getHost().getHostAddress()); + boolean added = mPrinters.add(serviceInfo.getHost()); if (added) { - mCallback.onChanged(mPrinters.size()); + mCallback.onChanged(new ArrayList<>(mPrinters)); } } } @@ -198,11 +192,10 @@ public class MDNSFilteredDiscovery implements NsdManager.DiscoveryListener { public void onServiceResolved(NsdServiceInfo serviceInfo) { if (mPrinterFilter.matchesCriteria(serviceInfo)) { if (mCallback != null) { - boolean removed = mPrinters - .remove(serviceInfo.getHost().getHostAddress()); + boolean removed = mPrinters.remove(serviceInfo.getHost()); if (removed) { - mCallback.onChanged(mPrinters.size()); + mCallback.onChanged(new ArrayList<>(mPrinters)); } } } diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java index f31c09b104fd..6bcf256a8033 100644 --- a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java +++ b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java @@ -135,10 +135,18 @@ public class TileUtils { * Name of the meta-data item that should be set in the AndroidManifest.xml * to specify the title that should be displayed for the preference. */ + @Deprecated public static final String META_DATA_PREFERENCE_TITLE = "com.android.settings.title"; /** * Name of the meta-data item that should be set in the AndroidManifest.xml + * to specify the title that should be displayed for the preference. + */ + public static final String META_DATA_PREFERENCE_TITLE_RES_ID = + "com.android.settings.title.resid"; + + /** + * Name of the meta-data item that should be set in the AndroidManifest.xml * to specify the summary text that should be displayed for the preference. */ public static final String META_DATA_PREFERENCE_SUMMARY = "com.android.settings.summary"; @@ -364,7 +372,16 @@ public class TileUtils { if (metaData.containsKey(META_DATA_PREFERENCE_ICON)) { icon = metaData.getInt(META_DATA_PREFERENCE_ICON); } - if (metaData.containsKey(META_DATA_PREFERENCE_TITLE)) { + int resId = 0; + if (metaData.containsKey(META_DATA_PREFERENCE_TITLE_RES_ID)) { + resId = metaData.getInt(META_DATA_PREFERENCE_TITLE_RES_ID); + if (resId != 0) { + title = res.getString(resId); + } + } + // Fallback to legacy title extraction if we couldn't get the title through + // res id. + if ((resId == 0) && metaData.containsKey(META_DATA_PREFERENCE_TITLE)) { if (metaData.get(META_DATA_PREFERENCE_TITLE) instanceof Integer) { title = res.getString(metaData.getInt(META_DATA_PREFERENCE_TITLE)); } else { diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java index 2d3c4a786f5c..5310b7a604b0 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java @@ -231,6 +231,51 @@ public class TileUtilsTest { } @Test + public void getTilesForIntent_shouldReadMetadataTitleAsString() throws RemoteException { + Intent intent = new Intent(); + Map<Pair<String, String>, Tile> addedCache = new ArrayMap<>(); + List<Tile> outTiles = new ArrayList<>(); + List<ResolveInfo> info = new ArrayList<>(); + ResolveInfo resolveInfo = newInfo(true, null /* category */, null, URI_GET_ICON, + URI_GET_SUMMARY, "my title", 0); + info.add(resolveInfo); + + when(mPackageManager.queryIntentActivitiesAsUser(eq(intent), anyInt(), anyInt())) + .thenReturn(info); + + TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache, + null /* defaultCategory */, outTiles, false /* usePriority */, + false /* checkCategory */); + + assertThat(outTiles.size()).isEqualTo(1); + assertThat(outTiles.get(0).title).isEqualTo("my title"); + } + + @Test + public void getTilesForIntent_shouldReadMetadataTitleFromResource() throws RemoteException { + Intent intent = new Intent(); + Map<Pair<String, String>, Tile> addedCache = new ArrayMap<>(); + List<Tile> outTiles = new ArrayList<>(); + List<ResolveInfo> info = new ArrayList<>(); + ResolveInfo resolveInfo = newInfo(true, null /* category */, null, URI_GET_ICON, + URI_GET_SUMMARY, null, 123); + info.add(resolveInfo); + + when(mPackageManager.queryIntentActivitiesAsUser(eq(intent), anyInt(), anyInt())) + .thenReturn(info); + + when(mResources.getString(eq(123))) + .thenReturn("my localized title"); + + TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache, + null /* defaultCategory */, outTiles, false /* usePriority */, + false /* checkCategory */); + + assertThat(outTiles.size()).isEqualTo(1); + assertThat(outTiles.get(0).title).isEqualTo("my localized title"); + } + + @Test public void getTilesForIntent_shouldNotProcessInvalidUriContentSystemApp() throws RemoteException { Intent intent = new Intent(); @@ -298,7 +343,13 @@ public class TileUtilsTest { } private static ResolveInfo newInfo(boolean systemApp, String category, String keyHint, - String iconUri, String summaryUri) { + String iconUri, String summaryUri) { + return newInfo(systemApp, category, keyHint, iconUri, summaryUri, null, 0); + } + + private static ResolveInfo newInfo(boolean systemApp, String category, String keyHint, + String iconUri, String summaryUri, String title, int titleResId) { + ResolveInfo info = new ResolveInfo(); info.system = systemApp; info.activityInfo = new ActivityInfo(); @@ -317,6 +368,13 @@ public class TileUtilsTest { if (summaryUri != null) { info.activityInfo.metaData.putString("com.android.settings.summary_uri", summaryUri); } + if (title != null) { + info.activityInfo.metaData.putString(TileUtils.META_DATA_PREFERENCE_TITLE, title); + } + if (titleResId != 0) { + info.activityInfo.metaData.putInt( + TileUtils.META_DATA_PREFERENCE_TITLE_RES_ID, titleResId); + } info.activityInfo.applicationInfo = new ApplicationInfo(); if (systemApp) { info.activityInfo.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM; diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index bf39bc4b96ea..55f32d7d8b43 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -22,6 +22,9 @@ android:sharedUserId="android.uid.systemui" coreApp="true"> + <protected-broadcast android:name="com.android.systemui.action.PLUGIN_CHANGED" /> + + <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> diff --git a/packages/SystemUI/src/com/android/systemui/plugins/PluginInstanceManager.java b/packages/SystemUI/src/com/android/systemui/plugins/PluginInstanceManager.java index 07ac52d718aa..a8daed531357 100644 --- a/packages/SystemUI/src/com/android/systemui/plugins/PluginInstanceManager.java +++ b/packages/SystemUI/src/com/android/systemui/plugins/PluginInstanceManager.java @@ -48,7 +48,7 @@ public class PluginInstanceManager<T extends Plugin> { private static final boolean DEBUG = false; private static final String TAG = "PluginInstanceManager"; - private static final String PLUGIN_PERMISSION = "com.android.systemui.permission.PLUGIN"; + public static final String PLUGIN_PERMISSION = "com.android.systemui.permission.PLUGIN"; private final Context mContext; private final PluginListener<T> mListener; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java index b5d22b1da288..d77796144282 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java @@ -24,6 +24,7 @@ import android.graphics.drawable.Drawable; import android.graphics.drawable.Icon; import android.hardware.input.InputManager; import android.media.AudioManager; +import android.metrics.LogMaker; import android.os.AsyncTask; import android.os.Bundle; import android.os.SystemClock; @@ -41,6 +42,9 @@ import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; import android.widget.ImageView; +import com.android.internal.logging.MetricsLogger; +import com.android.internal.logging.nano.MetricsProto.MetricsEvent; +import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.plugins.statusbar.phone.NavBarButtonProvider.ButtonInterface; @@ -60,6 +64,7 @@ public class KeyButtonView extends ImageView implements ButtonInterface { private boolean mLongClicked; private OnClickListener mOnClickListener; private final KeyButtonRipple mRipple; + private final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class); private final Runnable mCheckLongPress = new Runnable() { public void run() { @@ -252,6 +257,11 @@ public class KeyButtonView extends ImageView implements ButtonInterface { } void sendEvent(int action, int flags, long when) { + mMetricsLogger.write(new LogMaker(MetricsEvent.ACTION_NAV_BUTTON_EVENT) + .setType(MetricsEvent.TYPE_ACTION) + .setSubtype(mCode) + .addTaggedData(MetricsEvent.FIELD_NAV_ACTION, action) + .addTaggedData(MetricsEvent.FIELD_FLAGS, flags)); final int repeatCount = (flags & KeyEvent.FLAG_LONG_PRESS) != 0 ? 1 : 0; final KeyEvent ev = new KeyEvent(mDownTime, when, action, mCode, repeatCount, 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0, diff --git a/packages/SystemUI/src/com/android/systemui/tuner/PluginFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/PluginFragment.java index 266f05372813..f91e45d05e79 100644 --- a/packages/SystemUI/src/com/android/systemui/tuner/PluginFragment.java +++ b/packages/SystemUI/src/com/android/systemui/tuner/PluginFragment.java @@ -19,6 +19,7 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.net.Uri; @@ -26,15 +27,18 @@ import android.os.Bundle; import android.provider.Settings; import android.support.v14.preference.PreferenceFragment; import android.support.v14.preference.SwitchPreference; -import android.support.v7.preference.PreferenceCategory; import android.support.v7.preference.PreferenceScreen; import android.support.v7.preference.PreferenceViewHolder; +import android.util.ArrayMap; +import android.util.ArraySet; import android.view.View; import com.android.systemui.R; +import com.android.systemui.plugins.PluginInstanceManager; import com.android.systemui.plugins.PluginManager; import com.android.systemui.plugins.PluginPrefs; +import java.util.ArrayList; import java.util.List; import java.util.Set; @@ -51,7 +55,6 @@ public class PluginFragment extends PreferenceFragment { IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED); filter.addAction(Intent.ACTION_PACKAGE_CHANGED); filter.addAction(Intent.ACTION_PACKAGE_REMOVED); - filter.addAction(PluginManager.PLUGIN_CHANGED); filter.addDataScheme("package"); getContext().registerReceiver(mReceiver, filter); filter = new IntentFilter(Intent.ACTION_USER_UNLOCKED); @@ -74,24 +77,59 @@ public class PluginFragment extends PreferenceFragment { screen.setOrderingAsAdded(false); Context prefContext = getPreferenceManager().getContext(); mPluginPrefs = new PluginPrefs(getContext()); + PackageManager pm = getContext().getPackageManager(); + Set<String> pluginActions = mPluginPrefs.getPluginList(); + ArrayMap<String, ArraySet<String>> plugins = new ArrayMap<>(); for (String action : pluginActions) { - String name = action.replace("com.android.systemui.action.PLUGIN_", ""); - PreferenceCategory category = new PreferenceCategory(prefContext); - category.setTitle(name); - - List<ResolveInfo> result = getContext().getPackageManager().queryIntentServices( + String name = toName(action); + List<ResolveInfo> result = pm.queryIntentServices( new Intent(action), PackageManager.MATCH_DISABLED_COMPONENTS); - if (result.size() > 0) { - screen.addPreference(category); - } for (ResolveInfo info : result) { - category.addPreference(new PluginPreference(prefContext, info)); + String packageName = info.serviceInfo.packageName; + if (!plugins.containsKey(packageName)) { + plugins.put(packageName, new ArraySet<>()); + } + plugins.get(packageName).add(name); } } + + List<PackageInfo> apps = pm.getPackagesHoldingPermissions(new String[]{ + PluginInstanceManager.PLUGIN_PERMISSION}, + PackageManager.MATCH_DISABLED_COMPONENTS | PackageManager.GET_SERVICES); + apps.forEach(app -> { + if (!plugins.containsKey(app.packageName)) return; + SwitchPreference pref = new PluginPreference(prefContext, app); + pref.setSummary("Plugins: " + toString(plugins.get(app.packageName))); + screen.addPreference(pref); + }); setPreferenceScreen(screen); } + private String toString(ArraySet<String> plugins) { + StringBuilder b = new StringBuilder(); + for (String string : plugins) { + if (b.length() != 0) { + b.append(", "); + } + b.append(string); + } + return b.toString(); + } + + private String toName(String action) { + String str = action.replace("com.android.systemui.action.PLUGIN_", ""); + StringBuilder b = new StringBuilder(); + for (String s : str.split("_")) { + if (b.length() != 0) { + b.append(' '); + } + b.append(s.substring(0, 1)); + b.append(s.substring(1).toLowerCase()); + } + return b.toString(); + } + private final BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -100,31 +138,44 @@ public class PluginFragment extends PreferenceFragment { }; private static class PluginPreference extends SwitchPreference { - private final ComponentName mComponent; private final boolean mHasSettings; + private final PackageInfo mInfo; + private final PackageManager mPm; - public PluginPreference(Context prefContext, ResolveInfo info) { + public PluginPreference(Context prefContext, PackageInfo info) { super(prefContext); - mComponent = new ComponentName(info.serviceInfo.packageName, info.serviceInfo.name); - PackageManager pm = prefContext.getPackageManager(); - mHasSettings = pm.resolveActivity(new Intent(ACTION_PLUGIN_SETTINGS) - .setPackage(mComponent.getPackageName()), 0) != null; - setTitle(info.serviceInfo.loadLabel(pm)); - setChecked(pm.getComponentEnabledSetting(mComponent) - != PackageManager.COMPONENT_ENABLED_STATE_DISABLED); + mPm = prefContext.getPackageManager(); + mHasSettings = mPm.resolveActivity(new Intent(ACTION_PLUGIN_SETTINGS) + .setPackage(info.packageName), 0) != null; + mInfo = info; + setTitle(info.applicationInfo.loadLabel(mPm)); + setChecked(isPluginEnabled()); setWidgetLayoutResource(R.layout.tuner_widget_settings_switch); } + private boolean isPluginEnabled() { + for (int i = 0; i < mInfo.services.length; i++) { + ComponentName componentName = new ComponentName(mInfo.packageName, + mInfo.services[i].name); + if (mPm.getComponentEnabledSetting(componentName) + == PackageManager.COMPONENT_ENABLED_STATE_DISABLED) { + return false; + } + } + return true; + } + @Override protected boolean persistBoolean(boolean value) { - PackageManager pm = getContext().getPackageManager(); final int desiredState = value ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED : PackageManager.COMPONENT_ENABLED_STATE_DISABLED; - if (pm.getComponentEnabledSetting(mComponent) == desiredState) return true; - pm.setComponentEnabledSetting(mComponent, - desiredState, - PackageManager.DONT_KILL_APP); - final String pkg = mComponent.getPackageName(); + for (int i = 0; i < mInfo.services.length; i++) { + ComponentName componentName = new ComponentName(mInfo.packageName, + mInfo.services[i].name); + mPm.setComponentEnabledSetting(componentName, desiredState, + PackageManager.DONT_KILL_APP); + } + final String pkg = mInfo.packageName; final Intent intent = new Intent(PluginManager.PLUGIN_CHANGED, pkg != null ? Uri.fromParts("package", pkg, null) : null); getContext().sendBroadcast(intent); @@ -141,7 +192,7 @@ public class PluginFragment extends PreferenceFragment { holder.findViewById(R.id.settings).setOnClickListener(v -> { ResolveInfo result = v.getContext().getPackageManager().resolveActivity( new Intent(ACTION_PLUGIN_SETTINGS).setPackage( - mComponent.getPackageName()), 0); + mInfo.packageName), 0); if (result != null) { v.getContext().startActivity(new Intent().setComponent( new ComponentName(result.activityInfo.packageName, @@ -150,7 +201,7 @@ public class PluginFragment extends PreferenceFragment { }); holder.itemView.setOnLongClickListener(v -> { Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); - intent.setData(Uri.fromParts("package", mComponent.getPackageName(), null)); + intent.setData(Uri.fromParts("package", mInfo.packageName, null)); getContext().startActivity(intent); return true; }); diff --git a/packages/SystemUI/tests/src/com/android/systemui/plugins/PluginInstanceManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/plugins/PluginInstanceManagerTest.java index 4f0815d0f283..04441abee92e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/plugins/PluginInstanceManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/plugins/PluginInstanceManagerTest.java @@ -273,6 +273,11 @@ public class PluginInstanceManagerTest extends SysuiTestCase { @Override public void unregisterReceiver(BroadcastReceiver receiver) { } + + @Override + public void sendBroadcast(Intent intent) { + // Do nothing. + } } // This target class doesn't matter, it just needs to have a Requires to hit the flow where diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationViewWrapperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationViewWrapperTest.java index 2c49f99c295d..0dad52f2942e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationViewWrapperTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationViewWrapperTest.java @@ -41,7 +41,7 @@ public class NotificationViewWrapperTest { @Ignore("Broken") @Test public void constructor_doesntUseViewContext() throws Exception { - new TestableNotificationViewWrapper(mContext, new View(null /* context */), null /* row */); + new TestableNotificationViewWrapper(mContext, null /* view */, null /* row */); } static class TestableNotificationViewWrapper extends NotificationViewWrapper { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyButtonViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyButtonViewTest.java new file mode 100644 index 000000000000..21fddf2106d4 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyButtonViewTest.java @@ -0,0 +1,91 @@ +/* + * Copyright (C) 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. + */ + +package com.android.systemui.statusbar.policy; + +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_NAV_BUTTON_EVENT; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_FLAGS; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_NAV_ACTION; + +import static org.mockito.ArgumentMatchers.argThat; + +import android.metrics.LogMaker; +import android.testing.AndroidTestingRunner; +import android.testing.TestableLooper; +import android.testing.TestableLooper.RunWithLooper; +import android.view.KeyEvent; + +import com.android.internal.logging.MetricsLogger; +import com.android.internal.logging.nano.MetricsProto.MetricsEvent; +import com.android.systemui.SysuiTestCase; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentMatcher; +import org.mockito.Mockito; + +import java.util.Objects; + +@RunWith(AndroidTestingRunner.class) +@RunWithLooper +public class KeyButtonViewTest extends SysuiTestCase { + + private KeyButtonView mKeyButtonView; + private MetricsLogger mMetricsLogger; + + @Before + public void setup() throws Exception { + mMetricsLogger = mDependency.injectMockDependency(MetricsLogger.class); + TestableLooper.get(this).runWithLooper(() -> + mKeyButtonView = new KeyButtonView(mContext, null)); + } + + @Test + public void testMetrics() { + int action = 42; + int flags = 0x141; + int code = KeyEvent.KEYCODE_ENTER; + mKeyButtonView.setCode(code); + mKeyButtonView.sendEvent(action, flags); + + Mockito.verify(mMetricsLogger).write(argThat(new ArgumentMatcher<LogMaker>() { + public String mReason; + + @Override + public boolean matches(LogMaker argument) { + return checkField("category", argument.getCategory(), ACTION_NAV_BUTTON_EVENT) + && checkField("type", argument.getType(), MetricsEvent.TYPE_ACTION) + && checkField("subtype", argument.getSubtype(), code) + && checkField("FIELD_FLAGS", argument.getTaggedData(FIELD_FLAGS), flags) + && checkField("FIELD_NAV_ACTION", argument.getTaggedData(FIELD_NAV_ACTION), + action); + } + + private boolean checkField(String field, Object val, Object val2) { + if (!Objects.equals(val, val2)) { + mReason = "Expected " + field + " " + val2 + " but was " + val; + return false; + } + return true; + } + + @Override + public String toString() { + return mReason; + } + })); + } + +}
\ No newline at end of file diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto index 78bc01dc5389..b59e00d1956c 100644 --- a/proto/src/metrics_constants.proto +++ b/proto/src/metrics_constants.proto @@ -3892,6 +3892,15 @@ message MetricsEvent { // ACTION: QS -> Click date ACTION_QS_DATE = 930; + // ACTION: Event on nav button + ACTION_NAV_BUTTON_EVENT = 931; + + // FIELD: Flags for a nav button event + FIELD_FLAGS = 932; + + // FIELD: Action for a nav button event + FIELD_NAV_ACTION = 933; + // ---- End O Constants, all O constants go above this line ---- // Add new aosp constants above this line. diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java index 1968d2e925aa..cb6d4df355b1 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java @@ -183,9 +183,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { private final SimpleStringSplitter mStringColonSplitter = new SimpleStringSplitter(COMPONENT_NAME_SEPARATOR); - private final List<AccessibilityServiceInfo> mEnabledServicesForFeedbackTempList = - new ArrayList<>(); - private final Rect mTempRect = new Rect(); private final Rect mTempRect1 = new Rect(); @@ -568,7 +565,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { @Override public List<AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int feedbackType, int userId) { - List<AccessibilityServiceInfo> result = null; synchronized (mLock) { // We treat calls from a profile as if made by its parent as profiles // share the accessibility state of the parent. The call below @@ -577,24 +573,24 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { .resolveCallingUserIdEnforcingPermissionsLocked(userId); // The automation service can suppress other services. - UserState userState = getUserStateLocked(resolvedUserId); + final UserState userState = getUserStateLocked(resolvedUserId); if (userState.isUiAutomationSuppressingOtherServices()) { return Collections.emptyList(); } - result = mEnabledServicesForFeedbackTempList; - result.clear(); - List<Service> services = userState.mBoundServices; - for (int serviceCount = services.size(), i = 0; i < serviceCount; ++i) { - Service service = services.get(i); + final List<Service> services = userState.mBoundServices; + final int serviceCount = services.size(); + final List<AccessibilityServiceInfo> result = new ArrayList<>(serviceCount); + for (int i = 0; i < serviceCount; ++i) { + final Service service = services.get(i); // Don't report the UIAutomation (fake service) if (!sFakeAccessibilityServiceComponentName.equals(service.mComponentName) && (service.mFeedbackType & feedbackType) != 0) { result.add(service.mAccessibilityServiceInfo); } } + return result; } - return result; } @Override @@ -876,10 +872,10 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { */ @Override public void notifyAccessibilityButtonClicked() { - if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR) + if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR_SERVICE) != PackageManager.PERMISSION_GRANTED) { throw new SecurityException("Caller does not hold permission " - + android.Manifest.permission.STATUS_BAR); + + android.Manifest.permission.STATUS_BAR_SERVICE); } synchronized (mLock) { notifyAccessibilityButtonClickedLocked(); @@ -895,10 +891,10 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { */ @Override public void notifyAccessibilityButtonAvailabilityChanged(boolean available) { - if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR) + if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR_SERVICE) != PackageManager.PERMISSION_GRANTED) { throw new SecurityException("Caller does not hold permission " - + android.Manifest.permission.STATUS_BAR); + + android.Manifest.permission.STATUS_BAR_SERVICE); } synchronized (mLock) { notifyAccessibilityButtonAvailabilityChangedLocked(available); diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java index 502b5fc1ea6f..2bcc260b1c70 100644 --- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java +++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java @@ -283,13 +283,6 @@ public final class AutofillManagerService extends SystemService { } } - // Called by Shell command. - public void setSaveTimeout(int timeout) { - Slog.i(TAG, "setSaveTimeout(" + timeout + ")"); - mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG); - mUi.setSaveTimeout(timeout); - } - /** * Removes a cached service for a given user. */ diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java index 80560f18038e..6debc2fe26d7 100644 --- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java +++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java @@ -47,8 +47,6 @@ public final class AutofillManagerServiceShellCommand extends ShellCommand { switch (cmd) { case "save": return requestSave(); - case "set": - return requestSet(); case "list": return requestList(pw); case "destroy": @@ -76,9 +74,6 @@ public final class AutofillManagerServiceShellCommand extends ShellCommand { pw.println(" save [--user USER_ID]"); pw.println(" Request provider to save contents of the top activity."); pw.println(""); - pw.println(" set save_timeout MS"); - pw.println(" Sets how long (in ms) the save snack bar is shown."); - pw.println(""); pw.println(" reset"); pw.println(" Reset all pending sessions and cached service connections."); pw.println(""); @@ -91,18 +86,6 @@ public final class AutofillManagerServiceShellCommand extends ShellCommand { return 0; } - private int requestSet() { - final String type = getNextArgRequired(); - switch (type) { - case "save_timeout": - mService.setSaveTimeout(Integer.parseInt(getNextArgRequired())); - break; - default: - throw new IllegalArgumentException("Invalid 'set' type: " + type); - } - return 0; - } - private int requestDestroy(PrintWriter pw) { if (!isNextArgSessions(pw)) { return -1; diff --git a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java index 257256dc58e7..64dee584165e 100644 --- a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java +++ b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java @@ -262,7 +262,7 @@ public final class AutoFillUI { } mMetricsLogger.write(log); } - }, mSaveTimeoutMs); + }); }); } diff --git a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java index 2c08afadf10b..d35cc95e6d26 100644 --- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java +++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java @@ -98,7 +98,7 @@ final class SaveUi { private boolean mDestroyed; SaveUi(@NonNull Context context, @NonNull CharSequence providerLabel, @NonNull SaveInfo info, - @NonNull OnSaveListener listener, int lifeTimeMs) { + @NonNull OnSaveListener listener) { mListener = new OneTimeListener(listener); final LayoutInflater inflater = LayoutInflater.from(context); @@ -169,13 +169,6 @@ final class SaveUi { window.getAttributes().width = WindowManager.LayoutParams.MATCH_PARENT; mDialog.show(); - - mHandler.postDelayed(() -> { - if (!mListener.mDone) { - mListener.onCancel(null); - Slog.d(TAG, "Save snackbar timed out after " + lifeTimeMs + "ms"); - } - }, lifeTimeMs); } void destroy() { diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 3f2fdb09e75d..be5ff803ed56 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -1490,6 +1490,7 @@ public class ActivityManagerService extends IActivityManager.Stub boolean mSupportsSplitScreenMultiWindow; boolean mSupportsFreeformWindowManagement; boolean mSupportsPictureInPicture; + boolean mSupportsMultiDisplay; boolean mSupportsLeanbackOnly; IActivityController mController = null; boolean mControllerIsAMonkey = false; @@ -13827,6 +13828,8 @@ public class ActivityManagerService extends IActivityManager.Stub com.android.internal.R.fraction.thumbnail_fullscreen_scale, 1, 1); } mWaitForNetworkTimeoutMs = waitForNetworkTimeoutMs; + mSupportsMultiDisplay = res.getBoolean( + com.android.internal.R.bool.config_supportsMultiDisplay); } } diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java index 748aa6ff256a..601141827f3c 100644 --- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java +++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java @@ -247,6 +247,8 @@ final class ActivityManagerShellCommand extends ShellCommand { return runSupportsMultiwindow(pw); case "supports-split-screen-multi-window": return runSupportsSplitScreenMultiwindow(pw); + case "supports-multi-display": + return runSupportsMultiDisplay(pw); case "update-appinfo": return runUpdateApplicationInfo(pw); case "no-home-screen": @@ -2398,6 +2400,15 @@ final class ActivityManagerShellCommand extends ShellCommand { return 0; } + int runSupportsMultiDisplay(PrintWriter pw) throws RemoteException { + final Resources res = getResources(pw); + if (res == null) { + return -1; + } + pw.println(res.getBoolean(com.android.internal.R.bool.config_supportsMultiDisplay)); + return 0; + } + int runUpdateApplicationInfo(PrintWriter pw) throws RemoteException { int userid = UserHandle.parseUserArg(getNextArgRequired()); ArrayList<String> packages = new ArrayList<>(); @@ -2627,6 +2638,8 @@ final class ActivityManagerShellCommand extends ShellCommand { pw.println(" Returns true if the device supports multiwindow."); pw.println(" supports-split-screen-multi-window"); pw.println(" Returns true if the device supports split screen multiwindow."); + pw.println(" supports-multi-display"); + pw.println(" Returns true if the device supports multi-display."); pw.println(" suppress-resize-config-changes <true|false>"); pw.println(" Suppresses configuration changes due to user resizing an activity/task."); pw.println(" set-inactive [--user <USER_ID>] <PACKAGE> true|false"); diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index 3e3fee54bdd0..30e33c83e7be 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -2782,6 +2782,15 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D + " reparent task=" + task + " to stackId=" + stackId); } + // Ensure that we're not moving a task to a dynamic stack if device doesn't support + // multi-display. + // TODO(multi-display): Support non-dynamic stacks on secondary displays. + // TODO: Check ActivityView after fixing b/35349678. + if (StackId.isDynamicStack(stackId) && !mService.mSupportsMultiDisplay) { + throw new IllegalArgumentException("Device doesn't support multi-display, can not" + + " reparent task=" + task + " to stackId=" + stackId); + } + // Ensure that we aren't trying to move into a freeform stack without freeform // support if (stackId == FREEFORM_WORKSPACE_STACK_ID && !mService.mSupportsFreeformWindowManagement) { diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java index b4085697f2da..bb5f5884773e 100644 --- a/services/core/java/com/android/server/am/ActivityStarter.java +++ b/services/core/java/com/android/server/am/ActivityStarter.java @@ -2178,7 +2178,8 @@ class ActivityStarter { case ASSISTANT_STACK_ID: return r.isAssistantActivity(); default: - if (StackId.isDynamicStack(stackId)) { + // TODO: Check ActivityView after fixing b/35349678. + if (StackId.isDynamicStack(stackId) && mService.mSupportsMultiDisplay) { return true; } Slog.e(TAG, "isValidLaunchStackId: Unexpected stackId=" + stackId); diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java index 9f7c4a2793db..1e2b743d5e46 100644 --- a/services/core/java/com/android/server/pm/Installer.java +++ b/services/core/java/com/android/server/pm/Installer.java @@ -279,13 +279,14 @@ public class Installer extends SystemService { public void dexopt(String apkPath, int uid, @Nullable String pkgName, String instructionSet, int dexoptNeeded, @Nullable String outputPath, int dexFlags, - String compilerFilter, @Nullable String volumeUuid, @Nullable String sharedLibraries) + String compilerFilter, @Nullable String volumeUuid, @Nullable String sharedLibraries, + @Nullable String seInfo) throws InstallerException { assertValidInstructionSet(instructionSet); if (!checkBeforeRemote()) return; try { mInstalld.dexopt(apkPath, uid, pkgName, instructionSet, dexoptNeeded, outputPath, - dexFlags, compilerFilter, volumeUuid, sharedLibraries); + dexFlags, compilerFilter, volumeUuid, sharedLibraries, seInfo); } catch (Exception e) { throw InstallerException.from(e); } diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java index 6245ffc64009..498181b5179e 100644 --- a/services/core/java/com/android/server/pm/OtaDexoptService.java +++ b/services/core/java/com/android/server/pm/OtaDexoptService.java @@ -278,7 +278,7 @@ public class OtaDexoptService extends IOtaDexopt.Stub { public void dexopt(String apkPath, int uid, @Nullable String pkgName, String instructionSet, int dexoptNeeded, @Nullable String outputPath, int dexFlags, String compilerFilter, @Nullable String volumeUuid, - @Nullable String sharedLibraries) throws InstallerException { + @Nullable String sharedLibraries, @Nullable String seInfo) throws InstallerException { commands.add(buildCommand("dexopt", apkPath, uid, @@ -289,7 +289,8 @@ public class OtaDexoptService extends IOtaDexopt.Stub { dexFlags, compilerFilter, volumeUuid, - sharedLibraries)); + sharedLibraries, + seInfo)); } }; diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java index 781be34828ad..9039647cbffd 100644 --- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java +++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java @@ -204,7 +204,7 @@ public class PackageDexOptimizer { long startTime = System.currentTimeMillis(); mInstaller.dexopt(path, uid, pkg.packageName, isa, dexoptNeeded, oatDir, dexoptFlags, - compilerFilter, pkg.volumeUuid, sharedLibrariesPath); + compilerFilter, pkg.volumeUuid, sharedLibrariesPath, pkg.applicationInfo.seInfo); if (packageStats != null) { long endTime = System.currentTimeMillis(); @@ -283,7 +283,7 @@ public class PackageDexOptimizer { // TODO(calin): maybe add a separate call. mInstaller.dexopt(path, info.uid, info.packageName, isa, /*dexoptNeeded*/ 0, /*oatDir*/ null, dexoptFlags, - compilerFilter, info.volumeUuid, SKIP_SHARED_LIBRARY_CHECK); + compilerFilter, info.volumeUuid, SKIP_SHARED_LIBRARY_CHECK, info.seInfoUser); } return DEX_OPT_PERFORMED; diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index ce4d7ee7a523..dd3959001f44 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -1915,7 +1915,11 @@ public class PackageManagerService extends IPackageManager.Stub { // survive long enough to benefit of background optimizations. for (int userId : firstUsers) { PackageInfo info = getPackageInfo(packageName, /*flags*/ 0, userId); - mDexManager.notifyPackageInstalled(info, userId); + // There's a race currently where some install events may interleave with an uninstall. + // This can lead to package info being null (b/36642664). + if (info != null) { + mDexManager.notifyPackageInstalled(info, userId); + } } } @@ -8573,6 +8577,7 @@ public class PackageManagerService extends IPackageManager.Stub { @Override public boolean performDexOptSecondary(String packageName, String compilerFilter, boolean force) { + mDexManager.reconcileSecondaryDexFiles(packageName); return mDexManager.dexoptSecondaryDex(packageName, compilerFilter, force); } diff --git a/services/print/java/com/android/server/print/UserState.java b/services/print/java/com/android/server/print/UserState.java index 7474a64c32cb..75df892b30b1 100644 --- a/services/print/java/com/android/server/print/UserState.java +++ b/services/print/java/com/android/server/print/UserState.java @@ -45,17 +45,17 @@ import android.os.RemoteException; import android.os.UserHandle; import android.print.IPrintDocumentAdapter; import android.print.IPrintJobStateChangeListener; -import android.printservice.recommendation.IRecommendationsChangeListener; import android.print.IPrintServicesChangeListener; import android.print.IPrinterDiscoveryObserver; import android.print.PrintAttributes; import android.print.PrintJobId; import android.print.PrintJobInfo; import android.print.PrintManager; -import android.printservice.recommendation.RecommendationInfo; import android.print.PrinterId; import android.print.PrinterInfo; import android.printservice.PrintServiceInfo; +import android.printservice.recommendation.IRecommendationsChangeListener; +import android.printservice.recommendation.RecommendationInfo; import android.provider.DocumentsContract; import android.provider.Settings; import android.text.TextUtils; @@ -72,8 +72,9 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.os.BackgroundThread; import com.android.internal.os.SomeArgs; import com.android.server.print.RemotePrintService.PrintServiceCallbacks; +import com.android.server.print.RemotePrintServiceRecommendationService + .RemotePrintServiceRecommendationServiceCallbacks; import com.android.server.print.RemotePrintSpooler.PrintSpoolerCallbacks; -import com.android.server.print.RemotePrintServiceRecommendationService.RemotePrintServiceRecommendationServiceCallbacks; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -882,7 +883,7 @@ final class UserState implements PrintSpoolerCallbacks, PrintServiceCallbacks, + android.Manifest.permission.BIND_PRINT_SERVICE); continue; } - tempPrintServices.add(PrintServiceInfo.create(installedService, mContext)); + tempPrintServices.add(PrintServiceInfo.create(mContext, installedService)); } mInstalledServices.clear(); |