diff --git a/api/current.txt b/api/current.txt index 107c698d9aa94cabbf091cd3c1d7fd7138cf3ee0..12719786f6924d0a3bad02c0d09eeb7ffe9cb7ce 100644 --- a/api/current.txt +++ b/api/current.txt @@ -45993,6 +45993,7 @@ package android.telephony { field public static final int APPTYPE_USIM = 2; // 0x2 field public static final int AUTHTYPE_EAP_AKA = 129; // 0x81 field public static final int AUTHTYPE_EAP_SIM = 128; // 0x80 + field public static final long CALLBACK_ON_MORE_ERROR_CODE_CHANGE = 130595455L; // 0x7c8ba7fL field public static final int CALL_STATE_IDLE = 0; // 0x0 field public static final int CALL_STATE_OFFHOOK = 2; // 0x2 field public static final int CALL_STATE_RINGING = 1; // 0x1 diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp index 88db89dbd279a985a309e3bb8016fe6c9e97fb4a..72a8bea9a9188d8a166c3f14afa441ef88c66ca8 100644 --- a/cmds/statsd/Android.bp +++ b/cmds/statsd/Android.bp @@ -50,6 +50,7 @@ cc_defaults { srcs: [ ":statsd_aidl", + ":ICarStatsService.aidl", "src/active_config_list.proto", "src/statsd_config.proto", "src/uid_data.proto", @@ -69,6 +70,7 @@ cc_defaults { "src/config/ConfigKey.cpp", "src/config/ConfigListener.cpp", "src/config/ConfigManager.cpp", + "src/external/CarStatsPuller.cpp", "src/external/GpuStatsPuller.cpp", "src/external/Perfetto.cpp", "src/external/StatsPuller.cpp", diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp index dd651552929a1a3bdb588f00357804e28a5d4fdb..cb497fc4a79aa296fc6973863507fc8f81c002be 100644 --- a/cmds/statsd/src/StatsService.cpp +++ b/cmds/statsd/src/StatsService.cpp @@ -267,7 +267,9 @@ status_t StatsService::onTransact(uint32_t code, const Parcel& data, Parcel* rep IResultReceiver::asInterface(data.readStrongBinder()); err = command(in, out, err, args, resultReceiver); - resultReceiver->send(err); + if (resultReceiver != nullptr) { + resultReceiver->send(err); + } return NO_ERROR; } default: { return BnStatsManager::onTransact(code, data, reply, flags); } @@ -412,13 +414,20 @@ status_t StatsService::command(int in, int out, int err, Vector& args, return cmd_trigger_active_config_broadcast(out, args); } if (!args[0].compare(String8("data-subscribe"))) { - if (mShellSubscriber == nullptr) { - mShellSubscriber = new ShellSubscriber(mUidMap, mPullerManager); + { + std::lock_guard lock(mShellSubscriberMutex); + if (mShellSubscriber == nullptr) { + mShellSubscriber = new ShellSubscriber(mUidMap, mPullerManager); + } } int timeoutSec = -1; if (argCount >= 2) { timeoutSec = atoi(args[1].c_str()); } + if (resultReceiver == nullptr) { + ALOGI("Null resultReceiver given, no subscription will be started"); + return UNEXPECTED_NULL; + } mShellSubscriber->startNewSubscription(in, out, resultReceiver, timeoutSec); return NO_ERROR; } @@ -1386,7 +1395,10 @@ Status StatsService::sendBinaryPushStateChangedAtom(const android::String16& tra Status StatsService::sendWatchdogRollbackOccurredAtom(const int32_t rollbackTypeIn, const android::String16& packageNameIn, - const int64_t packageVersionCodeIn) { + const int64_t packageVersionCodeIn, + const int32_t rollbackReasonIn, + const android::String16& + failingPackageNameIn) { // Note: We skip the usage stats op check here since we do not have a package name. // This is ok since we are overloading the usage_stats permission. // This method only sends data, it does not receive it. @@ -1408,7 +1420,8 @@ Status StatsService::sendWatchdogRollbackOccurredAtom(const int32_t rollbackType } android::util::stats_write(android::util::WATCHDOG_ROLLBACK_OCCURRED, - rollbackTypeIn, String8(packageNameIn).string(), packageVersionCodeIn); + rollbackTypeIn, String8(packageNameIn).string(), packageVersionCodeIn, + rollbackReasonIn, String8(failingPackageNameIn).string()); // Fast return to save disk read. if (rollbackTypeIn != android::util::WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_SUCCESS diff --git a/cmds/statsd/src/StatsService.h b/cmds/statsd/src/StatsService.h index dba2502eeae7990efbca8ec888b3f97ffe23301a..f6ac6360723bb6eda6dbf39234ecbc9b2e3153ef 100644 --- a/cmds/statsd/src/StatsService.h +++ b/cmds/statsd/src/StatsService.h @@ -199,7 +199,9 @@ public: virtual Status sendWatchdogRollbackOccurredAtom( const int32_t rollbackTypeIn, const android::String16& packageNameIn, - const int64_t packageVersionCodeIn) override; + const int64_t packageVersionCodeIn, + const int32_t rollbackReasonIn, + const android::String16& failingPackageNameIn) override; /** * Binder call to get registered experiment IDs. @@ -376,6 +378,10 @@ private: sp mShellSubscriber; + /** + * Mutex for setting the shell subscriber + */ + mutable mutex mShellSubscriberMutex; std::shared_ptr mEventQueue; FRIEND_TEST(StatsLogProcessorTest, TestActivationsPersistAcrossSystemServerRestart); diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto index 4f4a04e88964aa7c3ea45efeea8b9f8cc63ef4ae..97fe7cddb4a5daa4061b5c966d1ec1c3114601d8 100644 --- a/cmds/statsd/src/atoms.proto +++ b/cmds/statsd/src/atoms.proto @@ -351,6 +351,7 @@ message Atom { 228 [(allow_from_any_uid) = true]; PerfettoUploaded perfetto_uploaded = 229 [(log_from_module) = "perfetto"]; + VmsClientConnectionStateChanged vms_client_connection_state_changed = 230; BootTimeEventDuration boot_time_event_duration_reported = 239; BootTimeEventElapsedTime boot_time_event_elapsed_time_reported = 240; BootTimeEventUtcTime boot_time_event_utc_time_reported = 241; @@ -360,7 +361,7 @@ message Atom { } // Pulled events will start at field 10000. - // Next: 10062 + // Next: 10067 oneof pulled { WifiBytesTransfer wifi_bytes_transfer = 10000; WifiBytesTransferByFgBg wifi_bytes_transfer_by_fg_bg = 10001; @@ -424,6 +425,8 @@ message Atom { CoolingDevice cooling_device = 10059; AppOps app_ops = 10060; ProcessSystemIonHeapSize process_system_ion_heap_size = 10061; + VmsClientStats vms_client_stats = 10065; + NotificationRemoteViews notification_remote_views = 10066; } // DO NOT USE field numbers above 100,000 in AOSP. @@ -1720,6 +1723,19 @@ message WatchdogRollbackOccurred { optional string package_name = 2; optional int32 package_version_code = 3; + + enum RollbackReasonType { + REASON_UNKNOWN = 0; + REASON_NATIVE_CRASH = 1; + REASON_EXPLICIT_HEALTH_CHECK = 2; + REASON_APP_CRASH = 3; + REASON_APP_NOT_RESPONDING = 4; + } + optional RollbackReasonType rollback_reason = 4; + + // Set by RollbackPackageHealthObserver to be the package that is failing when a rollback + // is initiated. Empty if the package is unknown. + optional string failing_package_name = 5; } /** @@ -3744,6 +3760,33 @@ message RoleRequestResultReported { optional Result result = 9; } +/** + * Logs when a Vehicle Maps Service client's connection state has changed + * + * Logged from: + * packages/services/Car/service/src/com/android/car/stats/VmsClientLog.java + */ +message VmsClientConnectionStateChanged { + // The UID of the VMS client app + optional int32 uid = 1 [(is_uid) = true]; + + enum State { + UNKNOWN = 0; + // Attempting to connect to the client + CONNECTING = 1; + // Client connection established + CONNECTED = 2; + // Client connection closed unexpectedly + DISCONNECTED = 3; + // Client connection closed by VMS + TERMINATED = 4; + // Error establishing the client connection + CONNECTION_ERROR = 5; + } + + optional State state = 2; +} + /** * Represents boot time event with duration in ms. * @@ -5008,6 +5051,24 @@ message ProcStatsPkgProc { optional ProcessStatsSectionProto proc_stats_section = 1; } +// Next Tag: 2 +message PackageRemoteViewInfoProto { + optional string package_name = 1; + // add per-package additional info here (like channels) +} + +// Next Tag: 2 +message NotificationRemoteViewsProto { + repeated PackageRemoteViewInfoProto package_remote_view_info = 1; +} + +/** + * Pulled from NotificationManagerService.java + */ +message NotificationRemoteViews { + optional NotificationRemoteViewsProto notification_remote_views = 1; +} + message PowerProfileProto { optional double cpu_suspend = 1; @@ -7140,7 +7201,6 @@ message AppCompatibilityChangeReported { // Where it was logged from. optional Source source = 4; - } /** @@ -7177,6 +7237,35 @@ message PerfettoUploaded { optional int64 trace_uuid_msb = 3; } +/** + * Pulls client metrics on data transferred via Vehicle Maps Service. + * Metrics are keyed by uid + layer. + * + * Pulled from: + * packages/services/Car/service/src/com/android/car/stats/CarStatsService.java + */ +message VmsClientStats { + // UID of the VMS client app + optional int32 uid = 1 [(is_uid) = true]; + + // VMS layer definition + optional int32 layer_type = 2; + optional int32 layer_channel = 3; + optional int32 layer_version = 4; + + // Bytes and packets sent by the client for the layer + optional int64 tx_bytes = 5; + optional int64 tx_packets = 6; + + // Bytes and packets received by the client for the layer + optional int64 rx_bytes = 7; + optional int64 rx_packets = 8; + + // Bytes and packets dropped due to client error + optional int64 dropped_bytes = 9; + optional int64 dropped_packets = 10; +} + /** * Information about an OTA update attempt by update_engine. * Logged from platform/system/update_engine/metrics_reporter_android.cc diff --git a/cmds/statsd/src/external/CarStatsPuller.cpp b/cmds/statsd/src/external/CarStatsPuller.cpp new file mode 100644 index 0000000000000000000000000000000000000000..70c0456b5eb4656fc87ad7a7ce5d4c3f7904dd08 --- /dev/null +++ b/cmds/statsd/src/external/CarStatsPuller.cpp @@ -0,0 +1,96 @@ +/* + * 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. + */ + +#define DEBUG false +#include "Log.h" + +#include +#include + +#include "CarStatsPuller.h" +#include "logd/LogEvent.h" +#include "stats_log_util.h" + +using android::binder::Status; +using com::android::internal::car::ICarStatsService; + +namespace android { +namespace os { +namespace statsd { + +static std::mutex gCarStatsMutex; +static sp gCarStats = nullptr; + +class CarStatsDeathRecipient : public android::IBinder::DeathRecipient { + public: + CarStatsDeathRecipient() = default; + ~CarStatsDeathRecipient() override = default; + + // android::IBinder::DeathRecipient override: + void binderDied(const android::wp& /* who */) override { + ALOGE("Car service has died"); + std::lock_guard lock(gCarStatsMutex); + if (gCarStats) { + sp binder = IInterface::asBinder(gCarStats); + binder->unlinkToDeath(this); + gCarStats = nullptr; + } + } +}; + +static sp gDeathRecipient = new CarStatsDeathRecipient(); + +static sp getCarService() { + std::lock_guard lock(gCarStatsMutex); + if (!gCarStats) { + const sp binder = defaultServiceManager()->checkService(String16("car_stats")); + if (!binder) { + ALOGW("Car service is unavailable"); + return nullptr; + } + gCarStats = interface_cast(binder); + binder->linkToDeath(gDeathRecipient); + } + return gCarStats; +} + +CarStatsPuller::CarStatsPuller(const int tagId) : StatsPuller(tagId) { +} + +bool CarStatsPuller::PullInternal(std::vector>* data) { + const sp carService = getCarService(); + if (!carService) { + return false; + } + + vector returned_value; + Status status = carService->pullData(mTagId, &returned_value); + if (!status.isOk()) { + ALOGW("CarStatsPuller::pull failed for %d", mTagId); + return false; + } + + data->clear(); + for (const StatsLogEventWrapper& it : returned_value) { + LogEvent::createLogEvents(it, *data); + } + VLOG("CarStatsPuller::pull succeeded for %d", mTagId); + return true; +} + +} // namespace statsd +} // namespace os +} // namespace android diff --git a/cmds/statsd/src/external/CarStatsPuller.h b/cmds/statsd/src/external/CarStatsPuller.h new file mode 100644 index 0000000000000000000000000000000000000000..ca0f1a9c9a17b00913b5653ca1b88c1804717628 --- /dev/null +++ b/cmds/statsd/src/external/CarStatsPuller.h @@ -0,0 +1,36 @@ +/* + * 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. + */ + +#pragma once + +#include "StatsPuller.h" + +namespace android { +namespace os { +namespace statsd { + +/** + * Pull atoms from CarService. + */ +class CarStatsPuller : public StatsPuller { +public: + explicit CarStatsPuller(const int tagId); + bool PullInternal(std::vector>* data) override; +}; + +} // namespace statsd +} // namespace os +} // namespace android diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp index 69e6a11b9ad75c3ddd9dc06388b44f659dcb8eeb..1c9d7763bc8308fc0e2a37859164ab306dd029b0 100644 --- a/cmds/statsd/src/external/StatsPullerManager.cpp +++ b/cmds/statsd/src/external/StatsPullerManager.cpp @@ -27,6 +27,7 @@ #include "../logd/LogEvent.h" #include "../stats_log_util.h" #include "../statscompanion_util.h" +#include "CarStatsPuller.h" #include "GpuStatsPuller.h" #include "PowerStatsPuller.h" #include "ResourceHealthManagerPuller.h" @@ -267,6 +268,13 @@ std::map StatsPullerManager::kAllPullAtomInfo = { // App ops {android::util::APP_OPS, {.puller = new StatsCompanionServicePuller(android::util::APP_OPS)}}, + // VmsClientStats + {android::util::VMS_CLIENT_STATS, + {.additiveFields = {5, 6, 7, 8, 9, 10}, + .puller = new CarStatsPuller(android::util::VMS_CLIENT_STATS)}}, + // NotiifcationRemoteViews. + {android::util::NOTIFICATION_REMOTE_VIEWS, + {.puller = new StatsCompanionServicePuller(android::util::NOTIFICATION_REMOTE_VIEWS)}}, }; StatsPullerManager::StatsPullerManager() : mNextPullTimeNs(NO_ALARM_UPDATE) { diff --git a/core/java/Android.bp b/core/java/Android.bp index fb27f74211fbc9460807696231aeaa6499534ac8..9a8e130436f8c8a9c055e0c4d7bdf3a4cc9ad5cb 100644 --- a/core/java/Android.bp +++ b/core/java/Android.bp @@ -7,3 +7,8 @@ filegroup { name: "IDropBoxManagerService.aidl", srcs: ["com/android/internal/os/IDropBoxManagerService.aidl"], } + +filegroup { + name: "ICarStatsService.aidl", + srcs: ["com/android/internal/car/ICarStatsService.aidl"], +} diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java index 7ecaacae6b0988ceb5baac240b2d784b7d4612a1..6519366cf7c61305c07013eb8fb6157d0d17e5c5 100644 --- a/core/java/android/accounts/AccountManager.java +++ b/core/java/android/accounts/AccountManager.java @@ -563,6 +563,21 @@ public class AccountManager { * account, or the AbstractAcccountAuthenticator managing the account did so or because the * client shares a signature with the managing AbstractAccountAuthenticator. * + *

Caution: This method returns personal and sensitive user data. + * If your app accesses, collects, uses, or shares personal and sensitive data, you must clearly + * disclose that fact to users. For apps published on Google Play, policies protecting user data + * require that you do the following:

+ *
    + *
  • Disclose to the user how your app accesses, collects, uses, or shares personal and + * sensitive data. Learn more about + * acceptable + * disclosure and consent.
  • + *
  • Provide a privacy policy that describes your use of this data on- and off-device.
  • + *
+ *

To learn more, visit the + * Google Play + * Policy regarding user data.

+ * *

* It is safe to call this method from the main thread. * @@ -649,6 +664,22 @@ public class AccountManager { * the account. For example, there are types corresponding to Google and Facebook. The exact * string token to use will be published somewhere associated with the authenticator in * question. + *

+ * + *

Caution: This method returns personal and sensitive user data. + * If your app accesses, collects, uses, or shares personal and sensitive data, you must clearly + * disclose that fact to users. For apps published on Google Play, policies protecting user data + * require that you do the following:

+ *
    + *
  • Disclose to the user how your app accesses, collects, uses, or shares personal and + * sensitive data. Learn more about + * acceptable + * disclosure and consent.
  • + *
  • Provide a privacy policy that describes your use of this data on- and off-device.
  • + *
+ *

To learn more, visit the + * Google Play + * Policy regarding user data.

* *

* It is safe to call this method from the main thread. diff --git a/core/java/android/animation/FloatEvaluator.java b/core/java/android/animation/FloatEvaluator.java index 9463aa12d116b9d3669ec023d486cf69fdbbdd1c..ae90e37d4c71bf4474f471f779a3922e212b6e8f 100644 --- a/core/java/android/animation/FloatEvaluator.java +++ b/core/java/android/animation/FloatEvaluator.java @@ -24,7 +24,7 @@ public class FloatEvaluator implements TypeEvaluator { /** * This function returns the result of linearly interpolating the start and end values, with * fraction representing the proportion between the start and end values. The - * calculation is a simple parametric calculation: result = x0 + t * (v1 - v0), + * calculation is a simple parametric calculation: result = x0 + t * (x1 - x0), * where x0 is startValue, x1 is endValue, * and t is fraction. * diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index 4132e025e5dad4646fd96298c10e0e8fc59277cb..e4c07db3fdf6394aa2213e1f75bda607631ceefd 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -2905,7 +2905,7 @@ public class ActivityManager { public static final int IMPORTANCE_CANT_SAVE_STATE_PRE_26 = 170; /** - * Constant for {@link #importance}: This process is contains services + * Constant for {@link #importance}: This process contains services * that should remain running. These are background services apps have * started, not something the user is aware of, so they may be killed by * the system relatively freely (though it is generally desired that they diff --git a/core/java/android/app/DisabledWallpaperManager.java b/core/java/android/app/DisabledWallpaperManager.java new file mode 100644 index 0000000000000000000000000000000000000000..518594191e6c7e7afc159e69766e9140a64c1ad7 --- /dev/null +++ b/core/java/android/app/DisabledWallpaperManager.java @@ -0,0 +1,346 @@ +/* + * 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 android.app; + +import android.annotation.NonNull; +import android.content.ComponentName; +import android.content.Intent; +import android.graphics.Bitmap; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.net.Uri; +import android.os.Bundle; +import android.os.Handler; +import android.os.IBinder; +import android.os.ParcelFileDescriptor; +import android.util.Log; + +import java.io.IOException; +import java.io.InputStream; + +/** + * A no-op implementation of {@link WallpaperManager}. + */ +final class DisabledWallpaperManager extends WallpaperManager { + + private static final String TAG = DisabledWallpaperManager.class.getSimpleName(); + + // Don't need to worry about synchronization + private static DisabledWallpaperManager sInstance; + + // TODO(b/138939803): STOPSHIP changed to false and/or remove it + private static final boolean DEBUG = true; + + @NonNull + static DisabledWallpaperManager getInstance() { + if (sInstance == null) { + sInstance = new DisabledWallpaperManager(); + } + return sInstance; + } + + private DisabledWallpaperManager() { + super(null, null, null); + } + + @Override + public boolean isWallpaperSupported() { + return false; + } + + @Override + public boolean isSetWallpaperAllowed() { + return false; + } + + // TODO(b/138939803): STOPSHIP methods below should not be necessary, + // callers should check if isWallpaperSupported(), consider removing them to keep this class + // simpler + + private static T unsupported() { + if (DEBUG) Log.w(TAG, "unsupported method called; returning null", new Exception()); + return null; + } + + private static boolean unsupportedBoolean() { + if (DEBUG) Log.w(TAG, "unsupported method called; returning false", new Exception()); + return false; + } + + @Override + public Drawable getDrawable() { + return unsupported(); + } + + @Override + public Drawable getBuiltInDrawable() { + return unsupported(); + } + + @Override + public Drawable getBuiltInDrawable(int which) { + return unsupported(); + } + + @Override + public Drawable getBuiltInDrawable(int outWidth, int outHeight, boolean scaleToFit, + float horizontalAlignment, float verticalAlignment) { + return unsupported(); + } + + @Override + public Drawable getBuiltInDrawable(int outWidth, int outHeight, boolean scaleToFit, + float horizontalAlignment, float verticalAlignment, int which) { + return unsupported(); + } + + @Override + public Drawable peekDrawable() { + return unsupported(); + } + + @Override + public Drawable getFastDrawable() { + return unsupported(); + } + + @Override + public Drawable peekFastDrawable() { + return unsupported(); + } + + @Override + public Bitmap getBitmap() { + return unsupported(); + } + + @Override + public Bitmap getBitmap(boolean hardware) { + return unsupported(); + } + + @Override + public Bitmap getBitmapAsUser(int userId, boolean hardware) { + return unsupported(); + } + + @Override + public ParcelFileDescriptor getWallpaperFile(int which) { + return unsupported(); + } + + @Override + public void addOnColorsChangedListener(OnColorsChangedListener listener, Handler handler) { + unsupported(); + } + + @Override + public void addOnColorsChangedListener(OnColorsChangedListener listener, Handler handler, + int userId) { + unsupported(); + } + + @Override + public void removeOnColorsChangedListener(OnColorsChangedListener callback) { + unsupported(); + } + + @Override + public void removeOnColorsChangedListener(OnColorsChangedListener callback, int userId) { + unsupported(); + } + + @Override + public WallpaperColors getWallpaperColors(int which) { + return unsupported(); + } + + @Override + public WallpaperColors getWallpaperColors(int which, int userId) { + return unsupported(); + } + + @Override + public ParcelFileDescriptor getWallpaperFile(int which, int userId) { + return unsupported(); + } + + @Override + public void forgetLoadedWallpaper() { + unsupported(); + } + + @Override + public WallpaperInfo getWallpaperInfo() { + return unsupported(); + } + + @Override + public WallpaperInfo getWallpaperInfo(int userId) { + return unsupported(); + } + + @Override + public int getWallpaperId(int which) { + return unsupported(); + } + + @Override + public int getWallpaperIdForUser(int which, int userId) { + return unsupported(); + } + + @Override + public Intent getCropAndSetWallpaperIntent(Uri imageUri) { + return unsupported(); + } + + @Override + public void setResource(int resid) throws IOException { + unsupported(); + } + + @Override + public int setResource(int resid, int which) throws IOException { + return unsupported(); + } + + @Override + public void setBitmap(Bitmap bitmap) throws IOException { + unsupported(); + } + + @Override + public int setBitmap(Bitmap fullImage, Rect visibleCropHint, boolean allowBackup) + throws IOException { + return unsupported(); + } + + @Override + public int setBitmap(Bitmap fullImage, Rect visibleCropHint, boolean allowBackup, int which) + throws IOException { + return unsupported(); + } + + @Override + public int setBitmap(Bitmap fullImage, Rect visibleCropHint, boolean allowBackup, int which, + int userId) throws IOException { + return unsupported(); + } + + @Override + public void setStream(InputStream bitmapData) throws IOException { + unsupported(); + } + + @Override + public int setStream(InputStream bitmapData, Rect visibleCropHint, boolean allowBackup) + throws IOException { + return unsupported(); + } + + @Override + public int setStream(InputStream bitmapData, Rect visibleCropHint, boolean allowBackup, + int which) throws IOException { + return unsupported(); + } + + @Override + public boolean hasResourceWallpaper(int resid) { + return unsupportedBoolean(); + } + + @Override + public int getDesiredMinimumWidth() { + return unsupported(); + } + + @Override + public int getDesiredMinimumHeight() { + return unsupported(); + } + + @Override + public void suggestDesiredDimensions(int minimumWidth, int minimumHeight) { + unsupported(); + } + + @Override + public void setDisplayPadding(Rect padding) { + unsupported(); + } + + @Override + public void setDisplayOffset(IBinder windowToken, int x, int y) { + unsupported(); + } + + @Override + public void clearWallpaper() { + unsupported(); + } + + @Override + public void clearWallpaper(int which, int userId) { + unsupported(); + } + + @Override + public boolean setWallpaperComponent(ComponentName name) { + return unsupportedBoolean(); + } + + @Override + public boolean setWallpaperComponent(ComponentName name, int userId) { + return unsupportedBoolean(); + } + + @Override + public void setWallpaperOffsets(IBinder windowToken, float xOffset, float yOffset) { + unsupported(); + } + + @Override + public void setWallpaperOffsetSteps(float xStep, float yStep) { + unsupported(); + } + + @Override + public void sendWallpaperCommand(IBinder windowToken, String action, int x, int y, int z, + Bundle extras) { + unsupported(); + } + + @Override + public void clearWallpaperOffsets(IBinder windowToken) { + unsupported(); + } + + @Override + public void clear() throws IOException { + unsupported(); + } + + @Override + public void clear(int which) throws IOException { + unsupported(); + } + + @Override + public boolean isWallpaperBackupEligible(int which) { + return unsupportedBoolean(); + } +} diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl index 9f51db88e7dc6315fd77dffdf8cde29ede6f6584..32668980d1319d9332d915a732cac7efaf2e5221 100644 --- a/core/java/android/app/INotificationManager.aidl +++ b/core/java/android/app/INotificationManager.aidl @@ -202,4 +202,6 @@ interface INotificationManager void setPrivateNotificationsAllowed(boolean allow); boolean getPrivateNotificationsAllowed(); + + long pullStats(long startNs, int report, boolean doAgg, out List stats); } diff --git a/core/java/android/app/IUiModeManager.aidl b/core/java/android/app/IUiModeManager.aidl index a3e0845af0cec2cb8466365c7a46f86d6350ea88..f5809ba627ff1f447b964a198cc3aa08e690024c 100644 --- a/core/java/android/app/IUiModeManager.aidl +++ b/core/java/android/app/IUiModeManager.aidl @@ -68,4 +68,9 @@ interface IUiModeManager { * Tells if Night mode is locked or not. */ boolean isNightModeLocked(); + + /** + * @hide + */ + boolean setNightModeActivated(boolean active); } diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java index 6acbf21e5602c39c7a1edbcf776c88a56291a6f7..bef8b04992f1a75108b7b328b701556262b0190a 100644 --- a/core/java/android/app/PendingIntent.java +++ b/core/java/android/app/PendingIntent.java @@ -1257,7 +1257,12 @@ public final class PendingIntent implements Parcelable { return b != null ? new PendingIntent(b, in.getClassCookie(PendingIntent.class)) : null; } - /*package*/ PendingIntent(IIntentSender target) { + /** + * Creates a PendingIntent with the given target. + * @param target the backing IIntentSender + * @hide + */ + public PendingIntent(IIntentSender target) { mTarget = target; } diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java index f60162d06f1d746c352f53e77e6b0d8c208d830d..7a736d69bbb55b6d6d1db71364adcbc725674832 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -746,11 +746,22 @@ final class SystemServiceRegistry { @Override public WallpaperManager createService(ContextImpl ctx) throws ServiceNotFoundException { - final IBinder b; - if (ctx.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.P) { - b = ServiceManager.getServiceOrThrow(Context.WALLPAPER_SERVICE); - } else { - b = ServiceManager.getService(Context.WALLPAPER_SERVICE); + final IBinder b = ServiceManager.getService(Context.WALLPAPER_SERVICE); + if (b == null) { + // There are 2 reason service can be null: + // 1.Device doesn't support it - that's fine + // 2.App is running on instant mode - should fail + final boolean enabled = Resources.getSystem() + .getBoolean(com.android.internal.R.bool.config_enableWallpaperService); + if (!enabled) { + // Life moves on... + return DisabledWallpaperManager.getInstance(); + } + if (ctx.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.P) { + // Instant app + throw new ServiceNotFoundException(Context.WALLPAPER_SERVICE); + } + // Bad state - WallpaperManager methods will throw exception } IWallpaperManager service = IWallpaperManager.Stub.asInterface(b); return new WallpaperManager(service, ctx.getOuterContext(), diff --git a/core/java/android/app/UiModeManager.java b/core/java/android/app/UiModeManager.java index 6582d240554bd2bfcaa7502ba6621ad44b9198c3..3633064834090ddb3d8d41d693e6381310f24164 100644 --- a/core/java/android/app/UiModeManager.java +++ b/core/java/android/app/UiModeManager.java @@ -473,4 +473,18 @@ public class UiModeManager { } return true; } + + /** + * @hide* + */ + public boolean setNightModeActivated(boolean active) { + if (mService != null) { + try { + return mService.setNightModeActivated(active); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + return false; + } } diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java index 102de950a129c7b7f8452267e61e8eb7b7eb8d83..7a6e314cf7793e0c3ed191cc6b7b12d9f1a52b63 100644 --- a/core/java/android/app/WallpaperManager.java +++ b/core/java/android/app/WallpaperManager.java @@ -510,7 +510,9 @@ public class WallpaperManager { /*package*/ WallpaperManager(IWallpaperManager service, Context context, Handler handler) { mContext = context; - initGlobals(service, context.getMainLooper()); + if (service != null) { + initGlobals(service, context.getMainLooper()); + } } /** diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 79a2c9010f35e080acb01e6f2b44c2e43423e0d5..5afd82f198a7d78e4be91f410ee091b7a537d4c4 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -4032,9 +4032,17 @@ public class DevicePolicyManager { * Make the device lock immediately, as if the lock screen timeout has expired at the point of * this call. *

+ * This method secures the device in response to an urgent situation, such as a lost or stolen + * device. After this method is called, the device must be unlocked using strong authentication + * (PIN, pattern, or password). This API is intended for use only by device admins. + *

* The calling device admin must have requested {@link DeviceAdminInfo#USES_POLICY_FORCE_LOCK} * to be able to call this method; if it has not, a security exception will be thrown. *

+ * If there's no lock type set, this method forces the device to go to sleep but doesn't lock + * the device. Device admins who find the device in this state can lock an otherwise-insecure + * device by first calling {@link #resetPassword} to set the password and then lock the device. + *

* This method can be called on the {@link DevicePolicyManager} instance returned by * {@link #getParentProfileInstance(ComponentName)} in order to lock the parent profile. *

@@ -4051,9 +4059,17 @@ public class DevicePolicyManager { * Make the device lock immediately, as if the lock screen timeout has expired at the point of * this call. *

+ * This method secures the device in response to an urgent situation, such as a lost or stolen + * device. After this method is called, the device must be unlocked using strong authentication + * (PIN, pattern, or password). This API is intended for use only by device admins. + *

* The calling device admin must have requested {@link DeviceAdminInfo#USES_POLICY_FORCE_LOCK} * to be able to call this method; if it has not, a security exception will be thrown. *

+ * If there's no lock type set, this method forces the device to go to sleep but doesn't lock + * the device. Device admins who find the device in this state can lock an otherwise-insecure + * device by first calling {@link #resetPassword} to set the password and then lock the device. + *

* This method can be called on the {@link DevicePolicyManager} instance returned by * {@link #getParentProfileInstance(ComponentName)} in order to lock the parent profile. * @@ -8082,7 +8098,7 @@ public class DevicePolicyManager { * Sets which system features are enabled when the device runs in lock task mode. This method * doesn't affect the features when lock task mode is inactive. Any system features not included * in {@code flags} are implicitly disabled when calling this method. By default, only - * {@link #LOCK_TASK_FEATURE_GLOBAL_ACTIONS} is enabled—all the other features are disabled. To + * {@link #LOCK_TASK_FEATURE_GLOBAL_ACTIONS} is enabled; all the other features are disabled. To * disable the global actions dialog, call this method omitting * {@link #LOCK_TASK_FEATURE_GLOBAL_ACTIONS}. * diff --git a/core/java/android/app/backup/WallpaperBackupHelper.java b/core/java/android/app/backup/WallpaperBackupHelper.java index 36f5f96732362502bd069e30ba429b8a849ea74d..5c0ddc1859db180cef420cf5d95fbcd0f95433ab 100644 --- a/core/java/android/app/backup/WallpaperBackupHelper.java +++ b/core/java/android/app/backup/WallpaperBackupHelper.java @@ -85,6 +85,10 @@ public class WallpaperBackupHelper extends FileBackupHelperBase implements Backu */ @Override public void restoreEntity(BackupDataInputStream data) { + if (mWpm == null) { + Slog.w(TAG, "restoreEntity(): no wallpaper service"); + return; + } final String key = data.getKey(); if (isKeyInList(key, mKeys)) { if (key.equals(WALLPAPER_IMAGE_KEY)) { diff --git a/core/java/android/app/contentsuggestions/ContentSuggestionsManager.java b/core/java/android/app/contentsuggestions/ContentSuggestionsManager.java index 1bb81b1487afdf46313e914088ef09b25eaba17c..1e6ab413618720996d6ffc08dd160089f50f2597 100644 --- a/core/java/android/app/contentsuggestions/ContentSuggestionsManager.java +++ b/core/java/android/app/contentsuggestions/ContentSuggestionsManager.java @@ -45,6 +45,17 @@ import java.util.concurrent.Executor; */ @SystemApi public final class ContentSuggestionsManager { + /** + * Key into the extras Bundle passed to {@link #provideContextImage(int, Bundle)}. + * This can be used to provide the bitmap to + * {@link android.service.contentsuggestions.ContentSuggestionsService}. + * The value must be a {@link android.graphics.Bitmap} with the + * config {@link android.graphics.Bitmap.Config.HARDWARE}. + * + * @hide + */ + public static final String EXTRA_BITMAP = "android.contentsuggestions.extra.BITMAP"; + private static final String TAG = ContentSuggestionsManager.class.getSimpleName(); /** @@ -70,7 +81,7 @@ public final class ContentSuggestionsManager { * system content suggestions service. * * @param taskId of the task to snapshot. - * @param imageContextRequestExtras sent with with request to provide implementation specific + * @param imageContextRequestExtras sent with request to provide implementation specific * extra information. */ public void provideContextImage( diff --git a/core/java/android/app/slice/SliceManager.java b/core/java/android/app/slice/SliceManager.java index 955093d3380e043b8c5c90ae06a876c8cc1062c1..90ecce2a2170082a2ffe759b6d460c33111fbc6d 100644 --- a/core/java/android/app/slice/SliceManager.java +++ b/core/java/android/app/slice/SliceManager.java @@ -390,6 +390,8 @@ public class SliceManager { } Bundle extras = new Bundle(); extras.putParcelable(SliceProvider.EXTRA_INTENT, intent); + extras.putParcelableArrayList(SliceProvider.EXTRA_SUPPORTED_SPECS, + new ArrayList<>(supportedSpecs)); final Bundle res = provider.call(SliceProvider.METHOD_MAP_INTENT, null, extras); if (res == null) { return null; diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java index 4acc6a5ed51b6dfc0429d60e8fa1f100164f8c25..c4ea080962f78cb5d5c686e41a92085758e50c6e 100644 --- a/core/java/android/bluetooth/BluetoothDevice.java +++ b/core/java/android/bluetooth/BluetoothDevice.java @@ -1112,6 +1112,24 @@ public final class BluetoothDevice implements Parcelable { return false; } + /** + * Get the Bluetooth alias of the remote device. + * If Alias is null, get the Bluetooth name instead. + * + * @return the Bluetooth alias, or null if no alias or there was a problem + * @hide + * @see #getAlias() + * @see #getName() + */ + @UnsupportedAppUsage(publicAlternatives = "Use {@link #getName()} instead.") + public String getAliasName() { + String name = getAlias(); + if (name == null) { + name = getName(); + } + return name; + } + /** * Get the most recent identified battery level of this Bluetooth device * diff --git a/core/java/android/bluetooth/le/ScanFilter.java b/core/java/android/bluetooth/le/ScanFilter.java index 038994fb55357d3eb2c999dd609392e679df139f..7511fd051e413e8ec51a1322d6bd11c6d0086135 100644 --- a/core/java/android/bluetooth/le/ScanFilter.java +++ b/core/java/android/bluetooth/le/ScanFilter.java @@ -671,8 +671,6 @@ public final class ScanFilter implements Parcelable { /** * Set filter on on manufacturerData. A negative manufacturerId is considered as invalid id. - *

- * Note the first two bytes of the {@code manufacturerData} is the manufacturerId. * * @throws IllegalArgumentException If the {@code manufacturerId} is invalid. */ diff --git a/core/java/android/content/ComponentName.java b/core/java/android/content/ComponentName.java index e955c2df2881ae1867a7cf9e3ac7af8943224ea7..f465395849f3c1326a83648ec66b3f4ab74c9507 100644 --- a/core/java/android/content/ComponentName.java +++ b/core/java/android/content/ComponentName.java @@ -305,6 +305,12 @@ public final class ComponentName implements Parcelable, Cloneable, ComparableTwo components are considered to be equal if the packages in which they reside have the + * same name, and if the classes that implement each component also have the same name. + */ @Override public boolean equals(Object obj) { try { diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index 99ca0484c8c744d5850a4cc71f13d3597bb5a0a2..ba91014a8756d25d422d22fe370ffef030c1990b 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -2689,6 +2689,9 @@ public class Intent implements Parcelable, Cloneable { * that application is first launched (that is the first time it is moved * out of the stopped state). The data contains the name of the package. * + *

When the application is first launched, the application itself doesn't receive this + * broadcast.

+ * *

This is a protected intent that can only be sent * by the system. */ diff --git a/core/java/android/content/SyncStats.java b/core/java/android/content/SyncStats.java index 03b2250edee146f2e10a640a67c3576aa3c670d6..9596a6016c44cfe66b662642fa65aa275041eb2f 100644 --- a/core/java/android/content/SyncStats.java +++ b/core/java/android/content/SyncStats.java @@ -58,7 +58,7 @@ public class SyncStats implements Parcelable { * attempted to update or delete a version of a resource on the server. This is expected * to clear itself automatically once the new state is retrieved from the server, * though it may remain until the user intervenes manually, perhaps by clearing the - * local storage and starting over frmo scratch. This is considered a hard error. + * local storage and starting over from scratch. This is considered a hard error. */ public long numConflictDetectedExceptions; diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java index 78db3d82ce938eac7720c0a0ad4522a122f7532f..2217807254e94325b3dd012bc40c1bb13184a91c 100644 --- a/core/java/android/content/pm/PackageInstaller.java +++ b/core/java/android/content/pm/PackageInstaller.java @@ -101,19 +101,6 @@ import java.util.concurrent.Executor; *

* The ApiDemos project contains examples of using this API: * ApiDemos/src/com/example/android/apis/content/InstallApk*.java. - *

- * On Android Q or above, an app installed notification will be posted - * by system after a new app is installed. - * To customize installer's notification icon, you should declare the following in the manifest - * <application> as follows:

- *
- * <meta-data android:name="com.android.packageinstaller.notification.smallIcon"
- * android:resource="@drawable/installer_notification_icon"/>
- * 
- *
- * <meta-data android:name="com.android.packageinstaller.notification.color"
- * android:resource="@color/installer_notification_color"/>
- * 
*/ public class PackageInstaller { private static final String TAG = "PackageInstaller"; diff --git a/core/java/android/content/pm/UserInfo.java b/core/java/android/content/pm/UserInfo.java index caf095884db254baa1ee3e24285752646f46e511..0a390fed204682a756cd85bafd7d974da4407de9 100644 --- a/core/java/android/content/pm/UserInfo.java +++ b/core/java/android/content/pm/UserInfo.java @@ -16,11 +16,16 @@ package android.content.pm; +import android.annotation.IntDef; import android.compat.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.Parcelable; import android.os.UserHandle; import android.os.UserManager; +import android.util.DebugUtils; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; /** * Per-user information. @@ -93,6 +98,25 @@ public class UserInfo implements Parcelable { */ public static final int FLAG_DEMO = 0x00000200; + /** + * @hide + */ + @IntDef(flag = true, prefix = "FLAG_", value = { + FLAG_PRIMARY, + FLAG_ADMIN, + FLAG_GUEST, + FLAG_RESTRICTED, + FLAG_INITIALIZED, + FLAG_MANAGED_PROFILE, + FLAG_DISABLED, + FLAG_QUIET_MODE, + FLAG_EPHEMERAL, + FLAG_DEMO + }) + @Retention(RetentionPolicy.SOURCE) + public @interface UserInfoFlag { + } + public static final int NO_PROFILE_GROUP_ID = UserHandle.USER_NULL; @UnsupportedAppUsage @@ -127,6 +151,18 @@ public class UserInfo implements Parcelable { @UnsupportedAppUsage public boolean guestToRemove; + /** + * This is used to optimize the creation of an user, i.e. OEMs might choose to pre-create a + * number of users at the first boot, so the actual creation later is faster. + * + *

A {@code preCreated} user is not a real user yet, so it should not show up on regular + * user operations (other than user creation per se). + * + *

Once the pre-created is used to create a "real" user later on, {@code preCreate} is set to + * {@code false}. + */ + public boolean preCreated; + @UnsupportedAppUsage public UserInfo(int id, String name, int flags) { this(id, name, null, flags); @@ -154,6 +190,13 @@ public class UserInfo implements Parcelable { @UnsupportedAppUsage public boolean isGuest() { + return isGuest(flags); + } + + /** + * Checks if the flag denotes a guest user. + */ + public static boolean isGuest(@UserInfoFlag int flags) { return (flags & FLAG_GUEST) == FLAG_GUEST; } @@ -164,6 +207,13 @@ public class UserInfo implements Parcelable { @UnsupportedAppUsage public boolean isManagedProfile() { + return isManagedProfile(flags); + } + + /** + * Checks if the flag denotes a managed profile. + */ + public static boolean isManagedProfile(@UserInfoFlag int flags) { return (flags & FLAG_MANAGED_PROFILE) == FLAG_MANAGED_PROFILE; } @@ -251,6 +301,7 @@ public class UserInfo implements Parcelable { lastLoggedInTime = orig.lastLoggedInTime; lastLoggedInFingerprint = orig.lastLoggedInFingerprint; partial = orig.partial; + preCreated = orig.preCreated; profileGroupId = orig.profileGroupId; restrictedProfileParentId = orig.restrictedProfileParentId; guestToRemove = orig.guestToRemove; @@ -267,6 +318,22 @@ public class UserInfo implements Parcelable { return "UserInfo{" + id + ":" + name + ":" + Integer.toHexString(flags) + "}"; } + /** @hide */ + public String toFullString() { + return "UserInfo[id=" + id + + ", name=" + name + + ", flags=" + flagsToString(flags) + + (preCreated ? " (pre-created)" : "") + + (partial ? " (partial)" : "") + + "]"; + } + + /** @hide */ + public static String flagsToString(int flags) { + return DebugUtils.flagsToString(UserInfo.class, "FLAG_", flags); + } + + @Override public int describeContents() { return 0; } @@ -280,9 +347,10 @@ public class UserInfo implements Parcelable { dest.writeLong(creationTime); dest.writeLong(lastLoggedInTime); dest.writeString(lastLoggedInFingerprint); - dest.writeInt(partial ? 1 : 0); + dest.writeBoolean(partial); + dest.writeBoolean(preCreated); dest.writeInt(profileGroupId); - dest.writeInt(guestToRemove ? 1 : 0); + dest.writeBoolean(guestToRemove); dest.writeInt(restrictedProfileParentId); dest.writeInt(profileBadge); } @@ -307,9 +375,10 @@ public class UserInfo implements Parcelable { creationTime = source.readLong(); lastLoggedInTime = source.readLong(); lastLoggedInFingerprint = source.readString(); - partial = source.readInt() != 0; + partial = source.readBoolean(); + preCreated = source.readBoolean(); profileGroupId = source.readInt(); - guestToRemove = source.readInt() != 0; + guestToRemove = source.readBoolean(); restrictedProfileParentId = source.readInt(); profileBadge = source.readInt(); } diff --git a/core/java/android/content/res/TypedArray.java b/core/java/android/content/res/TypedArray.java index 90affdfed39fc61e80e0a8d52cf5fe9369763a07..29c5c935c1bff1a3d8b1f75a370e99f4cede60bf 100644 --- a/core/java/android/content/res/TypedArray.java +++ b/core/java/android/content/res/TypedArray.java @@ -360,8 +360,9 @@ public class TypedArray { /** * Retrieve the boolean value for the attribute at index. *

- * If the attribute is an integer value, this method will return whether - * it is equal to zero. If the attribute is not a boolean or integer value, + * If the attribute is an integer value, this method returns false if the + * attribute is equal to zero, and true otherwise. + * If the attribute is not a boolean or integer value, * this method will attempt to coerce it to an integer using * {@link Integer#decode(String)} and return whether it is equal to zero. * diff --git a/core/java/android/hardware/camera2/params/MandatoryStreamCombination.java b/core/java/android/hardware/camera2/params/MandatoryStreamCombination.java index 6eaf54bd0d4da6d30667e7cce9e06a43ec96177b..23f18a80caf8abc8599a4b2ce69864a467490475 100644 --- a/core/java/android/hardware/camera2/params/MandatoryStreamCombination.java +++ b/core/java/android/hardware/camera2/params/MandatoryStreamCombination.java @@ -1163,7 +1163,7 @@ public final class MandatoryStreamCombination { if (orderedPreviewSizes != null) { for (Size size : orderedPreviewSizes) { if ((mDisplaySize.getWidth() >= size.getWidth()) && - (mDisplaySize.getWidth() >= size.getHeight())) { + (mDisplaySize.getHeight() >= size.getHeight())) { return size; } } diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 6ca5ff75691d7a568a0c78e4b40c362d0890cc22..d19ed7f9684117d78659973662bda2ef26716e66 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -3356,6 +3356,7 @@ public class ConnectivityManager { android.Manifest.permission.NETWORK_FACTORY}) public Network registerNetworkAgent(Messenger messenger, NetworkInfo ni, LinkProperties lp, NetworkCapabilities nc, int score, NetworkAgentConfig config, int providerId) { + try { return mService.registerNetworkAgent(messenger, ni, lp, nc, score, config, providerId); } catch (RemoteException e) { diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java index 732ceb560cab0e7388b6c135944ec32bae4e4b51..d25ee0e69e88d4de453a76347a6fc04e1745b07d 100644 --- a/core/java/android/net/LinkProperties.java +++ b/core/java/android/net/LinkProperties.java @@ -21,8 +21,6 @@ import android.annotation.Nullable; import android.annotation.SystemApi; import android.annotation.TestApi; import android.compat.annotation.UnsupportedAppUsage; -import android.net.util.LinkPropertiesUtils; -import android.net.util.LinkPropertiesUtils.CompareResult; import android.os.Build; import android.os.Parcel; import android.os.Parcelable; @@ -92,6 +90,36 @@ public final class LinkProperties implements Parcelable { // Indexed by interface name to allow modification and to prevent duplicates being added. private Hashtable mStackedLinks = new Hashtable<>(); + /** + * @hide + */ + public static class CompareResult { + public final List removed = new ArrayList<>(); + public final List added = new ArrayList<>(); + + public CompareResult() {} + + public CompareResult(Collection oldItems, Collection newItems) { + if (oldItems != null) { + removed.addAll(oldItems); + } + if (newItems != null) { + for (T newItem : newItems) { + if (!removed.remove(newItem)) { + added.add(newItem); + } + } + } + } + + @Override + public String toString() { + return "removed=[" + TextUtils.join(",", removed) + + "] added=[" + TextUtils.join(",", added) + + "]"; + } + } + /** * @hide */ @@ -1298,7 +1326,7 @@ public final class LinkProperties implements Parcelable { */ @UnsupportedAppUsage public boolean isIdenticalInterfaceName(@NonNull LinkProperties target) { - return LinkPropertiesUtils.isIdenticalInterfaceName(target, this); + return TextUtils.equals(getInterfaceName(), target.getInterfaceName()); } /** @@ -1321,7 +1349,10 @@ public final class LinkProperties implements Parcelable { */ @UnsupportedAppUsage public boolean isIdenticalAddresses(@NonNull LinkProperties target) { - return LinkPropertiesUtils.isIdenticalAddresses(target, this); + Collection targetAddresses = target.getAddresses(); + Collection sourceAddresses = getAddresses(); + return (sourceAddresses.size() == targetAddresses.size()) ? + sourceAddresses.containsAll(targetAddresses) : false; } /** @@ -1333,7 +1364,15 @@ public final class LinkProperties implements Parcelable { */ @UnsupportedAppUsage public boolean isIdenticalDnses(@NonNull LinkProperties target) { - return LinkPropertiesUtils.isIdenticalDnses(target, this); + Collection targetDnses = target.getDnsServers(); + String targetDomains = target.getDomains(); + if (mDomains == null) { + if (targetDomains != null) return false; + } else { + if (!mDomains.equals(targetDomains)) return false; + } + return (mDnses.size() == targetDnses.size()) ? + mDnses.containsAll(targetDnses) : false; } /** @@ -1386,7 +1425,9 @@ public final class LinkProperties implements Parcelable { */ @UnsupportedAppUsage public boolean isIdenticalRoutes(@NonNull LinkProperties target) { - return LinkPropertiesUtils.isIdenticalRoutes(target, this); + Collection targetRoutes = target.getRoutes(); + return (mRoutes.size() == targetRoutes.size()) ? + mRoutes.containsAll(targetRoutes) : false; } /** @@ -1398,7 +1439,8 @@ public final class LinkProperties implements Parcelable { */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) public boolean isIdenticalHttpProxy(@NonNull LinkProperties target) { - return LinkPropertiesUtils.isIdenticalHttpProxy(target, this); + return getHttpProxy() == null ? target.getHttpProxy() == null : + getHttpProxy().equals(target.getHttpProxy()); } /** @@ -1620,6 +1662,26 @@ public final class LinkProperties implements Parcelable { && isIdenticalCaptivePortalData(target); } + /** + * Compares the addresses in this LinkProperties with another + * LinkProperties, examining only addresses on the base link. + * + * @param target a LinkProperties with the new list of addresses + * @return the differences between the addresses. + * @hide + */ + public @NonNull CompareResult compareAddresses(@Nullable LinkProperties target) { + /* + * Duplicate the LinkAddresses into removed, we will be removing + * address which are common between mLinkAddresses and target + * leaving the addresses that are different. And address which + * are in target but not in mLinkAddresses are placed in the + * addedAddresses. + */ + return new CompareResult<>(mLinkAddresses, + target != null ? target.getLinkAddresses() : null); + } + /** * Compares the DNS addresses in this LinkProperties with another * LinkProperties, examining only DNS addresses on the base link. diff --git a/core/java/android/net/MacAddress.java b/core/java/android/net/MacAddress.java index 0e10c42e61db27e1a73945f99207acf503d1cb60..74c9aac05b41f3210025bef4acc7dcadd64e2dea 100644 --- a/core/java/android/net/MacAddress.java +++ b/core/java/android/net/MacAddress.java @@ -20,11 +20,11 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.compat.annotation.UnsupportedAppUsage; -import android.net.util.MacAddressUtils; import android.net.wifi.WifiInfo; import android.os.Parcel; import android.os.Parcelable; +import com.android.internal.util.BitUtils; import com.android.internal.util.Preconditions; import java.lang.annotation.Retention; @@ -33,6 +33,7 @@ import java.net.Inet6Address; import java.net.UnknownHostException; import java.security.SecureRandom; import java.util.Arrays; +import java.util.Random; /** * Representation of a MAC address. @@ -108,12 +109,20 @@ public final class MacAddress implements Parcelable { if (equals(BROADCAST_ADDRESS)) { return TYPE_BROADCAST; } - if ((mAddr & MULTICAST_MASK) != 0) { + if (isMulticastAddress()) { return TYPE_MULTICAST; } return TYPE_UNICAST; } + /** + * @return true if this MacAddress is a multicast address. + * @hide + */ + public boolean isMulticastAddress() { + return (mAddr & MULTICAST_MASK) != 0; + } + /** * @return true if this MacAddress is a locally assigned address. */ @@ -183,7 +192,7 @@ public final class MacAddress implements Parcelable { * @hide */ public static boolean isMacAddress(byte[] addr) { - return MacAddressUtils.isMacAddress(addr); + return addr != null && addr.length == ETHER_ADDR_LEN; } /** @@ -252,11 +261,26 @@ public final class MacAddress implements Parcelable { } private static byte[] byteAddrFromLongAddr(long addr) { - return MacAddressUtils.byteAddrFromLongAddr(addr); + byte[] bytes = new byte[ETHER_ADDR_LEN]; + int index = ETHER_ADDR_LEN; + while (index-- > 0) { + bytes[index] = (byte) addr; + addr = addr >> 8; + } + return bytes; } private static long longAddrFromByteAddr(byte[] addr) { - return MacAddressUtils.longAddrFromByteAddr(addr); + Preconditions.checkNotNull(addr); + if (!isMacAddress(addr)) { + throw new IllegalArgumentException( + Arrays.toString(addr) + " was not a valid MAC address"); + } + long longAddr = 0; + for (byte b : addr) { + longAddr = (longAddr << 8) + BitUtils.uint8(b); + } + return longAddr; } // Internal conversion function equivalent to longAddrFromByteAddr(byteAddrFromStringAddr(addr)) @@ -326,7 +350,50 @@ public final class MacAddress implements Parcelable { * @hide */ public static @NonNull MacAddress createRandomUnicastAddressWithGoogleBase() { - return MacAddressUtils.createRandomUnicastAddress(BASE_GOOGLE_MAC, new SecureRandom()); + return createRandomUnicastAddress(BASE_GOOGLE_MAC, new SecureRandom()); + } + + /** + * Returns a generated MAC address whose 46 bits, excluding the locally assigned bit and the + * unicast bit, are randomly selected. + * + * The locally assigned bit is always set to 1. The multicast bit is always set to 0. + * + * @return a random locally assigned, unicast MacAddress. + * + * @hide + */ + public static @NonNull MacAddress createRandomUnicastAddress() { + return createRandomUnicastAddress(null, new SecureRandom()); + } + + /** + * Returns a randomly generated MAC address using the given Random object and the same + * OUI values as the given MacAddress. + * + * The locally assigned bit is always set to 1. The multicast bit is always set to 0. + * + * @param base a base MacAddress whose OUI is used for generating the random address. + * If base == null then the OUI will also be randomized. + * @param r a standard Java Random object used for generating the random address. + * @return a random locally assigned MacAddress. + * + * @hide + */ + public static @NonNull MacAddress createRandomUnicastAddress(MacAddress base, Random r) { + long addr; + if (base == null) { + addr = r.nextLong() & VALID_LONG_MASK; + } else { + addr = (base.mAddr & OUI_MASK) | (NIC_MASK & r.nextLong()); + } + addr |= LOCALLY_ASSIGNED_MASK; + addr &= ~MULTICAST_MASK; + MacAddress mac = new MacAddress(addr); + if (mac.equals(DEFAULT_MAC_ADDRESS)) { + return createRandomUnicastAddress(base, r); + } + return mac; } // Convenience function for working around the lack of byte literals. diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java index 779f7bc91e8f4ad4edd27ab7f861883e5f04e9a3..08cc4e24b245ee3fe1ff16db3aada20096085076 100644 --- a/core/java/android/net/NetworkUtils.java +++ b/core/java/android/net/NetworkUtils.java @@ -31,6 +31,7 @@ import android.util.Pair; import java.io.FileDescriptor; import java.math.BigInteger; import java.net.Inet4Address; +import java.net.Inet6Address; import java.net.InetAddress; import java.net.SocketException; import java.net.UnknownHostException; @@ -311,6 +312,15 @@ public class NetworkUtils { return new Pair(address, prefixLength); } + /** + * Check if IP address type is consistent between two InetAddress. + * @return true if both are the same type. False otherwise. + */ + public static boolean addressTypeMatches(InetAddress left, InetAddress right) { + return (((left instanceof Inet4Address) && (right instanceof Inet4Address)) || + ((left instanceof Inet6Address) && (right instanceof Inet6Address))); + } + /** * Convert a 32 char hex string into a Inet6Address. * throws a runtime exception if the string isn't 32 chars, isn't hex or can't be diff --git a/core/java/android/net/RouteInfo.java b/core/java/android/net/RouteInfo.java index 2b9e9fe81b1b0858d02d9c341952255596f7ac6e..67bad532cd0d020f20089a1abe53300a5318ff82 100644 --- a/core/java/android/net/RouteInfo.java +++ b/core/java/android/net/RouteInfo.java @@ -22,7 +22,6 @@ import android.annotation.Nullable; import android.annotation.SystemApi; import android.annotation.TestApi; import android.compat.annotation.UnsupportedAppUsage; -import android.net.util.NetUtils; import android.os.Build; import android.os.Parcel; import android.os.Parcelable; @@ -484,7 +483,21 @@ public final class RouteInfo implements Parcelable { @UnsupportedAppUsage @Nullable public static RouteInfo selectBestRoute(Collection routes, InetAddress dest) { - return NetUtils.selectBestRoute(routes, dest); + if ((routes == null) || (dest == null)) return null; + + RouteInfo bestRoute = null; + // pick a longest prefix match under same address type + for (RouteInfo route : routes) { + if (NetworkUtils.addressTypeMatches(route.mDestination.getAddress(), dest)) { + if ((bestRoute != null) && + (bestRoute.mDestination.getPrefixLength() >= + route.mDestination.getPrefixLength())) { + continue; + } + if (route.matches(dest)) bestRoute = route; + } + } + return bestRoute; } /** diff --git a/core/java/android/net/nsd/NsdManager.java b/core/java/android/net/nsd/NsdManager.java index 535bf675cd0e54014cca8c1f9c5e25b6f6d27619..64f20b839a63880d19f029d3e19812ecb8c757b8 100644 --- a/core/java/android/net/nsd/NsdManager.java +++ b/core/java/android/net/nsd/NsdManager.java @@ -49,8 +49,8 @@ import java.util.concurrent.CountDownLatch; * limited to a local network over Multicast DNS. DNS service discovery is described at * http://files.dns-sd.org/draft-cheshire-dnsext-dns-sd.txt * - *

The API is asynchronous and responses to requests from an application are on listener - * callbacks on a seperate internal thread. + *

The API is asynchronous, and responses to requests from an application are on listener + * callbacks on a separate internal thread. * *

There are three main operations the API supports - registration, discovery and resolution. *

diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 6750fc77e705e85b0db86db50cfce583e55cbd9a..eb67492483f1e34e69ddd97b9bb5233bde9385cb 100755
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -245,7 +245,8 @@ public class Build {
         public static final String BASE_OS = SystemProperties.get("ro.build.version.base_os", "");
 
         /**
-         * The user-visible security patch level.
+         * The user-visible security patch level. This value represents the date when the device
+         * most recently applied a security patch.
          */
         public static final String SECURITY_PATCH = SystemProperties.get(
                 "ro.build.version.security_patch", "");
diff --git a/core/java/android/os/FileObserver.java b/core/java/android/os/FileObserver.java
index 4628910bfd5204d192bdbe9e10f0057a87051487..ca303d97323578b277570a1e7162a79c2a1a22a3 100644
--- a/core/java/android/os/FileObserver.java
+++ b/core/java/android/os/FileObserver.java
@@ -32,7 +32,7 @@ import java.util.List;
 
 /**
  * Monitors files (using inotify)
- * to fire an event after files are accessed or changed by by any process on
+ * to fire an event after files are accessed or changed by any process on
  * the device (including this one).  FileObserver is an abstract class;
  * subclasses must implement the event handler {@link #onEvent(int, String)}.
  *
diff --git a/core/java/android/os/IStatsManager.aidl b/core/java/android/os/IStatsManager.aidl
index e3f9326048d15daeae4d88226665e5c54886fde7..36ea1bcc91d947eb4fa04828289ea05e775dc2e4 100644
--- a/core/java/android/os/IStatsManager.aidl
+++ b/core/java/android/os/IStatsManager.aidl
@@ -224,7 +224,7 @@ interface IStatsManager {
      * Logs an event for watchdog rollbacks.
      */
      oneway void sendWatchdogRollbackOccurredAtom(in int rollbackType, in String packageName,
-         in long packageVersionCode);
+         in long packageVersionCode,  in int rollbackReason, in String failingPackageName);
 
     /**
      * Returns the most recently registered experiment IDs.
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index 63641e538b8e45c77140c40781313e4d83730e67..c30491a3965cabb5d99f6b6c750b431c00207431 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -41,6 +41,7 @@ interface IUserManager {
      */
 
     UserInfo createUser(in String name, int flags);
+    UserInfo preCreateUser(int flags);
     UserInfo createProfileForUser(in String name, int flags, int userHandle,
             in String[] disallowedPackages);
     UserInfo createRestrictedProfile(String name, int parentUserHandle);
@@ -53,7 +54,7 @@ interface IUserManager {
     void setUserIcon(int userHandle, in Bitmap icon);
     ParcelFileDescriptor getUserIcon(int userHandle);
     UserInfo getPrimaryUser();
-    List getUsers(boolean excludeDying);
+    List getUsers(boolean excludePartial, boolean excludeDying, boolean excludePreCreated);
     List getProfiles(int userHandle, boolean enabledOnly);
     int[] getProfileIds(int userId, boolean enabledOnly);
     boolean canAddMoreManagedProfiles(int userHandle, boolean allowedToRemoveOne);
@@ -92,6 +93,7 @@ interface IUserManager {
     boolean someUserHasSeedAccount(in String accountName, in String accountType);
     boolean isManagedProfile(int userId);
     boolean isDemoUser(int userId);
+    boolean isPreCreated(int userId);
     UserInfo createProfileForUserEvenWhenDisallowed(in String name, int flags, int userHandle,
             in String[] disallowedPackages);
     boolean isUserUnlockingOrUnlocked(int userId);
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 68c2764a78d7e125d595cc7019cd6cf4a0fa8726..1f2a6d9d59f89ed6e1b67d7efcbcef29a5b41d56 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -45,70 +45,10 @@ import java.util.concurrent.Executor;
  * 

* Device battery life will be significantly affected by the use of this API. * Do not acquire {@link WakeLock}s unless you really need them, use the minimum levels - * possible, and be sure to release them as soon as possible. - *

- * The primary API you'll use is {@link #newWakeLock(int, String) newWakeLock()}. - * This will create a {@link PowerManager.WakeLock} object. You can then use methods - * on the wake lock object to control the power state of the device. - *

- * In practice it's quite simple: - * {@samplecode - * PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); - * PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "My Tag"); - * wl.acquire(); - * ..screen will stay on during this section.. - * wl.release(); - * } - *

- * The following wake lock levels are defined, with varying effects on system power. - * These levels are mutually exclusive - you may only specify one of them. + * possible, and be sure to release them as soon as possible. In most cases, + * you'll want to use + * {@link android.view.WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON} instead. * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
Flag ValueCPU Screen Keyboard
{@link #PARTIAL_WAKE_LOCK}On* Off Off
{@link #SCREEN_DIM_WAKE_LOCK}On Dim Off
{@link #SCREEN_BRIGHT_WAKE_LOCK}On Bright Off
{@link #FULL_WAKE_LOCK}On Bright Bright
- *

- * *If you hold a partial wake lock, the CPU will continue to run, regardless of any - * display timeouts or the state of the screen and even after the user presses the power button. - * In all other wake locks, the CPU will run, but the user can still put the device to sleep - * using the power button. - *

- * In addition, you can add two more flags, which affect behavior of the screen only. - * These flags have no effect when combined with a {@link #PARTIAL_WAKE_LOCK}.

- * - * - * - * - * - * - * - * - * - * - * - *
Flag Value Description
{@link #ACQUIRE_CAUSES_WAKEUP}Normal wake locks don't actually turn on the illumination. Instead, they cause - * the illumination to remain on once it turns on (e.g. from user activity). This flag - * will force the screen and/or keyboard to turn on immediately, when the WakeLock is - * acquired. A typical use would be for notifications which are important for the user to - * see immediately.
{@link #ON_AFTER_RELEASE}If this flag is set, the user activity timer will be reset when the WakeLock is - * released, causing the illumination to remain on a bit longer. This can be used to - * reduce flicker if you are cycling between wake lock conditions.
*

* Any application using a WakeLock must request the {@code android.permission.WAKE_LOCK} * permission in an {@code } element of the application's manifest. @@ -923,7 +863,8 @@ public final class PowerManager { * {@link #FULL_WAKE_LOCK}, {@link #SCREEN_DIM_WAKE_LOCK} * and {@link #SCREEN_BRIGHT_WAKE_LOCK}. Exactly one wake lock level must be * specified as part of the {@code levelAndFlags} parameter. - *

+ *

+ *

* The wake lock flags are: {@link #ACQUIRE_CAUSES_WAKEUP} * and {@link #ON_AFTER_RELEASE}. Multiple flags can be combined as part of the * {@code levelAndFlags} parameters. diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index a507e2576df9847c20bbbc6c1c7a48156a80dd7c..0dfb7c380b0407ff46021ae3fce5e9470f351681 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -37,6 +37,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.IntentSender; import android.content.pm.UserInfo; +import android.content.pm.UserInfo.UserInfoFlag; import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.Bitmap; @@ -2006,18 +2007,20 @@ public class UserManager { /** * Creates a user with the specified name and options. For non-admin users, default user - * restrictions are going to be applied. - * Requires {@link android.Manifest.permission#MANAGE_USERS} permission. + * restrictions will be applied. + * + *

Requires {@link android.Manifest.permission#MANAGE_USERS} permission. * * @param name the user's name - * @param flags flags that identify the type of user and other properties. + * @param flags UserInfo flags that identify the type of user and other properties. * @see UserInfo * - * @return the UserInfo object for the created user, or null if the user could not be created. + * @return the UserInfo object for the created user, or {@code null} if the user could not be + * created. * @hide */ @UnsupportedAppUsage - public UserInfo createUser(String name, int flags) { + public @Nullable UserInfo createUser(@Nullable String name, @UserInfoFlag int flags) { UserInfo user = null; try { user = mService.createUser(name, flags); @@ -2033,6 +2036,44 @@ public class UserManager { return user; } + /** + * Pre-creates a user with the specified name and options. For non-admin users, default user + * restrictions will be applied. + * + *

This method can be used by OEMs to "warm" up the user creation by pre-creating some users + * at the first boot, so they when the "real" user is created (for example, + * by {@link #createUser(String, int)} or {@link #createGuest(Context, String)}), it takes + * less time. + * + *

This method completes the majority of work necessary for user creation: it + * creates user data, CE and DE encryption keys, app data directories, initializes the user and + * grants default permissions. When pre-created users become "real" users, only then are + * components notified of new user creation by firing user creation broadcasts. + * + *

All pre-created users are removed during system upgrade. + * + *

Requires {@link android.Manifest.permission#MANAGE_USERS} permission. + * + * @param flags UserInfo flags that identify the type of user and other properties. + * @see UserInfo + * + * @return the UserInfo object for the created user, or {@code null} if the user could not be + * created. + * + * @throw {@link IllegalArgumentException} if {@code flags} contains + * {@link UserInfo#FLAG_MANAGED_PROFILE}. + * + * @hide + */ + @RequiresPermission(android.Manifest.permission.MANAGE_USERS) + public @Nullable UserInfo preCreateUser(@UserInfoFlag int flags) { + try { + return mService.preCreateUser(flags); + } catch (RemoteException re) { + throw re.rethrowFromSystemServer(); + } + } + /** * Creates a guest user and configures it. * @param context an application context @@ -2340,6 +2381,8 @@ public class UserManager { /** * Return the number of users currently created on the device. + *

This API is not for use by third-party apps. It requires the {@code MANAGE_USERS} + * permission.

*/ public int getUserCount() { List users = getUsers(); @@ -2349,15 +2392,26 @@ public class UserManager { /** * Returns information for all users on this device, including ones marked for deletion. * To retrieve only users that are alive, use {@link #getUsers(boolean)}. - *

- * Requires {@link android.Manifest.permission#MANAGE_USERS} permission. + * * @return the list of users that exist on the device. * @hide */ @UnsupportedAppUsage + @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public List getUsers() { + return getUsers(/* excludeDying= */ false); + } + + /** + * Returns information for all users on this device, based on the filtering parameters. + * + * @hide + */ + @RequiresPermission(android.Manifest.permission.MANAGE_USERS) + public List getUsers(boolean excludePartial, boolean excludeDying, + boolean excludePreCreated) { try { - return mService.getUsers(false); + return mService.getUsers(excludePartial, excludeDying, excludePreCreated); } catch (RemoteException re) { throw re.rethrowFromSystemServer(); } @@ -2373,16 +2427,12 @@ public class UserManager { @SystemApi @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public long[] getSerialNumbersOfUsers(boolean excludeDying) { - try { - List users = mService.getUsers(excludeDying); - long[] result = new long[users.size()]; - for (int i = 0; i < result.length; i++) { - result[i] = users.get(i).serialNumber; - } - return result; - } catch (RemoteException re) { - throw re.rethrowFromSystemServer(); + List users = getUsers(excludeDying); + long[] result = new long[users.size()]; + for (int i = 0; i < result.length; i++) { + result[i] = users.get(i).serialNumber; } + return result; } /** @@ -2768,11 +2818,8 @@ public class UserManager { */ @UnsupportedAppUsage public @NonNull List getUsers(boolean excludeDying) { - try { - return mService.getUsers(excludeDying); - } catch (RemoteException re) { - throw re.rethrowFromSystemServer(); - } + return getUsers(/*excludePartial= */ true, excludeDying, + /* excludePreCreated= */ true); } /** diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index dcbbb709c5a051db0cd561e09c4f81607928f9f0..d6869c549dcfb0b8381e9cef40d314487844338e 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -660,6 +660,22 @@ public final class Settings { public static final String ACTION_NIGHT_DISPLAY_SETTINGS = "android.settings.NIGHT_DISPLAY_SETTINGS"; + /** + * Activity Action: Show settings to allow configuration of Dark theme. + *

+ * In some cases, a matching Activity may not exist, so ensure you + * safeguard against this. + *

+ * Input: Nothing. + *

+ * Output: Nothing. + * + * @hide + */ + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_DARK_THEME_SETTINGS = + "android.settings.DARK_THEME_SETTINGS"; + /** * Activity Action: Show settings to allow configuration of locale. *

@@ -7870,6 +7886,19 @@ public final class Settings { private static final Validator SILENCE_GESTURE_COUNT_VALIDATOR = NON_NEGATIVE_INTEGER_VALIDATOR; + /** + * Number of successful "Motion Sense" tap gestures to pause media. + * @hide + */ + public static final String AWARE_TAP_PAUSE_GESTURE_COUNT = "aware_tap_pause_gesture_count"; + + /** + * Number of touch interactions to pause media when a "Motion Sense" gesture could + * have been used. + * @hide + */ + public static final String AWARE_TAP_PAUSE_TOUCH_COUNT = "aware_tap_pause_touch_count"; + /** * The current night mode that has been selected by the user. Owned * and controlled by UiModeManagerService. Constants are as per @@ -8951,6 +8980,14 @@ public final class Settings { private static final Validator NAVIGATION_MODE_VALIDATOR = new SettingsValidators.DiscreteValueValidator(new String[] {"0", "1", "2"}); + /** + * Current provider of proximity-based sharing services. + * Default value in @string/config_defaultNearbySharingComponent. + * No VALIDATOR as this setting will not be backed up. + * @hide + */ + public static final String NEARBY_SHARING_COMPONENT = "nearby_sharing_component"; + /** * Controls whether aware is enabled. * @hide @@ -8967,6 +9004,14 @@ public final class Settings { private static final Validator AWARE_LOCK_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR; + /** + * Controls whether tap gesture is enabled. + * @hide + */ + public static final String TAP_GESTURE = "tap_gesture"; + + private static final Validator TAP_GESTURE_VALIDATOR = BOOLEAN_VALIDATOR; + /** * This are the settings to be backed up. * @@ -9049,8 +9094,6 @@ public final class Settings { DOZE_PICK_UP_GESTURE, DOZE_DOUBLE_TAP_GESTURE, DOZE_TAP_SCREEN_GESTURE, - DOZE_WAKE_LOCK_SCREEN_GESTURE, - DOZE_WAKE_DISPLAY_GESTURE, NFC_PAYMENT_DEFAULT_COMPONENT, AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN, FACE_UNLOCK_KEYGUARD_ENABLED, @@ -9058,9 +9101,6 @@ public final class Settings { FACE_UNLOCK_DISMISSES_KEYGUARD, FACE_UNLOCK_APP_ENABLED, FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION, - ASSIST_GESTURE_ENABLED, - ASSIST_GESTURE_SILENCE_ALERTS_ENABLED, - ASSIST_GESTURE_WAKE_ENABLED, VR_DISPLAY_MODE, NOTIFICATION_BADGING, NOTIFICATION_DISMISS_RTL, @@ -9093,12 +9133,9 @@ public final class Settings { TRUST_AGENTS_EXTEND_UNLOCK, UI_NIGHT_MODE, LOCK_SCREEN_WHEN_TRUST_LOST, - SKIP_GESTURE, SKIP_DIRECTION, - SILENCE_GESTURE, THEME_CUSTOMIZATION_OVERLAY_PACKAGES, NAVIGATION_MODE, - AWARE_ENABLED, SKIP_GESTURE_COUNT, SKIP_TOUCH_COUNT, SILENCE_ALARMS_GESTURE_COUNT, @@ -9109,7 +9146,9 @@ public final class Settings { SILENCE_TIMER_TOUCH_COUNT, DARK_MODE_DIALOG_SEEN, GLOBAL_ACTIONS_PANEL_ENABLED, - AWARE_LOCK_ENABLED + AWARE_LOCK_ENABLED, + AWARE_TAP_PAUSE_GESTURE_COUNT, + AWARE_TAP_PAUSE_TOUCH_COUNT }; /** @@ -9304,6 +9343,9 @@ public final class Settings { VALIDATORS.put(UI_NIGHT_MODE, UI_NIGHT_MODE_VALIDATOR); VALIDATORS.put(GLOBAL_ACTIONS_PANEL_ENABLED, GLOBAL_ACTIONS_PANEL_ENABLED_VALIDATOR); VALIDATORS.put(AWARE_LOCK_ENABLED, AWARE_LOCK_ENABLED_VALIDATOR); + VALIDATORS.put(AWARE_TAP_PAUSE_GESTURE_COUNT, NON_NEGATIVE_INTEGER_VALIDATOR); + VALIDATORS.put(AWARE_TAP_PAUSE_TOUCH_COUNT, NON_NEGATIVE_INTEGER_VALIDATOR); + VALIDATORS.put(TAP_GESTURE, TAP_GESTURE_VALIDATOR); } /** @@ -9883,13 +9925,34 @@ public final class Settings { * List of ISO country codes in which eUICC UI is shown. Country codes should be separated * by comma. * - *

Used to hide eUICC UI from users who are currently in countries no carriers support - * eUICC. + * Note: if {@link #EUICC_SUPPORTED_COUNTRIES} is empty, then {@link + * #EUICC_UNSUPPORTED_COUNTRIES} is used. + * + *

Used to hide eUICC UI from users who are currently in countries where no carriers + * support eUICC. + * * @hide */ //TODO(b/77914569) Changes this to System Api. public static final String EUICC_SUPPORTED_COUNTRIES = "euicc_supported_countries"; + /** + * List of ISO country codes in which eUICC UI is not shown. Country codes should be + * separated by comma. + * + * Note: if {@link #EUICC_SUPPORTED_COUNTRIES} is empty, then {@link + * #EUICC_UNSUPPORTED_COUNTRIES} is used. + * + *

Used to hide eUICC UI from users who are currently in countries where no carriers + * support eUICC. + * + * @hide + */ + //TODO(b/77914569) Changes this to System Api. + public static final String EUICC_UNSUPPORTED_COUNTRIES = "euicc_unsupported_countries"; + private static final Validator EUICC_UNSUPPORTED_COUNTRIES_VALIDATOR = + new SettingsValidators.ComponentNameListValidator(","); + /** * Whether any activity can be resized. When this is true, any * activity, regardless of manifest values, can be resized for multi-window. @@ -13860,6 +13923,7 @@ public final class Settings { VALIDATORS.put(DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD, DYNAMIC_POWER_SAVINGS_VALIDATOR); VALIDATORS.put(BLUETOOTH_ON, BLUETOOTH_ON_VALIDATOR); + VALIDATORS.put(EUICC_UNSUPPORTED_COUNTRIES, EUICC_UNSUPPORTED_COUNTRIES_VALIDATOR); VALIDATORS.put(PRIVATE_DNS_MODE, PRIVATE_DNS_MODE_VALIDATOR); VALIDATORS.put(PRIVATE_DNS_SPECIFIER, PRIVATE_DNS_SPECIFIER_VALIDATOR); VALIDATORS.put(SOFT_AP_TIMEOUT_ENABLED, SOFT_AP_TIMEOUT_ENABLED_VALIDATOR); diff --git a/core/java/android/service/autofill/FillRequest.java b/core/java/android/service/autofill/FillRequest.java index 91f77ea0462dafaf2d0729452a30f3fdb5366f32..63a38ddc2b1d108c12375ef3969af2651dbfecff 100644 --- a/core/java/android/service/autofill/FillRequest.java +++ b/core/java/android/service/autofill/FillRequest.java @@ -71,12 +71,21 @@ public final class FillRequest implements Parcelable { */ public static final int FLAG_COMPATIBILITY_MODE_REQUEST = 0x2; + /** + * Indicates the request came from a password field. + * + * (TODO: b/141703197) Temporary fix for augmented autofill showing passwords. + * + * @hide + */ + public static final @RequestFlags int FLAG_PASSWORD_INPUT_TYPE = 0x4; + /** @hide */ public static final int INVALID_REQUEST_ID = Integer.MIN_VALUE; /** @hide */ @IntDef(flag = true, prefix = { "FLAG_" }, value = { - FLAG_MANUAL_REQUEST, FLAG_COMPATIBILITY_MODE_REQUEST + FLAG_MANUAL_REQUEST, FLAG_COMPATIBILITY_MODE_REQUEST, FLAG_PASSWORD_INPUT_TYPE }) @Retention(RetentionPolicy.SOURCE) @interface RequestFlags{} @@ -100,7 +109,7 @@ public final class FillRequest implements Parcelable { @Nullable Bundle clientState, @RequestFlags int flags) { mId = id; mFlags = Preconditions.checkFlagsArgument(flags, - FLAG_MANUAL_REQUEST | FLAG_COMPATIBILITY_MODE_REQUEST); + FLAG_MANUAL_REQUEST | FLAG_COMPATIBILITY_MODE_REQUEST | FLAG_PASSWORD_INPUT_TYPE); mContexts = Preconditions.checkCollectionElementsNotNull(contexts, "contexts"); mClientState = clientState; } diff --git a/core/java/android/service/autofill/augmented/FillWindow.java b/core/java/android/service/autofill/augmented/FillWindow.java index 6a29d485b99735a561da3489b9cbed5a5dcab259..5d003706ac8308b039d1a77e526c16f77608b446 100644 --- a/core/java/android/service/autofill/augmented/FillWindow.java +++ b/core/java/android/service/autofill/augmented/FillWindow.java @@ -242,6 +242,7 @@ public final class FillWindow implements AutoCloseable { synchronized (mLock) { if (mDestroyed) return; if (mUpdateCalled) { + mFillView.setOnClickListener(null); hide(); mProxy.report(AutofillProxy.REPORT_EVENT_UI_DESTROYED); } diff --git a/core/java/android/service/contentsuggestions/ContentSuggestionsService.java b/core/java/android/service/contentsuggestions/ContentSuggestionsService.java index efc8e877f3c352f88d8b0ba1ca91d40983e3bc75..306b4830932ef85a073ad22161d91a770bc10952 100644 --- a/core/java/android/service/contentsuggestions/ContentSuggestionsService.java +++ b/core/java/android/service/contentsuggestions/ContentSuggestionsService.java @@ -64,14 +64,23 @@ public abstract class ContentSuggestionsService extends Service { @Override public void provideContextImage(int taskId, GraphicBuffer contextImage, int colorSpaceId, Bundle imageContextRequestExtras) { + if (imageContextRequestExtras.containsKey(ContentSuggestionsManager.EXTRA_BITMAP) + && contextImage != null) { + throw new IllegalArgumentException("Two bitmaps provided; expected one."); + } Bitmap wrappedBuffer = null; - if (contextImage != null) { - ColorSpace colorSpace = null; - if (colorSpaceId >= 0 && colorSpaceId < ColorSpace.Named.values().length) { - colorSpace = ColorSpace.get(ColorSpace.Named.values()[colorSpaceId]); + if (imageContextRequestExtras.containsKey(ContentSuggestionsManager.EXTRA_BITMAP)) { + wrappedBuffer = imageContextRequestExtras.getParcelable( + ContentSuggestionsManager.EXTRA_BITMAP); + } else { + if (contextImage != null) { + ColorSpace colorSpace = null; + if (colorSpaceId >= 0 && colorSpaceId < ColorSpace.Named.values().length) { + colorSpace = ColorSpace.get(ColorSpace.Named.values()[colorSpaceId]); + } + wrappedBuffer = Bitmap.wrapHardwareBuffer(contextImage, colorSpace); } - wrappedBuffer = Bitmap.wrapHardwareBuffer(contextImage, colorSpace); } mHandler.sendMessage( diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java index 5da34a343513ab2c82e36b77a41b3706b362d2c8..377f29acd1796a0ec73035a9f9b6e937203ff683 100644 --- a/core/java/android/service/notification/NotificationListenerService.java +++ b/core/java/android/service/notification/NotificationListenerService.java @@ -1514,6 +1514,7 @@ public abstract class NotificationListenerService extends Service { private ArrayList mSmartActions; private ArrayList mSmartReplies; private boolean mCanBubble; + private boolean mVisuallyInterruptive; private static final int PARCEL_VERSION = 2; @@ -1545,6 +1546,7 @@ public abstract class NotificationListenerService extends Service { out.writeTypedList(mSmartActions, flags); out.writeCharSequenceList(mSmartReplies); out.writeBoolean(mCanBubble); + out.writeBoolean(mVisuallyInterruptive); } /** @hide */ @@ -1577,6 +1579,7 @@ public abstract class NotificationListenerService extends Service { mSmartActions = in.createTypedArrayList(Notification.Action.CREATOR); mSmartReplies = in.readCharSequenceList(); mCanBubble = in.readBoolean(); + mVisuallyInterruptive = in.readBoolean(); } @@ -1763,6 +1766,11 @@ public abstract class NotificationListenerService extends Service { return mCanBubble; } + /** @hide */ + public boolean visuallyInterruptive() { + return mVisuallyInterruptive; + } + /** @hide */ public boolean isNoisy() { return mNoisy; @@ -1779,7 +1787,8 @@ public abstract class NotificationListenerService extends Service { ArrayList snoozeCriteria, boolean showBadge, int userSentiment, boolean hidden, long lastAudiblyAlertedMs, boolean noisy, ArrayList smartActions, - ArrayList smartReplies, boolean canBubble) { + ArrayList smartReplies, boolean canBubble, + boolean visuallyInterruptive) { mKey = key; mRank = rank; mIsAmbient = importance < NotificationManager.IMPORTANCE_LOW; @@ -1800,6 +1809,7 @@ public abstract class NotificationListenerService extends Service { mSmartActions = smartActions; mSmartReplies = smartReplies; mCanBubble = canBubble; + mVisuallyInterruptive = visuallyInterruptive; } /** @@ -1824,7 +1834,8 @@ public abstract class NotificationListenerService extends Service { other.mNoisy, other.mSmartActions, other.mSmartReplies, - other.mCanBubble); + other.mCanBubble, + other.mVisuallyInterruptive); } /** @@ -1876,7 +1887,8 @@ public abstract class NotificationListenerService extends Service { && ((mSmartActions == null ? 0 : mSmartActions.size()) == (other.mSmartActions == null ? 0 : other.mSmartActions.size())) && Objects.equals(mSmartReplies, other.mSmartReplies) - && Objects.equals(mCanBubble, other.mCanBubble); + && Objects.equals(mCanBubble, other.mCanBubble) + && Objects.equals(mVisuallyInterruptive, other.mVisuallyInterruptive); } } diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java index 4c08b596ee1ff0beb350429896e3f0e5d65afc4c..9f6065e695c5627e5ce8981a53562cfdb279bbbc 100755 --- a/core/java/android/util/DisplayMetrics.java +++ b/core/java/android/util/DisplayMetrics.java @@ -23,9 +23,8 @@ import android.os.SystemProperties; /** * A structure describing general information about a display, such as its * size, density, and font scaling. - *

To access the DisplayMetrics members, initialize an object like this:

- *
 DisplayMetrics metrics = new DisplayMetrics();
- * getWindowManager().getDefaultDisplay().getMetrics(metrics);
+ *

To access the DisplayMetrics members, retrieve display metrics like this:

+ *
context.getResources().getDisplayMetrics();
*/ public class DisplayMetrics { /** @@ -245,7 +244,7 @@ public class DisplayMetrics { * this density value will be 1; on a 120 dpi screen it would be .75; etc. * *

This value does not exactly follow the real screen size (as given by - * {@link #xdpi} and {@link #ydpi}, but rather is used to scale the size of + * {@link #xdpi} and {@link #ydpi}), but rather is used to scale the size of * the overall UI in steps based on gross changes in the display dpi. For * example, a 240x320 screen will have a density of 1 even if its width is * 1.8", 1.3", etc. However, if the screen resolution is increased to diff --git a/core/java/android/util/StatsLog.java b/core/java/android/util/StatsLog.java index 23fd4f2f61d3fb720cc7a6266c03fceb690d304c..9ac4cf267b4742bdb9f37535e946a3c3c525b3c6 100644 --- a/core/java/android/util/StatsLog.java +++ b/core/java/android/util/StatsLog.java @@ -179,6 +179,8 @@ public final class StatsLog extends StatsLogInternal { * @param rollbackType state of the rollback. * @param packageName package name being rolled back. * @param packageVersionCode version of the package being rolled back. + * @param rollbackReason reason the package is being rolled back. + * @param failingPackageName the package name causing the failure. * * @return True if the log request was sent to statsd. * @@ -186,7 +188,7 @@ public final class StatsLog extends StatsLogInternal { */ @RequiresPermission(allOf = {DUMP, PACKAGE_USAGE_STATS}) public static boolean logWatchdogRollbackOccurred(int rollbackType, String packageName, - long packageVersionCode) { + long packageVersionCode, int rollbackReason, String failingPackageName) { synchronized (sLogLock) { try { IStatsManager service = getIStatsManagerLocked(); @@ -198,7 +200,7 @@ public final class StatsLog extends StatsLogInternal { } service.sendWatchdogRollbackOccurredAtom(rollbackType, packageName, - packageVersionCode); + packageVersionCode, rollbackReason, failingPackageName); return true; } catch (RemoteException e) { sService = null; diff --git a/core/java/android/view/CompositionSamplingListener.java b/core/java/android/view/CompositionSamplingListener.java index e4309a6d9aa43c5630c680e3caf440755384aad5..f23bb40278ac50a22ff22cd0e92d8b9f3326c7c9 100644 --- a/core/java/android/view/CompositionSamplingListener.java +++ b/core/java/android/view/CompositionSamplingListener.java @@ -29,7 +29,7 @@ import java.util.concurrent.Executor; */ public abstract class CompositionSamplingListener { - private final long mNativeListener; + private long mNativeListener; private final Executor mExecutor; public CompositionSamplingListener(Executor executor) { @@ -37,13 +37,19 @@ public abstract class CompositionSamplingListener { mNativeListener = nativeCreate(this); } + public void destroy() { + if (mNativeListener == 0) { + return; + } + unregister(this); + nativeDestroy(mNativeListener); + mNativeListener = 0; + } + @Override protected void finalize() throws Throwable { try { - if (mNativeListener != 0) { - unregister(this); - nativeDestroy(mNativeListener); - } + destroy(); } finally { super.finalize(); } @@ -59,6 +65,9 @@ public abstract class CompositionSamplingListener { */ public static void register(CompositionSamplingListener listener, int displayId, IBinder stopLayer, Rect samplingArea) { + if (listener.mNativeListener == 0) { + return; + } Preconditions.checkArgument(displayId == Display.DEFAULT_DISPLAY, "default display only for now"); nativeRegister(listener.mNativeListener, stopLayer, samplingArea.left, samplingArea.top, @@ -69,6 +78,9 @@ public abstract class CompositionSamplingListener { * Unregisters a sampling listener. */ public static void unregister(CompositionSamplingListener listener) { + if (listener.mNativeListener == 0) { + return; + } nativeUnregister(listener.mNativeListener); } diff --git a/core/java/android/view/DisplayCutout.java b/core/java/android/view/DisplayCutout.java index 715181f28076fea529189ed272737503a476dec3..e77d7191d5b899e52a11ae41a9ebccc4552a26b6 100644 --- a/core/java/android/view/DisplayCutout.java +++ b/core/java/android/view/DisplayCutout.java @@ -66,6 +66,7 @@ public final class DisplayCutout { private static final String BOTTOM_MARKER = "@bottom"; private static final String DP_MARKER = "@dp"; private static final String RIGHT_MARKER = "@right"; + private static final String LEFT_MARKER = "@left"; /** * Category for overlays that allow emulating a display cutout on devices that don't have @@ -642,6 +643,9 @@ public final class DisplayCutout { if (spec.endsWith(RIGHT_MARKER)) { offsetX = displayWidth; spec = spec.substring(0, spec.length() - RIGHT_MARKER.length()).trim(); + } else if (spec.endsWith(LEFT_MARKER)) { + offsetX = 0; + spec = spec.substring(0, spec.length() - LEFT_MARKER.length()).trim(); } else { offsetX = displayWidth / 2f; } diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index 2c48af04aa18338a4999dce086906a9a8ca84224..fcd8127bbaa41138b37e610c2e4c48b5336292ac 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -190,8 +190,7 @@ public final class SurfaceControl implements Parcelable { private static native void nativeSetInputWindowInfo(long transactionObj, long nativeObject, InputWindowHandle handle); - private static native void nativeTransferTouchFocus(long transactionObj, IBinder fromToken, - IBinder toToken); + private static native boolean nativeGetProtectedContentSupport(); private static native void nativeSetMetadata(long transactionObj, long nativeObject, int key, Parcel data); @@ -2248,22 +2247,6 @@ public final class SurfaceControl implements Parcelable { return this; } - /** - * Transfers touch focus from one window to another. It is possible for multiple windows to - * have touch focus if they support split touch dispatch - * {@link android.view.WindowManager.LayoutParams#FLAG_SPLIT_TOUCH} but this - * method only transfers touch focus of the specified window without affecting - * other windows that may also have touch focus at the same time. - * @param fromToken The token of a window that currently has touch focus. - * @param toToken The token of the window that should receive touch focus in - * place of the first. - * @hide - */ - public Transaction transferTouchFocus(IBinder fromToken, IBinder toToken) { - nativeTransferTouchFocus(mNativeObject, fromToken, toToken); - return this; - } - /** * Waits until any changes to input windows have been sent from SurfaceFlinger to * InputFlinger before returning. diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 3313537965c4db9b5f8edcaf283a0111e9e371ce..fe60bba92739ac254fba729ce7fcd4628d53571a 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -492,7 +492,7 @@ import java.util.function.Predicate; * *

* To initiate a layout, call {@link #requestLayout}. This method is typically - * called by a view on itself when it believes that is can no longer fit within + * called by a view on itself when it believes that it can no longer fit within * its current bounds. *

* @@ -2850,7 +2850,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, /** * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL, - * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction. + * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph's text direction. * * Use with {@link #setTextAlignment(int)} */ @@ -2878,7 +2878,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, public static final int TEXT_ALIGNMENT_CENTER = 4; /** - * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved + * Align to the start of the view, which is ALIGN_LEFT if the view's resolved * layoutDirection is LTR, and ALIGN_RIGHT otherwise. * * Use with {@link #setTextAlignment(int)} @@ -2886,7 +2886,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, public static final int TEXT_ALIGNMENT_VIEW_START = 5; /** - * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved + * Align to the end of the view, which is ALIGN_RIGHT if the view's resolved * layoutDirection is LTR, and ALIGN_LEFT otherwise. * * Use with {@link #setTextAlignment(int)} @@ -3689,7 +3689,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * if the user swipes from the top of the screen. *

When system bars are hidden in immersive mode, they can be revealed temporarily with * system gestures, such as swiping from the top of the screen. These transient system bars - * will overlay app’s content, may have some degree of transparency, and will automatically + * will overlay app's content, may have some degree of transparency, and will automatically * hide after a short timeout. *

Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination @@ -10298,7 +10298,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** - * Gets the unique identifier of the window in which this View reseides. + * Gets the unique identifier of the window in which this View resides. * * @return The window accessibility id. * @@ -16136,7 +16136,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * by the most recent call to {@link #measure(int, int)}. This result is a bit mask * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}. * This should be used during measurement and layout calculations only. Use - * {@link #getHeight()} to see how wide a view is after layout. + * {@link #getHeight()} to see how high a view is after layout. * * @return The measured height of this view as a bit mask. */ @@ -26397,7 +26397,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, /** * Returns the over-scroll mode for this view. The result will be - * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS} + * one of {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS} * (allow over-scrolling only if the view content is larger than the container), * or {@link #OVER_SCROLL_NEVER}. * @@ -26414,7 +26414,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, /** * Set the over-scroll mode for this view. Valid over-scroll modes are - * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS} + * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS} * (allow over-scrolling only if the view content is larger than the container), * or {@link #OVER_SCROLL_NEVER}. * diff --git a/core/java/android/view/animation/AnimationUtils.java b/core/java/android/view/animation/AnimationUtils.java index 075b0ab728fadf11484d75e1e918f8e26c29de03..7ce0f4571f762ab23cc8d645c2927a88f0574650 100644 --- a/core/java/android/view/animation/AnimationUtils.java +++ b/core/java/android/view/animation/AnimationUtils.java @@ -127,7 +127,7 @@ public class AnimationUtils { * * @param context Application context used to access resources * @param id The resource id of the animation to load - * @return The animation object reference by the specified id + * @return The animation object referenced by the specified id * @throws NotFoundException when the animation cannot be loaded */ public static Animation loadAnimation(Context context, @AnimRes int id) @@ -208,7 +208,7 @@ public class AnimationUtils { * * @param context Application context used to access resources * @param id The resource id of the animation to load - * @return The animation object reference by the specified id + * @return The animation controller object referenced by the specified id * @throws NotFoundException when the layout animation controller cannot be loaded */ public static LayoutAnimationController loadLayoutAnimation(Context context, @AnimRes int id) @@ -331,7 +331,7 @@ public class AnimationUtils { * * @param context Application context used to access resources * @param id The resource id of the animation to load - * @return The animation object reference by the specified id + * @return The interpolator object referenced by the specified id * @throws NotFoundException */ public static Interpolator loadInterpolator(Context context, @AnimRes @InterpolatorRes int id) @@ -361,7 +361,7 @@ public class AnimationUtils { * * @param res The resources * @param id The resource id of the animation to load - * @return The interpolator object reference by the specified id + * @return The interpolator object referenced by the specified id * @throws NotFoundException * @hide */ diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java index 1f7ae0e7e2456e435594ca38e74d1f2e4d8c64c4..bfa34ed76f07deae860b820a32f5e4e047472c17 100644 --- a/core/java/android/view/autofill/AutofillManager.java +++ b/core/java/android/view/autofill/AutofillManager.java @@ -17,6 +17,7 @@ package android.view.autofill; import static android.service.autofill.FillRequest.FLAG_MANUAL_REQUEST; +import static android.service.autofill.FillRequest.FLAG_PASSWORD_INPUT_TYPE; import static android.view.autofill.Helper.sDebug; import static android.view.autofill.Helper.sVerbose; import static android.view.autofill.Helper.toList; @@ -60,6 +61,7 @@ import android.view.accessibility.AccessibilityManager; import android.view.accessibility.AccessibilityNodeInfo; import android.view.accessibility.AccessibilityNodeProvider; import android.view.accessibility.AccessibilityWindowInfo; +import android.widget.TextView; import com.android.internal.annotations.GuardedBy; import com.android.internal.logging.MetricsLogger; @@ -966,6 +968,10 @@ public final class AutofillManager { if (!isClientDisablingEnterExitEvent()) { final AutofillValue value = view.getAutofillValue(); + if (view instanceof TextView && ((TextView) view).isAnyPasswordInputType()) { + flags |= FLAG_PASSWORD_INPUT_TYPE; + } + if (!isActiveLocked()) { // Starts new session. startSessionLocked(id, null, value, flags); @@ -1130,6 +1136,10 @@ public final class AutofillManager { } else { // don't notify entered when Activity is already in background if (!isClientDisablingEnterExitEvent()) { + if (view instanceof TextView && ((TextView) view).isAnyPasswordInputType()) { + flags |= FLAG_PASSWORD_INPUT_TYPE; + } + if (!isActiveLocked()) { // Starts new session. startSessionLocked(id, bounds, null, flags); diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java index d395f5294d6c4c90b961bae8b2ee4e625c5191bd..e671708a110689d7879adde3c306b5cb6de3024c 100644 --- a/core/java/android/view/inputmethod/InputMethodManager.java +++ b/core/java/android/view/inputmethod/InputMethodManager.java @@ -92,7 +92,10 @@ import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.concurrent.CancellationException; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; /** @@ -421,6 +424,13 @@ public final class InputMethodManager { int mCursorCandStart; int mCursorCandEnd; + /** + * Initial startInput with {@link StartInputReason.WINDOW_FOCUS_GAIN} is executed + * in a background thread. Later, if there is an actual startInput it will wait on + * main thread till the background thread completes. + */ + private CompletableFuture mWindowFocusGainFuture; + /** * The instance that has previously been sent to the input method. */ @@ -645,14 +655,14 @@ public final class InputMethodManager { } catch (RemoteException e) { } } - // Check focus again in case that "onWindowFocus" is called before - // handling this message. - if (mServedView != null && canStartInput(mServedView)) { - if (checkFocusNoStartInput(mRestartOnNextWindowFocus)) { - final int reason = active ? StartInputReason.ACTIVATED_BY_IMMS - : StartInputReason.DEACTIVATED_BY_IMMS; - startInputInner(reason, null, 0, 0, 0); - } + } + // Check focus again in case that "onWindowFocus" is called before + // handling this message. + if (mServedView != null && canStartInput(mServedView)) { + if (checkFocusNoStartInput(mRestartOnNextWindowFocus)) { + final int reason = active ? StartInputReason.ACTIVATED_BY_IMMS + : StartInputReason.DEACTIVATED_BY_IMMS; + startInputInner(reason, null, 0, 0, 0); } } return; @@ -1215,6 +1225,10 @@ public final class InputMethodManager { */ void clearBindingLocked() { if (DEBUG) Log.v(TAG, "Clearing binding!"); + if (mWindowFocusGainFuture != null) { + mWindowFocusGainFuture.cancel(false /* mayInterruptIfRunning */); + mWindowFocusGainFuture = null; + } clearConnectionLocked(); setInputChannelLocked(null); mBindSequence = -1; @@ -1598,6 +1612,18 @@ public final class InputMethodManager { boolean startInputInner(@StartInputReason int startInputReason, @Nullable IBinder windowGainingFocus, @StartInputFlags int startInputFlags, @SoftInputModeFlags int softInputMode, int windowFlags) { + if (startInputReason != StartInputReason.WINDOW_FOCUS_GAIN + && mWindowFocusGainFuture != null) { + try { + mWindowFocusGainFuture.get(); + } catch (ExecutionException | InterruptedException e) { + // do nothing + } catch (CancellationException e) { + // window no longer has focus. + return true; + } + } + final View view; synchronized (mH) { view = mServedView; @@ -1951,31 +1977,38 @@ public final class InputMethodManager { startInputFlags |= StartInputFlags.FIRST_WINDOW_FOCUS_GAIN; } - if (checkFocusNoStartInput(forceNewFocus)) { - // We need to restart input on the current focus view. This - // should be done in conjunction with telling the system service - // about the window gaining focus, to help make the transition - // smooth. - if (startInputInner(StartInputReason.WINDOW_FOCUS_GAIN, rootView.getWindowToken(), - startInputFlags, softInputMode, windowFlags)) { - return; - } + final boolean forceNewFocus1 = forceNewFocus; + final int startInputFlags1 = startInputFlags; + if (mWindowFocusGainFuture != null) { + mWindowFocusGainFuture.cancel(false/* mayInterruptIfRunning */); } + mWindowFocusGainFuture = CompletableFuture.runAsync(() -> { + if (checkFocusNoStartInput(forceNewFocus1)) { + // We need to restart input on the current focus view. This + // should be done in conjunction with telling the system service + // about the window gaining focus, to help make the transition + // smooth. + if (startInputInner(StartInputReason.WINDOW_FOCUS_GAIN, rootView.getWindowToken(), + startInputFlags1, softInputMode, windowFlags)) { + return; + } + } - // For some reason we didn't do a startInput + windowFocusGain, so - // we'll just do a window focus gain and call it a day. - synchronized (mH) { - try { - if (DEBUG) Log.v(TAG, "Reporting focus gain, without startInput"); - mService.startInputOrWindowGainedFocus( - StartInputReason.WINDOW_FOCUS_GAIN_REPORT_ONLY, mClient, - rootView.getWindowToken(), startInputFlags, softInputMode, windowFlags, - null, null, 0 /* missingMethodFlags */, - rootView.getContext().getApplicationInfo().targetSdkVersion); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); + // For some reason we didn't do a startInput + windowFocusGain, so + // we'll just do a window focus gain and call it a day. + synchronized (mH) { + try { + if (DEBUG) Log.v(TAG, "Reporting focus gain, without startInput"); + mService.startInputOrWindowGainedFocus( + StartInputReason.WINDOW_FOCUS_GAIN_REPORT_ONLY, mClient, + rootView.getWindowToken(), startInputFlags1, softInputMode, windowFlags, + null, null, 0 /* missingMethodFlags */, + rootView.getContext().getApplicationInfo().targetSdkVersion); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } - } + }); } /** @hide */ @@ -1990,6 +2023,10 @@ public final class InputMethodManager { // If the mCurRootView is losing window focus, release the strong reference to it // so as not to prevent it from being garbage-collected. mCurRootView = null; + if (mWindowFocusGainFuture != null) { + mWindowFocusGainFuture.cancel(false /* mayInterruptIfRunning */); + mWindowFocusGainFuture = null; + } } else { if (DEBUG) { Log.v(TAG, "Ignoring onPreWindowFocus()." diff --git a/core/java/android/webkit/CookieManager.java b/core/java/android/webkit/CookieManager.java index 23d12374453fd74af2478b0b941b6b868d6fea4f..3824c22a40a733f554a461fda298ee84402d9f1e 100644 --- a/core/java/android/webkit/CookieManager.java +++ b/core/java/android/webkit/CookieManager.java @@ -22,7 +22,10 @@ import android.net.WebAddress; /** * Manages the cookies used by an application's {@link WebView} instances. - * Cookies are manipulated according to RFC2109. + *

+ * CookieManager represents cookies as strings in the same format as the + * HTTP {@code Cookie} and {@code Set-Cookie} header fields (defined in + * RFC6265bis). */ public abstract class CookieManager { /** diff --git a/core/java/android/webkit/WebChromeClient.java b/core/java/android/webkit/WebChromeClient.java index 4db630808ef1be54c3e42c93c4a603deb186a6c6..f8522edb7dcd22af7ad6ac7d022ff0839f201d67 100644 --- a/core/java/android/webkit/WebChromeClient.java +++ b/core/java/android/webkit/WebChromeClient.java @@ -71,11 +71,24 @@ public class WebChromeClient { } /** - * Notify the host application that the current page has entered full - * screen mode. The host application must show the custom View which - * contains the web contents — video or other HTML content — - * in full screen mode. Also see "Full screen support" documentation on - * {@link WebView}. + * Notify the host application that the current page has entered full screen mode. After this + * call, web content will no longer be rendered in the WebView, but will instead be rendered + * in {@code view}. The host application should add this View to a Window which is configured + * with {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN} flag in order to + * actually display this web content full screen. + * + *

The application may explicitly exit fullscreen mode by invoking {@code callback} (ex. when + * the user presses the back button). However, this is generally not necessary as the web page + * will often show its own UI to close out of fullscreen. Regardless of how the WebView exits + * fullscreen mode, WebView will invoke {@link #onHideCustomView()}, signaling for the + * application to remove the custom View. + * + *

If this method is not overridden, WebView will report to the web page it does not support + * fullscreen mode and will not honor the web page's request to run in fullscreen mode. + * + *

Note: if overriding this method, the application must also override + * {@link #onHideCustomView()}. + * * @param view is the View object to be shown. * @param callback invoke this callback to request the page to exit * full screen mode. @@ -98,10 +111,13 @@ public class WebChromeClient { CustomViewCallback callback) {}; /** - * Notify the host application that the current page has exited full - * screen mode. The host application must hide the custom View, ie. the - * View passed to {@link #onShowCustomView} when the content entered fullscreen. - * Also see "Full screen support" documentation on {@link WebView}. + * Notify the host application that the current page has exited full screen mode. The host + * application must hide the custom View (the View which was previously passed to {@link + * #onShowCustomView(View, CustomViewCallback) onShowCustomView()}). After this call, web + * content will render in the original WebView again. + * + *

Note: if overriding this method, the application must also override + * {@link #onShowCustomView(View, CustomViewCallback) onShowCustomView()}. */ public void onHideCustomView() {} diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java index 8a5b64d95f19bf17c9a61eb0e70f4242f99bacb6..2d27a789ebcbd210f1bb47716d110f98961311ca 100644 --- a/core/java/android/webkit/WebSettings.java +++ b/core/java/android/webkit/WebSettings.java @@ -328,6 +328,9 @@ public abstract class WebSettings { *

* The built-in mechanisms are the only currently supported zoom * mechanisms, so it is recommended that this setting is always enabled. + * However, on-screen zoom controls are deprecated in Android (see + * {@link android.widget.ZoomButtonsController}) so it's recommended to + * disable {@link #setDisplayZoomControls}. * * @param enabled whether the WebView should use its built-in zoom mechanisms */ @@ -347,7 +350,9 @@ public abstract class WebSettings { /** * Sets whether the WebView should display on-screen zoom controls when * using the built-in zoom mechanisms. See {@link #setBuiltInZoomControls}. - * The default is {@code true}. + * The default is {@code true}. However, on-screen zoom controls are deprecated + * in Android (see {@link android.widget.ZoomButtonsController}) so it's + * recommended to set this to {@code false}. * * @param enabled whether the WebView should display on-screen zoom controls */ diff --git a/core/java/android/widget/ArrayAdapter.java b/core/java/android/widget/ArrayAdapter.java index 6c38c8b9a0f59955851c03066c693589b9475c2d..de9f76d6eea17b4cc7a1a2e7fb13317a3d321608 100644 --- a/core/java/android/widget/ArrayAdapter.java +++ b/core/java/android/widget/ArrayAdapter.java @@ -49,9 +49,6 @@ import java.util.List; * To customize what type of view is used for the data object, * override {@link #getView(int, View, ViewGroup)} * and inflate a view resource. - * For a code example, see - * the - * CustomChoiceList sample. *

*

* For an example of using an array adapter with a ListView, see the diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java index 72603444f5ff5fbf9fb307e09d5a0905435e1055..53ea793071abdc5b8291647d8ae647e07e60c1fd 100644 --- a/core/java/android/widget/ListView.java +++ b/core/java/android/widget/ListView.java @@ -120,10 +120,6 @@ import java.util.function.Predicate; * * Making ListView Scrolling Smooth for more ways to ensure a smooth user experience.

* - *

For a more complete example of creating a custom adapter, see the - * - * Custom Choice List sample app.

- * *

To specify an action when a user clicks or taps on a single list item, see * * Handling click events.

diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java index b2fedf7a3a7fd7bc907f509118efca4686e43196..e4a34b943657d7afc6fd8d904912e97fe5501a04 100644 --- a/core/java/android/widget/NumberPicker.java +++ b/core/java/android/widget/NumberPicker.java @@ -1268,12 +1268,12 @@ public class NumberPicker extends LinearLayout { * current value is set to the {@link NumberPicker#getMaxValue()} value. *

*

- * If the argument is less than the {@link NumberPicker#getMaxValue()} and + * If the argument is more than the {@link NumberPicker#getMaxValue()} and * {@link NumberPicker#getWrapSelectorWheel()} is false the * current value is set to the {@link NumberPicker#getMaxValue()} value. *

*

- * If the argument is less than the {@link NumberPicker#getMaxValue()} and + * If the argument is more than the {@link NumberPicker#getMaxValue()} and * {@link NumberPicker#getWrapSelectorWheel()} is true the * current value is set to the {@link NumberPicker#getMinValue()} value. *

diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java index 521922df97e020c6329cf5f88d93b08afc32d577..d8624f9d3e9e29269e7637e36daa88d106d8f015 100644 --- a/core/java/android/widget/RelativeLayout.java +++ b/core/java/android/widget/RelativeLayout.java @@ -72,7 +72,7 @@ import java.util.TreeSet; * *

This behavior has been preserved for apps that set android:targetSdkVersion="17" * or older in their manifest's uses-sdk tag for compatibility. Apps targeting SDK - * version 18 or newer will receive the correct behavior

+ * version 18 or newer will receive the correct behavior.

* *

See the Relative * Layout guide.

diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 65711db01e368247be04ca840fce393d0ec3e8ee..75d83438efda6ed72e1b0ff2c7018475f2c83398 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -6582,6 +6582,16 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return mTransformation instanceof PasswordTransformationMethod; } + /** + * Returns true if the current inputType is any type of password. + * + * @hide + */ + public boolean isAnyPasswordInputType() { + final int inputType = getInputType(); + return isPasswordInputType(inputType) || isVisiblePasswordInputType(inputType); + } + static boolean isPasswordInputType(int inputType) { final int variation = inputType & (EditorInfo.TYPE_MASK_CLASS | EditorInfo.TYPE_MASK_VARIATION); diff --git a/core/java/com/android/internal/app/AbstractResolverComparator.java b/core/java/com/android/internal/app/AbstractResolverComparator.java index 9ac979b5471657920c3b1994165651a5a143dd75..3a6a71d8eab6aff44f4fde15a2bef377fd3c3d70 100644 --- a/core/java/com/android/internal/app/AbstractResolverComparator.java +++ b/core/java/com/android/internal/app/AbstractResolverComparator.java @@ -30,6 +30,7 @@ import android.util.Log; import com.android.internal.app.ResolverActivity.ResolvedComponentInfo; +import java.text.Collator; import java.util.ArrayList; import java.util.Comparator; import java.util.List; @@ -37,7 +38,7 @@ import java.util.List; /** * Used to sort resolved activities in {@link ResolverListController}. */ -abstract class AbstractResolverComparator implements Comparator { +public abstract class AbstractResolverComparator implements Comparator { private static final int NUM_OF_TOP_ANNOTATIONS_TO_USE = 3; private static final boolean DEBUG = false; @@ -62,6 +63,8 @@ abstract class AbstractResolverComparator implements Comparator mAzComparator; + protected final Handler mHandler = new Handler(Looper.getMainLooper()) { public void handleMessage(Message msg) { switch (msg.what) { @@ -90,7 +93,7 @@ abstract class AbstractResolverComparator implements Comparator { + Collator mCollator; + AzInfoComparator(Context context) { + mCollator = Collator.getInstance(context.getResources().getConfiguration().locale); + } + + @Override + public int compare(ResolveInfo lhsp, ResolveInfo rhsp) { + if (lhsp == null) { + return -1; + } else if (rhsp == null) { + return 1; + } + return mCollator.compare(lhsp.activityInfo.packageName, rhsp.activityInfo.packageName); + } + } + } diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java index c0c9dd32a52a0fd7b77cc385401acbfe1e956ac3..e130eb22fc2ae4e93f024ed83683cb6d6b7dc4a6 100644 --- a/core/java/com/android/internal/app/ChooserActivity.java +++ b/core/java/com/android/internal/app/ChooserActivity.java @@ -44,6 +44,7 @@ import android.content.IntentFilter; import android.content.IntentSender; import android.content.IntentSender.SendIntentException; import android.content.ServiceConnection; +import android.content.SharedPreferences; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.LabeledIntent; @@ -54,6 +55,7 @@ import android.content.pm.ResolveInfo; import android.content.pm.ShortcutInfo; import android.content.pm.ShortcutManager; import android.content.res.Configuration; +import android.content.res.Resources; import android.database.Cursor; import android.database.DataSetObserver; import android.graphics.Bitmap; @@ -69,6 +71,7 @@ import android.metrics.LogMaker; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; +import android.os.Environment; import android.os.Handler; import android.os.IBinder; import android.os.Message; @@ -78,10 +81,12 @@ import android.os.RemoteException; import android.os.ResultReceiver; import android.os.UserHandle; import android.os.UserManager; +import android.os.storage.StorageManager; import android.provider.DeviceConfig; import android.provider.DocumentsContract; import android.provider.Downloads; import android.provider.OpenableColumns; +import android.provider.Settings; import android.service.chooser.ChooserTarget; import android.service.chooser.ChooserTargetService; import android.service.chooser.IChooserTargetResult; @@ -104,6 +109,7 @@ import android.view.animation.AccelerateInterpolator; import android.view.animation.DecelerateInterpolator; import android.widget.AbsListView; import android.widget.BaseAdapter; +import android.widget.Button; import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; @@ -120,9 +126,11 @@ import com.android.internal.widget.ResolverDrawerLayout; import com.google.android.collect.Lists; +import java.io.File; import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.net.URISyntaxException; import java.text.Collator; import java.util.ArrayList; import java.util.Arrays; @@ -156,6 +164,9 @@ public class ChooserActivity extends ResolverActivity { private static final String PREF_NUM_SHEET_EXPANSIONS = "pref_num_sheet_expansions"; + private static final String CHIP_LABEL_METADATA_KEY = "android.service.chooser.chip_label"; + private static final String CHIP_ICON_METADATA_KEY = "android.service.chooser.chip_icon"; + private static final boolean DEBUG = false; /** @@ -256,6 +267,9 @@ public class ChooserActivity extends ResolverActivity { private static final int MAX_EXTRA_INITIAL_INTENTS = 2; private static final int MAX_EXTRA_CHOOSER_TARGETS = 2; + private SharedPreferences mPinnedSharedPrefs; + private static final String PINNED_SHARED_PREFS_NAME = "chooser_pin_settings"; + private boolean mListViewDataChanged = false; @Retention(SOURCE) @@ -519,6 +533,15 @@ public class ChooserActivity extends ResolverActivity { mIsSuccessfullySelected = false; Intent intent = getIntent(); Parcelable targetParcelable = intent.getParcelableExtra(Intent.EXTRA_INTENT); + if (targetParcelable instanceof Uri) { + try { + targetParcelable = Intent.parseUri(targetParcelable.toString(), + Intent.URI_INTENT_SCHEME); + } catch (URISyntaxException ex) { + // doesn't parse as an intent; let the next test fail and error out + } + } + if (!(targetParcelable instanceof Intent)) { Log.w("ChooserActivity", "Target is not an intent: " + targetParcelable); finish(); @@ -600,6 +623,8 @@ public class ChooserActivity extends ResolverActivity { Intent.EXTRA_CHOOSER_REFINEMENT_INTENT_SENDER); setSafeForwardingMode(true); + mPinnedSharedPrefs = getPinnedSharedPrefs(this); + pa = intent.getParcelableArrayExtra(Intent.EXTRA_EXCLUDE_COMPONENTS); if (pa != null) { ComponentName[] names = new ComponentName[pa.length]; @@ -731,6 +756,23 @@ public class ChooserActivity extends ResolverActivity { } } + + static SharedPreferences getPinnedSharedPrefs(Context context) { + // The code below is because in the android:ui process, no one can hear you scream. + // The package info in the context isn't initialized in the way it is for normal apps, + // so the standard, name-based context.getSharedPreferences doesn't work. Instead, we + // build the path manually below using the same policy that appears in ContextImpl. + // This fails silently under the hood if there's a problem, so if we find ourselves in + // the case where we don't have access to credential encrypted storage we just won't + // have our pinned target info. + final File prefsFile = new File(new File( + Environment.getDataUserCePackageDirectory(StorageManager.UUID_PRIVATE_INTERNAL, + context.getUserId(), context.getPackageName()), + "shared_prefs"), + PINNED_SHARED_PREFS_NAME + ".xml"); + return context.getSharedPreferences(prefsFile, MODE_PRIVATE); + } + /** * Returns true if app prediction service is defined and the component exists on device. */ @@ -778,12 +820,19 @@ public class ChooserActivity extends ResolverActivity { return new PackageMonitor() { @Override public void onSomePackagesChanged() { - mAdapter.handlePackagesChanged(); - bindProfileView(); + handlePackagesChanged(); } }; } + /** + * Update UI to reflect changes in data. + */ + public void handlePackagesChanged() { + mAdapter.handlePackagesChanged(); + bindProfileView(); + } + private void onCopyButtonClicked(View v) { Intent targetIntent = getTargetIntent(); if (targetIntent == null) { @@ -868,6 +917,108 @@ public class ChooserActivity extends ResolverActivity { } } + private ComponentName getNearbySharingComponent() { + String nearbyComponent = Settings.Secure.getString( + getContentResolver(), + Settings.Secure.NEARBY_SHARING_COMPONENT); + if (TextUtils.isEmpty(nearbyComponent)) { + nearbyComponent = getString(R.string.config_defaultNearbySharingComponent); + } + if (TextUtils.isEmpty(nearbyComponent)) { + return null; + } + return ComponentName.unflattenFromString(nearbyComponent); + } + + private TargetInfo getNearbySharingTarget(Intent originalIntent) { + final ComponentName cn = getNearbySharingComponent(); + if (cn == null) return null; + + final Intent resolveIntent = new Intent(); + resolveIntent.setComponent(cn); + final ResolveInfo ri = getPackageManager().resolveActivity( + resolveIntent, PackageManager.GET_META_DATA); + if (ri == null || ri.activityInfo == null) { + Log.e(TAG, "Device-specified nearby sharing component (" + cn + + ") not available"); + return null; + } + + // Allow the nearby sharing component to provide a more appropriate icon and label + // for the chip. + CharSequence name = null; + Drawable icon = null; + final Bundle metaData = ri.activityInfo.metaData; + if (metaData != null) { + try { + final Resources pkgRes = getPackageManager().getResourcesForActivity(cn); + final int nameResId = metaData.getInt(CHIP_LABEL_METADATA_KEY); + name = pkgRes.getString(nameResId); + final int resId = metaData.getInt(CHIP_ICON_METADATA_KEY); + icon = pkgRes.getDrawable(resId); + } catch (Resources.NotFoundException ex) { + } catch (NameNotFoundException ex) { + } + } + if (TextUtils.isEmpty(name)) { + name = ri.loadLabel(getPackageManager()); + } + if (icon == null) { + icon = ri.loadIcon(getPackageManager()); + } + + final DisplayResolveInfo dri = new DisplayResolveInfo( + originalIntent, ri, name, "", null); + dri.setDisplayIcon(icon); + return dri; + } + + private Button createActionButton(Drawable icon, CharSequence title, View.OnClickListener r) { + Button b = (Button) LayoutInflater.from(this).inflate(R.layout.chooser_action_button, null); + if (icon != null) { + final int size = getResources() + .getDimensionPixelSize(R.dimen.chooser_action_button_icon_size); + icon.setBounds(0, 0, size, size); + b.setCompoundDrawablesRelative(icon, null, null, null); + } + b.setText(title); + b.setOnClickListener(r); + return b; + } + + private Button createCopyButton() { + final Button b = createActionButton( + getDrawable(R.drawable.ic_menu_copy_material), + getString(R.string.copy), this::onCopyButtonClicked); + b.setId(R.id.chooser_copy_button); + return b; + } + + private @Nullable Button createNearbyButton(Intent originalIntent) { + final TargetInfo ti = getNearbySharingTarget(originalIntent); + if (ti == null) return null; + + return createActionButton( + ti.getDisplayIcon(), + ti.getDisplayLabel(), + (View unused) -> { + safelyStartActivity(ti); + finish(); + } + ); + } + + private void addActionButton(ViewGroup parent, Button b) { + if (b == null) return; + final ViewGroup.MarginLayoutParams lp = new ViewGroup.MarginLayoutParams( + LayoutParams.WRAP_CONTENT, + LayoutParams.WRAP_CONTENT + ); + final int gap = getResources().getDimensionPixelSize(R.dimen.resolver_icon_margin) / 2; + lp.setMarginsRelative(gap, 0, gap, 0); + parent.addView(b, lp); + } + private ViewGroup displayContentPreview(@ContentPreviewType int previewType, Intent targetIntent, LayoutInflater layoutInflater, ViewGroup convertView, ViewGroup parent) { @@ -901,8 +1052,10 @@ public class ChooserActivity extends ResolverActivity { ViewGroup contentPreviewLayout = (ViewGroup) layoutInflater.inflate( R.layout.chooser_grid_preview_text, parent, false); - contentPreviewLayout.findViewById(R.id.copy_button).setOnClickListener( - this::onCopyButtonClicked); + final ViewGroup actionRow = + (ViewGroup) contentPreviewLayout.findViewById(R.id.chooser_action_row); + addActionButton(actionRow, createCopyButton()); + addActionButton(actionRow, createNearbyButton(targetIntent)); CharSequence sharingText = targetIntent.getCharSequenceExtra(Intent.EXTRA_TEXT); if (sharingText == null) { @@ -1060,7 +1213,8 @@ public class ChooserActivity extends ResolverActivity { // TODO(b/120417119): Disable file copy until after moving to sysui, // due to permissions issues - contentPreviewLayout.findViewById(R.id.file_copy_button).setVisibility(View.GONE); + //((ViewGroup) contentPreviewLayout.findViewById(R.id.chooser_action_row)) + // .addView(createCopyButton()); String action = targetIntent.getAction(); if (Intent.ACTION_SEND.equals(action)) { @@ -1277,9 +1431,10 @@ public class ChooserActivity extends ResolverActivity { } ComponentName name = ri.activityInfo.getComponentName(); + boolean pinned = mPinnedSharedPrefs.getBoolean(name.flattenToString(), false); ResolverTargetActionsDialogFragment f = new ResolverTargetActionsDialogFragment(ri.loadLabel(getPackageManager()), - name); + name, pinned); f.show(getFragmentManager(), TARGET_DETAILS_FRAGMENT_TAG); } @@ -1511,7 +1666,7 @@ public class ChooserActivity extends ResolverActivity { } return new IntentFilter(intent.getAction(), dataString); } catch (Exception e) { - Log.e(TAG, "failed to get target intent filter " + e); + Log.e(TAG, "failed to get target intent filter", e); return null; } } @@ -1956,6 +2111,12 @@ public class ChooserActivity extends ResolverActivity { } return false; } + + @Override + public boolean isComponentPinned(ComponentName name) { + return mPinnedSharedPrefs.getBoolean(name.flattenToString(), false); + } + } @Override @@ -2089,6 +2250,10 @@ public class ChooserActivity extends ResolverActivity { public boolean isSuspended() { return false; } + + public boolean isPinned() { + return false; + } } final class PlaceHolderTargetInfo extends NotSelectableTargetInfo { @@ -2177,6 +2342,10 @@ public class ChooserActivity extends ResolverActivity { return mIsSuspended; } + public boolean isPinned() { + return mSourceInfo != null && mSourceInfo.isPinned(); + } + /** * Since ShortcutInfos are returned by ShortcutManager, we can cache the shortcuts and skip * the call to LauncherApps#getShortcuts(ShortcutQuery). @@ -2428,6 +2597,12 @@ public class ChooserActivity extends ResolverActivity { } } + @Override + protected boolean shouldAddFooterView() { + // To accommodate for window insets + return true; + } + public class ChooserListAdapter extends ResolveListAdapter { public static final int TARGET_BAD = -1; public static final int TARGET_CALLER = 0; diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java index 871e4f84f3b6c9cb87a47427d3fd470c535c6c02..d42c0bc5661aa61dec4f75c118da296e205ed7dd 100644 --- a/core/java/com/android/internal/app/ResolverActivity.java +++ b/core/java/com/android/internal/app/ResolverActivity.java @@ -386,30 +386,47 @@ public class ResolverActivity extends Activity { finish(); } + /** + * Numerous layouts are supported, each with optional ViewGroups. + * Make sure the inset gets added to the correct View, using + * a footer for Lists so it can properly scroll under the navbar. + */ + protected boolean shouldAddFooterView() { + if (useLayoutWithDefault()) return true; + + View buttonBar = findViewById(R.id.button_bar); + if (buttonBar == null || buttonBar.getVisibility() == View.GONE) return true; + + return false; + } + protected WindowInsets onApplyWindowInsets(View v, WindowInsets insets) { mSystemWindowInsets = insets.getSystemWindowInsets(); mResolverDrawerLayout.setPadding(mSystemWindowInsets.left, mSystemWindowInsets.top, mSystemWindowInsets.right, 0); + resetButtonBar(); + + // Need extra padding so the list can fully scroll up + if (shouldAddFooterView()) { + if (mFooterSpacer == null) { + mFooterSpacer = new Space(getApplicationContext()); + } else { + ((ListView) mAdapterView).removeFooterView(mFooterSpacer); + } + mFooterSpacer.setLayoutParams(new AbsListView.LayoutParams(LayoutParams.MATCH_PARENT, + mSystemWindowInsets.bottom)); + ((ListView) mAdapterView).addFooterView(mFooterSpacer); + } + View emptyView = findViewById(R.id.empty); if (emptyView != null) { emptyView.setPadding(0, 0, 0, mSystemWindowInsets.bottom - + getResources().getDimensionPixelSize( - R.dimen.chooser_edge_margin_normal) * 2); + + getResources().getDimensionPixelSize( + R.dimen.chooser_edge_margin_normal) * 2); } - if (mFooterSpacer == null) { - mFooterSpacer = new Space(getApplicationContext()); - } else { - ((ListView) mAdapterView).removeFooterView(mFooterSpacer); - } - mFooterSpacer.setLayoutParams(new AbsListView.LayoutParams(LayoutParams.MATCH_PARENT, - mSystemWindowInsets.bottom)); - ((ListView) mAdapterView).addFooterView(mFooterSpacer); - - resetButtonBar(); - return insets.consumeSystemWindowInsets(); } @@ -565,7 +582,7 @@ public class ResolverActivity extends Activity { intent.getData().getHost(), mAdapter.getFilteredItem().getDisplayLabel()); } else if (mAdapter.areAllTargetsBrowsers()) { - dialogTitle = getString(ActionTitle.BROWSABLE_TITLE_RES); + dialogTitle = getString(ActionTitle.BROWSABLE_TITLE_RES); } else { dialogTitle = getString(ActionTitle.BROWSABLE_HOST_TITLE_RES, intent.getData().getHost()); @@ -1308,6 +1325,7 @@ public class ResolverActivity extends Activity { // In case this method is called again (due to activity recreation), avoid adding a new // header if one is already present. if (useHeader && listView != null && listView.getHeaderViewsCount() == 0) { + listView.setHeaderDividersEnabled(true); listView.addHeaderView(LayoutInflater.from(this).inflate( R.layout.resolver_different_item_header, listView, false)); } @@ -1350,11 +1368,13 @@ public class ResolverActivity extends Activity { final ViewGroup buttonLayout = findViewById(R.id.button_bar); if (buttonLayout != null) { buttonLayout.setVisibility(View.VISIBLE); - int inset = mSystemWindowInsets != null ? mSystemWindowInsets.bottom : 0; - buttonLayout.setPadding(buttonLayout.getPaddingLeft(), buttonLayout.getPaddingTop(), - buttonLayout.getPaddingRight(), getResources().getDimensionPixelSize( - R.dimen.resolver_button_bar_spacing) + inset); + if (!useLayoutWithDefault()) { + int inset = mSystemWindowInsets != null ? mSystemWindowInsets.bottom : 0; + buttonLayout.setPadding(buttonLayout.getPaddingLeft(), buttonLayout.getPaddingTop(), + buttonLayout.getPaddingRight(), getResources().getDimensionPixelSize( + R.dimen.resolver_button_bar_spacing) + inset); + } mOnceButton = (Button) buttonLayout.findViewById(R.id.button_once); mAlwaysButton = (Button) buttonLayout.findViewById(R.id.button_always); @@ -1411,6 +1431,7 @@ public class ResolverActivity extends Activity { private final Intent mResolvedIntent; private final List mSourceIntents = new ArrayList<>(); private boolean mIsSuspended; + private boolean mPinned = false; public DisplayResolveInfo(Intent originalIntent, ResolveInfo pri, CharSequence pLabel, CharSequence pInfo, Intent pOrigIntent) { @@ -1514,6 +1535,15 @@ public class ResolverActivity extends Activity { public boolean isSuspended() { return mIsSuspended; } + + @Override + public boolean isPinned() { + return mPinned; + } + + public void setPinned(boolean pinned) { + mPinned = pinned; + } } List getDisplayList() { @@ -1614,6 +1644,11 @@ public class ResolverActivity extends Activity { * @return true if this target can be selected by the user */ boolean isSuspended(); + + /** + * @return true if this target should be pinned to the front by the request of the user + */ + boolean isPinned(); } public class ResolveListAdapter extends BaseAdapter { @@ -1920,6 +1955,10 @@ public class ResolverActivity extends Activity { final Intent replaceIntent = getReplacementIntent(add.activityInfo, intent); final DisplayResolveInfo dri = new DisplayResolveInfo(intent, add, roLabel, extraInfo, replaceIntent); + dri.setPinned(rci.isPinned()); + if (rci.isPinned()) { + Log.i(TAG, "Pinned item: " + rci.name); + } addResolveInfo(dri); if (replaceIntent == intent) { // Only add alternates if we didn't get a specific replacement from @@ -2061,7 +2100,9 @@ public class ResolverActivity extends Activity { CharSequence subLabel = info.getExtendedInfo(); if (TextUtils.equals(label, subLabel)) subLabel = null; - if (!TextUtils.equals(holder.text2.getText(), subLabel)) { + if (!TextUtils.equals(holder.text2.getText(), subLabel) + && !TextUtils.isEmpty(subLabel)) { + holder.text2.setVisibility(View.VISIBLE); holder.text2.setText(subLabel); } @@ -2086,6 +2127,7 @@ public class ResolverActivity extends Activity { public final ComponentName name; private final List mIntents = new ArrayList<>(); private final List mResolveInfos = new ArrayList<>(); + private boolean mPinned; public ResolvedComponentInfo(ComponentName name, Intent intent, ResolveInfo info) { this.name = name; @@ -2126,6 +2168,15 @@ public class ResolverActivity extends Activity { } return -1; } + + public boolean isPinned() { + return mPinned; + } + + public void setPinned(boolean pinned) { + mPinned = pinned; + } + } static class ViewHolder { diff --git a/core/java/com/android/internal/app/ResolverListController.java b/core/java/com/android/internal/app/ResolverListController.java index 5f92cddbaa38c0f3df37f15d75a10f3ddf01ebe7..7efd5e16392c27ce02d7b67cb55b0a939962bccb 100644 --- a/core/java/com/android/internal/app/ResolverListController.java +++ b/core/java/com/android/internal/app/ResolverListController.java @@ -156,11 +156,22 @@ public class ResolverListController { newInfo.activityInfo.packageName, newInfo.activityInfo.name); final ResolverActivity.ResolvedComponentInfo rci = new ResolverActivity.ResolvedComponentInfo(name, intent, newInfo); + rci.setPinned(isComponentPinned(name)); into.add(rci); } } } + + /** + * Whether this component is pinned by the user. Always false for resolver; overridden in + * Chooser. + */ + public boolean isComponentPinned(ComponentName name) { + return false; + } + + // Filter out any activities that the launched uid does not have permission for. // To preserve the inputList, optionally will return the original list if any modification has // been made. diff --git a/core/java/com/android/internal/app/ResolverTargetActionsDialogFragment.java b/core/java/com/android/internal/app/ResolverTargetActionsDialogFragment.java index a49240cd0019c6d092e708240d8dca251110cebd..aec4bfab373c625d0b7c12efa1d63c58cf28d313 100644 --- a/core/java/com/android/internal/app/ResolverTargetActionsDialogFragment.java +++ b/core/java/com/android/internal/app/ResolverTargetActionsDialogFragment.java @@ -23,6 +23,7 @@ import android.app.DialogFragment; import android.content.ComponentName; import android.content.DialogInterface; import android.content.Intent; +import android.content.SharedPreferences; import android.net.Uri; import android.os.Bundle; import android.provider.Settings; @@ -36,26 +37,33 @@ public class ResolverTargetActionsDialogFragment extends DialogFragment implements DialogInterface.OnClickListener { private static final String NAME_KEY = "componentName"; private static final String TITLE_KEY = "title"; + private static final String PINNED_KEY = "pinned"; // Sync with R.array.resolver_target_actions_* resources - private static final int APP_INFO_INDEX = 0; + private static final int TOGGLE_PIN_INDEX = 0; + private static final int APP_INFO_INDEX = 1; public ResolverTargetActionsDialogFragment() { } - public ResolverTargetActionsDialogFragment(CharSequence title, ComponentName name) { + public ResolverTargetActionsDialogFragment(CharSequence title, ComponentName name, + boolean pinned) { Bundle args = new Bundle(); args.putCharSequence(TITLE_KEY, title); args.putParcelable(NAME_KEY, name); + args.putBoolean(PINNED_KEY, pinned); setArguments(args); } @Override public Dialog onCreateDialog(Bundle savedInstanceState) { final Bundle args = getArguments(); + final int itemRes = args.getBoolean(PINNED_KEY, false) + ? R.array.resolver_target_actions_unpin + : R.array.resolver_target_actions_pin; return new Builder(getContext()) .setCancelable(true) - .setItems(R.array.resolver_target_actions, this) + .setItems(itemRes, this) .setTitle(args.getCharSequence(TITLE_KEY)) .create(); } @@ -65,6 +73,19 @@ public class ResolverTargetActionsDialogFragment extends DialogFragment final Bundle args = getArguments(); ComponentName name = args.getParcelable(NAME_KEY); switch (which) { + case TOGGLE_PIN_INDEX: + SharedPreferences sp = ChooserActivity.getPinnedSharedPrefs(getContext()); + final String key = name.flattenToString(); + boolean currentVal = sp.getBoolean(name.flattenToString(), false); + if (currentVal) { + sp.edit().remove(key).apply(); + } else { + sp.edit().putBoolean(key, true).apply(); + } + + // Force the chooser to requery and resort things + ((ChooserActivity) getActivity()).handlePackagesChanged(); + break; case APP_INFO_INDEX: Intent in = new Intent().setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) .setData(Uri.fromParts("package", name.getPackageName(), null)) diff --git a/core/java/com/android/internal/car/ICarStatsService.aidl b/core/java/com/android/internal/car/ICarStatsService.aidl new file mode 100644 index 0000000000000000000000000000000000000000..170b448ba33ff6e72dfdcc65cc5aed73e1b83661 --- /dev/null +++ b/core/java/com/android/internal/car/ICarStatsService.aidl @@ -0,0 +1,31 @@ +/* + * 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.internal.car; + +import android.os.StatsLogEventWrapper; + +/** + * Interface for pulling statsd atoms from automotive devices. + * + * @hide + */ +interface ICarStatsService { + /** + * Pull the specified atom. Results will be sent to statsd when complete. + */ + StatsLogEventWrapper[] pullData(int atomId); +} diff --git a/core/java/com/android/internal/colorextraction/ColorExtractor.java b/core/java/com/android/internal/colorextraction/ColorExtractor.java index 3003ce80cbc1b41d9ab4b5401d20e1383ca12270..f0da0d5decd714af9e868467bd3e4bc764473321 100644 --- a/core/java/com/android/internal/colorextraction/ColorExtractor.java +++ b/core/java/com/android/internal/colorextraction/ColorExtractor.java @@ -73,8 +73,10 @@ public class ColorExtractor implements WallpaperManager.OnColorsChangedListener } mOnColorsChangedListeners = new ArrayList<>(); - wallpaperManager.addOnColorsChangedListener(this, null /* handler */); - initExtractColors(wallpaperManager, immediately); + if (wallpaperManager.isWallpaperSupported()) { + wallpaperManager.addOnColorsChangedListener(this, null /* handler */); + initExtractColors(wallpaperManager, immediately); + } } private void initExtractColors(WallpaperManager wallpaperManager, boolean immediately) { diff --git a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java index 33b53253768674bd247566aadd09159f3ef3f2ab..334e61a241935075e9f3f5547e39400c8742972d 100644 --- a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java +++ b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java @@ -47,6 +47,20 @@ public final class SystemUiDeviceConfigFlags { */ public static final String NAS_MAX_SUGGESTIONS = "nas_max_suggestions"; + // Flags related to screenshot intelligence + + /** + * (bool) Whether to enable smart actions in screenshot notifications. + */ + public static final String ENABLE_SCREENSHOT_NOTIFICATION_SMART_ACTIONS = + "enable_screenshot_notification_smart_actions"; + + /** + * (int) Timeout value in ms to get smart actions for screenshot notification. + */ + public static final String SCREENSHOT_NOTIFICATION_SMART_ACTIONS_TIMEOUT_MS = + "screenshot_notification_smart_actions_timeout_ms"; + // Flags related to Smart Suggestions - these are read in SmartReplyConstants. /** (boolean) Whether to enable smart suggestions in notifications. */ diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 3d6f233679d783c3ff1361d3742d3fafe44d94f0..5d50582517a370ea49f187f131c061bf6aaca8c8 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -1872,6 +1872,7 @@ public class BatteryStatsImpl extends BatteryStats { mCount = computeCurrentCountLocked(); mUnpluggedReportedTotalTime = mCurrentReportedTotalTime = 0; mUnpluggedReportedCount = mCurrentReportedCount = 0; + mTrackingReportedValues = false; } public void setUpdateVersion(int version) { diff --git a/core/java/com/android/internal/util/ScreenshotHelper.java b/core/java/com/android/internal/util/ScreenshotHelper.java index cac691cf7d451f74d2983f1a58c624a222bc1325..d24d78c6f3dab793598b1b5263cef15853cfca0b 100644 --- a/core/java/com/android/internal/util/ScreenshotHelper.java +++ b/core/java/com/android/internal/util/ScreenshotHelper.java @@ -6,6 +6,7 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; +import android.net.Uri; import android.os.Handler; import android.os.IBinder; import android.os.Message; @@ -58,7 +59,7 @@ public class ScreenshotHelper { */ public void takeScreenshot(final int screenshotType, final boolean hasStatus, final boolean hasNav, @NonNull Handler handler, - @Nullable Consumer completionConsumer) { + @Nullable Consumer completionConsumer) { takeScreenshot(screenshotType, hasStatus, hasNav, SCREENSHOT_TIMEOUT_MS, handler, completionConsumer); } @@ -83,12 +84,12 @@ public class ScreenshotHelper { * the screenshot attempt will be cancelled and `completionConsumer` * will be run. * @param handler A handler used in case the screenshot times out - * @param completionConsumer Consumes `false` if a screenshot was not taken, and `true` if the - * screenshot was taken. + * @param completionConsumer Consumes `null` if a screenshot was not taken, and the URI of the + * screenshot if the screenshot was taken. */ public void takeScreenshot(final int screenshotType, final boolean hasStatus, final boolean hasNav, long timeoutMs, @NonNull Handler handler, - @Nullable Consumer completionConsumer) { + @Nullable Consumer completionConsumer) { synchronized (mScreenshotLock) { if (mScreenshotConnection != null) { return; @@ -108,7 +109,7 @@ public class ScreenshotHelper { } } if (completionConsumer != null) { - completionConsumer.accept(false); + completionConsumer.accept(null); } } }; @@ -134,8 +135,9 @@ public class ScreenshotHelper { handler.removeCallbacks(mScreenshotTimeout); } } + if (completionConsumer != null) { - completionConsumer.accept(true); + completionConsumer.accept((Uri) msg.obj); } } }; @@ -148,7 +150,7 @@ public class ScreenshotHelper { } catch (RemoteException e) { Log.e(TAG, "Couldn't take screenshot: " + e); if (completionConsumer != null) { - completionConsumer.accept(false); + completionConsumer.accept(null); } } } diff --git a/core/jni/android/graphics/ByteBufferStreamAdaptor.cpp b/core/jni/android/graphics/ByteBufferStreamAdaptor.cpp index 173818b13837ce38cb7805618d8e1374b226dfa0..d443fd8cdf14cb63dbb99022a27f9926ebcd9792 100644 --- a/core/jni/android/graphics/ByteBufferStreamAdaptor.cpp +++ b/core/jni/android/graphics/ByteBufferStreamAdaptor.cpp @@ -1,6 +1,7 @@ #include "ByteBufferStreamAdaptor.h" #include "core_jni_helpers.h" #include "Utils.h" +#include #include @@ -9,6 +10,24 @@ using namespace android; static jmethodID gByteBuffer_getMethodID; static jmethodID gByteBuffer_setPositionMethodID; +/** + * Helper method for accessing the JNI interface pointer. + * + * Image decoding (which this supports) is started on a thread that is already + * attached to the Java VM. But an AnimatedImageDrawable continues decoding on + * the AnimatedImageThread, which is not attached. This will attach if + * necessary. + */ +static JNIEnv* requireEnv(JavaVM* jvm) { + JNIEnv* env; + if (jvm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_6) != JNI_OK) { + if (jvm->AttachCurrentThreadAsDaemon(&env, nullptr) != JNI_OK) { + LOG_ALWAYS_FATAL("Failed to AttachCurrentThread!"); + } + } + return env; +} + class ByteBufferStream : public SkStreamAsset { private: ByteBufferStream(JavaVM* jvm, jobject jbyteBuffer, size_t initialPosition, size_t length, @@ -46,7 +65,7 @@ public: } ~ByteBufferStream() override { - auto* env = get_env_or_die(mJvm); + auto* env = requireEnv(mJvm); env->DeleteGlobalRef(mByteBuffer); env->DeleteGlobalRef(mStorage); } @@ -63,7 +82,7 @@ public: return this->setPosition(mPosition + size) ? size : 0; } - auto* env = get_env_or_die(mJvm); + auto* env = requireEnv(mJvm); size_t bytesRead = 0; do { const size_t requested = (size > kStorageSize) ? kStorageSize : size; @@ -146,7 +165,7 @@ private: // Range has already been checked by the caller. bool setPosition(size_t newPosition) { - auto* env = get_env_or_die(mJvm); + auto* env = requireEnv(mJvm); env->CallObjectMethod(mByteBuffer, gByteBuffer_setPositionMethodID, newPosition + mInitialPosition); if (env->ExceptionCheck()) { @@ -185,7 +204,7 @@ public: } ~ByteArrayStream() override { - auto* env = get_env_or_die(mJvm); + auto* env = requireEnv(mJvm); env->DeleteGlobalRef(mByteArray); } @@ -197,7 +216,7 @@ public: return 0; } - auto* env = get_env_or_die(mJvm); + auto* env = requireEnv(mJvm); if (buffer) { env->GetByteArrayRegion(mByteArray, mPosition + mOffset, size, reinterpret_cast(buffer)); diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp index ff14a2acc4d776b52f0c5172e3f870d7b0ff82fa..ca10c8d5a25286a0492f35e575a20d44e990ae59 100644 --- a/core/jni/android_view_Surface.cpp +++ b/core/jni/android_view_Surface.cpp @@ -488,7 +488,7 @@ static jlong create(JNIEnv* env, jclass clazz, jlong rootNodePtr, jlong surfaceP proxy->setWideGamut(true); } proxy->setSwapBehavior(SwapBehavior::kSwap_discardBuffer); - proxy->setSurface(surface); + proxy->setSurface(surface, false); // Shadows can't be used via this interface, so just set the light source // to all 0s. proxy->setLightAlpha(0, 0); diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp index 030d3be8a6707b7cce377d3e1a5f112942f8f687..b2aef78a79af5daa7555835f6c4f1254c29a4cbf 100644 --- a/core/jni/android_view_SurfaceControl.cpp +++ b/core/jni/android_view_SurfaceControl.cpp @@ -463,15 +463,6 @@ static void nativeSetInputWindowInfo(JNIEnv* env, jclass clazz, jlong transactio transaction->setInputWindowInfo(ctrl, *handle->getInfo()); } -static void nativeTransferTouchFocus(JNIEnv* env, jclass clazz, jlong transactionObj, - jobject fromTokenObj, jobject toTokenObj) { - auto transaction = reinterpret_cast(transactionObj); - - sp fromToken(ibinderForJavaObject(env, fromTokenObj)); - sp toToken(ibinderForJavaObject(env, toTokenObj)); - transaction->transferTouchFocus(fromToken, toToken); -} - static void nativeSyncInputWindows(JNIEnv* env, jclass clazz, jlong transactionObj) { auto transaction = reinterpret_cast(transactionObj); transaction->syncInputWindows(); @@ -1381,8 +1372,6 @@ static const JNINativeMethod sSurfaceControlMethods[] = { (void*)nativeCaptureLayers }, {"nativeSetInputWindowInfo", "(JJLandroid/view/InputWindowHandle;)V", (void*)nativeSetInputWindowInfo }, - {"nativeTransferTouchFocus", "(JLandroid/os/IBinder;Landroid/os/IBinder;)V", - (void*)nativeTransferTouchFocus }, {"nativeSetMetadata", "(JJILandroid/os/Parcel;)V", (void*)nativeSetMetadata }, {"nativeGetDisplayedContentSamplingAttributes", diff --git a/core/proto/android/app/settings_enums.proto b/core/proto/android/app/settings_enums.proto index 5690af59236f3845a45eaee4abdce8f414d51239..59797f7f4bf6c56aa3a7bf593098916e7b60d00c 100644 --- a/core/proto/android/app/settings_enums.proto +++ b/core/proto/android/app/settings_enums.proto @@ -2417,10 +2417,15 @@ enum PageId { // OS: Q SETTINGS_AWARE_DISPLAY = 1750; + // OPEN: Settings > System > Input & Gesture > tap gesture + // CATEGORY: SETTINGS + // OS: Q + SETTINGS_GESTURE_TAP = 1751; + // OPEN: Settings > Developer Options > Platform Compat // CATEGORY: SETTINGS // OS: R - SETTINGS_PLATFORM_COMPAT_DASHBOARD = 1805; + SETTINGS_PLATFORM_COMPAT_DASHBOARD = 1805; // OPEN: Settings > Developer Options > Wireless debugging // CATEGORY: SETTINGS @@ -2436,6 +2441,7 @@ enum PageId { // OPEN: Settings > Developer Options > Wireless debugging // > Pair device with QR code > Scan QR code > Pairing device dialog // CATEGORY: SETTINGS + // OS: R ADB_WIRELESS_DEVICE_QR_PAIRING_DIALOG = 1833; // OPEN: Settings > Developer Options > Wireless debugging diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto index ca7131477cdc985a4ab365d87b2abdcfc5a7db2e..3d99b726e6fe02240880d0d18413c4c27cf841d9 100644 --- a/core/proto/android/providers/settings/global.proto +++ b/core/proto/android/providers/settings/global.proto @@ -385,6 +385,7 @@ message GlobalSettingsProto { optional SettingProto provisioned = 1 [ (android.privacy).dest = DEST_AUTOMATIC ]; optional SettingProto factory_reset_timeout_millis = 2 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto unsupported_countries = 3 [ (android.privacy).dest = DEST_AUTOMATIC ]; } optional Euicc euicc = 52; diff --git a/core/proto/android/providers/settings/secure.proto b/core/proto/android/providers/settings/secure.proto index 61799eefdca643a44b6657102cde9c816af470ba..ef413b9b04cf24cc297f029b226ff17b2749b44f 100644 --- a/core/proto/android/providers/settings/secure.proto +++ b/core/proto/android/providers/settings/secure.proto @@ -211,6 +211,11 @@ message SecureSettingsProto { optional SettingProto silence_timer_touch_count = 11 [ (android.privacy).dest = DEST_AUTOMATIC ]; optional SettingProto skip_touch_count = 12 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto aware_tap_pause_gesture_count = 13 [ + (android.privacy).dest = + DEST_AUTOMATIC ]; + optional SettingProto aware_tap_pause_touch_count = 14 [ (android.privacy).dest = + DEST_AUTOMATIC ]; } optional Gesture gesture = 74; diff --git a/core/proto/android/service/notification.proto b/core/proto/android/service/notification.proto index 1ec05fb5e9fc2e0d98b47e7b560cad8a2302350a..ecb4193a2c6c1eb5c2fc39b522bb1955db748ad1 100644 --- a/core/proto/android/service/notification.proto +++ b/core/proto/android/service/notification.proto @@ -264,3 +264,14 @@ message ZenPolicyProto { optional Sender priority_calls = 16; optional Sender priority_messages = 17; } + +// Next Tag: 2 +message PackageRemoteViewInfoProto { + optional string package_name = 1; + // add per-package additional info here (like channels) +} + +// Next Tag: 2 +message NotificationRemoteViewsProto { + repeated PackageRemoteViewInfoProto package_remote_view_info = 1; +} \ No newline at end of file diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index e8cfa272a7a581ef2bacf23a3e446bd0e31fc8f4..9817cebf1c8340d4c9fbc1b8fffd02e271bd9b86 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -346,6 +346,10 @@ + + + + diff --git a/core/res/res/drawable/chooser_action_button_bg.xml b/core/res/res/drawable/chooser_action_button_bg.xml new file mode 100644 index 0000000000000000000000000000000000000000..a434c0b9b6a9b0b459e9195fdedafc2cdb7a7291 --- /dev/null +++ b/core/res/res/drawable/chooser_action_button_bg.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + diff --git a/core/res/res/drawable/ic_content_copy_gm2.xml b/core/res/res/drawable/ic_content_copy_gm2.xml deleted file mode 100644 index ee58738b75d00196e4b38dbc16878e2d7385eec0..0000000000000000000000000000000000000000 --- a/core/res/res/drawable/ic_content_copy_gm2.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - diff --git a/core/res/res/drawable/ic_menu_copy_material.xml b/core/res/res/drawable/ic_menu_copy_material.xml index c03723b1fb339a6c94455e2d5083c9c4723858d2..8c9f1c514b97bb1a320d2678b32598b5e28e1c0d 100644 --- a/core/res/res/drawable/ic_menu_copy_material.xml +++ b/core/res/res/drawable/ic_menu_copy_material.xml @@ -1,26 +1,27 @@ - + - + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24" + android:autoMirrored="true" + android:tint="?attr/colorControlNormal"> + diff --git a/core/res/res/layout/chooser_action_button.xml b/core/res/res/layout/chooser_action_button.xml new file mode 100644 index 0000000000000000000000000000000000000000..119b2e90292d6da5722d3ec30b9fdca8e81d7e3d --- /dev/null +++ b/core/res/res/layout/chooser_action_button.xml @@ -0,0 +1,30 @@ + + +