diff options
249 files changed, 3241 insertions, 1785 deletions
diff --git a/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java b/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java index 4b7a7f624a3e..32107b4e789e 100644 --- a/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java +++ b/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java @@ -119,9 +119,20 @@ public class UserLifecycleTests { } @Test + public void createUser() { + while (mRunner.keepRunning()) { + final int userId = createUserNoFlags(); + + mRunner.pauseTiming(); + removeUser(userId); + mRunner.resumeTiming(); + } + } + + @Test public void createAndStartUser() throws Exception { while (mRunner.keepRunning()) { - final int userId = createUser(); + final int userId = createUserNoFlags(); final CountDownLatch latch = new CountDownLatch(1); registerBroadcastReceiver(Intent.ACTION_USER_STARTED, latch, userId); @@ -140,7 +151,7 @@ public class UserLifecycleTests { while (mRunner.keepRunning()) { mRunner.pauseTiming(); final int startUser = mAm.getCurrentUser(); - final int userId = createUser(); + final int userId = createUserNoFlags(); mRunner.resumeTiming(); switchUser(userId); @@ -197,7 +208,7 @@ public class UserLifecycleTests { public void stopUser() throws Exception { while (mRunner.keepRunning()) { mRunner.pauseTiming(); - final int userId = createUser(); + final int userId = createUserNoFlags(); final CountDownLatch latch = new CountDownLatch(1); registerBroadcastReceiver(Intent.ACTION_USER_STARTED, latch, userId); mIam.startUserInBackground(userId); @@ -217,7 +228,7 @@ public class UserLifecycleTests { while (mRunner.keepRunning()) { mRunner.pauseTiming(); final int startUser = mAm.getCurrentUser(); - final int userId = createUser(); + final int userId = createUserNoFlags(); final CountDownLatch latch = new CountDownLatch(1); registerUserSwitchObserver(null, latch, userId); mRunner.resumeTiming(); @@ -237,7 +248,7 @@ public class UserLifecycleTests { while (mRunner.keepRunning()) { mRunner.pauseTiming(); final int startUser = mAm.getCurrentUser(); - final int userId = createUser(UserInfo.FLAG_EPHEMERAL | UserInfo.FLAG_DEMO); + final int userId = createUserWithFlags(UserInfo.FLAG_EPHEMERAL | UserInfo.FLAG_DEMO); switchUser(userId); final CountDownLatch latch = new CountDownLatch(1); InstrumentationRegistry.getContext().registerReceiver(new BroadcastReceiver() { @@ -396,7 +407,6 @@ public class UserLifecycleTests { public void managedProfileCreateUnlockInstallAndLaunchApp() throws Exception { assumeTrue(mHasManagedUserFeature); - final String packageName = "perftests.multiuser.apps.dummyapp"; while (mRunner.keepRunning()) { mRunner.pauseTiming(); WindowManagerGlobal.getWindowManagerService().dismissKeyguard(null, null); @@ -433,12 +443,12 @@ public class UserLifecycleTests { } /** Creates a new user, returning its userId. */ - private int createUser() { - return createUser(0); + private int createUserNoFlags() { + return createUserWithFlags(/* flags= */ 0); } /** Creates a new user with the given flags, returning its userId. */ - private int createUser(int flags) { + private int createUserWithFlags(int flags) { int userId = mUm.createUser("TestUser", flags).id; mUsersToRemove.add(userId); return userId; @@ -501,7 +511,7 @@ public class UserLifecycleTests { private int initializeNewUserAndSwitchBack(boolean stopNewUser) throws Exception { final int origUser = mAm.getCurrentUser(); // First, create and switch to testUser, waiting for its ACTION_USER_UNLOCKED - final int testUser = createUser(); + final int testUser = createUserNoFlags(); final CountDownLatch latch1 = new CountDownLatch(1); registerBroadcastReceiver(Intent.ACTION_USER_UNLOCKED, latch1, testUser); mAm.switchUser(testUser); diff --git a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java index d0e38b4a4e36..65aaf20ecacb 100644 --- a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java +++ b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java @@ -67,6 +67,7 @@ import android.os.UserHandle; import android.provider.Settings; import android.util.ArrayMap; import android.util.ArraySet; +import android.util.AtomicFile; import android.util.KeyValueListParser; import android.util.MutableLong; import android.util.Pair; @@ -79,7 +80,6 @@ import android.util.Xml; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.IBatteryStats; -import com.android.internal.os.AtomicFile; import com.android.internal.os.BackgroundThread; import com.android.internal.util.DumpUtils; import com.android.internal.util.FastXmlSerializer; diff --git a/api/current.txt b/api/current.txt index 359ce3aa4373..26c90dff3c6b 100644 --- a/api/current.txt +++ b/api/current.txt @@ -5320,10 +5320,12 @@ package android.app { ctor public Notification(android.os.Parcel); method public android.app.Notification clone(); method public int describeContents(); + method @Nullable public android.util.Pair<android.app.RemoteInput,android.app.Notification.Action> findRemoteInputActionPair(boolean); method public boolean getAllowSystemGeneratedContextualActions(); method public int getBadgeIconType(); method @Nullable public android.app.Notification.BubbleMetadata getBubbleMetadata(); method public String getChannelId(); + method @NonNull public java.util.List<android.app.Notification.Action> getContextualActions(); method public String getGroup(); method public int getGroupAlertBehavior(); method public android.graphics.drawable.Icon getLargeIcon(); @@ -5719,6 +5721,7 @@ package android.app { method public String getDataMimeType(); method public android.net.Uri getDataUri(); method public android.os.Bundle getExtras(); + method @NonNull public static java.util.List<android.app.Notification.MessagingStyle.Message> getMessagesFromBundleArray(@Nullable android.os.Parcelable[]); method @Deprecated public CharSequence getSender(); method @Nullable public android.app.Person getSenderPerson(); method public CharSequence getText(); @@ -5816,6 +5819,7 @@ package android.app { method public android.net.Uri getSound(); method public long[] getVibrationPattern(); method public boolean hasUserSetImportance(); + method public boolean hasUserSetSound(); method public void setAllowBubbles(boolean); method public void setBypassDnd(boolean); method public void setDescription(String); @@ -41736,6 +41740,7 @@ package android.service.notification { method public int getUid(); method public android.os.UserHandle getUser(); method @Deprecated public int getUserId(); + method public boolean isAppGroup(); method public boolean isClearable(); method public boolean isGroup(); method public boolean isOngoing(); diff --git a/api/system-current.txt b/api/system-current.txt index 1c5f772f2e1b..2843916c25b7 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -521,8 +521,6 @@ package android.app { } public class Notification implements android.os.Parcelable { - method @Nullable public android.util.Pair<android.app.RemoteInput,android.app.Notification.Action> findRemoteInputActionPair(boolean); - method @NonNull public java.util.List<android.app.Notification.Action> getContextualActions(); field public static final String CATEGORY_CAR_EMERGENCY = "car_emergency"; field public static final String CATEGORY_CAR_INFORMATION = "car_information"; field public static final String CATEGORY_CAR_WARNING = "car_warning"; @@ -531,10 +529,6 @@ package android.app { field public static final int FLAG_AUTOGROUP_SUMMARY = 1024; // 0x400 } - public static final class Notification.MessagingStyle.Message { - method @Nullable public static android.app.Notification.MessagingStyle.Message getMessageFromBundle(@NonNull android.os.Bundle); - } - public static final class Notification.TvExtender implements android.app.Notification.Extender { ctor public Notification.TvExtender(); ctor public Notification.TvExtender(android.app.Notification); @@ -6710,10 +6704,6 @@ package android.service.notification { field @NonNull public static final android.os.Parcelable.Creator<android.service.notification.SnoozeCriterion> CREATOR; } - public class StatusBarNotification implements android.os.Parcelable { - method public boolean isAppGroup(); - } - } package android.service.oemlock { @@ -9319,7 +9309,7 @@ package android.telephony.ims.feature { field public static final int STATE_UNAVAILABLE = 0; // 0x0 } - public static class ImsFeature.Capabilities { + @Deprecated public static class ImsFeature.Capabilities { field @Deprecated protected int mCapabilities; } @@ -9353,7 +9343,7 @@ package android.telephony.ims.feature { public static class MmTelFeature.MmTelCapabilities extends android.telephony.ims.feature.ImsFeature.Capabilities { ctor public MmTelFeature.MmTelCapabilities(); ctor @Deprecated public MmTelFeature.MmTelCapabilities(android.telephony.ims.feature.ImsFeature.Capabilities); - ctor public MmTelFeature.MmTelCapabilities(int); + ctor public MmTelFeature.MmTelCapabilities(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int); method public final void addCapabilities(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int); method public final boolean isCapable(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int); method public final void removeCapabilities(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int); diff --git a/api/test-current.txt b/api/test-current.txt index 43b9086a8dec..6e28f67e9a68 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -97,8 +97,7 @@ package android.app { method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public void removeStacksInWindowingModes(int[]) throws java.lang.SecurityException; method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public void removeStacksWithActivityTypes(int[]) throws java.lang.SecurityException; method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public void resizeDockedStack(android.graphics.Rect, android.graphics.Rect); - method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public void resizeStack(int, android.graphics.Rect) throws java.lang.SecurityException; - method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public void resizeStack(int, android.graphics.Rect, boolean); + method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public void resizePinnedStack(int, android.graphics.Rect, boolean); method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public void resizeTask(int, android.graphics.Rect); method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public void setDisplayToSingleTaskInstance(int); method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public void setTaskWindowingMode(int, int, boolean) throws java.lang.SecurityException; diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp index 19fa64073183..c9a4b3ba6368 100644 --- a/cmds/statsd/Android.bp +++ b/cmds/statsd/Android.bp @@ -65,7 +65,7 @@ cc_defaults { "src/condition/condition_util.cpp", "src/condition/SimpleConditionTracker.cpp", "src/condition/ConditionWizard.cpp", - "src/condition/StateTracker.cpp", + "src/condition/StateConditionTracker.cpp", "src/config/ConfigKey.cpp", "src/config/ConfigListener.cpp", "src/config/ConfigManager.cpp", @@ -204,6 +204,10 @@ cc_test { ], srcs: [ + // atom_field_options.proto needs field_options.proto, but that is + // not included in libprotobuf-cpp-lite, so compile it here. + ":libprotobuf-internal-protos", + "src/atom_field_options.proto", "src/atoms.proto", "src/stats_log.proto", @@ -227,7 +231,7 @@ cc_test { "tests/FieldValue_test.cpp", "tests/condition/CombinationConditionTracker_test.cpp", "tests/condition/SimpleConditionTracker_test.cpp", - "tests/condition/StateTracker_test.cpp", + "tests/condition/StateConditionTracker_test.cpp", "tests/condition/ConditionTimer_test.cpp", "tests/metrics/OringDurationTracker_test.cpp", "tests/metrics/MaxDurationTracker_test.cpp", @@ -262,11 +266,11 @@ cc_test { ], proto: { - type: "full", + type: "lite", include_dirs: ["external/protobuf/src"], }, - shared_libs: ["libprotobuf-cpp-full"], + shared_libs: ["libprotobuf-cpp-lite"], } @@ -279,6 +283,10 @@ cc_benchmark { defaults: ["statsd_defaults"], srcs: [ + // atom_field_options.proto needs field_options.proto, but that is + // not included in libprotobuf-cpp-lite, so compile it here. + ":libprotobuf-internal-protos", + "src/atom_field_options.proto", "src/atoms.proto", "src/stats_log.proto", @@ -293,7 +301,7 @@ cc_benchmark { ], proto: { - type: "full", + type: "lite", include_dirs: ["external/protobuf/src"], }, @@ -315,7 +323,7 @@ cc_benchmark { shared_libs: [ "libgtest_prod", "libstatslog", - "libprotobuf-cpp-full", + "libprotobuf-cpp-lite", ], } diff --git a/cmds/statsd/src/anomaly/AnomalyTracker.cpp b/cmds/statsd/src/anomaly/AnomalyTracker.cpp index d1dcb5df7838..7ace44eef564 100644 --- a/cmds/statsd/src/anomaly/AnomalyTracker.cpp +++ b/cmds/statsd/src/anomaly/AnomalyTracker.cpp @@ -24,6 +24,7 @@ #include "subscriber/IncidentdReporter.h" #include "subscriber/SubscriberReporter.h" +#include <inttypes.h> #include <statslog.h> #include <time.h> @@ -224,7 +225,7 @@ void AnomalyTracker::declareAnomaly(const int64_t& timestampNs, int64_t metricId } if (!mSubscriptions.empty()) { - ALOGI("An anomaly (%lld) %s has occurred! Informing subscribers.", + ALOGI("An anomaly (%" PRId64 ") %s has occurred! Informing subscribers.", mAlert.id(), key.toString().c_str()); informSubscribers(key, metricId, metricValue); } else { diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto index 2c8a5562c979..ae751ce6d7ab 100644 --- a/cmds/statsd/src/atoms.proto +++ b/cmds/statsd/src/atoms.proto @@ -334,6 +334,7 @@ message Atom { BackGesture back_gesture_reported_reported = 224; UpdateEngineUpdateAttemptReported update_engine_update_attempt_reported = 225; UpdateEngineSuccessfulUpdateReported update_engine_successful_update_reported = 226; + CameraActionEvent camera_action_event = 227; } // Pulled events will start at field 10000. @@ -7164,3 +7165,29 @@ message FrameTimingHistogram { // It's required that len(time_millis) == len(frame_count) repeated int64 frame_counts = 2; } + + +/** + * Information about camera facing and API level usage. + * Logged from: + * frameworks/base/services/core/java/com/android/server/camera/CameraServiceProxy.java + */ +message CameraActionEvent { + // Camera session duration + optional int64 duration = 1; + + // Camera API level used + optional int32 api_level = 2; + + // Name of client package + optional string package_name = 3; + + // Camera facing + enum Facing { + UNKNOWN = 0; + BACK = 1; + FRONT = 2; + EXTERNAL = 3; + } + optional Facing facing = 4; +} diff --git a/cmds/statsd/src/condition/StateTracker.cpp b/cmds/statsd/src/condition/StateConditionTracker.cpp index 18c7178dd7d7..7f3eeddba831 100644 --- a/cmds/statsd/src/condition/StateTracker.cpp +++ b/cmds/statsd/src/condition/StateConditionTracker.cpp @@ -16,7 +16,7 @@ #define DEBUG false // STOPSHIP if true #include "Log.h" -#include "StateTracker.h" +#include "StateConditionTracker.h" #include "guardrail/StatsdStats.h" namespace android { @@ -27,7 +27,7 @@ using std::string; using std::unordered_set; using std::vector; -StateTracker::StateTracker(const ConfigKey& key, const int64_t& id, const int index, +StateConditionTracker::StateConditionTracker(const ConfigKey& key, const int64_t& id, const int index, const SimplePredicate& simplePredicate, const unordered_map<int64_t, int>& trackerNameIndexMap, const vector<Matcher> primaryKeys) @@ -69,19 +69,19 @@ StateTracker::StateTracker(const ConfigKey& key, const int64_t& id, const int in mInitialized = true; } -StateTracker::~StateTracker() { - VLOG("~StateTracker()"); +StateConditionTracker::~StateConditionTracker() { + VLOG("~StateConditionTracker()"); } -bool StateTracker::init(const vector<Predicate>& allConditionConfig, +bool StateConditionTracker::init(const vector<Predicate>& allConditionConfig, const vector<sp<ConditionTracker>>& allConditionTrackers, const unordered_map<int64_t, int>& conditionIdIndexMap, vector<bool>& stack) { return mInitialized; } -void StateTracker::dumpState() { - VLOG("StateTracker %lld DUMP:", (long long)mConditionId); +void StateConditionTracker::dumpState() { + VLOG("StateConditionTracker %lld DUMP:", (long long)mConditionId); for (const auto& value : mSlicedState) { VLOG("\t%s -> %s", value.first.toString().c_str(), value.second.toString().c_str()); } @@ -95,7 +95,7 @@ void StateTracker::dumpState() { } } -bool StateTracker::hitGuardRail(const HashableDimensionKey& newKey) { +bool StateConditionTracker::hitGuardRail(const HashableDimensionKey& newKey) { if (mSlicedState.find(newKey) != mSlicedState.end()) { // if the condition is not sliced or the key is not new, we are good! return false; @@ -114,7 +114,7 @@ bool StateTracker::hitGuardRail(const HashableDimensionKey& newKey) { return false; } -void StateTracker::evaluateCondition(const LogEvent& event, +void StateConditionTracker::evaluateCondition(const LogEvent& event, const vector<MatchingState>& eventMatcherValues, const vector<sp<ConditionTracker>>& mAllConditions, vector<ConditionState>& conditionCache, @@ -135,7 +135,7 @@ void StateTracker::evaluateCondition(const LogEvent& event, return; } - VLOG("StateTracker evaluate event %s", event.ToString().c_str()); + VLOG("StateConditionTracker evaluate event %s", event.ToString().c_str()); // Primary key can exclusive fields must be simple fields. so there won't be more than // one keys matched. @@ -151,7 +151,7 @@ void StateTracker::evaluateCondition(const LogEvent& event, } hitGuardRail(primaryKey); - VLOG("StateTracker: key %s state %s", primaryKey.toString().c_str(), state.toString().c_str()); + VLOG("StateConditionTracker: key %s state %s", primaryKey.toString().c_str(), state.toString().c_str()); auto it = mSlicedState.find(primaryKey); if (it == mSlicedState.end()) { @@ -176,7 +176,7 @@ void StateTracker::evaluateCondition(const LogEvent& event, return; } -void StateTracker::isConditionMet( +void StateConditionTracker::isConditionMet( const ConditionKey& conditionParameters, const vector<sp<ConditionTracker>>& allConditions, const bool isPartialLink, vector<ConditionState>& conditionCache) const { diff --git a/cmds/statsd/src/condition/StateTracker.h b/cmds/statsd/src/condition/StateConditionTracker.h index 5ae4441713cd..0efe1fb3fcb2 100644 --- a/cmds/statsd/src/condition/StateTracker.h +++ b/cmds/statsd/src/condition/StateConditionTracker.h @@ -25,14 +25,14 @@ namespace android { namespace os { namespace statsd { -class StateTracker : public virtual ConditionTracker { +class StateConditionTracker : public virtual ConditionTracker { public: - StateTracker(const ConfigKey& key, const int64_t& id, const int index, + StateConditionTracker(const ConfigKey& key, const int64_t& id, const int index, const SimplePredicate& simplePredicate, const std::unordered_map<int64_t, int>& trackerNameIndexMap, const vector<Matcher> primaryKeys); - ~StateTracker(); + ~StateConditionTracker(); bool init(const std::vector<Predicate>& allConditionConfig, const std::vector<sp<ConditionTracker>>& allConditionTrackers, @@ -46,8 +46,8 @@ public: std::vector<bool>& changedCache) override; /** - * Note: dimensionFields will be ignored in StateTracker, because we demand metrics - * must take the entire dimension fields from StateTracker. This is to make implementation + * Note: dimensionFields will be ignored in StateConditionTracker, because we demand metrics + * must take the entire dimension fields from StateConditionTracker. This is to make implementation * simple and efficient. * * For example: wakelock duration by uid process states: @@ -109,7 +109,7 @@ private: // maps from [primary_key] to [primary_key, exclusive_state]. std::unordered_map<HashableDimensionKey, HashableDimensionKey> mSlicedState; - FRIEND_TEST(StateTrackerTest, TestStateChange); + FRIEND_TEST(StateConditionTrackerTest, TestStateChange); }; } // namespace statsd diff --git a/cmds/statsd/src/metrics/metrics_manager_util.cpp b/cmds/statsd/src/metrics/metrics_manager_util.cpp index dd32c08faba3..40484f4fb86b 100644 --- a/cmds/statsd/src/metrics/metrics_manager_util.cpp +++ b/cmds/statsd/src/metrics/metrics_manager_util.cpp @@ -21,7 +21,7 @@ #include "../condition/CombinationConditionTracker.h" #include "../condition/SimpleConditionTracker.h" -#include "../condition/StateTracker.h" +#include "../condition/StateConditionTracker.h" #include "../external/StatsPullerManager.h" #include "../matchers/CombinationLogMatchingTracker.h" #include "../matchers/SimpleLogMatchingTracker.h" @@ -35,6 +35,8 @@ #include "stats_util.h" #include "statslog.h" +#include <inttypes.h> + using std::set; using std::string; using std::unordered_map; @@ -182,13 +184,13 @@ bool initLogTrackers(const StatsdConfig& config, const UidMap& uidMap, } /** - * A StateTracker is built from a SimplePredicate which has only "start", and no "stop" + * A StateConditionTracker is built from a SimplePredicate which has only "start", and no "stop" * or "stop_all". The start must be an atom matcher that matches a state atom. It must * have dimension, the dimension must be the state atom's primary fields plus exclusive state - * field. For example, the StateTracker is used in tracking UidProcessState and ScreenState. + * field. For example, the StateConditionTracker is used in tracking UidProcessState and ScreenState. * */ -bool isStateTracker(const SimplePredicate& simplePredicate, vector<Matcher>* primaryKeys) { +bool isStateConditionTracker(const SimplePredicate& simplePredicate, vector<Matcher>* primaryKeys) { // 1. must not have "stop". must have "dimension" if (!simplePredicate.has_stop() && simplePredicate.has_dimensions()) { auto it = android::util::AtomsInfo::kStateAtomsFieldOptions.find( @@ -240,8 +242,8 @@ bool initConditions(const ConfigKey& key, const StatsdConfig& config, switch (condition.contents_case()) { case Predicate::ContentsCase::kSimplePredicate: { vector<Matcher> primaryKeys; - if (isStateTracker(condition.simple_predicate(), &primaryKeys)) { - allConditionTrackers.push_back(new StateTracker(key, condition.id(), index, + if (isStateConditionTracker(condition.simple_predicate(), &primaryKeys)) { + allConditionTrackers.push_back(new StateConditionTracker(key, condition.id(), index, condition.simple_predicate(), logTrackerMap, primaryKeys)); } else { @@ -593,7 +595,7 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t for (int i = 0; i < config.no_report_metric_size(); ++i) { const auto no_report_metric = config.no_report_metric(i); if (metricMap.find(no_report_metric) == metricMap.end()) { - ALOGW("no_report_metric %lld not exist", no_report_metric); + ALOGW("no_report_metric %" PRId64 " not exist", no_report_metric); return false; } noReportMetricIds.insert(no_report_metric); diff --git a/cmds/statsd/src/metrics/metrics_manager_util.h b/cmds/statsd/src/metrics/metrics_manager_util.h index 028231ff908c..3704969039c4 100644 --- a/cmds/statsd/src/metrics/metrics_manager_util.h +++ b/cmds/statsd/src/metrics/metrics_manager_util.h @@ -113,7 +113,7 @@ bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, UidMap& vector<int>& metricsWithActivation, std::set<int64_t>& noReportMetricIds); -bool isStateTracker(const SimplePredicate& simplePredicate, std::vector<Matcher>* primaryKeys); +bool isStateConditionTracker(const SimplePredicate& simplePredicate, std::vector<Matcher>* primaryKeys); } // namespace statsd } // namespace os diff --git a/cmds/statsd/tests/condition/StateTracker_test.cpp b/cmds/statsd/tests/condition/StateConditionTracker_test.cpp index 9a66254afce0..fbf6efdcf966 100644 --- a/cmds/statsd/tests/condition/StateTracker_test.cpp +++ b/cmds/statsd/tests/condition/StateConditionTracker_test.cpp @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "src/condition/StateTracker.h" +#include "src/condition/StateConditionTracker.h" #include "tests/statsd_test_util.h" #include <gmock/gmock.h> @@ -50,7 +50,7 @@ void makeUidProcStateEvent(int32_t uid, int32_t state, LogEvent* event) { event->init(); } -TEST(StateTrackerTest, TestStateChange) { +TEST(StateConditionTrackerTest, TestStateChange) { int uid1 = 111; int uid2 = 222; @@ -60,7 +60,7 @@ TEST(StateTrackerTest, TestStateChange) { trackerNameIndexMap[StringToId("UidProcState")] = 0; vector<Matcher> primaryFields; primaryFields.push_back(getSimpleMatcher(kUidProcTag, 1)); - StateTracker tracker(ConfigKey(12, 123), 123, 0, getUidProcStatePredicate(), + StateConditionTracker tracker(ConfigKey(12, 123), 123, 0, getUidProcStatePredicate(), trackerNameIndexMap, primaryFields); LogEvent event(kUidProcTag, 0 /*timestamp*/); diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java index 1fd7e52314e3..92aabb591e03 100644 --- a/core/java/android/app/ActivityManagerInternal.java +++ b/core/java/android/app/ActivityManagerInternal.java @@ -18,6 +18,7 @@ package android.app; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.UserIdInt; import android.content.ComponentName; import android.content.IIntentReceiver; import android.content.IIntentSender; @@ -30,7 +31,6 @@ import android.net.Uri; import android.os.Bundle; import android.os.IBinder; import android.os.TransactionTooLargeException; -import android.view.RemoteAnimationAdapter; import java.util.ArrayList; import java.util.List; @@ -51,12 +51,12 @@ public abstract class ActivityManagerInternal { /** * Verify that calling app has access to the given provider. */ - public abstract String checkContentProviderAccess(String authority, int userId); + public abstract String checkContentProviderAccess(String authority, @UserIdInt int userId); /** * Verify that calling UID has access to the given provider. */ - public abstract int checkContentProviderUriPermission(Uri uri, int userId, + public abstract int checkContentProviderUriPermission(Uri uri, @UserIdInt int userId, int callingUid, int modeFlags); // Called by the power manager. @@ -71,7 +71,7 @@ public abstract class ActivityManagerInternal { /** * Kill foreground apps from the specified user. */ - public abstract void killForegroundAppsForUser(int userHandle); + public abstract void killForegroundAppsForUser(@UserIdInt int userId); /** * Sets how long a {@link PendingIntent} can be temporarily whitelist to by bypass restrictions @@ -174,7 +174,7 @@ public abstract class ActivityManagerInternal { * Checks to see if the calling pid is allowed to handle the user. Returns adjusted user id as * needed. */ - public abstract int handleIncomingUser(int callingPid, int callingUid, int userId, + public abstract int handleIncomingUser(int callingPid, int callingUid, @UserIdInt int userId, boolean allowAll, int allowMode, String name, String callerPackage); /** Checks if the calling binder pid as the permission. */ @@ -184,7 +184,7 @@ public abstract class ActivityManagerInternal { public abstract int getCurrentUserId(); /** Returns true if the user is running. */ - public abstract boolean isUserRunning(int userId, int flags); + public abstract boolean isUserRunning(@UserIdInt int userId, int flags); /** Trims memory usage in the system by removing/stopping unused application processes. */ public abstract void trimApplications(); @@ -211,7 +211,7 @@ public abstract class ActivityManagerInternal { * @param started */ public abstract void updateBatteryStats( - ComponentName activity, int uid, int userId, boolean resumed); + ComponentName activity, int uid, @UserIdInt int userId, boolean resumed); /** * Update UsageStats of the activity. @@ -222,23 +222,23 @@ public abstract class ActivityManagerInternal { * @param taskRoot TaskRecord's root */ public abstract void updateActivityUsageStats( - ComponentName activity, int userId, int event, IBinder appToken, + ComponentName activity, @UserIdInt int userId, int event, IBinder appToken, ComponentName taskRoot); public abstract void updateForegroundTimeIfOnBattery( String packageName, int uid, long cpuTimeDiff); - public abstract void sendForegroundProfileChanged(int userId); + public abstract void sendForegroundProfileChanged(@UserIdInt int userId); /** * Returns whether the given user requires credential entry at this time. This is used to * intercept activity launches for work apps when the Work Challenge is present. */ - public abstract boolean shouldConfirmCredentials(int userId); + public abstract boolean shouldConfirmCredentials(@UserIdInt int userId); public abstract int[] getCurrentProfileIds(); public abstract UserInfo getCurrentUser(); - public abstract void ensureNotSpecialUser(int userId); - public abstract boolean isCurrentProfile(int userId); - public abstract boolean hasStartedUserState(int userId); + public abstract void ensureNotSpecialUser(@UserIdInt int userId); + public abstract boolean isCurrentProfile(@UserIdInt int userId); + public abstract boolean hasStartedUserState(@UserIdInt int userId); public abstract void finishUserSwitch(Object uss); /** Schedule the execution of all pending app GCs. */ @@ -261,15 +261,16 @@ public abstract class ActivityManagerInternal { public abstract int broadcastIntentInPackage(String packageName, int uid, int realCallingUid, int realCallingPid, Intent intent, String resolvedType, IIntentReceiver resultTo, int resultCode, String resultData, Bundle resultExtras, String requiredPermission, - Bundle bOptions, boolean serialized, boolean sticky, int userId, + Bundle bOptions, boolean serialized, boolean sticky, @UserIdInt int userId, boolean allowBackgroundActivityStarts); public abstract ComponentName startServiceInPackage(int uid, Intent service, - String resolvedType, boolean fgRequired, String callingPackage, int userId, + String resolvedType, boolean fgRequired, String callingPackage, @UserIdInt int userId, boolean allowBackgroundActivityStarts) throws TransactionTooLargeException; public abstract void disconnectActivityFromServices(Object connectionHolder, Object conns); - public abstract void cleanUpServices(int userId, ComponentName component, Intent baseIntent); - public abstract ActivityInfo getActivityInfoForUser(ActivityInfo aInfo, int userId); + public abstract void cleanUpServices(@UserIdInt int userId, ComponentName component, + Intent baseIntent); + public abstract ActivityInfo getActivityInfoForUser(ActivityInfo aInfo, @UserIdInt int userId); public abstract void ensureBootCompleted(); public abstract void updateOomLevelsForDisplay(int displayId); public abstract boolean isActivityStartsLoggingEnabled(); @@ -328,7 +329,7 @@ public abstract class ActivityManagerInternal { public abstract boolean isAppBad(ApplicationInfo info); /** Remove pending backup for the given userId. */ - public abstract void clearPendingBackup(int userId); + public abstract void clearPendingBackup(@UserIdInt int userId); /** * When power button is very long pressed, call this interface to do some pre-shutdown work diff --git a/core/java/android/app/ActivityTaskManager.java b/core/java/android/app/ActivityTaskManager.java index 4ef554dc64cc..ac8c9f466f33 100644 --- a/core/java/android/app/ActivityTaskManager.java +++ b/core/java/android/app/ActivityTaskManager.java @@ -202,21 +202,6 @@ public class ActivityTaskManager { } /** - * Resizes the input stack id to the given bounds. - * @param stackId Id of the stack to resize. - * @param bounds Bounds to resize the stack to or {@code null} for fullscreen. - */ - @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) - public void resizeStack(int stackId, Rect bounds) throws SecurityException { - try { - getService().resizeStack(stackId, bounds, false /* allowResizeInDockedMode */, - false /* preserveWindows */, false /* animate */, -1 /* animationDuration */); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** * Removes stacks in the windowing modes from the system if they are of activity type * ACTIVITY_TYPE_STANDARD or ACTIVITY_TYPE_UNDEFINED */ @@ -362,10 +347,13 @@ public class ActivityTaskManager { * @param animate Whether we should play an animation for resizing stack. */ @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) - public void resizeStack(int stackId, Rect bounds, boolean animate) { + public void resizePinnedStack(int stackId, Rect bounds, boolean animate) { try { - getService().resizeStack(stackId, bounds, false, false, animate /* animate */, - -1 /* animationDuration */); + if (animate) { + getService().animateResizePinnedStack(stackId, bounds, -1 /* animationDuration */); + } else { + getService().resizePinnedStack(bounds, null /* tempPinnedTaskBounds */); + } } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl index dbe50c3d24a0..dca00a2bbd83 100644 --- a/core/java/android/app/IActivityManager.aidl +++ b/core/java/android/app/IActivityManager.aidl @@ -406,23 +406,6 @@ interface IActivityManager { List<ActivityManager.StackInfo> getAllStackInfos(); @UnsupportedAppUsage void moveTaskToStack(int taskId, int stackId, boolean toTop); - /** - * Resizes the input stack id to the given bounds. - * - * @param stackId Id of the stack to resize. - * @param bounds Bounds to resize the stack to or {@code null} for fullscreen. - * @param allowResizeInDockedMode True if the resize should be allowed when the docked stack is - * active. - * @param preserveWindows True if the windows of activities contained in the stack should be - * preserved. - * @param animate True if the stack resize should be animated. - * @param animationDuration The duration of the resize animation in milliseconds or -1 if the - * default animation duration should be used. - * @throws RemoteException - */ - @UnsupportedAppUsage - void resizeStack(int stackId, in Rect bounds, boolean allowResizeInDockedMode, - boolean preserveWindows, boolean animate, int animationDuration); void setFocusedStack(int stackId); ActivityManager.StackInfo getFocusedStackInfo(); @UnsupportedAppUsage diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl index 47b784b3eaaf..dda3bb53ebe3 100644 --- a/core/java/android/app/IActivityTaskManager.aidl +++ b/core/java/android/app/IActivityTaskManager.aidl @@ -234,21 +234,15 @@ interface IActivityTaskManager { void setTaskWindowingMode(int taskId, int windowingMode, boolean toTop); void moveTaskToStack(int taskId, int stackId, boolean toTop); /** - * Resizes the input stack id to the given bounds. + * Resizes the input pinned stack to the given bounds with animation. * - * @param stackId Id of the stack to resize. + * @param stackId Id of the pinned stack to resize. * @param bounds Bounds to resize the stack to or {@code null} for fullscreen. - * @param allowResizeInDockedMode True if the resize should be allowed when the docked stack is - * active. - * @param preserveWindows True if the windows of activities contained in the stack should be - * preserved. - * @param animate True if the stack resize should be animated. * @param animationDuration The duration of the resize animation in milliseconds or -1 if the * default animation duration should be used. * @throws RemoteException */ - void resizeStack(int stackId, in Rect bounds, boolean allowResizeInDockedMode, - boolean preserveWindows, boolean animate, int animationDuration); + void animateResizePinnedStack(int stackId, in Rect bounds, int animationDuration); boolean setTaskWindowingModeSplitScreenPrimary(int taskId, int createMode, boolean toTop, boolean animate, in Rect initialBounds, boolean showRecents); /** diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index f065ff791dce..bb4e99873f26 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -3274,11 +3274,8 @@ public class Notification implements Parcelable * * @param requiresFreeform requires the remoteinput to allow freeform or not. * @return the result pair, {@code null} if no result is found. - * - * @hide */ @Nullable - @SystemApi public Pair<RemoteInput, Action> findRemoteInputActionPair(boolean requiresFreeform) { if (actions == null) { return null; @@ -3301,11 +3298,9 @@ public class Notification implements Parcelable } /** - * Returns the actions that are contextual out of the actions in this notification. - * - * @hide + * Returns the actions that are contextual (that is, suggested because of the content of the + * notification) out of the actions in this notification. */ - @SystemApi public @NonNull List<Notification.Action> getContextualActions() { if (actions == null) return Collections.emptyList(); @@ -7705,11 +7700,11 @@ public class Notification implements Parcelable } /** - * @return A list of messages read from the bundles. - * - * @hide + * Returns a list of messages read from the given bundle list, e.g. + * {@link #EXTRA_MESSAGES} or {@link #EXTRA_HISTORIC_MESSAGES}. */ - public static List<Message> getMessagesFromBundleArray(Parcelable[] bundles) { + @NonNull + public static List<Message> getMessagesFromBundleArray(@Nullable Parcelable[] bundles) { if (bundles == null) { return new ArrayList<>(); } @@ -7726,13 +7721,12 @@ public class Notification implements Parcelable } /** - * @return The message that is stored in the bundle or null if the message couldn't be - * resolved. - * + * Returns the message that is stored in the bundle (e.g. one of the values in the lists + * in {@link #EXTRA_MESSAGES} or {@link #EXTRA_HISTORIC_MESSAGES}) or null if the + * message couldn't be resolved. * @hide */ @Nullable - @SystemApi public static Message getMessageFromBundle(@NonNull Bundle bundle) { try { if (!bundle.containsKey(KEY_TEXT) || !bundle.containsKey(KEY_TIMESTAMP)) { diff --git a/core/java/android/app/NotificationChannel.java b/core/java/android/app/NotificationChannel.java index 93e4ddcbb016..20d977b7da10 100644 --- a/core/java/android/app/NotificationChannel.java +++ b/core/java/android/app/NotificationChannel.java @@ -710,6 +710,14 @@ public final class NotificationChannel implements Parcelable { } /** + * Returns whether the user has chosen the sound of this channel. + * @see #getSound() + */ + public boolean hasUserSetSound() { + return (mUserLockedFields & USER_LOCKED_SOUND) != 0; + } + + /** * @hide */ public void populateFromXmlForRestore(XmlPullParser parser, Context context) { diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index 2a17800dd446..3418b7be42d6 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -5413,8 +5413,8 @@ public class Intent implements Parcelable, Cloneable { "android.intent.extra.ALLOW_MULTIPLE"; /** - * The integer userHandle carried with broadcast intents related to addition, removal and - * switching of users and managed profiles - {@link #ACTION_USER_ADDED}, + * The integer userHandle (i.e. userId) carried with broadcast intents related to addition, + * removal and switching of users and managed profiles - {@link #ACTION_USER_ADDED}, * {@link #ACTION_USER_REMOVED} and {@link #ACTION_USER_SWITCHED}. * * @hide diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java index 861ae7ba122e..9cf54f41a64b 100644 --- a/core/java/android/content/res/Configuration.java +++ b/core/java/android/content/res/Configuration.java @@ -1222,7 +1222,15 @@ public final class Configuration implements Parcelable, Comparable<Configuration .setVariant(variant) .setScript(script) .build(); - list.add(locale); + // Log a WTF here if a repeated locale is found to avoid throwing an + // exception in system server when LocaleList is created below + final int inListIndex = list.indexOf(locale); + if (inListIndex != -1) { + Slog.wtf(TAG, "Repeated locale (" + list.get(inListIndex) + ")" + + " found when trying to add: " + locale.toString()); + } else { + list.add(locale); + } } catch (IllformedLocaleException e) { Slog.e(TAG, "readFromProto error building locale with: " + "language-" + language + ";country-" + country diff --git a/core/java/android/os/UserHandle.java b/core/java/android/os/UserHandle.java index 4e17f7e92013..0754dc78a629 100644 --- a/core/java/android/os/UserHandle.java +++ b/core/java/android/os/UserHandle.java @@ -128,8 +128,9 @@ public final class UserHandle implements Parcelable { @UnsupportedAppUsage public static final int AID_CACHE_GID_START = android.os.Process.FIRST_APPLICATION_CACHE_GID; + /** The userId represented by this UserHandle. */ @UnsupportedAppUsage - final int mHandle; + final @UserIdInt int mHandle; /** * Checks to see if the user id is the same for the two uids, i.e., they belong to the same @@ -270,7 +271,7 @@ public final class UserHandle implements Parcelable { } /** @hide */ - public static int getSharedAppGid(int userId, int appId) { + public static int getSharedAppGid(@UserIdInt int userId, @AppIdInt int appId) { if (appId >= AID_APP_START && appId <= AID_APP_END) { return (appId - AID_APP_START) + AID_SHARED_GID_START; } else if (appId >= AID_ROOT && appId <= AID_APP_START) { @@ -300,7 +301,7 @@ public final class UserHandle implements Parcelable { } /** @hide */ - public static int getCacheAppGid(int userId, int appId) { + public static int getCacheAppGid(@UserIdInt int userId, @AppIdInt int appId) { if (appId >= AID_APP_START && appId <= AID_APP_END) { return getUid(userId, (appId - AID_APP_START) + AID_CACHE_GID_START); } else { @@ -432,8 +433,8 @@ public final class UserHandle implements Parcelable { /** @hide */ @UnsupportedAppUsage - public UserHandle(int h) { - mHandle = h; + public UserHandle(@UserIdInt int userId) { + mHandle = userId; } /** diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index a7fa96bc1d90..baf748f4a20d 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -1794,14 +1794,14 @@ public class UserManager { /** * Returns the UserInfo object describing a specific user. * Requires {@link android.Manifest.permission#MANAGE_USERS} permission. - * @param userHandle the user handle of the user whose information is being requested. + * @param userId the user handle of the user whose information is being requested. * @return the UserInfo object for a specific user. * @hide */ @UnsupportedAppUsage - public UserInfo getUserInfo(@UserIdInt int userHandle) { + public UserInfo getUserInfo(@UserIdInt int userId) { try { - return mService.getUserInfo(userHandle); + return mService.getUserInfo(userId); } catch (RemoteException re) { throw re.rethrowFromSystemServer(); } @@ -2066,15 +2066,15 @@ public class UserManager { * * @param name the user's name * @param flags flags that identify the type of user and other properties. - * @param userHandle new user will be a profile of this user. + * @param userId new user will be a profile of this user. * * @return the {@link UserInfo} object for the created user, or null if the user * could not be created. * @hide */ @UnsupportedAppUsage - public UserInfo createProfileForUser(String name, int flags, @UserIdInt int userHandle) { - return createProfileForUser(name, flags, userHandle, null); + public UserInfo createProfileForUser(String name, int flags, @UserIdInt int userId) { + return createProfileForUser(name, flags, userId, null); } /** @@ -2084,17 +2084,17 @@ public class UserManager { * * @param name the user's name * @param flags flags that identify the type of user and other properties. - * @param userHandle new user will be a profile of this user. + * @param userId new user will be a profile of this user. * @param disallowedPackages packages that will not be installed in the profile being created. * * @return the {@link UserInfo} object for the created user, or null if the user * could not be created. * @hide */ - public UserInfo createProfileForUser(String name, int flags, @UserIdInt int userHandle, + public UserInfo createProfileForUser(String name, int flags, @UserIdInt int userId, String[] disallowedPackages) { try { - return mService.createProfileForUser(name, flags, userHandle, disallowedPackages); + return mService.createProfileForUser(name, flags, userId, disallowedPackages); } catch (RemoteException re) { throw re.rethrowFromSystemServer(); } @@ -2109,9 +2109,9 @@ public class UserManager { * @hide */ public UserInfo createProfileForUserEvenWhenDisallowed(String name, int flags, - @UserIdInt int userHandle, String[] disallowedPackages) { + @UserIdInt int userId, String[] disallowedPackages) { try { - return mService.createProfileForUserEvenWhenDisallowed(name, flags, userHandle, + return mService.createProfileForUserEvenWhenDisallowed(name, flags, userId, disallowedPackages); } catch (RemoteException re) { throw re.rethrowFromSystemServer(); @@ -2280,12 +2280,12 @@ public class UserManager { * @hide * Marks the guest user for deletion to allow a new guest to be created before deleting * the current user who is a guest. - * @param userHandle + * @param userId * @return */ - public boolean markGuestForDeletion(@UserIdInt int userHandle) { + public boolean markGuestForDeletion(@UserIdInt int userId) { try { - return mService.markGuestForDeletion(userHandle); + return mService.markGuestForDeletion(userId); } catch (RemoteException re) { throw re.rethrowFromSystemServer(); } @@ -2317,16 +2317,16 @@ public class UserManager { * <p>Requires {@link android.Manifest.permission#MANAGE_USERS} and * {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} permissions. * - * @param userHandle the id of the user to become admin + * @param userId the id of the user to become admin * @hide */ @RequiresPermission(allOf = { Manifest.permission.INTERACT_ACROSS_USERS_FULL, Manifest.permission.MANAGE_USERS }) - public void setUserAdmin(@UserIdInt int userHandle) { + public void setUserAdmin(@UserIdInt int userId) { try { - mService.setUserAdmin(userHandle); + mService.setUserAdmin(userId); } catch (RemoteException re) { throw re.rethrowFromSystemServer(); } @@ -2337,9 +2337,9 @@ public class UserManager { * * @hide */ - public void evictCredentialEncryptionKey(@UserIdInt int userHandle) { + public void evictCredentialEncryptionKey(@UserIdInt int userId) { try { - mService.evictCredentialEncryptionKey(userHandle); + mService.evictCredentialEncryptionKey(userId); } catch (RemoteException re) { throw re.rethrowFromSystemServer(); } @@ -2400,9 +2400,9 @@ public class UserManager { Manifest.permission.INTERACT_ACROSS_USERS_FULL, Manifest.permission.MANAGE_USERS }) - public @Nullable String getUserAccount(@UserIdInt int userHandle) { + public @Nullable String getUserAccount(@UserIdInt int userId) { try { - return mService.getUserAccount(userHandle); + return mService.getUserAccount(userId); } catch (RemoteException re) { throw re.rethrowFromSystemServer(); } @@ -2416,9 +2416,9 @@ public class UserManager { Manifest.permission.INTERACT_ACROSS_USERS_FULL, Manifest.permission.MANAGE_USERS }) - public void setUserAccount(@UserIdInt int userHandle, @Nullable String accountName) { + public void setUserAccount(@UserIdInt int userId, @Nullable String accountName) { try { - mService.setUserAccount(userHandle, accountName); + mService.setUserAccount(userId, accountName); } catch (RemoteException re) { throw re.rethrowFromSystemServer(); } @@ -2477,20 +2477,19 @@ public class UserManager { } /** - * Returns list of the profiles of userHandle including - * userHandle itself. + * Returns list of the profiles of userId including userId itself. * Note that this returns both enabled and not enabled profiles. See * {@link #getEnabledProfiles(int)} if you need only the enabled ones. * * Requires {@link android.Manifest.permission#MANAGE_USERS} permission. - * @param userHandle profiles of this user will be returned. + * @param userId profiles of this user will be returned. * @return the list of profiles. * @hide */ @UnsupportedAppUsage - public List<UserInfo> getProfiles(@UserIdInt int userHandle) { + public List<UserInfo> getProfiles(@UserIdInt int userId) { try { - return mService.getProfiles(userHandle, false /* enabledOnly */); + return mService.getProfiles(userId, false /* enabledOnly */); } catch (RemoteException re) { throw re.rethrowFromSystemServer(); } @@ -2512,19 +2511,18 @@ public class UserManager { } /** - * Returns list of the profiles of userHandle including - * userHandle itself. + * Returns list of the profiles of userId including userId itself. * Note that this returns only enabled. * * Requires {@link android.Manifest.permission#MANAGE_USERS} permission. - * @param userHandle profiles of this user will be returned. + * @param userId profiles of this user will be returned. * @return the list of profiles. * @hide */ @UnsupportedAppUsage - public List<UserInfo> getEnabledProfiles(@UserIdInt int userHandle) { + public List<UserInfo> getEnabledProfiles(@UserIdInt int userId) { try { - return mService.getProfiles(userHandle, true /* enabledOnly */); + return mService.getProfiles(userId, true /* enabledOnly */); } catch (RemoteException re) { throw re.rethrowFromSystemServer(); } @@ -2584,14 +2582,14 @@ public class UserManager { /** * Returns the device credential owner id of the profile from - * which this method is called, or userHandle if called from a user that + * which this method is called, or userId if called from a user that * is not a profile. * * @hide */ - public int getCredentialOwnerProfile(@UserIdInt int userHandle) { + public int getCredentialOwnerProfile(@UserIdInt int userId) { try { - return mService.getCredentialOwnerProfile(userHandle); + return mService.getCredentialOwnerProfile(userId); } catch (RemoteException re) { throw re.rethrowFromSystemServer(); } @@ -2604,9 +2602,9 @@ public class UserManager { * @hide */ @UnsupportedAppUsage - public UserInfo getProfileParent(@UserIdInt int userHandle) { + public UserInfo getProfileParent(@UserIdInt int userId) { try { - return mService.getProfileParent(userHandle); + return mService.getProfileParent(userId); } catch (RemoteException re) { throw re.rethrowFromSystemServer(); } @@ -2785,13 +2783,13 @@ public class UserManager { /** * Removes a user and all associated data. * Requires {@link android.Manifest.permission#MANAGE_USERS} permission. - * @param userHandle the integer handle of the user, where 0 is the primary user. + * @param userId the integer handle of the user. * @hide */ @UnsupportedAppUsage - public boolean removeUser(@UserIdInt int userHandle) { + public boolean removeUser(@UserIdInt int userId) { try { - return mService.removeUser(userHandle); + return mService.removeUser(userId); } catch (RemoteException re) { throw re.rethrowFromSystemServer(); } @@ -2823,9 +2821,9 @@ public class UserManager { * @see {@link #removeUser(int)} * @hide */ - public boolean removeUserEvenWhenDisallowed(@UserIdInt int userHandle) { + public boolean removeUserEvenWhenDisallowed(@UserIdInt int userId) { try { - return mService.removeUserEvenWhenDisallowed(userHandle); + return mService.removeUserEvenWhenDisallowed(userId); } catch (RemoteException re) { throw re.rethrowFromSystemServer(); } @@ -2835,13 +2833,13 @@ public class UserManager { * Updates the user's name. * Requires {@link android.Manifest.permission#MANAGE_USERS} permission. * - * @param userHandle the user's integer handle + * @param userId the user's integer id * @param name the new name for the user * @hide */ - public void setUserName(@UserIdInt int userHandle, String name) { + public void setUserName(@UserIdInt int userId, String name) { try { - mService.setUserName(userHandle, name); + mService.setUserName(userId, name); } catch (RemoteException re) { throw re.rethrowFromSystemServer(); } @@ -2862,13 +2860,13 @@ public class UserManager { /** * Sets the user's photo. - * @param userHandle the user for whom to change the photo. + * @param userId the user for whom to change the photo. * @param icon the bitmap to set as the photo. * @hide */ - public void setUserIcon(@UserIdInt int userHandle, Bitmap icon) { + public void setUserIcon(@UserIdInt int userId, Bitmap icon) { try { - mService.setUserIcon(userHandle, icon); + mService.setUserIcon(userId, icon); } catch (RemoteException re) { throw re.rethrowFromSystemServer(); } @@ -2889,15 +2887,15 @@ public class UserManager { /** * Returns a file descriptor for the user's photo. PNG data can be read from this file. - * @param userHandle the user whose photo we want to read. + * @param userId the user whose photo we want to read. * @return a {@link Bitmap} of the user's photo, or null if there's no photo. * @see com.android.internal.util.UserIcons#getDefaultUserIcon for a default. * @hide */ @UnsupportedAppUsage - public Bitmap getUserIcon(@UserIdInt int userHandle) { + public Bitmap getUserIcon(@UserIdInt int userId) { try { - ParcelFileDescriptor fd = mService.getUserIcon(userHandle); + ParcelFileDescriptor fd = mService.getUserIcon(userId); if (fd != null) { try { return BitmapFactory.decodeFileDescriptor(fd.getFileDescriptor()); @@ -2999,27 +2997,27 @@ public class UserManager { } /** - * Returns a serial number on this device for a given userHandle. User handles can be recycled + * Returns a serial number on this device for a given userId. User handles can be recycled * when deleting and creating users, but serial numbers are not reused until the device is wiped. - * @param userHandle - * @return a serial number associated with that user, or -1 if the userHandle is not valid. + * @param userId + * @return a serial number associated with that user, or -1 if the userId is not valid. * @hide */ @UnsupportedAppUsage - public int getUserSerialNumber(@UserIdInt int userHandle) { + public int getUserSerialNumber(@UserIdInt int userId) { try { - return mService.getUserSerialNumber(userHandle); + return mService.getUserSerialNumber(userId); } catch (RemoteException re) { throw re.rethrowFromSystemServer(); } } /** - * Returns a userHandle on this device for a given user serial number. User handles can be + * Returns a userId on this device for a given user serial number. User handles can be * recycled when deleting and creating users, but serial numbers are not reused until the device * is wiped. * @param userSerialNumber - * @return the userHandle associated with that user serial number, or -1 if the serial number + * @return the userId associated with that user serial number, or -1 if the serial number * is not valid. * @hide */ diff --git a/core/java/android/os/UserManagerInternal.java b/core/java/android/os/UserManagerInternal.java index ddd949d64a1f..a5b71f64668d 100644 --- a/core/java/android/os/UserManagerInternal.java +++ b/core/java/android/os/UserManagerInternal.java @@ -137,7 +137,7 @@ public abstract class UserManagerInternal { String[] disallowedPackages); /** - * Same as {@link UserManager#removeUser(int userHandle)}, but bypasses the check for + * Same as {@link UserManager#removeUser(int userId)}, but bypasses the check for * {@link UserManager#DISALLOW_REMOVE_USER} and * {@link UserManager#DISALLOW_REMOVE_MANAGED_PROFILE} and does not require the * {@link android.Manifest.permission#MANAGE_USERS} permission. diff --git a/core/java/android/service/notification/StatusBarNotification.java b/core/java/android/service/notification/StatusBarNotification.java index 205df7e12483..b8378a3474ac 100644 --- a/core/java/android/service/notification/StatusBarNotification.java +++ b/core/java/android/service/notification/StatusBarNotification.java @@ -170,10 +170,7 @@ public class StatusBarNotification implements Parcelable { /** * Returns true if application asked that this notification be part of a group. - * - * @hide */ - @SystemApi public boolean isAppGroup() { if (getNotification().getGroup() != null || getNotification().getSortKey() != null) { return true; diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java index bfab580ea077..937990f7e88e 100644 --- a/core/java/android/service/notification/ZenModeConfig.java +++ b/core/java/android/service/notification/ZenModeConfig.java @@ -1639,7 +1639,7 @@ public class ZenModeConfig implements Parcelable { @UnsupportedAppUsage public String name; // required for automatic @UnsupportedAppUsage - public int zenMode; + public int zenMode; // ie: Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS @UnsupportedAppUsage public Uri conditionId; // required for automatic public Condition condition; // optional diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java index 2efebf6457ab..7e22dd9f0ac8 100644 --- a/core/java/android/view/DisplayInfo.java +++ b/core/java/android/view/DisplayInfo.java @@ -18,6 +18,7 @@ package android.view; import static android.view.DisplayInfoProto.APP_HEIGHT; import static android.view.DisplayInfoProto.APP_WIDTH; +import static android.view.DisplayInfoProto.FLAGS; import static android.view.DisplayInfoProto.LOGICAL_HEIGHT; import static android.view.DisplayInfoProto.LOGICAL_WIDTH; import static android.view.DisplayInfoProto.NAME; @@ -708,6 +709,7 @@ public final class DisplayInfo implements Parcelable { protoOutputStream.write(APP_WIDTH, appWidth); protoOutputStream.write(APP_HEIGHT, appHeight); protoOutputStream.write(NAME, name); + protoOutputStream.write(FLAGS, flags); protoOutputStream.end(token); } diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index 522ad642ef0d..d5559aaa7146 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -105,8 +105,6 @@ public final class SurfaceControl implements Parcelable { long relativeToObject, int zorder); private static native void nativeSetPosition(long transactionObj, long nativeObject, float x, float y); - private static native void nativeSetGeometryAppliesWithResize(long transactionObj, - long nativeObject); private static native void nativeSetSize(long transactionObj, long nativeObject, int w, int h); private static native void nativeSetTransparentRegionHint(long transactionObj, long nativeObject, Region region); @@ -1104,16 +1102,6 @@ public final class SurfaceControl implements Parcelable { /** * @hide */ - public void setGeometryAppliesWithResize() { - checkNotReleased(); - synchronized(SurfaceControl.class) { - sGlobalTransaction.setGeometryAppliesWithResize(this); - } - } - - /** - * @hide - */ public void setBufferSize(int w, int h) { checkNotReleased(); synchronized(SurfaceControl.class) { @@ -2488,20 +2476,6 @@ public final class SurfaceControl implements Parcelable { } /** - * If the buffer size changes in this transaction, position and crop updates specified - * in this transaction will not complete until a buffer of the new size - * arrives. As transform matrix and size are already frozen in this fashion, - * this enables totally freezing the surface until the resize has completed - * (at which point the geometry influencing aspects of this transaction will then occur) - * @hide - */ - public Transaction setGeometryAppliesWithResize(SurfaceControl sc) { - sc.checkNotReleased(); - nativeSetGeometryAppliesWithResize(mNativeObject, sc.mNativeObject); - return this; - } - - /** * Sets the security of the surface. Setting the flag is equivalent to creating the * Surface with the {@link #SECURE} flag. * @hide diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 3a51eaa5d7d1..85aba3c3f535 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -468,7 +468,6 @@ public final class ViewRootImpl implements ViewParent, private final UnhandledKeyManager mUnhandledKeyManager = new UnhandledKeyManager(); boolean mWindowAttributesChanged = false; - int mWindowAttributesChangesFlag = 0; // These can be accessed by any thread, must be protected with a lock. // Surface can never be reassigned or cleared (use Surface.clear()). @@ -865,7 +864,6 @@ public final class ViewRootImpl implements ViewParent, mSoftInputMode = attrs.softInputMode; mWindowAttributesChanged = true; - mWindowAttributesChangesFlag = WindowManager.LayoutParams.EVERYTHING_CHANGED; mAttachInfo.mRootView = view; mAttachInfo.mScalingRequired = mTranslator != null; mAttachInfo.mApplicationScale = @@ -1269,14 +1267,12 @@ public final class ViewRootImpl implements ViewParent, attrs.systemUiVisibility = mWindowAttributes.systemUiVisibility; attrs.subtreeSystemUiVisibility = mWindowAttributes.subtreeSystemUiVisibility; - mWindowAttributesChangesFlag = mWindowAttributes.copyFrom(attrs); - if ((mWindowAttributesChangesFlag - & WindowManager.LayoutParams.TRANSLUCENT_FLAGS_CHANGED) != 0) { + final int changes = mWindowAttributes.copyFrom(attrs); + if ((changes & WindowManager.LayoutParams.TRANSLUCENT_FLAGS_CHANGED) != 0) { // Recompute system ui visibility. mAttachInfo.mRecomputeGlobalAttributes = true; } - if ((mWindowAttributesChangesFlag - & WindowManager.LayoutParams.LAYOUT_CHANGED) != 0) { + if ((changes & WindowManager.LayoutParams.LAYOUT_CHANGED) != 0) { // Request to update light center. mAttachInfo.mNeedsUpdateLightCenter = true; } @@ -2037,8 +2033,6 @@ public final class ViewRootImpl implements ViewParent, } } - mWindowAttributesChangesFlag = 0; - Rect frame = mWinFrame; if (mFirst) { mFullRedrawNeeded = true; @@ -3313,14 +3307,19 @@ public final class ViewRootImpl implements ViewParent, public void requestTransparentRegion(View child) { // the test below should not fail unless someone is messing with us checkThread(); - if (mView == child) { + if (mView != child) { + return; + } + + if ((mView.mPrivateFlags & View.PFLAG_REQUEST_TRANSPARENT_REGIONS) == 0) { mView.mPrivateFlags |= View.PFLAG_REQUEST_TRANSPARENT_REGIONS; // Need to make sure we re-evaluate the window attributes next // time around, to ensure the window has the correct format. mWindowAttributesChanged = true; - mWindowAttributesChangesFlag = 0; - requestLayout(); } + + // Always request layout to apply the latest transparent region. + requestLayout(); } /** diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index 9cd356f6d653..b2d70321178e 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -2891,8 +2891,6 @@ public interface WindowManager extends ViewManager { public static final int COLOR_MODE_CHANGED = 1 << 26; /** {@hide} */ public static final int INSET_FLAGS_CHANGED = 1 << 27; - /** {@hide} */ - public static final int EVERYTHING_CHANGED = 0xffffffff; // internal buffer to backup/restore parameters under compatibility mode. private int[] mCompatibilityParamsBackup = null; diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java index faeecda7250c..de77aaae1653 100644 --- a/core/java/com/android/internal/app/ChooserActivity.java +++ b/core/java/com/android/internal/app/ChooserActivity.java @@ -493,6 +493,9 @@ public class ChooserActivity extends ResolverActivity { @Override protected void onCreate(Bundle savedInstanceState) { final long intentReceivedTime = System.currentTimeMillis(); + // This is the only place this value is being set. Effectively final. + mIsAppPredictorComponentAvailable = isAppPredictionServiceAvailable(); + mIsSuccessfullySelected = false; Intent intent = getIntent(); Parcelable targetParcelable = intent.getParcelableExtra(Intent.EXTRA_INTENT); @@ -619,9 +622,6 @@ public class ChooserActivity extends ResolverActivity { .addTaggedData(MetricsEvent.FIELD_SHARESHEET_MIMETYPE, target.getType()) .addTaggedData(MetricsEvent.FIELD_TIME_TO_APP_TARGETS, systemCost)); - // This is the only place this value is being set. Effectively final. - mIsAppPredictorComponentAvailable = isAppPredictionServiceAvailable(); - AppPredictor appPredictor = getAppPredictorForDirectShareIfEnabled(); if (appPredictor != null) { mDirectShareAppTargetCache = new HashMap<>(); diff --git a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java index 7c50337a780f..5142d3cd2b99 100644 --- a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java +++ b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java @@ -50,10 +50,19 @@ public final class SystemUiDeviceConfigFlags { // Flags related to controls /** - * (boolean) Wether to have split behavior when opening QS + * (boolean) Whether to have split behavior when opening QS */ public static final String QS_SPLIT_ENABLED = "qs_split_enabled"; + /** + * (int) Open settings panels for WiFi and BT tiles + * 0 - default behavior, link to settings + * 1 - open panel on long press, click remains the same + * 2 - open panel on click, long press remains the same + * 3 - use details on long press + */ + public static final String QS_USE_SETTINGS_PANELS = "qs_use_settings_panels"; + // 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/util/ScreenshotHelper.java b/core/java/com/android/internal/util/ScreenshotHelper.java index 7fd94c6859fb..cac691cf7d45 100644 --- a/core/java/com/android/internal/util/ScreenshotHelper.java +++ b/core/java/com/android/internal/util/ScreenshotHelper.java @@ -1,6 +1,7 @@ package com.android.internal.util; import android.annotation.NonNull; +import android.annotation.Nullable; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -13,6 +14,8 @@ import android.os.RemoteException; import android.os.UserHandle; import android.util.Log; +import java.util.function.Consumer; + public class ScreenshotHelper { private static final String TAG = "ScreenshotHelper"; @@ -34,17 +37,58 @@ public class ScreenshotHelper { } /** + * Request a screenshot be taken with a specific timeout. + * + * Added to support reducing unit test duration; the method variant without a timeout argument + * is recommended for general use. + * + * @param screenshotType The type of screenshot, for example either + * {@link android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN} + * or + * {@link android.view.WindowManager.TAKE_SCREENSHOT_SELECTED_REGION} + * @param hasStatus {@code true} if the status bar is currently showing. {@code false} + * if + * not. + * @param hasNav {@code true} if the navigation bar is currently showing. {@code + * false} + * if not. + * @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. + */ + public void takeScreenshot(final int screenshotType, final boolean hasStatus, + final boolean hasNav, @NonNull Handler handler, + @Nullable Consumer<Boolean> completionConsumer) { + takeScreenshot(screenshotType, hasStatus, hasNav, SCREENSHOT_TIMEOUT_MS, handler, + completionConsumer); + } + + /** * Request a screenshot be taken. * - * @param screenshotType The type of screenshot, for example either - * {@link android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN} - * or {@link android.view.WindowManager.TAKE_SCREENSHOT_SELECTED_REGION} - * @param hasStatus {@code true} if the status bar is currently showing. {@code false} if not. - * @param hasNav {@code true} if the navigation bar is currently showing. {@code false} if not. - * @param handler A handler used in case the screenshot times out + * Added to support reducing unit test duration; the method variant without a timeout argument + * is recommended for general use. + * + * @param screenshotType The type of screenshot, for example either + * {@link android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN} + * or + * {@link android.view.WindowManager.TAKE_SCREENSHOT_SELECTED_REGION} + * @param hasStatus {@code true} if the status bar is currently showing. {@code false} + * if + * not. + * @param hasNav {@code true} if the navigation bar is currently showing. {@code + * false} + * if not. + * @param timeoutMs If the screenshot hasn't been completed within this time period, + * 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. */ public void takeScreenshot(final int screenshotType, final boolean hasStatus, - final boolean hasNav, @NonNull Handler handler) { + final boolean hasNav, long timeoutMs, @NonNull Handler handler, + @Nullable Consumer<Boolean> completionConsumer) { synchronized (mScreenshotLock) { if (mScreenshotConnection != null) { return; @@ -54,7 +98,8 @@ public class ScreenshotHelper { final Intent serviceIntent = new Intent(); final Runnable mScreenshotTimeout = new Runnable() { - @Override public void run() { + @Override + public void run() { synchronized (mScreenshotLock) { if (mScreenshotConnection != null) { mContext.unbindService(mScreenshotConnection); @@ -62,6 +107,9 @@ public class ScreenshotHelper { notifyScreenshotError(); } } + if (completionConsumer != null) { + completionConsumer.accept(false); + } } }; @@ -86,15 +134,22 @@ public class ScreenshotHelper { handler.removeCallbacks(mScreenshotTimeout); } } + if (completionConsumer != null) { + completionConsumer.accept(true); + } } }; msg.replyTo = new Messenger(h); - msg.arg1 = hasStatus ? 1: 0; - msg.arg2 = hasNav ? 1: 0; + msg.arg1 = hasStatus ? 1 : 0; + msg.arg2 = hasNav ? 1 : 0; + try { messenger.send(msg); } catch (RemoteException e) { Log.e(TAG, "Couldn't take screenshot: " + e); + if (completionConsumer != null) { + completionConsumer.accept(false); + } } } } @@ -115,7 +170,7 @@ public class ScreenshotHelper { Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE, UserHandle.CURRENT)) { mScreenshotConnection = conn; - handler.postDelayed(mScreenshotTimeout, SCREENSHOT_TIMEOUT_MS); + handler.postDelayed(mScreenshotTimeout, timeoutMs); } } } diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp index a52a7ed982ec..4cb2d1502610 100644 --- a/core/jni/android_util_Process.cpp +++ b/core/jni/android_util_Process.cpp @@ -658,6 +658,12 @@ static jlong android_os_Process_getTotalMemory(JNIEnv* env, jobject clazz) return si.totalram; } +/* + * The outFields array is initialized to -1 to allow the caller to identify + * when the status file (and therefore the process) they specified is invalid. + * This array should not be overwritten or cleared before we know that the + * status file can be read. + */ void android_os_Process_readProcLines(JNIEnv* env, jobject clazz, jstring fileStr, jobjectArray reqFields, jlongArray outFields) { @@ -706,14 +712,14 @@ void android_os_Process_readProcLines(JNIEnv* env, jobject clazz, jstring fileSt return; } - //ALOGI("Clearing %" PRId32 " sizes", count); - for (i=0; i<count; i++) { - sizesArray[i] = 0; - } - int fd = open(file.string(), O_RDONLY | O_CLOEXEC); if (fd >= 0) { + //ALOGI("Clearing %" PRId32 " sizes", count); + for (i=0; i<count; i++) { + sizesArray[i] = 0; + } + const size_t BUFFER_SIZE = 4096; char* buffer = (char*)malloc(BUFFER_SIZE); int len = read(fd, buffer, BUFFER_SIZE-1); diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp index 67f52f464efa..bf0f10eb50c6 100644 --- a/core/jni/android_view_SurfaceControl.cpp +++ b/core/jni/android_view_SurfaceControl.cpp @@ -397,15 +397,6 @@ static void nativeSetGeometry(JNIEnv* env, jclass clazz, jlong transactionObj, j transaction->setGeometry(ctrl, source, dst, orientation); } -static void nativeSetGeometryAppliesWithResize(JNIEnv* env, jclass clazz, -jlong transactionObj, - jlong nativeObject) { - auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj); - - SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject); - transaction->setGeometryAppliesWithResize(ctrl); -} - static void nativeSetSize(JNIEnv* env, jclass clazz, jlong transactionObj, jlong nativeObject, jint w, jint h) { auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj); @@ -1295,8 +1286,6 @@ static const JNINativeMethod sSurfaceControlMethods[] = { (void*)nativeSetRelativeLayer }, {"nativeSetPosition", "(JJFF)V", (void*)nativeSetPosition }, - {"nativeSetGeometryAppliesWithResize", "(JJ)V", - (void*)nativeSetGeometryAppliesWithResize }, {"nativeSetSize", "(JJII)V", (void*)nativeSetSize }, {"nativeSetTransparentRegionHint", "(JJLandroid/graphics/Region;)V", diff --git a/core/proto/android/view/displayinfo.proto b/core/proto/android/view/displayinfo.proto index 49c0a290c368..984be2a2e417 100644 --- a/core/proto/android/view/displayinfo.proto +++ b/core/proto/android/view/displayinfo.proto @@ -33,4 +33,5 @@ message DisplayInfoProto { // The human-readable name of the display. // Eg: "Built-in Screen" optional string name = 5; + optional int32 flags = 6; } diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml index b2f9183e4457..797d75f5a54f 100644 --- a/core/res/res/values-en-rCA/strings.xml +++ b/core/res/res/values-en-rCA/strings.xml @@ -1256,10 +1256,10 @@ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Tap to see all networks"</string> <string name="wifi_available_action_connect" msgid="2635699628459488788">"Connect"</string> <string name="wifi_available_action_all_networks" msgid="4368435796357931006">"All networks"</string> - <string name="wifi_suggestion_title" msgid="6396033039578436801">"Allow suggested Wi‑Fi networks?"</string> - <string name="wifi_suggestion_content" msgid="5603992011371520746">"<xliff:g id="NAME">%s</xliff:g> suggested networks. Device may connect automatically."</string> - <string name="wifi_suggestion_action_allow_app" msgid="7978995387498669901">"Allow"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="6434097275967940372">"No, thanks"</string> + <string name="wifi_suggestion_title" msgid="9099832833531486167">"Connect to Wi‑Fi networks?"</string> + <string name="wifi_suggestion_content" msgid="5883181205841582873">"Suggested by <xliff:g id="NAME">%s</xliff:g>"</string> + <string name="wifi_suggestion_action_allow_app" msgid="3689946344485394085">"Yes"</string> + <string name="wifi_suggestion_action_disallow_app" msgid="7977918905605931385">"No"</string> <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi will turn on automatically"</string> <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"When you\'re near a high‑quality saved network"</string> <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Don\'t turn back on"</string> diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml index a6aa60430425..7ea76500e4ea 100644 --- a/core/res/res/values-en-rXC/strings.xml +++ b/core/res/res/values-en-rXC/strings.xml @@ -1256,10 +1256,10 @@ <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Tap to see all networks"</string> <string name="wifi_available_action_connect" msgid="2635699628459488788">"Connect"</string> <string name="wifi_available_action_all_networks" msgid="4368435796357931006">"All networks"</string> - <string name="wifi_suggestion_title" msgid="6396033039578436801">"Allow suggested Wi‑Fi networks?"</string> - <string name="wifi_suggestion_content" msgid="5603992011371520746">"<xliff:g id="NAME">%s</xliff:g> suggested networks. Device may connect automatically."</string> - <string name="wifi_suggestion_action_allow_app" msgid="7978995387498669901">"Allow"</string> - <string name="wifi_suggestion_action_disallow_app" msgid="6434097275967940372">"No thanks"</string> + <string name="wifi_suggestion_title" msgid="9099832833531486167">"Connect to Wi‑Fi networks?"</string> + <string name="wifi_suggestion_content" msgid="5883181205841582873">"Suggested by <xliff:g id="NAME">%s</xliff:g>"</string> + <string name="wifi_suggestion_action_allow_app" msgid="3689946344485394085">"Yes"</string> + <string name="wifi_suggestion_action_disallow_app" msgid="7977918905605931385">"No"</string> <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi will turn on automatically"</string> <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"When you\'re near a high quality saved network"</string> <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Don\'t turn back on"</string> diff --git a/core/tests/coretests/src/android/os/ProcessTest.java b/core/tests/coretests/src/android/os/ProcessTest.java index 9de450196fa0..ae4edb97aab0 100644 --- a/core/tests/coretests/src/android/os/ProcessTest.java +++ b/core/tests/coretests/src/android/os/ProcessTest.java @@ -17,13 +17,12 @@ package android.os; -import androidx.test.filters.MediumTest; - import junit.framework.TestCase; public class ProcessTest extends TestCase { - @MediumTest + private static final int BAD_PID = 0; + public void testProcessGetUidFromName() throws Exception { assertEquals(android.os.Process.SYSTEM_UID, Process.getUidForName("system")); assertEquals(Process.BLUETOOTH_UID, Process.getUidForName("bluetooth")); @@ -37,7 +36,6 @@ public class ProcessTest extends TestCase { Process.getUidForName("u3_a100")); } - @MediumTest public void testProcessGetUidFromNameFailure() throws Exception { // Failure cases assertEquals(-1, Process.getUidForName("u2a_foo")); @@ -49,4 +47,29 @@ public class ProcessTest extends TestCase { assertEquals(-1, Process.getUidForName("u2jhsajhfkjhsafkhskafhkashfkjashfkjhaskjfdhakj3")); } + /** + * Tests getUidForPid() by ensuring that it returns the correct value when the process queried + * doesn't exist. + */ + public void testGetUidForPidInvalidPid() { + assertEquals(-1, Process.getUidForPid(BAD_PID)); + } + + /** + * Tests getParentPid() by ensuring that it returns the correct value when the process queried + * doesn't exist. + */ + public void testGetParentPidInvalidPid() { + assertEquals(-1, Process.getParentPid(BAD_PID)); + } + + /** + * Tests getThreadGroupLeader() by ensuring that it returns the correct value when the + * thread queried doesn't exist. + */ + public void testGetThreadGroupLeaderInvalidTid() { + // This function takes a TID instead of a PID but BAD_PID should also be a bad TID. + assertEquals(-1, Process.getThreadGroupLeader(BAD_PID)); + } + } diff --git a/core/tests/coretests/src/android/service/notification/StatusBarNotificationTest.java b/core/tests/coretests/src/android/service/notification/StatusBarNotificationTest.java index 6161108d4d70..a5a98a98f0be 100644 --- a/core/tests/coretests/src/android/service/notification/StatusBarNotificationTest.java +++ b/core/tests/coretests/src/android/service/notification/StatusBarNotificationTest.java @@ -19,6 +19,8 @@ package android.service.notification; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertNull; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -181,6 +183,22 @@ public class StatusBarNotificationTest { logMaker.getTaggedData(MetricsEvent.FIELD_NOTIFICATION_STYLE)); } + @Test + public void testIsAppGroup() { + StatusBarNotification sbn = getNotification(PKG, GROUP_ID_1, CHANNEL_ID); + assertTrue(sbn.isAppGroup()); + + sbn = getNotification(PKG, null, CHANNEL_ID); + assertFalse(sbn.isAppGroup()); + + Notification.Builder nb = getNotificationBuilder(null, CHANNEL_ID) + .setSortKey("something"); + + sbn = getNotification(PKG, nb); + assertTrue(sbn.isAppGroup()); + + } + private StatusBarNotification getNotification(String pkg, String group, String channelId) { return getNotification(pkg, getNotificationBuilder(group, channelId)); } diff --git a/core/tests/screenshothelpertests/Android.bp b/core/tests/screenshothelpertests/Android.bp new file mode 100644 index 000000000000..3d54b68b7ddc --- /dev/null +++ b/core/tests/screenshothelpertests/Android.bp @@ -0,0 +1,28 @@ +android_test { + name: "ScreenshotHelperTests", + + srcs: [ + "src/**/*.java", + ], + + static_libs: [ + "frameworks-base-testutils", + "androidx.test.runner", + "androidx.test.rules", + "androidx.test.ext.junit", + "mockito-target-minus-junit4", + "platform-test-annotations", + ], + + libs: [ + "android.test.runner", + "android.test.base", + "android.test.mock", + ], + + platform_apis: true, + test_suites: ["device-tests"], + + certificate: "platform", +} + diff --git a/core/tests/screenshothelpertests/AndroidManifest.xml b/core/tests/screenshothelpertests/AndroidManifest.xml new file mode 100644 index 000000000000..2e12ef4db358 --- /dev/null +++ b/core/tests/screenshothelpertests/AndroidManifest.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. +--> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + android:installLocation="internalOnly" + package="com.android.internal.util" + android:sharedUserId="android.uid.systemui" > + + <application > + <uses-library android:name="android.test.runner" /> + </application> + + <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner" + android:targetPackage="com.android.internal.util" + android:label="Screenshot Helper Tests" /> + + <protected-broadcast android:name="android.intent.action.USER_PRESENT" /> + +</manifest> diff --git a/core/tests/screenshothelpertests/src/com/android/internal/util/ScreenshotHelperTest.java b/core/tests/screenshothelpertests/src/com/android/internal/util/ScreenshotHelperTest.java new file mode 100644 index 000000000000..848364584ef3 --- /dev/null +++ b/core/tests/screenshothelpertests/src/com/android/internal/util/ScreenshotHelperTest.java @@ -0,0 +1,98 @@ +/* + * 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.util; + +import static android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN; +import static android.view.WindowManager.TAKE_SCREENSHOT_SELECTED_REGION; + +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.fail; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; + +import android.content.Context; +import android.os.Handler; +import android.os.Looper; + +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +@RunWith(AndroidJUnit4.class) +public final class ScreenshotHelperTest { + private Context mContext; + private ScreenshotHelper mScreenshotHelper; + private Handler mHandler; + + + @Before + public void setUp() { + // `ScreenshotHelper.notifyScreenshotError()` calls `Context.sendBroadcastAsUser()` and + // `Context.bindServiceAsUser`. + // + // This raises a `SecurityException` if the device is locked. Calling either `Context` + // method results in a broadcast of `android.intent.action. USER_PRESENT`. Only the system + // process is allowed to broadcast that `Intent`. + mContext = Mockito.spy(Context.class); + Mockito.doNothing().when(mContext).sendBroadcastAsUser(any(), any()); + Mockito.doReturn(true).when(mContext).bindServiceAsUser(any(), any(), anyInt(), any()); + + mHandler = new Handler(Looper.getMainLooper()); + mScreenshotHelper = new ScreenshotHelper(mContext); + } + + @Test + public void testFullscreenScreenshot() { + mScreenshotHelper.takeScreenshot(TAKE_SCREENSHOT_FULLSCREEN, false, false, mHandler, null); + } + + @Test + public void testSelectedRegionScreenshot() { + mScreenshotHelper.takeScreenshot(TAKE_SCREENSHOT_SELECTED_REGION, false, false, mHandler, + null); + } + + @Test + public void testScreenshotTimesOut() { + long timeoutMs = 10; + + CountDownLatch lock = new CountDownLatch(1); + mScreenshotHelper.takeScreenshot(TAKE_SCREENSHOT_FULLSCREEN, false, false, timeoutMs, + mHandler, + worked -> { + assertFalse(worked); + lock.countDown(); + }); + + try { + // Add tolerance for delay to prevent flakes. + long awaitDurationMs = timeoutMs + 100; + if (!lock.await(awaitDurationMs, TimeUnit.MILLISECONDS)) { + fail("lock never freed"); + } + } catch (InterruptedException e) { + fail("lock interrupted"); + } + } +} diff --git a/libs/hwui/service/GraphicsStatsService.cpp b/libs/hwui/service/GraphicsStatsService.cpp index 8b5912b2081a..12c5b836f711 100644 --- a/libs/hwui/service/GraphicsStatsService.cpp +++ b/libs/hwui/service/GraphicsStatsService.cpp @@ -282,9 +282,9 @@ void dumpAsTextToFd(protos::GraphicsStatsProto* proto, int fd) { return; } dprintf(fd, "\nPackage: %s", proto->package_name().c_str()); - dprintf(fd, "\nVersion: %lld", proto->version_code()); - dprintf(fd, "\nStats since: %lldns", proto->stats_start()); - dprintf(fd, "\nStats end: %lldns", proto->stats_end()); + dprintf(fd, "\nVersion: %" PRId64, proto->version_code()); + dprintf(fd, "\nStats since: %" PRId64 "ns", proto->stats_start()); + dprintf(fd, "\nStats end: %" PRId64 "ns", proto->stats_end()); auto summary = proto->summary(); dprintf(fd, "\nTotal frames rendered: %d", summary.total_frames()); dprintf(fd, "\nJanky frames: %d (%.2f%%)", summary.janky_frames(), diff --git a/libs/protoutil/include/android/util/ProtoOutputStream.h b/libs/protoutil/include/android/util/ProtoOutputStream.h index a6af4757a140..42bf03e6de05 100644 --- a/libs/protoutil/include/android/util/ProtoOutputStream.h +++ b/libs/protoutil/include/android/util/ProtoOutputStream.h @@ -98,6 +98,7 @@ public: bool write(uint64_t fieldId, double val); bool write(uint64_t fieldId, float val); bool write(uint64_t fieldId, int val); + bool write(uint64_t fieldId, long val); bool write(uint64_t fieldId, long long val); bool write(uint64_t fieldId, bool val); bool write(uint64_t fieldId, std::string val); diff --git a/libs/protoutil/src/ProtoOutputStream.cpp b/libs/protoutil/src/ProtoOutputStream.cpp index 6cfa357b580b..ea9b79a0353f 100644 --- a/libs/protoutil/src/ProtoOutputStream.cpp +++ b/libs/protoutil/src/ProtoOutputStream.cpp @@ -116,6 +116,34 @@ ProtoOutputStream::write(uint64_t fieldId, int val) } bool +ProtoOutputStream::write(uint64_t fieldId, long val) +{ + if (mCompact) return false; + const uint32_t id = (uint32_t)fieldId; + switch (fieldId & FIELD_TYPE_MASK) { + case FIELD_TYPE_DOUBLE: writeDoubleImpl(id, (double)val); break; + case FIELD_TYPE_FLOAT: writeFloatImpl(id, (float)val); break; + case FIELD_TYPE_INT64: writeInt64Impl(id, (long long)val); break; + case FIELD_TYPE_UINT64: writeUint64Impl(id, (uint64_t)val); break; + case FIELD_TYPE_INT32: writeInt32Impl(id, (int)val); break; + case FIELD_TYPE_FIXED64: writeFixed64Impl(id, (uint64_t)val); break; + case FIELD_TYPE_FIXED32: writeFixed32Impl(id, (uint32_t)val); break; + case FIELD_TYPE_UINT32: writeUint32Impl(id, (uint32_t)val); break; + case FIELD_TYPE_SFIXED32: writeSFixed32Impl(id, (int)val); break; + case FIELD_TYPE_SFIXED64: writeSFixed64Impl(id, (long long)val); break; + case FIELD_TYPE_SINT32: writeZigzagInt32Impl(id, (int)val); break; + case FIELD_TYPE_SINT64: writeZigzagInt64Impl(id, (long long)val); break; + case FIELD_TYPE_ENUM: writeEnumImpl(id, (int)val); break; + case FIELD_TYPE_BOOL: writeBoolImpl(id, val != 0); break; + default: + ALOGW("Field type %d is not supported when writing long val.", + (int)((fieldId & FIELD_TYPE_MASK) >> FIELD_TYPE_SHIFT)); + return false; + } + return true; +} + +bool ProtoOutputStream::write(uint64_t fieldId, long long val) { return internalWrite(fieldId, val, "long long"); diff --git a/packages/BackupEncryption/Android.bp b/packages/BackupEncryption/Android.bp new file mode 100644 index 000000000000..50dbcdb1b4c7 --- /dev/null +++ b/packages/BackupEncryption/Android.bp @@ -0,0 +1,24 @@ +// +// 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. +// + +android_app { + name: "BackupEncryption", + srcs: ["src/**/*.java"], + optimize: { enabled: false }, + platform_apis: true, + certificate: "platform", + privileged: true, +}
\ No newline at end of file diff --git a/packages/BackupEncryption/AndroidManifest.xml b/packages/BackupEncryption/AndroidManifest.xml new file mode 100644 index 000000000000..a705df5a425b --- /dev/null +++ b/packages/BackupEncryption/AndroidManifest.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * Copyright (c) 2016 Google Inc. + * + * 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. + */ +--> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.server.backup.encryption" + android:sharedUserId="android.uid.system" > + + <application android:allowBackup="false" /> +</manifest> diff --git a/packages/BackupEncryption/proguard.flags b/packages/BackupEncryption/proguard.flags new file mode 100644 index 000000000000..851ce8caab43 --- /dev/null +++ b/packages/BackupEncryption/proguard.flags @@ -0,0 +1 @@ +-keep class com.android.server.backup.encryption diff --git a/services/backup/java/com/android/server/backup/encryption/chunk/Chunk.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunk/Chunk.java index 5bec1a94e915..ba328609a77e 100644 --- a/services/backup/java/com/android/server/backup/encryption/chunk/Chunk.java +++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunk/Chunk.java @@ -1,3 +1,19 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package com.android.server.backup.encryption.chunk; import android.util.proto.ProtoInputStream; @@ -51,4 +67,4 @@ public class Chunk { public byte[] getHash() { return mHash; } -}
\ No newline at end of file +} diff --git a/services/backup/java/com/android/server/backup/encryption/chunk/ChunkHash.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunk/ChunkHash.java index 1ae598ec9920..1630eb8ff4e8 100644 --- a/services/backup/java/com/android/server/backup/encryption/chunk/ChunkHash.java +++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunk/ChunkHash.java @@ -11,12 +11,13 @@ * 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 + * limitations under the License. */ package com.android.server.backup.encryption.chunk; import com.android.internal.util.Preconditions; + import java.util.Arrays; import java.util.Base64; diff --git a/services/backup/java/com/android/server/backup/encryption/chunk/ChunkListingMap.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunk/ChunkListingMap.java index a44890118717..a44890118717 100644 --- a/services/backup/java/com/android/server/backup/encryption/chunk/ChunkListingMap.java +++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunk/ChunkListingMap.java diff --git a/services/backup/java/com/android/server/backup/encryption/chunk/ChunkOrderingType.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunk/ChunkOrderingType.java index df36c9409732..8cb028e46e9d 100644 --- a/services/backup/java/com/android/server/backup/encryption/chunk/ChunkOrderingType.java +++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunk/ChunkOrderingType.java @@ -11,7 +11,7 @@ * 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 + * limitations under the License. */ package com.android.server.backup.encryption.chunk; @@ -21,6 +21,7 @@ import static com.android.server.backup.encryption.chunk.ChunksMetadataProto.EXP import static com.android.server.backup.encryption.chunk.ChunksMetadataProto.INLINE_LENGTHS; import android.annotation.IntDef; + import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; diff --git a/services/backup/java/com/android/server/backup/encryption/chunk/EncryptedChunkOrdering.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunk/EncryptedChunkOrdering.java index 3a6d1f62faaa..edf1b9abb822 100644 --- a/services/backup/java/com/android/server/backup/encryption/chunk/EncryptedChunkOrdering.java +++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunk/EncryptedChunkOrdering.java @@ -11,7 +11,7 @@ * 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 + * limitations under the License. */ package com.android.server.backup.encryption.chunk; @@ -38,6 +38,7 @@ public class EncryptedChunkOrdering { private final byte[] mEncryptedChunkOrdering; + /** Get the encrypted chunk ordering */ public byte[] encryptedChunkOrdering() { return mEncryptedChunkOrdering; } diff --git a/services/backup/java/com/android/server/backup/encryption/chunking/BackupWriter.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/BackupWriter.java index 68d9d145139f..baa820cbd558 100644 --- a/services/backup/java/com/android/server/backup/encryption/chunking/BackupWriter.java +++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/BackupWriter.java @@ -11,7 +11,7 @@ * 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 + * limitations under the License. */ package com.android.server.backup.encryption.chunking; diff --git a/services/backup/java/com/android/server/backup/encryption/chunking/ByteRange.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/ByteRange.java index 004d9e3b45f1..004d9e3b45f1 100644 --- a/services/backup/java/com/android/server/backup/encryption/chunking/ByteRange.java +++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/ByteRange.java diff --git a/services/backup/java/com/android/server/backup/encryption/chunking/ChunkEncryptor.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/ChunkEncryptor.java index 812cfbd76e31..48abc8cc4088 100644 --- a/services/backup/java/com/android/server/backup/encryption/chunking/ChunkEncryptor.java +++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/ChunkEncryptor.java @@ -11,16 +11,18 @@ * 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 + * limitations under the License. */ package com.android.server.backup.encryption.chunking; import com.android.server.backup.encryption.chunk.ChunkHash; + import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; + import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; diff --git a/services/backup/java/com/android/server/backup/encryption/chunking/ChunkHasher.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/ChunkHasher.java index 145b7bf82517..02d498ccd726 100644 --- a/services/backup/java/com/android/server/backup/encryption/chunking/ChunkHasher.java +++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/ChunkHasher.java @@ -11,14 +11,16 @@ * 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 + * limitations under the License. */ package com.android.server.backup.encryption.chunking; import com.android.server.backup.encryption.chunk.ChunkHash; + import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; + import javax.crypto.Mac; import javax.crypto.SecretKey; diff --git a/services/backup/java/com/android/server/backup/encryption/chunking/Chunker.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/Chunker.java index b91913e5fc80..c9a6293ed060 100644 --- a/services/backup/java/com/android/server/backup/encryption/chunking/Chunker.java +++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/Chunker.java @@ -11,7 +11,7 @@ * 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 + * limitations under the License. */ package com.android.server.backup.encryption.chunking; diff --git a/services/backup/java/com/android/server/backup/encryption/chunking/DecryptedChunkFileOutput.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/DecryptedChunkFileOutput.java index ae2e150de4bc..ae2e150de4bc 100644 --- a/services/backup/java/com/android/server/backup/encryption/chunking/DecryptedChunkFileOutput.java +++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/DecryptedChunkFileOutput.java diff --git a/services/backup/java/com/android/server/backup/encryption/chunking/DiffScriptBackupWriter.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/DiffScriptBackupWriter.java index 69fb5cbf606d..69fb5cbf606d 100644 --- a/services/backup/java/com/android/server/backup/encryption/chunking/DiffScriptBackupWriter.java +++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/DiffScriptBackupWriter.java diff --git a/services/backup/java/com/android/server/backup/encryption/chunking/DiffScriptWriter.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/DiffScriptWriter.java index 49d15712d4cc..49d15712d4cc 100644 --- a/services/backup/java/com/android/server/backup/encryption/chunking/DiffScriptWriter.java +++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/DiffScriptWriter.java diff --git a/services/backup/java/com/android/server/backup/encryption/chunking/EncryptedChunk.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/EncryptedChunk.java index 1f936eb2bfa5..cde59fa189de 100644 --- a/services/backup/java/com/android/server/backup/encryption/chunking/EncryptedChunk.java +++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/EncryptedChunk.java @@ -11,13 +11,14 @@ * 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 + * limitations under the License. */ package com.android.server.backup.encryption.chunking; import com.android.internal.util.Preconditions; import com.android.server.backup.encryption.chunk.ChunkHash; + import java.util.Arrays; import java.util.Objects; diff --git a/services/backup/java/com/android/server/backup/encryption/chunking/EncryptedChunkEncoder.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/EncryptedChunkEncoder.java index eaf701ce0bf5..16beda32af17 100644 --- a/services/backup/java/com/android/server/backup/encryption/chunking/EncryptedChunkEncoder.java +++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/EncryptedChunkEncoder.java @@ -11,12 +11,13 @@ * 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 + * limitations under the License. */ package com.android.server.backup.encryption.chunking; import com.android.server.backup.encryption.chunk.ChunkOrderingType; + import java.io.IOException; /** Encodes an {@link EncryptedChunk} as bytes to write to the encrypted backup file. */ diff --git a/services/backup/java/com/android/server/backup/encryption/chunking/InlineLengthsEncryptedChunkEncoder.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/InlineLengthsEncryptedChunkEncoder.java index 5c902cad7495..7b38dd4a1dc3 100644 --- a/services/backup/java/com/android/server/backup/encryption/chunking/InlineLengthsEncryptedChunkEncoder.java +++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/InlineLengthsEncryptedChunkEncoder.java @@ -11,13 +11,14 @@ * 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 + * limitations under the License. */ package com.android.server.backup.encryption.chunking; import com.android.server.backup.encryption.chunk.ChunkOrderingType; import com.android.server.backup.encryption.chunk.ChunksMetadataProto; + import java.io.IOException; /** diff --git a/services/backup/java/com/android/server/backup/encryption/chunking/LengthlessEncryptedChunkEncoder.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/LengthlessEncryptedChunkEncoder.java index 4b849818f1c3..567f75d59513 100644 --- a/services/backup/java/com/android/server/backup/encryption/chunking/LengthlessEncryptedChunkEncoder.java +++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/LengthlessEncryptedChunkEncoder.java @@ -11,13 +11,14 @@ * 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 + * limitations under the License. */ package com.android.server.backup.encryption.chunking; import com.android.server.backup.encryption.chunk.ChunkOrderingType; import com.android.server.backup.encryption.chunk.ChunksMetadataProto; + import java.io.IOException; /** diff --git a/services/backup/java/com/android/server/backup/encryption/chunking/OutputStreamWrapper.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/OutputStreamWrapper.java index 4aea60121810..4aea60121810 100644 --- a/services/backup/java/com/android/server/backup/encryption/chunking/OutputStreamWrapper.java +++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/OutputStreamWrapper.java diff --git a/services/backup/java/com/android/server/backup/encryption/chunking/RawBackupWriter.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/RawBackupWriter.java index 839dc7c7b5ce..b211b0fc9470 100644 --- a/services/backup/java/com/android/server/backup/encryption/chunking/RawBackupWriter.java +++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/RawBackupWriter.java @@ -11,7 +11,7 @@ * 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 + * limitations under the License. */ package com.android.server.backup.encryption.chunking; @@ -21,18 +21,18 @@ import java.io.OutputStream; /** Writes data straight to an output stream. */ public class RawBackupWriter implements BackupWriter { - private final OutputStream outputStream; - private long bytesWritten; + private final OutputStream mOutputStream; + private long mBytesWritten; /** Constructs a new writer which writes bytes to the given output stream. */ public RawBackupWriter(OutputStream outputStream) { - this.outputStream = outputStream; + this.mOutputStream = outputStream; } @Override public void writeBytes(byte[] bytes) throws IOException { - outputStream.write(bytes); - bytesWritten += bytes.length; + mOutputStream.write(bytes); + mBytesWritten += bytes.length; } @Override @@ -42,11 +42,11 @@ public class RawBackupWriter implements BackupWriter { @Override public long getBytesWritten() { - return bytesWritten; + return mBytesWritten; } @Override public void flush() throws IOException { - outputStream.flush(); + mOutputStream.flush(); } } diff --git a/services/backup/java/com/android/server/backup/encryption/chunking/SingleStreamDiffScriptWriter.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/SingleStreamDiffScriptWriter.java index 0e4bd58345d5..0e4bd58345d5 100644 --- a/services/backup/java/com/android/server/backup/encryption/chunking/SingleStreamDiffScriptWriter.java +++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/SingleStreamDiffScriptWriter.java diff --git a/services/backup/java/com/android/server/backup/encryption/chunking/cdc/ContentDefinedChunker.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/cdc/ContentDefinedChunker.java index 18011f620b24..18011f620b24 100644 --- a/services/backup/java/com/android/server/backup/encryption/chunking/cdc/ContentDefinedChunker.java +++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/cdc/ContentDefinedChunker.java diff --git a/services/backup/java/com/android/server/backup/encryption/chunking/cdc/FingerprintMixer.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/cdc/FingerprintMixer.java index e9f30505c112..e9f30505c112 100644 --- a/services/backup/java/com/android/server/backup/encryption/chunking/cdc/FingerprintMixer.java +++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/cdc/FingerprintMixer.java diff --git a/services/backup/java/com/android/server/backup/encryption/chunking/cdc/Hkdf.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/cdc/Hkdf.java index 6f4f549ab2d7..6f4f549ab2d7 100644 --- a/services/backup/java/com/android/server/backup/encryption/chunking/cdc/Hkdf.java +++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/cdc/Hkdf.java diff --git a/services/backup/java/com/android/server/backup/encryption/chunking/cdc/IsChunkBreakpoint.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/cdc/IsChunkBreakpoint.java index e867e7c1b801..e867e7c1b801 100644 --- a/services/backup/java/com/android/server/backup/encryption/chunking/cdc/IsChunkBreakpoint.java +++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/cdc/IsChunkBreakpoint.java diff --git a/services/backup/java/com/android/server/backup/encryption/chunking/cdc/RabinFingerprint64.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/cdc/RabinFingerprint64.java index 1e14ffa5ad77..1e14ffa5ad77 100644 --- a/services/backup/java/com/android/server/backup/encryption/chunking/cdc/RabinFingerprint64.java +++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/cdc/RabinFingerprint64.java diff --git a/services/backup/java/com/android/server/backup/encryption/keys/RecoverableKeyStoreSecondaryKey.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/keys/RecoverableKeyStoreSecondaryKey.java index f356b4f102e2..f356b4f102e2 100644 --- a/services/backup/java/com/android/server/backup/encryption/keys/RecoverableKeyStoreSecondaryKey.java +++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/keys/RecoverableKeyStoreSecondaryKey.java diff --git a/services/backup/java/com/android/server/backup/encryption/keys/RecoverableKeyStoreSecondaryKeyManager.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/keys/RecoverableKeyStoreSecondaryKeyManager.java index c89076b9928f..c89076b9928f 100644 --- a/services/backup/java/com/android/server/backup/encryption/keys/RecoverableKeyStoreSecondaryKeyManager.java +++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/keys/RecoverableKeyStoreSecondaryKeyManager.java diff --git a/services/backup/java/com/android/server/backup/encryption/keys/TertiaryKeyGenerator.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/keys/TertiaryKeyGenerator.java index a425c720b9b8..a425c720b9b8 100644 --- a/services/backup/java/com/android/server/backup/encryption/keys/TertiaryKeyGenerator.java +++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/keys/TertiaryKeyGenerator.java diff --git a/services/backup/java/com/android/server/backup/encryption/keys/TertiaryKeyRotationTracker.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/keys/TertiaryKeyRotationTracker.java index ec90f6c8c95e..ec90f6c8c95e 100644 --- a/services/backup/java/com/android/server/backup/encryption/keys/TertiaryKeyRotationTracker.java +++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/keys/TertiaryKeyRotationTracker.java diff --git a/services/backup/java/com/android/server/backup/encryption/storage/BackupEncryptionDb.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/storage/BackupEncryptionDb.java index 9f6c03a6f393..9f6c03a6f393 100644 --- a/services/backup/java/com/android/server/backup/encryption/storage/BackupEncryptionDb.java +++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/storage/BackupEncryptionDb.java diff --git a/services/backup/java/com/android/server/backup/encryption/storage/BackupEncryptionDbContract.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/storage/BackupEncryptionDbContract.java index 5e8a8d9fc2ae..5e8a8d9fc2ae 100644 --- a/services/backup/java/com/android/server/backup/encryption/storage/BackupEncryptionDbContract.java +++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/storage/BackupEncryptionDbContract.java diff --git a/services/backup/java/com/android/server/backup/encryption/storage/BackupEncryptionDbHelper.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/storage/BackupEncryptionDbHelper.java index c70634248dca..c70634248dca 100644 --- a/services/backup/java/com/android/server/backup/encryption/storage/BackupEncryptionDbHelper.java +++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/storage/BackupEncryptionDbHelper.java diff --git a/services/backup/java/com/android/server/backup/encryption/storage/EncryptionDbException.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/storage/EncryptionDbException.java index 82f7dead1b50..82f7dead1b50 100644 --- a/services/backup/java/com/android/server/backup/encryption/storage/EncryptionDbException.java +++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/storage/EncryptionDbException.java diff --git a/services/backup/java/com/android/server/backup/encryption/storage/TertiaryKey.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/storage/TertiaryKey.java index 39a2c6ebb9c3..39a2c6ebb9c3 100644 --- a/services/backup/java/com/android/server/backup/encryption/storage/TertiaryKey.java +++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/storage/TertiaryKey.java diff --git a/services/backup/java/com/android/server/backup/encryption/storage/TertiaryKeysTable.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/storage/TertiaryKeysTable.java index d8d40c402a84..d8d40c402a84 100644 --- a/services/backup/java/com/android/server/backup/encryption/storage/TertiaryKeysTable.java +++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/storage/TertiaryKeysTable.java diff --git a/services/backup/java/com/android/server/backup/encryption/tasks/BackupEncrypter.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/tasks/BackupEncrypter.java index 95d0d97b4073..95d0d97b4073 100644 --- a/services/backup/java/com/android/server/backup/encryption/tasks/BackupEncrypter.java +++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/tasks/BackupEncrypter.java diff --git a/services/backup/java/com/android/server/backup/encryption/tasks/BackupStreamEncrypter.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/tasks/BackupStreamEncrypter.java index 45798d32885a..45798d32885a 100644 --- a/services/backup/java/com/android/server/backup/encryption/tasks/BackupStreamEncrypter.java +++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/tasks/BackupStreamEncrypter.java diff --git a/services/backup/java/com/android/server/backup/encryption/tasks/DecryptedChunkOutput.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/tasks/DecryptedChunkOutput.java index e3df3c1eb96f..e3df3c1eb96f 100644 --- a/services/backup/java/com/android/server/backup/encryption/tasks/DecryptedChunkOutput.java +++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/tasks/DecryptedChunkOutput.java diff --git a/services/backup/java/com/android/server/backup/encryption/tasks/EncryptedRestoreException.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/tasks/EncryptedRestoreException.java index 487c0d92f6fd..487c0d92f6fd 100644 --- a/services/backup/java/com/android/server/backup/encryption/tasks/EncryptedRestoreException.java +++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/tasks/EncryptedRestoreException.java diff --git a/packages/BackupEncryption/test/robolectric/Android.bp b/packages/BackupEncryption/test/robolectric/Android.bp new file mode 100644 index 000000000000..6d1abbb61a8e --- /dev/null +++ b/packages/BackupEncryption/test/robolectric/Android.bp @@ -0,0 +1,32 @@ +// Copyright (C) 2018 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. + +android_robolectric_test { + name: "BackupEncryptionRoboTests", + srcs: [ + "src/**/*.java", + ":FrameworksServicesRoboShadows", + ], + java_resource_dirs: ["config"], + libs: [ + "platform-test-annotations", + "testng", + ], + instrumentation_for: "BackupEncryption", +} + +filegroup { + name: "BackupEncryptionRoboShadows", + srcs: ["src/com/android/server/testing/shadows/**/*.java"], +} diff --git a/packages/BackupEncryption/test/robolectric/AndroidManifest.xml b/packages/BackupEncryption/test/robolectric/AndroidManifest.xml new file mode 100644 index 000000000000..ae5cdd918abd --- /dev/null +++ b/packages/BackupEncryption/test/robolectric/AndroidManifest.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + 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. + --> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + coreApp="true" + package="com.android.server.backup.encryption.robotests"> + + <application/> + +</manifest> diff --git a/packages/BackupEncryption/test/robolectric/config/robolectric.properties b/packages/BackupEncryption/test/robolectric/config/robolectric.properties new file mode 100644 index 000000000000..26fceb3f84a4 --- /dev/null +++ b/packages/BackupEncryption/test/robolectric/config/robolectric.properties @@ -0,0 +1,17 @@ +# +# 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. +# + +sdk=NEWEST_SDK diff --git a/services/robotests/backup/src/com/android/server/backup/encryption/chunk/ChunkHashTest.java b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/chunk/ChunkHashTest.java index 3f57240bc0e9..c12464c50175 100644 --- a/services/robotests/backup/src/com/android/server/backup/encryption/chunk/ChunkHashTest.java +++ b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/chunk/ChunkHashTest.java @@ -11,7 +11,7 @@ * 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 + * limitations under the License. */ package com.android.server.backup.encryption.chunk; diff --git a/services/robotests/backup/src/com/android/server/backup/encryption/chunk/ChunkListingMapTest.java b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/chunk/ChunkListingMapTest.java index 24e5573b891d..24e5573b891d 100644 --- a/services/robotests/backup/src/com/android/server/backup/encryption/chunk/ChunkListingMapTest.java +++ b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/chunk/ChunkListingMapTest.java diff --git a/services/robotests/backup/src/com/android/server/backup/encryption/chunk/ChunkTest.java b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/chunk/ChunkTest.java index 17c9a86169be..1796f56ce17a 100644 --- a/services/robotests/backup/src/com/android/server/backup/encryption/chunk/ChunkTest.java +++ b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/chunk/ChunkTest.java @@ -11,7 +11,7 @@ * 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 + * limitations under the License. */ package com.android.server.backup.encryption.chunk; diff --git a/services/robotests/backup/src/com/android/server/backup/encryption/chunk/EncryptedChunkOrderingTest.java b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/chunk/EncryptedChunkOrderingTest.java index 0bf14174e5c3..c6b29b7b7236 100644 --- a/services/robotests/backup/src/com/android/server/backup/encryption/chunk/EncryptedChunkOrderingTest.java +++ b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/chunk/EncryptedChunkOrderingTest.java @@ -11,7 +11,7 @@ * 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 + * limitations under the License. */ package com.android.server.backup.encryption.chunk; diff --git a/services/robotests/backup/src/com/android/server/backup/encryption/chunking/ByteRangeTest.java b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/chunking/ByteRangeTest.java index 8df08262c9fa..8df08262c9fa 100644 --- a/services/robotests/backup/src/com/android/server/backup/encryption/chunking/ByteRangeTest.java +++ b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/chunking/ByteRangeTest.java diff --git a/services/robotests/backup/src/com/android/server/backup/encryption/chunking/ChunkEncryptorTest.java b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/chunking/ChunkEncryptorTest.java index d0e5fb335da9..19e3b28f85e7 100644 --- a/services/robotests/backup/src/com/android/server/backup/encryption/chunking/ChunkEncryptorTest.java +++ b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/chunking/ChunkEncryptorTest.java @@ -11,7 +11,7 @@ * 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 + * limitations under the License. */ package com.android.server.backup.encryption.chunking; @@ -78,22 +78,22 @@ public class ChunkEncryptorTest { // Return NONCE_1, then NONCE_2 for invocations of mSecureRandomMock.nextBytes(). doAnswer( - new Answer<Void>() { - private int mInvocation = 0; - - @Override - public Void answer(InvocationOnMock invocation) { - byte[] nonceDestination = invocation.getArgument(0); - System.arraycopy( - NONCES[this.mInvocation], - 0, - nonceDestination, - 0, - GCM_NONCE_LENGTH_BYTES); - this.mInvocation++; - return null; - } - }) + new Answer<Void>() { + private int mInvocation = 0; + + @Override + public Void answer(InvocationOnMock invocation) { + byte[] nonceDestination = invocation.getArgument(0); + System.arraycopy( + NONCES[this.mInvocation], + 0, + nonceDestination, + 0, + GCM_NONCE_LENGTH_BYTES); + this.mInvocation++; + return null; + } + }) .when(mSecureRandomMock) .nextBytes(any(byte[].class)); } diff --git a/services/robotests/backup/src/com/android/server/backup/encryption/chunking/ChunkHasherTest.java b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/chunking/ChunkHasherTest.java index 2bbbf2857146..72a927db743d 100644 --- a/services/robotests/backup/src/com/android/server/backup/encryption/chunking/ChunkHasherTest.java +++ b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/chunking/ChunkHasherTest.java @@ -11,7 +11,7 @@ * 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 + * limitations under the License. */ package com.android.server.backup.encryption.chunking; diff --git a/services/robotests/backup/src/com/android/server/backup/encryption/chunking/DecryptedChunkFileOutputTest.java b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/chunking/DecryptedChunkFileOutputTest.java index 823a63c22da4..823a63c22da4 100644 --- a/services/robotests/backup/src/com/android/server/backup/encryption/chunking/DecryptedChunkFileOutputTest.java +++ b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/chunking/DecryptedChunkFileOutputTest.java diff --git a/services/robotests/backup/src/com/android/server/backup/encryption/chunking/DiffScriptBackupWriterTest.java b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/chunking/DiffScriptBackupWriterTest.java index 2af6f2bee8ff..2af6f2bee8ff 100644 --- a/services/robotests/backup/src/com/android/server/backup/encryption/chunking/DiffScriptBackupWriterTest.java +++ b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/chunking/DiffScriptBackupWriterTest.java diff --git a/services/robotests/backup/src/com/android/server/backup/encryption/chunking/EncryptedChunkTest.java b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/chunking/EncryptedChunkTest.java index 8e801a133909..325b601e2ccb 100644 --- a/services/robotests/backup/src/com/android/server/backup/encryption/chunking/EncryptedChunkTest.java +++ b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/chunking/EncryptedChunkTest.java @@ -11,7 +11,7 @@ * 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 + * limitations under the License. */ package com.android.server.backup.encryption.chunking; diff --git a/services/robotests/backup/src/com/android/server/backup/encryption/chunking/InlineLengthsEncryptedChunkEncoderTest.java b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/chunking/InlineLengthsEncryptedChunkEncoderTest.java index 2f872beacd17..634acdc42eaf 100644 --- a/services/robotests/backup/src/com/android/server/backup/encryption/chunking/InlineLengthsEncryptedChunkEncoderTest.java +++ b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/chunking/InlineLengthsEncryptedChunkEncoderTest.java @@ -11,7 +11,7 @@ * 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 + * limitations under the License. */ package com.android.server.backup.encryption.chunking; diff --git a/services/robotests/backup/src/com/android/server/backup/encryption/chunking/LengthlessEncryptedChunkEncoderTest.java b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/chunking/LengthlessEncryptedChunkEncoderTest.java index 978bddb7301a..d231603e18b1 100644 --- a/services/robotests/backup/src/com/android/server/backup/encryption/chunking/LengthlessEncryptedChunkEncoderTest.java +++ b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/chunking/LengthlessEncryptedChunkEncoderTest.java @@ -11,7 +11,7 @@ * 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 + * limitations under the License. */ package com.android.server.backup.encryption.chunking; diff --git a/services/robotests/backup/src/com/android/server/backup/encryption/chunking/RawBackupWriterTest.java b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/chunking/RawBackupWriterTest.java index 19ef8fb339ba..966d3e2d583d 100644 --- a/services/robotests/backup/src/com/android/server/backup/encryption/chunking/RawBackupWriterTest.java +++ b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/chunking/RawBackupWriterTest.java @@ -11,7 +11,7 @@ * 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 + * limitations under the License. */ package com.android.server.backup.encryption.chunking; diff --git a/services/robotests/backup/src/com/android/server/backup/encryption/chunking/SingleStreamDiffScriptWriterTest.java b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/chunking/SingleStreamDiffScriptWriterTest.java index 73baf80a2c70..73baf80a2c70 100644 --- a/services/robotests/backup/src/com/android/server/backup/encryption/chunking/SingleStreamDiffScriptWriterTest.java +++ b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/chunking/SingleStreamDiffScriptWriterTest.java diff --git a/services/robotests/backup/src/com/android/server/backup/encryption/chunking/cdc/ContentDefinedChunkerTest.java b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/chunking/cdc/ContentDefinedChunkerTest.java index 77b734785424..77b734785424 100644 --- a/services/robotests/backup/src/com/android/server/backup/encryption/chunking/cdc/ContentDefinedChunkerTest.java +++ b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/chunking/cdc/ContentDefinedChunkerTest.java diff --git a/services/robotests/backup/src/com/android/server/backup/encryption/chunking/cdc/FingerprintMixerTest.java b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/chunking/cdc/FingerprintMixerTest.java index 936b5dca033d..936b5dca033d 100644 --- a/services/robotests/backup/src/com/android/server/backup/encryption/chunking/cdc/FingerprintMixerTest.java +++ b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/chunking/cdc/FingerprintMixerTest.java diff --git a/services/robotests/backup/src/com/android/server/backup/encryption/chunking/cdc/HkdfTest.java b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/chunking/cdc/HkdfTest.java index 549437454e9c..549437454e9c 100644 --- a/services/robotests/backup/src/com/android/server/backup/encryption/chunking/cdc/HkdfTest.java +++ b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/chunking/cdc/HkdfTest.java diff --git a/services/robotests/backup/src/com/android/server/backup/encryption/chunking/cdc/IsChunkBreakpointTest.java b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/chunking/cdc/IsChunkBreakpointTest.java index 277dc372e73c..277dc372e73c 100644 --- a/services/robotests/backup/src/com/android/server/backup/encryption/chunking/cdc/IsChunkBreakpointTest.java +++ b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/chunking/cdc/IsChunkBreakpointTest.java diff --git a/services/robotests/backup/src/com/android/server/backup/encryption/chunking/cdc/RabinFingerprint64Test.java b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/chunking/cdc/RabinFingerprint64Test.java index 729580cf5101..729580cf5101 100644 --- a/services/robotests/backup/src/com/android/server/backup/encryption/chunking/cdc/RabinFingerprint64Test.java +++ b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/chunking/cdc/RabinFingerprint64Test.java diff --git a/services/robotests/backup/src/com/android/server/backup/encryption/keys/RecoverableKeyStoreSecondaryKeyManagerTest.java b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/keys/RecoverableKeyStoreSecondaryKeyManagerTest.java index 5342efa18a97..5342efa18a97 100644 --- a/services/robotests/backup/src/com/android/server/backup/encryption/keys/RecoverableKeyStoreSecondaryKeyManagerTest.java +++ b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/keys/RecoverableKeyStoreSecondaryKeyManagerTest.java diff --git a/services/robotests/backup/src/com/android/server/backup/encryption/keys/RecoverableKeyStoreSecondaryKeyTest.java b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/keys/RecoverableKeyStoreSecondaryKeyTest.java index 89977f82c145..89977f82c145 100644 --- a/services/robotests/backup/src/com/android/server/backup/encryption/keys/RecoverableKeyStoreSecondaryKeyTest.java +++ b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/keys/RecoverableKeyStoreSecondaryKeyTest.java diff --git a/services/robotests/backup/src/com/android/server/backup/encryption/keys/TertiaryKeyGeneratorTest.java b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/keys/TertiaryKeyGeneratorTest.java index 48216f8d7aca..48216f8d7aca 100644 --- a/services/robotests/backup/src/com/android/server/backup/encryption/keys/TertiaryKeyGeneratorTest.java +++ b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/keys/TertiaryKeyGeneratorTest.java diff --git a/services/robotests/backup/src/com/android/server/backup/encryption/keys/TertiaryKeyRotationTrackerTest.java b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/keys/TertiaryKeyRotationTrackerTest.java index 49bb410ceb65..49bb410ceb65 100644 --- a/services/robotests/backup/src/com/android/server/backup/encryption/keys/TertiaryKeyRotationTrackerTest.java +++ b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/keys/TertiaryKeyRotationTrackerTest.java diff --git a/services/robotests/backup/src/com/android/server/backup/encryption/storage/BackupEncryptionDbTest.java b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/storage/BackupEncryptionDbTest.java index 87f21bfa59c2..87f21bfa59c2 100644 --- a/services/robotests/backup/src/com/android/server/backup/encryption/storage/BackupEncryptionDbTest.java +++ b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/storage/BackupEncryptionDbTest.java diff --git a/services/robotests/backup/src/com/android/server/backup/encryption/storage/TertiaryKeysTableTest.java b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/storage/TertiaryKeysTableTest.java index 319ec89f445e..319ec89f445e 100644 --- a/services/robotests/backup/src/com/android/server/backup/encryption/storage/TertiaryKeysTableTest.java +++ b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/storage/TertiaryKeysTableTest.java diff --git a/services/robotests/backup/src/com/android/server/backup/encryption/tasks/BackupStreamEncrypterTest.java b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/tasks/BackupStreamEncrypterTest.java index 21c4e07577da..21c4e07577da 100644 --- a/services/robotests/backup/src/com/android/server/backup/encryption/tasks/BackupStreamEncrypterTest.java +++ b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/encryption/tasks/BackupStreamEncrypterTest.java diff --git a/services/robotests/backup/src/com/android/server/backup/testing/RandomInputStream.java b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/testing/RandomInputStream.java index 998da0bf9696..998da0bf9696 100644 --- a/services/robotests/backup/src/com/android/server/backup/testing/RandomInputStream.java +++ b/packages/BackupEncryption/test/robolectric/src/com/android/server/backup/testing/RandomInputStream.java diff --git a/services/robotests/backup/src/com/android/server/backup/testing/CryptoTestUtils.java b/packages/BackupEncryption/test/robolectric/src/com/android/server/testing/CryptoTestUtils.java index 0428796f51fa..3f3494d2c22c 100644 --- a/services/robotests/backup/src/com/android/server/backup/testing/CryptoTestUtils.java +++ b/packages/BackupEncryption/test/robolectric/src/com/android/server/testing/CryptoTestUtils.java @@ -11,7 +11,7 @@ * 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 + * limitations under the License. */ package com.android.server.backup.testing; diff --git a/services/robotests/src/com/android/server/testing/shadows/ShadowInternalRecoveryServiceException.java b/packages/BackupEncryption/test/robolectric/src/com/android/server/testing/shadows/ShadowInternalRecoveryServiceException.java index 9c06d81ce550..9c06d81ce550 100644 --- a/services/robotests/src/com/android/server/testing/shadows/ShadowInternalRecoveryServiceException.java +++ b/packages/BackupEncryption/test/robolectric/src/com/android/server/testing/shadows/ShadowInternalRecoveryServiceException.java diff --git a/services/robotests/src/com/android/server/testing/shadows/ShadowRecoveryController.java b/packages/BackupEncryption/test/robolectric/src/com/android/server/testing/shadows/ShadowRecoveryController.java index 7dad8a4e3ff3..7dad8a4e3ff3 100644 --- a/services/robotests/src/com/android/server/testing/shadows/ShadowRecoveryController.java +++ b/packages/BackupEncryption/test/robolectric/src/com/android/server/testing/shadows/ShadowRecoveryController.java diff --git a/packages/CarSystemUI/res/values/integers_car.xml b/packages/CarSystemUI/res/values/integers_car.xml index 862ba751aa55..fb67b302a4ae 100644 --- a/packages/CarSystemUI/res/values/integers_car.xml +++ b/packages/CarSystemUI/res/values/integers_car.xml @@ -32,6 +32,6 @@ at will result in remaining closed the panel if released--> <integer name="notification_settle_close_percentage">80</integer> <!-- The delay before the unlock dialog pops up --> - <integer name="unlock_dialog_delay_ms">3000</integer> + <integer name="unlock_dialog_delay_ms">0</integer> </resources> diff --git a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIRootComponent.java b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIRootComponent.java index d6b766b80939..27146fbac789 100644 --- a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIRootComponent.java +++ b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIRootComponent.java @@ -26,6 +26,7 @@ import dagger.Component; DependencyProvider.class, DependencyBinder.class, ServiceBinder.class, + SystemUIBinder.class, SystemUIFactory.ContextHolder.class, SystemUIModule.class, CarSystemUIModule.class diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml index e591121d4b59..83636dc19beb 100644 --- a/packages/SettingsLib/res/values-te/strings.xml +++ b/packages/SettingsLib/res/values-te/strings.xml @@ -143,7 +143,7 @@ <string name="data_usage_ota" msgid="5377889154805560860">"సిస్టమ్ అప్డేట్లు"</string> <string name="tether_settings_title_usb" msgid="6688416425801386511">"USB టీథరింగ్"</string> <string name="tether_settings_title_wifi" msgid="3277144155960302049">"పోర్టబుల్ హాట్స్పాట్"</string> - <string name="tether_settings_title_bluetooth" msgid="355855408317564420">"బ్లూటూత్ టెథెరింగ్"</string> + <string name="tether_settings_title_bluetooth" msgid="355855408317564420">"బ్లూటూత్ టీథరింగ్"</string> <string name="tether_settings_title_usb_bluetooth" msgid="5355828977109785001">"టీథరింగ్"</string> <string name="tether_settings_title_all" msgid="8356136101061143841">"టీథరింగ్ & పోర్టబుల్ హాట్స్పాట్"</string> <string name="managed_user_title" msgid="8109605045406748842">"అన్ని కార్యాలయ అనువర్తనాలు"</string> @@ -376,7 +376,7 @@ <string name="daltonizer_mode_protanomaly" msgid="8424148009038666065">"ప్రొటానోమలీ (ఎరుపు-ఆకుపచ్చ రంగు)"</string> <string name="daltonizer_mode_tritanomaly" msgid="481725854987912389">"ట్రైటనోమలీ (నీలం-పసుపు రంగు)"</string> <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"రంగు సవరణ"</string> - <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ఈ ఫీచర్ ప్రయోగాత్మకమైనది, పనితీరుపై ప్రభావం చూపవచ్చు."</string> + <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"ఈ లక్షణం ప్రయోగాత్మకమైనది మరియు పనితీరుపై ప్రభావం చూపవచ్చు."</string> <string name="daltonizer_type_overridden" msgid="3116947244410245916">"<xliff:g id="TITLE">%1$s</xliff:g> ద్వారా భర్తీ చేయబడింది"</string> <string name="power_remaining_settings_home_page" msgid="4845022416859002011">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string> <string name="power_remaining_duration_only" msgid="6123167166221295462">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> సమయం మిగిలి ఉంది"</string> @@ -414,7 +414,7 @@ <string name="disabled" msgid="9206776641295849915">"నిలిపివేయబడింది"</string> <string name="external_source_trusted" msgid="2707996266575928037">"అనుమతించినవి"</string> <string name="external_source_untrusted" msgid="2677442511837596726">"అనుమతించబడలేదు"</string> - <string name="install_other_apps" msgid="6986686991775883017">"తెలియని యాప్లను ఇన్స్టాల్ చేయడం"</string> + <string name="install_other_apps" msgid="6986686991775883017">"తెలియని యాప్లను ఇన్స్టాల్ చేయండి"</string> <string name="home" msgid="3256884684164448244">"సెట్టింగ్ల హోమ్"</string> <string-array name="battery_labels"> <item msgid="8494684293649631252">"0%"</item> diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml index 0d3e8de0559d..5dca4759a629 100644 --- a/packages/SettingsLib/res/values-uz/strings.xml +++ b/packages/SettingsLib/res/values-uz/strings.xml @@ -201,7 +201,7 @@ <string name="vpn_settings_not_available" msgid="956841430176985598">"Ushbu foydalanuvchi uchun VPN sozlamalari mavjud emas"</string> <string name="tethering_settings_not_available" msgid="6765770438438291012">"Ushbu foydalanuvchi uchun Modem rejimi sozlamalari mavjud emas"</string> <string name="apn_settings_not_available" msgid="7873729032165324000">"Ushbu foydalanuvchi uchun Internetga kirish nuqtasi (APN) sozlamalari mavjud emas"</string> - <string name="enable_adb" msgid="7982306934419797485">"USB orqali nosozliklarni aniqlash"</string> + <string name="enable_adb" msgid="7982306934419797485">"USB orqali nosozliklarni tuzatish"</string> <string name="enable_adb_summary" msgid="4881186971746056635">"USB orqali kompyuterga ulanganda tuzatish rejimi yoqilsin"</string> <string name="clear_adb_keys" msgid="4038889221503122743">"USB orqali nosozliklarni tuzatishni taqiqlash"</string> <string name="bugreport_in_power" msgid="7923901846375587241">"Xatoliklar hisoboti"</string> @@ -264,7 +264,7 @@ <string name="mobile_data_always_on_summary" msgid="8149773901431697910">"Mobil internet har doim yoniq tursin, hatto Wi-Fi yoniq bo‘lsa ham (bir tarmoqdan ikkinchisiga tezroq o‘tish uchun)."</string> <string name="tethering_hardware_offload_summary" msgid="7726082075333346982">"Modem rejimida apparatli tezlashtirishdan foydalanish (agar mavjud bo‘lsa)"</string> <string name="adb_warning_title" msgid="6234463310896563253">"USB orqali nosozliklarni tuzatishga ruxsat berilsinmi?"</string> - <string name="adb_warning_message" msgid="7316799925425402244">"USB orqali nosozliklarni aniqlash faqat dasturlash maqsadlarida yoqiladi. Undan maʼlumotlarni qurilmangiz va kompyuter o‘rtasida ko‘chirish, ilovalarni xabarnomasiz o‘rnatish va jurnal maʼlumotlarini o‘qish uchun foydalaniladi."</string> + <string name="adb_warning_message" msgid="7316799925425402244">"USB orqali nosozliklarni tuzatish faqat dasturlash maqsadlarida yoqiladi. Undan ma‘lumotlarni qurilmangiz va kompyuter o‘rtasida ko‘chirish, ilovalarni xabarnomasiz o‘rnatish va jurnal ma‘lumotlarini o‘qish uchun foydalaniladi."</string> <string name="adb_keys_warning_message" msgid="5659849457135841625">"USB orqali nosozliklarni tuzatishga berilgan ruxsat siz hisobingizga kirgan barcha kompyuterlar uchun bekor qilinsinmi?"</string> <string name="dev_settings_warning_title" msgid="7244607768088540165">"Dasturlash sozlamalariga ruxsat berilsinmi?"</string> <string name="dev_settings_warning_message" msgid="2298337781139097964">"Bu sozlamalar faqat dasturlash maqsadlariga mo‘ljallangan. Shuning uchun, ular qurilmangizga va undagi ilovalariga shikast yetkazib, noto‘g‘ri ishlashiga sabab bo‘lishi mumkin."</string> diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml index c64130210d37..e85199f9ca0d 100644 --- a/packages/SettingsLib/res/values-zh-rTW/strings.xml +++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml @@ -329,7 +329,7 @@ <string name="show_all_anrs" msgid="4924885492787069007">"顯示背景 ANR"</string> <string name="show_all_anrs_summary" msgid="6636514318275139826">"為背景應用程式顯示「應用程式無回應」對話方塊"</string> <string name="show_notification_channel_warnings" msgid="1399948193466922683">"顯示通知管道警告"</string> - <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"當應用程式未經有效管道發布通知時,在畫面上顯示警告"</string> + <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"當應用程式未經有效管道發佈通知時,在畫面上顯示警告"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"強制允許將應用程式寫入外部儲存空間"</string> <string name="force_allow_on_external_summary" msgid="3640752408258034689">"允許將任何應用程式寫入外部儲存空間 (無論資訊清單值為何)"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"將活動強制設為可調整大小"</string> diff --git a/packages/Shell/res/values-zh-rTW/strings.xml b/packages/Shell/res/values-zh-rTW/strings.xml index 96671c8c0175..fc6397dc2013 100644 --- a/packages/Shell/res/values-zh-rTW/strings.xml +++ b/packages/Shell/res/values-zh-rTW/strings.xml @@ -25,9 +25,9 @@ <string name="bugreport_finished_text" product="watch" msgid="1223616207145252689">"系統即將在手機上顯示錯誤報告"</string> <string name="bugreport_finished_text" product="tv" msgid="5758325479058638893">"選取即可分享錯誤報告"</string> <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"輕觸即可分享錯誤報告"</string> - <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"選取即可分享不包含螢幕截圖的錯誤報告;你也可以等候螢幕畫面擷取完畢"</string> - <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"輕觸即可分享無螢幕截圖的錯誤報告;你也可以等候螢幕畫面擷取完畢"</string> - <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"輕觸即可分享無螢幕截圖的錯誤報告;你也可以等候螢幕畫面擷取完畢"</string> + <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"選取即可分享不包含螢幕擷取畫面的錯誤報告;你也可以等候螢幕畫面擷取完畢"</string> + <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"輕觸即可分享無螢幕擷圖的錯誤報告;你也可以等候螢幕畫面擷取完畢"</string> + <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"輕觸即可分享無螢幕擷圖的錯誤報告;你也可以等候螢幕畫面擷取完畢"</string> <string name="bugreport_confirm" msgid="5917407234515812495">"錯誤報告的資料來自系統的各種記錄檔,當中可能包含敏感資料 (例如應用程式使用情形和位置資料)。請務必只與你信任的使用者和應用程式分享錯誤報告。"</string> <string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"不要再顯示"</string> <string name="bugreport_storage_title" msgid="5332488144740527109">"錯誤報告"</string> @@ -35,9 +35,9 @@ <string name="bugreport_add_details_to_zip_failed" msgid="1302931926486712371">"無法在 ZIP 檔案中加入錯誤報告"</string> <string name="bugreport_unnamed" msgid="2800582406842092709">"未命名"</string> <string name="bugreport_info_action" msgid="2158204228510576227">"詳細資料"</string> - <string name="bugreport_screenshot_action" msgid="8677781721940614995">"螢幕截圖"</string> - <string name="bugreport_screenshot_taken" msgid="5684211273096253120">"已成功拍攝螢幕截圖。"</string> - <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"無法拍攝螢幕截圖。"</string> + <string name="bugreport_screenshot_action" msgid="8677781721940614995">"螢幕擷取畫面"</string> + <string name="bugreport_screenshot_taken" msgid="5684211273096253120">"已成功拍攝螢幕擷取畫面。"</string> + <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"無法拍攝螢幕擷取畫面。"</string> <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"錯誤報告 <xliff:g id="ID">#%d</xliff:g> 的詳細資料"</string> <string name="bugreport_info_name" msgid="4414036021935139527">"檔案名稱"</string> <string name="bugreport_info_title" msgid="2306030793918239804">"錯誤標題"</string> diff --git a/packages/SystemUI/docs/plugin_hooks.md b/packages/SystemUI/docs/plugin_hooks.md index 9fe2e181971a..2fb0c996111a 100644 --- a/packages/SystemUI/docs/plugin_hooks.md +++ b/packages/SystemUI/docs/plugin_hooks.md @@ -56,6 +56,11 @@ Expected interface: [ClockPlugin](/packages/SystemUI/plugin/src/com/android/syst Use: Allows replacement of the keyguard main clock. +### Action: com.android.systemui.action.PLUGIN_NPV +Expected interface: [NPVPlugin](/packages/SystemUI/plugin/src/com/android/systemui/plugins/NPVPlugin.java) + +Use: Attach a view under QQS for prototyping. + # Global plugin dependencies These classes can be accessed by any plugin using PluginDependency as long as they @Requires them. diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/NPVPlugin.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/NPVPlugin.java new file mode 100644 index 000000000000..1426266a7048 --- /dev/null +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/NPVPlugin.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.plugins; + +import android.view.View; +import android.widget.FrameLayout; + +import com.android.systemui.plugins.annotations.ProvidesInterface; + +/** + * Plugin to attach custom views under QQS. + * + * A parent view is provided to the plugin to which they can add Views. + * <br> + * The parent is a {@link FrameLayout} with same background as QS and 96dp height. + * + * {@see NPVPluginManager} + * {@see status_bar_expanded_plugin_frame} + */ +@ProvidesInterface(action = NPVPlugin.ACTION, version = NPVPlugin.VERSION) +public interface NPVPlugin extends Plugin { + String ACTION = "com.android.systemui.action.PLUGIN_NPV"; + int VERSION = 1; + + /** + * Attach views to the parent. + * + * @param parent a {@link FrameLayout} to which to attach views. Preferably a root view. + * @return a view attached to parent. + */ + View attachToRoot(FrameLayout parent); + + /** + * Indicate to the plugin when it is listening (QS expanded) + * @param listening + */ + default void setListening(boolean listening) {}; +} diff --git a/packages/SystemUI/res/layout/auth_biometric_contents.xml b/packages/SystemUI/res/layout/auth_biometric_contents.xml index aed200f69bc3..925e4fad103d 100644 --- a/packages/SystemUI/res/layout/auth_biometric_contents.xml +++ b/packages/SystemUI/res/layout/auth_biometric_contents.xml @@ -56,7 +56,7 @@ android:scaleType="fitXY" /> <TextView - android:id="@+id/error" + android:id="@+id/indicator" android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingHorizontal="24dp" diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml index 7a9400887c75..e7c6b2574f5f 100644 --- a/packages/SystemUI/res/layout/status_bar_expanded.xml +++ b/packages/SystemUI/res/layout/status_bar_expanded.xml @@ -111,4 +111,6 @@ android:visibility="invisible" android:background="@drawable/qs_navbar_scrim" /> + <include layout="@layout/status_bar_expanded_plugin_frame"/> + </com.android.systemui.statusbar.phone.NotificationPanelView> diff --git a/packages/SystemUI/res/layout/status_bar_expanded_plugin_frame.xml b/packages/SystemUI/res/layout/status_bar_expanded_plugin_frame.xml new file mode 100644 index 000000000000..4849dfb777ed --- /dev/null +++ b/packages/SystemUI/res/layout/status_bar_expanded_plugin_frame.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + 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. +--> + +<FrameLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/plugin_frame" + android:theme="@style/qs_theme" + android:layout_width="@dimen/qs_panel_width" + android:layout_height="96dp" + android:layout_gravity="center_horizontal" + android:layout_marginTop="@*android:dimen/quick_qs_total_height" + android:layout_marginLeft="@dimen/notification_side_paddings" + android:layout_marginRight="@dimen/notification_side_paddings" + android:visibility="gone" + android:background="@drawable/qs_background_primary"/>
\ No newline at end of file diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml index 938cb0dd3b12..9903cc04e97a 100644 --- a/packages/SystemUI/res/values-en-rCA/strings.xml +++ b/packages/SystemUI/res/values-en-rCA/strings.xml @@ -401,7 +401,6 @@ <string name="speed_bump_explanation" msgid="1288875699658819755">"Less urgent notifications below"</string> <string name="notification_tap_again" msgid="7590196980943943842">"Tap again to open"</string> <string name="keyguard_unlock" msgid="6035822649218712063">"Swipe up to open"</string> - <string name="keyguard_retry" msgid="5221600879614948709">"Swipe up to try again"</string> <string name="do_disclosure_generic" msgid="5615898451805157556">"This device is managed by your organisation"</string> <string name="do_disclosure_with_name" msgid="5640615509915445501">"This device is managed by <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> <string name="phone_hint" msgid="4872890986869209950">"Swipe from icon for phone"</string> @@ -545,7 +544,6 @@ <string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"This keeps it in view until you unpin. Touch & hold Home to unpin."</string> <string name="screen_pinning_toast" msgid="2266705122951934150">"To unpin this screen, touch & hold Back and Overview buttons"</string> <string name="screen_pinning_toast_recents_invisible" msgid="8252402309499161281">"To unpin this screen, touch & hold Back and Home buttons"</string> - <string name="screen_pinning_toast_gesture_nav" msgid="5070548776081664958">"To unpin this screen, swipe up & hold"</string> <string name="screen_pinning_positive" msgid="3783985798366751226">"Got it"</string> <string name="screen_pinning_negative" msgid="3741602308343880268">"No, thanks"</string> <string name="screen_pinning_start" msgid="1022122128489278317">"Screen pinned"</string> diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml index 139215aa196f..d8c862affe08 100644 --- a/packages/SystemUI/res/values-en-rXC/strings.xml +++ b/packages/SystemUI/res/values-en-rXC/strings.xml @@ -401,7 +401,6 @@ <string name="speed_bump_explanation" msgid="1288875699658819755">"Less urgent notifications below"</string> <string name="notification_tap_again" msgid="7590196980943943842">"Tap again to open"</string> <string name="keyguard_unlock" msgid="6035822649218712063">"Swipe up to open"</string> - <string name="keyguard_retry" msgid="5221600879614948709">"Swipe up to try again"</string> <string name="do_disclosure_generic" msgid="5615898451805157556">"This device is managed by your organization"</string> <string name="do_disclosure_with_name" msgid="5640615509915445501">"This device is managed by <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string> <string name="phone_hint" msgid="4872890986869209950">"Swipe from icon for phone"</string> @@ -545,7 +544,6 @@ <string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"This keeps it in view until you unpin. Touch & hold Home to unpin."</string> <string name="screen_pinning_toast" msgid="2266705122951934150">"To unpin this screen, touch & hold Back and Overview buttons"</string> <string name="screen_pinning_toast_recents_invisible" msgid="8252402309499161281">"To unpin this screen, touch & hold Back and Home buttons"</string> - <string name="screen_pinning_toast_gesture_nav" msgid="5070548776081664958">"To unpin this screen, swipe up & hold"</string> <string name="screen_pinning_positive" msgid="3783985798366751226">"Got it"</string> <string name="screen_pinning_negative" msgid="3741602308343880268">"No thanks"</string> <string name="screen_pinning_start" msgid="1022122128489278317">"Screen pinned"</string> diff --git a/packages/SystemUI/src/com/android/systemui/ContextComponentHelper.java b/packages/SystemUI/src/com/android/systemui/ContextComponentHelper.java index 62826d806adc..5fe5792219c3 100644 --- a/packages/SystemUI/src/com/android/systemui/ContextComponentHelper.java +++ b/packages/SystemUI/src/com/android/systemui/ContextComponentHelper.java @@ -24,4 +24,7 @@ import android.app.Service; public interface ContextComponentHelper { /** Turns a classname into an instance of the class or returns null. */ Service resolveService(String className); + + /** Turns a classname into an instance of the class or returns null. */ + SystemUI resolveSystemUI(String className); } diff --git a/packages/SystemUI/src/com/android/systemui/ContextComponentResolver.java b/packages/SystemUI/src/com/android/systemui/ContextComponentResolver.java index e8f019688997..cee21c167fa0 100644 --- a/packages/SystemUI/src/com/android/systemui/ContextComponentResolver.java +++ b/packages/SystemUI/src/com/android/systemui/ContextComponentResolver.java @@ -22,17 +22,22 @@ import java.util.Map; import javax.inject.Inject; import javax.inject.Provider; +import javax.inject.Singleton; /** * Used during Service and Activity instantiation to make them injectable. */ +@Singleton public class ContextComponentResolver implements ContextComponentHelper { private final Map<Class<?>, Provider<Service>> mServiceCreators; + private final Map<Class<?>, Provider<SystemUI>> mSystemUICreators; @Inject ContextComponentResolver( - Map<Class<?>, Provider<Service>> serviceCreators) { + Map<Class<?>, Provider<Service>> serviceCreators, + Map<Class<?>, Provider<SystemUI>> systemUICreators) { mServiceCreators = serviceCreators; + mSystemUICreators = systemUICreators; } /** @@ -43,6 +48,14 @@ public class ContextComponentResolver implements ContextComponentHelper { return resolve(className, mServiceCreators); } + /** + * Looks up the SystemUI class name to see if Dagger has an instance of it. + */ + @Override + public SystemUI resolveSystemUI(String className) { + return resolve(className, mSystemUICreators); + } + private <T> T resolve(String className, Map<Class<?>, Provider<T>> creators) { for (Map.Entry<Class<?>, Provider<T>> p : creators.entrySet()) { if (p.getKey().getName().equals(className)) { diff --git a/packages/SystemUI/src/com/android/systemui/CornerHandleView.java b/packages/SystemUI/src/com/android/systemui/CornerHandleView.java index a94952c5bc19..6209c2c36206 100644 --- a/packages/SystemUI/src/com/android/systemui/CornerHandleView.java +++ b/packages/SystemUI/src/com/android/systemui/CornerHandleView.java @@ -19,6 +19,7 @@ package com.android.systemui; import android.animation.ArgbEvaluator; import android.content.Context; import android.graphics.Canvas; +import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.graphics.RectF; @@ -27,6 +28,7 @@ import android.util.DisplayMetrics; import android.view.ContextThemeWrapper; import android.view.View; +import com.android.internal.graphics.ColorUtils; import com.android.settingslib.Utils; /** @@ -107,6 +109,7 @@ public class CornerHandleView extends View { mPaint.setColor((int) ArgbEvaluator.getInstance().evaluate(darkIntensity, mLightColor, mDarkColor)); + updateShadow(); if (getVisibility() == VISIBLE) { invalidate(); } @@ -118,6 +121,21 @@ public class CornerHandleView extends View { canvas.drawPath(mPath, mPaint); } + private void updateShadow() { + if (ColorUtils.calculateLuminance(mPaint.getColor()) > 0.7f) { + mPaint.setShadowLayer(/** radius */ 5,/** shadowDx */ 0, /** shadowDy */ -1, + /** color */ ColorUtils.setAlphaComponent(/** color */ Color.BLACK, + /** alpha */ 102)); + } else { + mPaint.setShadowLayer(/** radius */ 0, /** shadowDx */ 0, /** shadowDy */ 0, + /** color */ Color.TRANSPARENT); + } + + if (getVisibility() == VISIBLE) { + invalidate(); + } + } + private static float convertDpToPixel(float dp, Context context) { return dp * ((float) context.getResources().getDisplayMetrics().densityDpi / DisplayMetrics.DENSITY_DEFAULT); diff --git a/packages/SystemUI/src/com/android/systemui/SystemUI.java b/packages/SystemUI/src/com/android/systemui/SystemUI.java index 78a12467cd1c..30fbef6cbefb 100644 --- a/packages/SystemUI/src/com/android/systemui/SystemUI.java +++ b/packages/SystemUI/src/com/android/systemui/SystemUI.java @@ -24,7 +24,6 @@ import android.os.Bundle; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.Map; -import java.util.function.Function; public abstract class SystemUI implements SysUiServiceProvider { public Context mContext; @@ -62,7 +61,4 @@ public abstract class SystemUI implements SysUiServiceProvider { n.addExtras(extras); } - - public interface Injector extends Function<Context, SystemUI> { - } } diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java index 1c210b177ae7..56b5d080acc0 100644 --- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java +++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java @@ -54,6 +54,8 @@ public class SystemUIApplication extends Application implements SysUiServiceProv public static final String TAG = "SystemUIService"; private static final boolean DEBUG = false; + private ContextComponentHelper mComponentHelper; + /** * Hold a reference on the stuff we start. */ @@ -78,6 +80,8 @@ public class SystemUIApplication extends Application implements SysUiServiceProv Trace.TRACE_TAG_APP); log.traceBegin("DependencyInjection"); mContextAvailableCallback.onContextAvailable(this); + mComponentHelper = SystemUIFactory + .getInstance().getRootComponent().getContextComponentHelper(); log.traceEnd(); // Set the application theme that is inherited by all services. Note that setting the @@ -186,14 +190,12 @@ public class SystemUIApplication extends Application implements SysUiServiceProv if (DEBUG) Log.d(TAG, "loading: " + clsName); log.traceBegin("StartServices" + clsName); long ti = System.currentTimeMillis(); - Class cls; try { - cls = Class.forName(clsName); - Object o = cls.newInstance(); - if (o instanceof SystemUI.Injector) { - o = ((SystemUI.Injector) o).apply(this); + SystemUI obj = mComponentHelper.resolveSystemUI(clsName); + if (obj == null) { + obj = (SystemUI) Class.forName(clsName).newInstance(); } - mServices[i] = (SystemUI) o; + mServices[i] = obj; } catch (ClassNotFoundException ex) { throw new RuntimeException(ex); } catch (IllegalAccessException ex) { @@ -211,7 +213,7 @@ public class SystemUIApplication extends Application implements SysUiServiceProv // Warn if initialization of component takes too long ti = System.currentTimeMillis() - ti; if (ti > 1000) { - Log.w(TAG, "Initialization of " + cls.getName() + " took " + ti + " ms"); + Log.w(TAG, "Initialization of " + clsName + " took " + ti + " ms"); } if (mBootCompleted) { mServices[i].onBootCompleted(); diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIBinder.java b/packages/SystemUI/src/com/android/systemui/SystemUIBinder.java new file mode 100644 index 000000000000..88d659039b4b --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/SystemUIBinder.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui; + +import com.android.systemui.keyguard.KeyguardViewMediator; + +import dagger.Binds; +import dagger.Module; +import dagger.multibindings.ClassKey; +import dagger.multibindings.IntoMap; + +/** + * Services and Activities that are injectable should go here. + */ +@Module +public abstract class SystemUIBinder { + /** Inject into KeyguardViewMediator. */ + @Binds + @IntoMap + @ClassKey(KeyguardViewMediator.class) + public abstract SystemUI bindKeyguardViewMediator(KeyguardViewMediator sysui); +} diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIRootComponent.java b/packages/SystemUI/src/com/android/systemui/SystemUIRootComponent.java index b77667e339af..6ce673b0e9b6 100644 --- a/packages/SystemUI/src/com/android/systemui/SystemUIRootComponent.java +++ b/packages/SystemUI/src/com/android/systemui/SystemUIRootComponent.java @@ -38,10 +38,18 @@ import dagger.Component; DependencyProvider.class, DependencyBinder.class, ServiceBinder.class, + SystemUIBinder.class, SystemUIFactory.ContextHolder.class, SystemUIModule.class, SystemUIDefaultModule.class}) public interface SystemUIRootComponent { + + /** + * Creates a GarbageMonitor. + */ + @Singleton + ContextComponentHelper getContextComponentHelper(); + /** * Main dependency providing module. */ @@ -66,7 +74,7 @@ public interface SystemUIRootComponent { InjectionInflationController.ViewCreator createViewCreator(); /** - * Creatse a GarbageMonitor. + * Creates a GarbageMonitor. */ @Singleton GarbageMonitor createGarbageMonitor(); diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java index 9cf738541276..5dd3cb1d8bdc 100644 --- a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java +++ b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java @@ -383,6 +383,15 @@ final class AssistHandleReminderExpBehavior implements BehaviorController { mIsLearned = mLearningCount >= getLearningCount() || mLearningTimeElapsed >= getLearningTimeMs(); + + mHandler.post(this::recordLearnTimeElapsed); + } + + private void recordLearnTimeElapsed() { + if (mContext != null) { + Settings.Secure.putLong( + mContext.getContentResolver(), LEARNING_TIME_ELAPSED_KEY, mLearningTimeElapsed); + } } private void resetConsecutiveTaskSwitches() { diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java index e42eb0a19f74..eb60b3db7a11 100644 --- a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java +++ b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java @@ -21,6 +21,7 @@ import android.os.AsyncTask; import android.os.Binder; import android.os.Bundle; import android.os.Handler; +import android.os.HandlerThread; import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; @@ -163,8 +164,10 @@ public class AssistManager implements ConfigurationChangedReceiver { mAssistUtils = new AssistUtils(context); mAssistDisclosure = new AssistDisclosure(context, new Handler()); mPhoneStateMonitor = new PhoneStateMonitor(context); - mHandleController = - new AssistHandleBehaviorController(context, mAssistUtils, new Handler()); + final HandlerThread assistHandleThread = new HandlerThread("AssistHandleThread"); + assistHandleThread.start(); + mHandleController = new AssistHandleBehaviorController( + context, mAssistUtils, assistHandleThread.getThreadHandler()); registerVoiceInteractionSessionListener(); mInterestingConfigChanges = new InterestingConfigChanges(ActivityInfo.CONFIG_ORIENTATION diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFaceView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFaceView.java index 74cc9c39741e..a68b61e4da45 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFaceView.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFaceView.java @@ -154,18 +154,18 @@ public class AuthBiometricFaceView extends AuthBiometricView { @Override protected void handleResetAfterError() { - resetErrorView(mContext, mErrorView); + resetErrorView(mContext, mIndicatorView); } @Override protected void handleResetAfterHelp() { - resetErrorView(mContext, mErrorView); + resetErrorView(mContext, mIndicatorView); } @Override protected void onFinishInflate() { super.onFinishInflate(); - mIconController = new IconController(mContext, mIconView, mErrorView); + mIconController = new IconController(mContext, mIconView, mIndicatorView); } @Override @@ -174,7 +174,7 @@ public class AuthBiometricFaceView extends AuthBiometricView { if (newState == STATE_AUTHENTICATING_ANIMATING_IN || (newState == STATE_AUTHENTICATING && mSize == AuthDialog.SIZE_MEDIUM)) { - resetErrorView(mContext, mErrorView); + resetErrorView(mContext, mIndicatorView); } // Do this last since the state variable gets updated. diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java index f26083998c76..df14a1716571 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java @@ -21,6 +21,8 @@ import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ValueAnimator; import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.content.Context; import android.hardware.biometrics.BiometricPrompt; import android.os.Bundle; @@ -127,8 +129,8 @@ public abstract class AuthBiometricView extends LinearLayout { return mBiometricView.findViewById(R.id.description); } - public TextView getErrorView() { - return mBiometricView.findViewById(R.id.error); + public TextView getIndicatorView() { + return mBiometricView.findViewById(R.id.indicator); } public ImageView getIconView() { @@ -150,7 +152,7 @@ public abstract class AuthBiometricView extends LinearLayout { private TextView mSubtitleView; private TextView mDescriptionView; protected ImageView mIconView; - @VisibleForTesting protected TextView mErrorView; + @VisibleForTesting protected TextView mIndicatorView; @VisibleForTesting Button mNegativeButton; @VisibleForTesting Button mPositiveButton; @VisibleForTesting Button mTryAgainButton; @@ -165,6 +167,7 @@ public abstract class AuthBiometricView extends LinearLayout { private float mIconOriginalY; protected boolean mDialogSizeAnimating; + protected Bundle mSavedState; /** * Delay after authentication is confirmed, before the dialog should be animated away. @@ -252,7 +255,7 @@ public abstract class AuthBiometricView extends LinearLayout { mTitleView.setVisibility(View.GONE); mSubtitleView.setVisibility(View.GONE); mDescriptionView.setVisibility(View.GONE); - mErrorView.setVisibility(View.GONE); + mIndicatorView.setVisibility(View.GONE); mNegativeButton.setVisibility(View.GONE); final float iconPadding = getResources() @@ -284,7 +287,7 @@ public abstract class AuthBiometricView extends LinearLayout { final float opacity = (float) animation.getAnimatedValue(); mTitleView.setAlpha(opacity); - mErrorView.setAlpha(opacity); + mIndicatorView.setAlpha(opacity); mNegativeButton.setAlpha(opacity); mTryAgainButton.setAlpha(opacity); @@ -304,7 +307,7 @@ public abstract class AuthBiometricView extends LinearLayout { public void onAnimationStart(Animator animation) { super.onAnimationStart(animation); mTitleView.setVisibility(View.VISIBLE); - mErrorView.setVisibility(View.VISIBLE); + mIndicatorView.setVisibility(View.VISIBLE); mNegativeButton.setVisibility(View.VISIBLE); mTryAgainButton.setVisibility(View.VISIBLE); @@ -339,6 +342,7 @@ public abstract class AuthBiometricView extends LinearLayout { public void updateState(@BiometricState int newState) { Log.v(TAG, "newState: " + newState); + switch (newState) { case STATE_AUTHENTICATING_ANIMATING_IN: case STATE_AUTHENTICATING: @@ -353,7 +357,7 @@ public abstract class AuthBiometricView extends LinearLayout { if (mSize != AuthDialog.SIZE_SMALL) { mPositiveButton.setVisibility(View.GONE); mNegativeButton.setVisibility(View.GONE); - mErrorView.setVisibility(View.INVISIBLE); + mIndicatorView.setVisibility(View.INVISIBLE); } mHandler.postDelayed(() -> mCallback.onAction(Callback.ACTION_AUTHENTICATED), getDelayAfterAuthenticatedDurationMs()); @@ -364,9 +368,10 @@ public abstract class AuthBiometricView extends LinearLayout { mNegativeButton.setText(R.string.cancel); mNegativeButton.setContentDescription(getResources().getString(R.string.cancel)); mPositiveButton.setEnabled(true); - mErrorView.setTextColor(mTextColorHint); - mErrorView.setText(R.string.biometric_dialog_tap_confirm); - mErrorView.setVisibility(View.VISIBLE); + mPositiveButton.setVisibility(View.VISIBLE); + mIndicatorView.setTextColor(mTextColorHint); + mIndicatorView.setText(R.string.biometric_dialog_tap_confirm); + mIndicatorView.setVisibility(View.VISIBLE); break; case STATE_ERROR: @@ -409,6 +414,27 @@ public abstract class AuthBiometricView extends LinearLayout { updateState(STATE_HELP); } + public void onSaveState(@NonNull Bundle outState) { + outState.putInt(AuthDialog.KEY_BIOMETRIC_TRY_AGAIN_VISIBILITY, + mTryAgainButton.getVisibility()); + outState.putInt(AuthDialog.KEY_BIOMETRIC_STATE, mState); + outState.putString(AuthDialog.KEY_BIOMETRIC_INDICATOR_STRING, + mIndicatorView.getText().toString()); + outState.putBoolean(AuthDialog.KEY_BIOMETRIC_INDICATOR_ERROR_SHOWING, + mHandler.hasCallbacks(mResetErrorRunnable)); + outState.putBoolean(AuthDialog.KEY_BIOMETRIC_INDICATOR_HELP_SHOWING, + mHandler.hasCallbacks(mResetHelpRunnable)); + outState.putInt(AuthDialog.KEY_BIOMETRIC_DIALOG_SIZE, mSize); + } + + /** + * Invoked after inflation but before being attached to window. + * @param savedState + */ + public void restoreState(@Nullable Bundle savedState) { + mSavedState = savedState; + } + private void setTextOrHide(TextView view, String string) { if (TextUtils.isEmpty(string)) { view.setVisibility(View.GONE); @@ -429,25 +455,28 @@ public abstract class AuthBiometricView extends LinearLayout { private void showTemporaryMessage(String message, Runnable resetMessageRunnable) { removePendingAnimations(); - mErrorView.setText(message); - mErrorView.setTextColor(mTextColorError); - mErrorView.setVisibility(View.VISIBLE); + mIndicatorView.setText(message); + mIndicatorView.setTextColor(mTextColorError); + mIndicatorView.setVisibility(View.VISIBLE); mHandler.postDelayed(resetMessageRunnable, BiometricPrompt.HIDE_DIALOG_DELAY); } @Override protected void onFinishInflate() { super.onFinishInflate(); - initializeViews(); + onFinishInflateInternal(); } + /** + * After inflation, but before things like restoreState, onAttachedToWindow, etc. + */ @VisibleForTesting - void initializeViews() { + void onFinishInflateInternal() { mTitleView = mInjector.getTitleView(); mSubtitleView = mInjector.getSubtitleView(); mDescriptionView = mInjector.getDescriptionView(); mIconView = mInjector.getIconView(); - mErrorView = mInjector.getErrorView(); + mIndicatorView = mInjector.getIndicatorView(); mNegativeButton = mInjector.getNegativeButton(); mPositiveButton = mInjector.getPositiveButton(); mTryAgainButton = mInjector.getTryAgainButton(); @@ -474,13 +503,49 @@ public abstract class AuthBiometricView extends LinearLayout { @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); + onAttachedToWindowInternal(); + } + + /** + * Contains all the testable logic that should be invoked when {@link #onAttachedToWindow()} is + * invoked. + */ + @VisibleForTesting + void onAttachedToWindowInternal() { setText(mTitleView, mBundle.getString(BiometricPrompt.KEY_TITLE)); setText(mNegativeButton, mBundle.getString(BiometricPrompt.KEY_NEGATIVE_TEXT)); setTextOrHide(mSubtitleView, mBundle.getString(BiometricPrompt.KEY_SUBTITLE)); setTextOrHide(mDescriptionView, mBundle.getString(BiometricPrompt.KEY_DESCRIPTION)); - updateState(STATE_AUTHENTICATING_ANIMATING_IN); + if (mSavedState == null) { + updateState(STATE_AUTHENTICATING_ANIMATING_IN); + } else { + // Restore as much state as possible first + updateState(mSavedState.getInt(AuthDialog.KEY_BIOMETRIC_STATE)); + + // Restore positive button state + mTryAgainButton.setVisibility( + mSavedState.getInt(AuthDialog.KEY_BIOMETRIC_TRY_AGAIN_VISIBILITY)); + + // Restore indicator text state + final String indicatorText = + mSavedState.getString(AuthDialog.KEY_BIOMETRIC_INDICATOR_STRING); + if (mSavedState.getBoolean(AuthDialog.KEY_BIOMETRIC_INDICATOR_HELP_SHOWING)) { + onHelp(indicatorText); + } else if (mSavedState.getBoolean(AuthDialog.KEY_BIOMETRIC_INDICATOR_ERROR_SHOWING)) { + onAuthenticationFailed(indicatorText); + } + } + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + + // Empty the handler, otherwise things like ACTION_AUTHENTICATED may be duplicated once + // the new dialog is restored. + mHandler.removeCallbacksAndMessages(null /* all */); } @Override @@ -521,13 +586,24 @@ public abstract class AuthBiometricView extends LinearLayout { @Override public void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); + onLayoutInternal(); + } + /** + * Contains all the testable logic that should be invoked when + * {@link #onLayout(boolean, int, int, int, int)}, is invoked. + */ + @VisibleForTesting + void onLayoutInternal() { // Start with initial size only once. Subsequent layout changes don't matter since we // only care about the initial icon position. if (mIconOriginalY == 0) { mIconOriginalY = mIconView.getY(); - updateSize(mRequireConfirmation ? AuthDialog.SIZE_MEDIUM - : AuthDialog.SIZE_SMALL); + if (mSavedState == null) { + updateSize(mRequireConfirmation ? AuthDialog.SIZE_MEDIUM : AuthDialog.SIZE_SMALL); + } else { + updateSize(mSavedState.getInt(AuthDialog.KEY_BIOMETRIC_DIALOG_SIZE)); + } } } } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java index 9cb5fcf4de00..e198060da9aa 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java @@ -17,6 +17,8 @@ package com.android.systemui.biometrics; import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.content.Context; import android.graphics.PixelFormat; import android.os.Binder; @@ -269,7 +271,8 @@ public class AuthContainerView extends LinearLayout } @Override - public void show(WindowManager wm) { + public void show(WindowManager wm, @Nullable Bundle savedState) { + mBiometricView.restoreState(savedState); wm.addView(this, getLayoutParams(mWindowToken)); } @@ -308,13 +311,8 @@ public class AuthContainerView extends LinearLayout } @Override - public void onSaveState(Bundle outState) { - - } - - @Override - public void restoreState(Bundle savedState) { - + public void onSaveState(@NonNull Bundle outState) { + mBiometricView.onSaveState(outState); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java index dcd01c682726..ab89034c3b65 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java @@ -272,11 +272,7 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks, + " type: " + type); } - if (savedState != null) { - // SavedState is only non-null if it's from onConfigurationChanged. Restore the state - // even though it may be removed / re-created again - newDialog.restoreState(savedState); - } else if (mCurrentDialog != null) { + if (mCurrentDialog != null) { // If somehow we're asked to show a dialog, the old one doesn't need to be animated // away. This can happen if the app cancels and re-starts auth during configuration // change. This is ugly because we also have to do things on onConfigurationChanged @@ -286,7 +282,7 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks, mReceiver = (IBiometricServiceReceiverInternal) args.arg2; mCurrentDialog = newDialog; - mCurrentDialog.show(mWindowManager); + mCurrentDialog.show(mWindowManager, savedState); } private void onDialogDismissed(@DismissedReason int reason) { diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialog.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialog.java index a6a857ca5945..fb904231c175 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialog.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialog.java @@ -17,7 +17,8 @@ package com.android.systemui.biometrics; import android.annotation.IntDef; -import android.hardware.biometrics.BiometricPrompt; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.os.Bundle; import android.view.WindowManager; @@ -28,28 +29,12 @@ import java.lang.annotation.RetentionPolicy; * Interface for the biometric dialog UI. */ public interface AuthDialog { - - // TODO: Clean up save/restore state - String[] KEYS_TO_BACKUP = { - BiometricPrompt.KEY_TITLE, - BiometricPrompt.KEY_USE_DEFAULT_TITLE, - BiometricPrompt.KEY_SUBTITLE, - BiometricPrompt.KEY_DESCRIPTION, - BiometricPrompt.KEY_POSITIVE_TEXT, - BiometricPrompt.KEY_NEGATIVE_TEXT, - BiometricPrompt.KEY_REQUIRE_CONFIRMATION, - BiometricPrompt.KEY_ALLOW_DEVICE_CREDENTIAL, - BiometricPrompt.KEY_FROM_CONFIRM_DEVICE_CREDENTIAL, - - BiometricDialogView.KEY_TRY_AGAIN_VISIBILITY, - BiometricDialogView.KEY_CONFIRM_VISIBILITY, - BiometricDialogView.KEY_CONFIRM_ENABLED, - BiometricDialogView.KEY_STATE, - BiometricDialogView.KEY_ERROR_TEXT_VISIBILITY, - BiometricDialogView.KEY_ERROR_TEXT_STRING, - BiometricDialogView.KEY_ERROR_TEXT_IS_TEMPORARY, - BiometricDialogView.KEY_ERROR_TEXT_COLOR, - }; + String KEY_BIOMETRIC_TRY_AGAIN_VISIBILITY = "try_agian_visibility"; + String KEY_BIOMETRIC_STATE = "state"; + String KEY_BIOMETRIC_INDICATOR_STRING = "indicator_string"; // error / help / hint + String KEY_BIOMETRIC_INDICATOR_ERROR_SHOWING = "error_is_temporary"; + String KEY_BIOMETRIC_INDICATOR_HELP_SHOWING = "hint_is_temporary"; + String KEY_BIOMETRIC_DIALOG_SIZE = "size"; int SIZE_UNKNOWN = 0; int SIZE_SMALL = 1; @@ -68,7 +53,7 @@ public interface AuthDialog { * Show the dialog. * @param wm */ - void show(WindowManager wm); + void show(WindowManager wm, @Nullable Bundle savedState); /** * Dismiss the dialog without sending a callback. @@ -107,13 +92,7 @@ public interface AuthDialog { * Save the current state. * @param outState */ - void onSaveState(Bundle outState); - - /** - * Restore a previous state. - * @param savedState - */ - void restoreState(Bundle savedState); + void onSaveState(@NonNull Bundle outState); /** * Get the client's package name diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogView.java b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogView.java index 89d08d795128..b985e1c2a4d4 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogView.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogView.java @@ -23,6 +23,7 @@ import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ValueAnimator; import android.annotation.IntDef; +import android.annotation.Nullable; import android.app.admin.DevicePolicyManager; import android.content.Context; import android.graphics.Outline; @@ -738,7 +739,10 @@ public abstract class BiometricDialogView extends LinearLayout implements AuthDi } @Override - public void show(WindowManager wm) { + public void show(WindowManager wm, @Nullable Bundle savedState) { + if (savedState != null) { + restoreState(savedState); + } wm.addView(this, getLayoutParams(mWindowToken)); } @@ -832,7 +836,6 @@ public abstract class BiometricDialogView extends LinearLayout implements AuthDi bundle.putInt(KEY_DIALOG_SIZE, mSize); } - @Override public void restoreState(Bundle bundle) { mRestoredState = bundle; diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java index 13d6470a351f..cc250b46c040 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java @@ -168,7 +168,7 @@ public class BubbleStackView extends FrameLayout { * Callback to run after the flyout hides. Also called if a new flyout is shown before the * previous one animates out. */ - private Runnable mAfterFlyoutHides; + private Runnable mFlyoutOnHide; /** Layout change listener that moves the stack to the nearest valid position on rotation. */ private OnLayoutChangeListener mOrientationChangedListener; @@ -1366,111 +1366,106 @@ public class BubbleStackView extends FrameLayout { @VisibleForTesting void animateInFlyoutForBubble(Bubble bubble) { final CharSequence updateMessage = bubble.getUpdateMessage(getContext()); - if (!bubble.showFlyoutForBubble()) { // In case flyout was suppressed for this update, reset now. bubble.setSuppressFlyout(false); return; } - if (updateMessage == null || isExpanded() || mIsExpansionAnimating || mIsGestureInProgress - || mBubbleToExpandAfterFlyoutCollapse != null) { + || mBubbleToExpandAfterFlyoutCollapse != null + || bubble.getIconView() == null) { // Skip the message if none exists, we're expanded or animating expansion, or we're - // about to expand a bubble from the previous tapped flyout. + // about to expand a bubble from the previous tapped flyout, or if bubble view is null. return; } - - if (bubble.getIconView() != null) { - // Temporarily suppress the dot while the flyout is visible. - bubble.getIconView().setSuppressDot( - true /* suppressDot */, false /* animate */); - - mFlyout.removeCallbacks(mAnimateInFlyout); - mFlyoutDragDeltaX = 0f; - - if (mAfterFlyoutHides != null) { - mAfterFlyoutHides.run(); + mFlyoutDragDeltaX = 0f; + clearFlyoutOnHide(); + mFlyoutOnHide = () -> { + resetDot(bubble); + if (mBubbleToExpandAfterFlyoutCollapse == null) { + return; } - - mAfterFlyoutHides = () -> { - final boolean suppressDot = !bubble.showBubbleDot(); - // If we're going to suppress the dot, make it visible first so it'll - // visibly animate away. - if (suppressDot) { - bubble.getIconView().setSuppressDot( - false /* suppressDot */, false /* animate */); - } - // Reset dot suppression. If we're not suppressing due to DND, then - // stop suppressing it with no animation (since the flyout has - // transformed into the dot). If we are suppressing due to DND, animate - // it away. - bubble.getIconView().setSuppressDot( - suppressDot /* suppressDot */, - suppressDot /* animate */); - - if (mBubbleToExpandAfterFlyoutCollapse != null) { - mBubbleData.setSelectedBubble(mBubbleToExpandAfterFlyoutCollapse); - mBubbleData.setExpanded(true); - mBubbleToExpandAfterFlyoutCollapse = null; - } - }; - - mFlyout.setVisibility(INVISIBLE); - - // Post in case layout isn't complete and getWidth returns 0. - post(() -> { - // An auto-expanding bubble could have been posted during the time it takes to - // layout. - if (isExpanded()) { - return; - } - - final Runnable afterShow = () -> { - mAnimateInFlyout = () -> { - mFlyout.setVisibility(VISIBLE); - bubble.getIconView().setSuppressDot( - true /* suppressDot */, false /* animate */); - mFlyoutDragDeltaX = - mStackAnimationController.isStackOnLeftSide() - ? -mFlyout.getWidth() - : mFlyout.getWidth(); - animateFlyoutCollapsed(false /* collapsed */, 0 /* velX */); - mFlyout.postDelayed(mHideFlyout, FLYOUT_HIDE_AFTER); - }; - - mFlyout.postDelayed(mAnimateInFlyout, 200); + mBubbleData.setSelectedBubble(mBubbleToExpandAfterFlyoutCollapse); + mBubbleData.setExpanded(true); + mBubbleToExpandAfterFlyoutCollapse = null; + }; + mFlyout.setVisibility(INVISIBLE); + + // Temporarily suppress the dot while the flyout is visible. + bubble.getIconView().setSuppressDot( + true /* suppressDot */, false /* animate */); + + // Start flyout expansion. Post in case layout isn't complete and getWidth returns 0. + post(() -> { + // An auto-expanding bubble could have been posted during the time it takes to + // layout. + if (isExpanded()) { + return; + } + final Runnable expandFlyoutAfterDelay = () -> { + mAnimateInFlyout = () -> { + mFlyout.setVisibility(VISIBLE); + mFlyoutDragDeltaX = + mStackAnimationController.isStackOnLeftSide() + ? -mFlyout.getWidth() + : mFlyout.getWidth(); + animateFlyoutCollapsed(false /* collapsed */, 0 /* velX */); + mFlyout.postDelayed(mHideFlyout, FLYOUT_HIDE_AFTER); }; - - mFlyout.setupFlyoutStartingAsDot( - updateMessage, mStackAnimationController.getStackPosition(), getWidth(), - mStackAnimationController.isStackOnLeftSide(), - bubble.getIconView().getBadgeColor(), - afterShow, - mAfterFlyoutHides, - bubble.getIconView().getDotCenter()); - mFlyout.bringToFront(); - }); - } - + mFlyout.postDelayed(mAnimateInFlyout, 200); + }; + mFlyout.setupFlyoutStartingAsDot( + updateMessage, mStackAnimationController.getStackPosition(), getWidth(), + mStackAnimationController.isStackOnLeftSide(), + bubble.getIconView().getBadgeColor() /* dotColor */, + expandFlyoutAfterDelay /* onLayoutComplete */, + mFlyoutOnHide, + bubble.getIconView().getDotCenter()); + mFlyout.bringToFront(); + }); mFlyout.removeCallbacks(mHideFlyout); mFlyout.postDelayed(mHideFlyout, FLYOUT_HIDE_AFTER); logBubbleEvent(bubble, StatsLog.BUBBLE_UICHANGED__ACTION__FLYOUT); } - /** Hide the flyout immediately and cancel any pending hide runnables. */ - private void hideFlyoutImmediate() { - if (mAfterFlyoutHides != null) { - mAfterFlyoutHides.run(); + private void resetDot(Bubble bubble) { + final boolean suppressDot = !bubble.showBubbleDot(); + // If we're going to suppress the dot, make it visible first so it'll + // visibly animate away. + + if (suppressDot) { + bubble.getIconView().setSuppressDot( + false /* suppressDot */, false /* animate */); } + // Reset dot suppression. If we're not suppressing due to DND, then + // stop suppressing it with no animation (since the flyout has + // transformed into the dot). If we are suppressing due to DND, animate + // it away. + bubble.getIconView().setSuppressDot( + suppressDot /* suppressDot */, + suppressDot /* animate */); + } + /** Hide the flyout immediately and cancel any pending hide runnables. */ + private void hideFlyoutImmediate() { + clearFlyoutOnHide(); mFlyout.removeCallbacks(mAnimateInFlyout); mFlyout.removeCallbacks(mHideFlyout); mFlyout.hideFlyout(); } + private void clearFlyoutOnHide() { + mFlyout.removeCallbacks(mAnimateInFlyout); + if (mFlyoutOnHide == null) { + return; + } + mFlyoutOnHide.run(); + mFlyoutOnHide = null; + } + @Override public void getBoundsOnScreen(Rect outRect) { if (!mIsExpanded) { diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java index 603c4169c169..4512aa822e3b 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java @@ -61,7 +61,7 @@ public class BubbleView extends FrameLayout { // mBubbleIconFactory cannot be static because it depends on Context. private BubbleIconFactory mBubbleIconFactory; - private boolean mSuppressDot = false; + private boolean mSuppressDot; private Bubble mBubble; @@ -140,6 +140,7 @@ public class BubbleView extends FrameLayout { public void setAppIcon(Drawable appIcon) { mUserBadgedAppIcon = appIcon; } + /** * @return the {@link ExpandableNotificationRow} view to display notification content when the * bubble is expanded. @@ -154,7 +155,6 @@ public class BubbleView extends FrameLayout { updateDotVisibility(animate, null /* after */); } - /** * Sets whether or not to hide the dot even if we'd otherwise show it. This is used while the * flyout is visible or animating, to hide the dot until the flyout visually transforms into it. @@ -166,7 +166,7 @@ public class BubbleView extends FrameLayout { /** Sets the position of the 'new' dot, animating it out and back in if requested. */ void setDotPosition(boolean onLeft, boolean animate) { - if (animate && onLeft != mBadgedImageView.getDotOnLeft() && !mSuppressDot) { + if (animate && onLeft != mBadgedImageView.getDotOnLeft() && shouldShowDot()) { animateDot(false /* showDot */, () -> { mBadgedImageView.setDotOnLeft(onLeft); animateDot(true /* showDot */, null); @@ -190,12 +190,12 @@ public class BubbleView extends FrameLayout { * after animation if requested. */ private void updateDotVisibility(boolean animate, Runnable after) { - boolean showDot = mBubble.showBubbleDot() && !mSuppressDot; - + final boolean showDot = shouldShowDot(); if (animate) { animateDot(showDot, after); } else { mBadgedImageView.setShowDot(showDot); + mBadgedImageView.setDotScale(showDot ? 1f : 0f); } } @@ -203,27 +203,25 @@ public class BubbleView extends FrameLayout { * Animates the badge to show or hide. */ private void animateDot(boolean showDot, Runnable after) { - if (mBadgedImageView.isShowingDot() != showDot) { - if (showDot) { - mBadgedImageView.setShowDot(true); - } - mBadgedImageView.clearAnimation(); - mBadgedImageView.animate().setDuration(200) - .setInterpolator(Interpolators.FAST_OUT_SLOW_IN) - .setUpdateListener((valueAnimator) -> { - float fraction = valueAnimator.getAnimatedFraction(); - fraction = showDot ? fraction : 1f - fraction; - mBadgedImageView.setDotScale(fraction); - }).withEndAction(() -> { - if (!showDot) { - mBadgedImageView.setShowDot(false); - } - - if (after != null) { - after.run(); - } - }).start(); + if (mBadgedImageView.isShowingDot() == showDot) { + return; } + // Do NOT wait until after animation ends to setShowDot + // to avoid overriding more recent showDot states. + mBadgedImageView.setShowDot(showDot); + mBadgedImageView.clearAnimation(); + mBadgedImageView.animate().setDuration(200) + .setInterpolator(Interpolators.FAST_OUT_SLOW_IN) + .setUpdateListener((valueAnimator) -> { + float fraction = valueAnimator.getAnimatedFraction(); + fraction = showDot ? fraction : 1f - fraction; + mBadgedImageView.setDotScale(fraction); + }).withEndAction(() -> { + mBadgedImageView.setDotScale(showDot ? 1f : 0f); + if (after != null) { + after.run(); + } + }).start(); } void updateViews() { @@ -273,7 +271,11 @@ public class BubbleView extends FrameLayout { iconPath.transform(matrix); mBadgedImageView.drawDot(iconPath); - animateDot(mBubble.showBubbleDot() /* showDot */, null /* after */); + animateDot(shouldShowDot(), null /* after */); + } + + boolean shouldShowDot() { + return mBubble.showBubbleDot() && !mSuppressDot; } int getBadgeColor() { diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java index 3f598ffad709..c9c6a0c6868b 100644 --- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java +++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java @@ -614,7 +614,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener, mHandler.postDelayed(new Runnable() { @Override public void run() { - mScreenshotHelper.takeScreenshot(1, true, true, mHandler); + mScreenshotHelper.takeScreenshot(1, true, true, mHandler, null); MetricsLogger.action(mContext, MetricsEvent.ACTION_SCREENSHOT_POWER_MENU); } diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java index 7b22a49fc88a..29606347f009 100644 --- a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java +++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java @@ -111,7 +111,12 @@ public class ImageWallpaperRenderer implements GLWallpaperRenderer, mBitmap = mWallpaperManager.getBitmap(); mWallpaperManager.forgetLoadedWallpaper(); if (mBitmap != null) { - mSurfaceSize.set(0, 0, mBitmap.getWidth(), mBitmap.getHeight()); + float scale = (float) mScissor.height() / mBitmap.getHeight(); + int surfaceHeight = Math.max(mScissor.height(), mBitmap.getHeight()); + int surfaceWidth = scale > 1f + ? Math.round(mBitmap.getWidth() * scale) + : mBitmap.getWidth(); + mSurfaceSize.set(0, 0, surfaceWidth, surfaceHeight); } } return mBitmap != null; diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index e69688079e57..d2a9c750bbc6 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -99,6 +99,8 @@ import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; +import javax.inject.Inject; + /** * Mediates requests related to the keyguard. This includes queries about the * state of the keyguard, power management events that effect whether the keyguard @@ -216,6 +218,7 @@ public class KeyguardViewMediator extends SystemUI { private boolean mBootSendUserPresent; private boolean mShuttingDown; private boolean mDozing; + private final FalsingManager mFalsingManager; /** High level access to the power manager for WakeLocks */ private PowerManager mPM; @@ -678,6 +681,13 @@ public class KeyguardViewMediator extends SystemUI { } }; + @Inject + public KeyguardViewMediator(FalsingManager falsingManager) { + super(); + + mFalsingManager = falsingManager; + } + public void userActivity() { mPM.userActivity(SystemClock.uptimeMillis(), false); } @@ -1603,7 +1613,7 @@ public class KeyguardViewMediator extends SystemUI { Trace.beginSection("KeyguardViewMediator#handleMessage START_KEYGUARD_EXIT_ANIM"); StartKeyguardExitAnimParams params = (StartKeyguardExitAnimParams) msg.obj; handleStartKeyguardExitAnimation(params.startTime, params.fadeoutDuration); - Dependency.get(FalsingManager.class).onSucccessfulUnlock(); + mFalsingManager.onSucccessfulUnlock(); Trace.endSection(); break; case KEYGUARD_DONE_PENDING_TIMEOUT: @@ -2075,11 +2085,10 @@ public class KeyguardViewMediator extends SystemUI { public StatusBarKeyguardViewManager registerStatusBar(StatusBar statusBar, ViewGroup container, NotificationPanelView panelView, BiometricUnlockController biometricUnlockController, ViewGroup lockIconContainer, - View notificationContainer, KeyguardBypassController bypassController, - FalsingManager falsingManager) { + View notificationContainer, KeyguardBypassController bypassController) { mStatusBarKeyguardViewManager.registerStatusBar(statusBar, container, panelView, biometricUnlockController, mDismissCallbackRegistry, lockIconContainer, - notificationContainer, bypassController, falsingManager); + notificationContainer, bypassController, mFalsingManager); return mStatusBarKeyguardViewManager; } diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java index 17402905b21a..3be3422a36ad 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java @@ -16,6 +16,9 @@ package com.android.systemui.pip.phone; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; +import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; + import android.app.ActivityManager; import android.app.ActivityTaskManager; import android.app.IActivityManager; @@ -182,7 +185,6 @@ public class PipManager implements BasePipManager { ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener); mInputConsumerController = InputConsumerController.getPipInputConsumer(); - mInputConsumerController.registerInputConsumer(); mMediaController = new PipMediaController(context, mActivityManager); mMenuController = new PipMenuActivityController(context, mActivityManager, mMediaController, mInputConsumerController); @@ -190,6 +192,18 @@ public class PipManager implements BasePipManager { mMenuController, mInputConsumerController); mAppOpsListener = new PipAppOpsListener(context, mActivityManager, mTouchHandler.getMotionHelper()); + + // If SystemUI restart, and it already existed a pinned stack, + // register the pip input consumer to ensure touch can send to it. + try { + ActivityManager.StackInfo stackInfo = mActivityTaskManager.getStackInfo( + WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED); + if (stackInfo != null) { + mInputConsumerController.registerInputConsumer(); + } + } catch (RemoteException e) { + e.printStackTrace(); + } } /** diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java index 21f58128322d..4f2a6d82a08e 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java @@ -48,7 +48,6 @@ import android.content.ComponentName; import android.content.Intent; import android.content.pm.ParceledListSlice; import android.graphics.Color; -import android.graphics.PointF; import android.graphics.Rect; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; @@ -64,7 +63,6 @@ import android.util.Pair; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; -import android.view.ViewConfiguration; import android.view.ViewGroup; import android.view.WindowManager.LayoutParams; import android.view.accessibility.AccessibilityManager; @@ -92,6 +90,7 @@ public class PipMenuActivity extends Activity { public static final int MESSAGE_UPDATE_ACTIONS = 4; public static final int MESSAGE_UPDATE_DISMISS_FRACTION = 5; public static final int MESSAGE_ANIMATION_ENDED = 6; + public static final int MESSAGE_TOUCH_EVENT = 7; private static final int INITIAL_DISMISS_DELAY = 3500; private static final int POST_INTERACTION_DISMISS_DELAY = 2000; @@ -128,10 +127,6 @@ public class PipMenuActivity extends Activity { } }; - private PipTouchState mTouchState; - private PointF mDownPosition = new PointF(); - private PointF mDownDelta = new PointF(); - private ViewConfiguration mViewConfig; private Handler mHandler = new Handler(); private Messenger mToControllerMessenger; private Messenger mMessenger = new Messenger(new Handler() { @@ -169,6 +164,12 @@ public class PipMenuActivity extends Activity { mAllowTouches = true; break; } + + case MESSAGE_TOUCH_EVENT: { + final MotionEvent ev = (MotionEvent) msg.obj; + dispatchTouchEvent(ev); + break; + } } } }); @@ -184,15 +185,7 @@ public class PipMenuActivity extends Activity { protected void onCreate(@Nullable Bundle savedInstanceState) { // Set the flags to allow us to watch for outside touches and also hide the menu and start // manipulating the PIP in the same touch gesture - mViewConfig = ViewConfiguration.get(this); - mTouchState = new PipTouchState(mViewConfig, mHandler, () -> { - if (mMenuState == MENU_STATE_CLOSE) { - showPipMenu(); - } else { - expandPip(); - } - }); - getWindow().addFlags(LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH | LayoutParams.FLAG_SLIPPERY); + getWindow().addFlags(LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH); super.onCreate(savedInstanceState); setContentView(R.layout.pip_menu_activity); @@ -204,32 +197,6 @@ public class PipMenuActivity extends Activity { mViewRoot.setBackground(mBackgroundDrawable); mMenuContainer = findViewById(R.id.menu_container); mMenuContainer.setAlpha(0); - mMenuContainer.setOnTouchListener((v, event) -> { - mTouchState.onTouchEvent(event); - switch (event.getAction()) { - case MotionEvent.ACTION_UP: - if (mTouchState.isDoubleTap() || mMenuState == MENU_STATE_FULL) { - // Expand to fullscreen if this is a double tap or we are already expanded - expandPip(); - } else if (!mTouchState.isWaitingForDoubleTap()) { - // User has stalled long enough for this not to be a drag or a double tap, - // just expand the menu if necessary - if (mMenuState == MENU_STATE_CLOSE) { - showPipMenu(); - } - } else { - // Next touch event _may_ be the second tap for the double-tap, schedule a - // fallback runnable to trigger the menu if no touch event occurs before the - // next tap - mTouchState.scheduleDoubleTapTimeoutCallback(); - } - // Fall through - case MotionEvent.ACTION_CANCEL: - mTouchState.reset(); - break; - } - return true; - }); mSettingsButton = findViewById(R.id.settings); mSettingsButton.setAlpha(0); mSettingsButton.setOnClickListener((v) -> { @@ -240,7 +207,11 @@ public class PipMenuActivity extends Activity { mDismissButton = findViewById(R.id.dismiss); mDismissButton.setAlpha(0); mDismissButton.setOnClickListener(v -> dismissPip()); - findViewById(R.id.expand_button).setOnClickListener(v -> expandPip()); + findViewById(R.id.expand_button).setOnClickListener(v -> { + if (mMenuContainer.getAlpha() != 0) { + expandPip(); + } + }); mActionsGroup = findViewById(R.id.actions_group); mBetweenActionPaddingLand = getResources().getDimensionPixelSize( R.dimen.pip_between_action_padding_land); @@ -298,27 +269,14 @@ public class PipMenuActivity extends Activity { @Override public boolean dispatchTouchEvent(MotionEvent ev) { if (!mAllowTouches) { - return super.dispatchTouchEvent(ev); + return false; } // On the first action outside the window, hide the menu switch (ev.getAction()) { case MotionEvent.ACTION_OUTSIDE: hideMenu(); - break; - case MotionEvent.ACTION_DOWN: - mDownPosition.set(ev.getX(), ev.getY()); - mDownDelta.set(0f, 0f); - break; - case MotionEvent.ACTION_MOVE: - mDownDelta.set(ev.getX() - mDownPosition.x, ev.getY() - mDownPosition.y); - if (mDownDelta.length() > mViewConfig.getScaledTouchSlop() - && mMenuState != MENU_STATE_NONE) { - // Restore the input consumer and let that drive the movement of this menu - notifyRegisterInputConsumer(); - cancelDelayedFinish(); - } - break; + return true; } return super.dispatchTouchEvent(ev); } @@ -381,7 +339,6 @@ public class PipMenuActivity extends Activity { if (allowMenuTimeout) { repostDelayedFinish(POST_INTERACTION_DISMISS_DELAY); } - notifyUnregisterInputConsumer(); } } @@ -506,11 +463,13 @@ public class PipMenuActivity extends Activity { actionView.setContentDescription(action.getContentDescription()); if (action.isEnabled()) { actionView.setOnClickListener(v -> { - try { - action.getActionIntent().send(); - } catch (CanceledException e) { - Log.w(TAG, "Failed to send action", e); - } + mHandler.post(() -> { + try { + action.getActionIntent().send(); + } catch (CanceledException e) { + Log.w(TAG, "Failed to send action", e); + } + }); }); } actionView.setEnabled(action.isEnabled()); @@ -554,18 +513,6 @@ public class PipMenuActivity extends Activity { mBackgroundDrawable.setAlpha(alpha); } - private void notifyRegisterInputConsumer() { - Message m = Message.obtain(); - m.what = PipMenuActivityController.MESSAGE_REGISTER_INPUT_CONSUMER; - sendMessage(m, "Could not notify controller to register input consumer"); - } - - private void notifyUnregisterInputConsumer() { - Message m = Message.obtain(); - m.what = PipMenuActivityController.MESSAGE_UNREGISTER_INPUT_CONSUMER; - sendMessage(m, "Could not notify controller to unregister input consumer"); - } - private void notifyMenuStateChange(int menuState) { mMenuState = menuState; Message m = Message.obtain(); @@ -583,11 +530,6 @@ public class PipMenuActivity extends Activity { }, false /* notifyMenuVisibility */, false /* isDismissing */); } - private void minimizePip() { - sendEmptyMessage(PipMenuActivityController.MESSAGE_MINIMIZE_PIP, - "Could not notify controller to minimize PIP"); - } - private void dismissPip() { // Do not notify menu visibility when hiding the menu, the controller will do this when it // handles the message @@ -597,12 +539,6 @@ public class PipMenuActivity extends Activity { }, false /* notifyMenuVisibility */, true /* isDismissing */); } - private void showPipMenu() { - Message m = Message.obtain(); - m.what = PipMenuActivityController.MESSAGE_SHOW_MENU; - sendMessage(m, "Could not notify controller to show PIP menu"); - } - private void showSettings() { final Pair<ComponentName, Integer> topPipActivityInfo = PipUtils.getTopPinnedActivity(this, ActivityManager.getService()); diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java index 14459d6b8111..62c59e5842ff 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java @@ -37,6 +37,7 @@ import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; import android.util.Log; +import android.view.MotionEvent; import com.android.systemui.pip.phone.PipMediaController.ActionListener; import com.android.systemui.shared.system.InputConsumerController; @@ -156,14 +157,6 @@ public class PipMenuActivityController { mListeners.forEach(l -> l.onPipShowMenu()); break; } - case MESSAGE_REGISTER_INPUT_CONSUMER: { - mInputConsumerController.registerInputConsumer(); - break; - } - case MESSAGE_UNREGISTER_INPUT_CONSUMER: { - mInputConsumerController.unregisterInputConsumer(); - break; - } case MESSAGE_UPDATE_ACTIVITY_CALLBACK: { mToActivityMessenger = msg.replyTo; setStartActivityRequested(false); @@ -212,15 +205,12 @@ public class PipMenuActivityController { } public void onActivityPinned() { - if (mMenuState == MENU_STATE_NONE) { - // If the menu is not visible, then re-register the input consumer if it is not already - // registered - mInputConsumerController.registerInputConsumer(); - } + mInputConsumerController.registerInputConsumer(); } public void onActivityUnpinned() { hideMenu(); + mInputConsumerController.unregisterInputConsumer(); setStartActivityRequested(false); } @@ -495,11 +485,7 @@ public class PipMenuActivityController { Log.d(TAG, "onMenuStateChanged() mMenuState=" + mMenuState + " menuState=" + menuState + " resize=" + resize); } - if (menuState == MENU_STATE_NONE) { - mInputConsumerController.registerInputConsumer(); - } else { - mInputConsumerController.unregisterInputConsumer(); - } + if (menuState != mMenuState) { mListeners.forEach(l -> l.onPipMenuStateChanged(menuState, resize)); if (menuState == MENU_STATE_FULL) { @@ -521,6 +507,22 @@ public class PipMenuActivityController { mStartActivityRequestedTime = requested ? SystemClock.uptimeMillis() : 0; } + /** + * Handles touch event sent from pip input consumer. + */ + void handleTouchEvent(MotionEvent ev) { + if (mToActivityMessenger != null) { + Message m = Message.obtain(); + m.what = PipMenuActivity.MESSAGE_TOUCH_EVENT; + m.obj = ev; + try { + mToActivityMessenger.send(m); + } catch (RemoteException e) { + Log.e(TAG, "Could not dispatch touch event", e); + } + } + } + public void dump(PrintWriter pw, String prefix) { final String innerPrefix = prefix + " "; pw.println(prefix + TAG); diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java index 9c65994425ed..fa6047755619 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java @@ -551,9 +551,8 @@ public class PipMotionHelper implements Handler.Callback, PipAppOpsListener.Call return true; } - mActivityTaskManager.resizeStack(stackInfo.stackId, toBounds, - false /* allowResizeInDockedMode */, true /* preserveWindows */, - true /* animate */, duration); + mActivityTaskManager.animateResizePinnedStack(stackInfo.stackId, toBounds, + duration); mBounds.set(toBounds); } catch (RemoteException e) { Log.e(TAG, "Could not animate resize pinned stack to bounds: " + toBounds, e); diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java index b05058a92650..30cf412671bc 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java @@ -363,6 +363,8 @@ public class PipTouchHandler { // Update the touch state mTouchState.onTouchEvent(ev); + boolean shouldDeliverToMenu = mMenuState != MENU_STATE_NONE; + switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: { mMotionHelper.synchronizePinnedStackBounds(); @@ -378,6 +380,8 @@ public class PipTouchHandler { break; } } + + shouldDeliverToMenu = !mTouchState.isDragging(); break; } case MotionEvent.ACTION_UP: { @@ -394,6 +398,7 @@ public class PipTouchHandler { // Fall through to clean up } case MotionEvent.ACTION_CANCEL: { + shouldDeliverToMenu = !mTouchState.startedDragging() && !mTouchState.isDragging(); mTouchState.reset(); break; } @@ -425,7 +430,20 @@ public class PipTouchHandler { break; } } - return mMenuState == MENU_STATE_NONE; + + // Deliver the event to PipMenuActivity to handle button click if the menu has shown. + if (shouldDeliverToMenu) { + final MotionEvent cloneEvent = MotionEvent.obtain(ev); + // Send the cancel event and cancel menu timeout if it starts to drag. + if (mTouchState.startedDragging()) { + cloneEvent.setAction(MotionEvent.ACTION_CANCEL); + mMenuController.pokeMenu(); + } + + mMenuController.handleTouchEvent(cloneEvent); + } + + return true; } /** @@ -741,11 +759,11 @@ public class PipTouchHandler { mMotionHelper.animateToClosestSnapTarget(mMovementBounds, null /* updateListener */, null /* animatorListener */); setMinimizedStateInternal(false); + } else if (mTouchState.isDoubleTap()) { + // Expand to fullscreen if this is a double tap + mMotionHelper.expandPip(); } else if (mMenuState != MENU_STATE_FULL) { - if (mTouchState.isDoubleTap()) { - // Expand to fullscreen if this is a double tap - mMotionHelper.expandPip(); - } else if (!mTouchState.isWaitingForDoubleTap()) { + if (!mTouchState.isWaitingForDoubleTap()) { // User has stalled long enough for this not to be a drag or a double tap, just // expand the menu mMenuController.showMenu(MENU_STATE_FULL, mMotionHelper.getBounds(), @@ -756,9 +774,6 @@ public class PipTouchHandler { // next tap mTouchState.scheduleDoubleTapTimeoutCallback(); } - } else { - mMenuController.hideMenu(); - mMotionHelper.expandPip(); } return true; } diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java index 69efbc8575e0..e3f65ef812fb 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java @@ -106,6 +106,7 @@ public class PipTouchState { mIsDoubleTap = !mPreviouslyDragging && (mDownTouchTime - mLastDownTouchTime) < DOUBLE_TAP_TIMEOUT; mIsWaitingForDoubleTap = false; + mIsDragging = false; mLastDownTouchTime = mDownTouchTime; if (mDoubleTapTimeoutCallback != null) { mHandler.removeCallbacks(mDoubleTapTimeoutCallback); diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java index 5f2614ef4479..918af4f0cd4c 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java +++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java @@ -441,8 +441,8 @@ public class PipManager implements BasePipManager { } try { int animationDurationMs = -1; - mActivityTaskManager.resizeStack(mPinnedStackId, mCurrentPipBounds, - true, true, true, animationDurationMs); + mActivityTaskManager.animateResizePinnedStack(mPinnedStackId, mCurrentPipBounds, + animationDurationMs); } catch (RemoteException e) { Log.e(TAG, "resizeStack failed", e); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java index 37113cfac2f3..1211e135d1b7 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java @@ -107,11 +107,6 @@ public class QuickQSPanel extends QSPanel { } @Override - protected boolean shouldShowDetail() { - return !mExpanded; - } - - @Override protected void drawTile(TileRecord r, State state) { if (state instanceof SignalState) { SignalState copy = new SignalState(); diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java index b135f7b27c3f..effea6a877b8 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java +++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java @@ -159,8 +159,11 @@ public class TileLifecycleManager extends BroadcastReceiver implements mBindTryCount++; try { mIsBound = mContext.bindServiceAsUser(mIntent, this, - Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE - | Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS, mUser); + Context.BIND_AUTO_CREATE + | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE + | Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS + | Context.BIND_WAIVE_PRIORITY, + mUser); } catch (SecurityException e) { Log.e(TAG, "Failed to bind to service", e); mIsBound = false; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java index 90455395db45..3d6ee4cf9617 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java @@ -63,6 +63,8 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.PagedTileLayout.TilePage; import com.android.systemui.qs.QSHost; import com.android.systemui.qs.QuickStatusBarHeader; +import com.android.systemui.qs.tiles.QSSettingsControllerKt; +import com.android.systemui.qs.tiles.QSSettingsPanel; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -121,9 +123,16 @@ public abstract class QSTileImpl<TState extends State> implements QSTile, Lifecy */ abstract public int getMetricsCategory(); + /** + * Experimental option on whether to use settings panels. Only loaded on creation, so the tile + * needs to be removed and added for this to take effect. + */ + protected final QSSettingsPanel mQSSettingsPanelOption; + protected QSTileImpl(QSHost host) { mHost = host; mContext = host.getContext(); + mQSSettingsPanelOption = QSSettingsControllerKt.getQSSettingsPanelOption(); } @NonNull @@ -288,6 +297,10 @@ public abstract class QSTileImpl<TState extends State> implements QSTile, Lifecy } protected void handleLongClick() { + if (mQSSettingsPanelOption == QSSettingsPanel.USE_DETAIL) { + showDetail(true); + return; + } Dependency.get(ActivityStarter.class).postStartActivityDismissingKeyguard( getLongClickIntent(), 0); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/QSSettingsController.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/QSSettingsController.kt new file mode 100644 index 000000000000..c7ef0be508aa --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/QSSettingsController.kt @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.qs.tiles + +import android.provider.DeviceConfig +import com.android.internal.config.sysui.SystemUiDeviceConfigFlags + +enum class QSSettingsPanel { + DEFAULT, + OPEN_LONG_PRESS, + OPEN_CLICK, + USE_DETAIL +} + +fun getQSSettingsPanelOption(): QSSettingsPanel = + when (DeviceConfig.getInt(DeviceConfig.NAMESPACE_SYSTEMUI, + SystemUiDeviceConfigFlags.QS_USE_SETTINGS_PANELS, 0)) { + 1 -> QSSettingsPanel.OPEN_LONG_PRESS + 2 -> QSSettingsPanel.OPEN_CLICK + 3 -> QSSettingsPanel.USE_DETAIL + else -> QSSettingsPanel.DEFAULT + }
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java index 0e7362c3d081..b79b662a2bd7 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java @@ -56,6 +56,7 @@ import javax.inject.Inject; /** Quick settings tile: Wifi **/ public class WifiTile extends QSTileImpl<SignalState> { private static final Intent WIFI_SETTINGS = new Intent(Settings.ACTION_WIFI_SETTINGS); + private static final Intent WIFI_PANEL = new Intent(Settings.Panel.ACTION_WIFI); protected final NetworkController mController; private final AccessPointController mWifiController; @@ -112,11 +113,16 @@ public class WifiTile extends QSTileImpl<SignalState> { @Override public Intent getLongClickIntent() { - return WIFI_SETTINGS; + if (mQSSettingsPanelOption == QSSettingsPanel.OPEN_LONG_PRESS) return WIFI_PANEL; + else return WIFI_SETTINGS; } @Override protected void handleClick() { + if (mQSSettingsPanelOption == QSSettingsPanel.OPEN_CLICK) { + mActivityStarter.postStartActivityDismissingKeyguard(WIFI_PANEL, 0); + return; + } // Secondary clicks are header clicks, just toggle. mState.copyTo(mStateBeforeClick); boolean wifiEnabled = mState.value; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java index 2964889f1399..6f5fe8b629fb 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java @@ -31,6 +31,7 @@ import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BA import android.annotation.NonNull; import android.app.Notification; +import android.app.Notification.MessagingStyle.Message; import android.app.NotificationChannel; import android.app.NotificationManager.Policy; import android.app.Person; @@ -89,7 +90,6 @@ public final class NotificationEntry { public StatusBarNotification notification; private Ranking mRanking; - public NotificationChannel channel; public long lastAudiblyAlertedMs; public boolean noisy; public boolean ambient; @@ -243,7 +243,6 @@ public final class NotificationEntry { public void setRanking(@NonNull Ranking ranking) { mRanking = ranking; - channel = ranking.getChannel(); lastAudiblyAlertedMs = ranking.getLastAudiblyAlertedMillis(); importance = ranking.getImportance(); ambient = ranking.isAmbient(); @@ -259,6 +258,10 @@ public final class NotificationEntry { canBubble = ranking.canBubble(); } + public NotificationChannel getChannel() { + return mRanking.getChannel(); + } + public void setInterruption() { interruption = true; } @@ -545,21 +548,18 @@ public final class NotificationEntry { if (!ArrayUtils.isEmpty(replyTexts)) { return true; } - Parcelable[] messages = extras.getParcelableArray(Notification.EXTRA_MESSAGES); - if (messages != null && messages.length > 0) { - Parcelable message = messages[messages.length - 1]; - if (message instanceof Bundle) { - Notification.MessagingStyle.Message lastMessage = - Notification.MessagingStyle.Message.getMessageFromBundle( - (Bundle) message); - if (lastMessage != null) { - Person senderPerson = lastMessage.getSenderPerson(); - if (senderPerson == null) { - return true; - } - Person user = extras.getParcelable(Notification.EXTRA_MESSAGING_PERSON); - return Objects.equals(user, senderPerson); + List<Message> messages = Message.getMessagesFromBundleArray( + extras.getParcelableArray(Notification.EXTRA_MESSAGES)); + if (messages != null && !messages.isEmpty()) { + Message lastMessage = messages.get(messages.size() -1); + + if (lastMessage != null) { + Person senderPerson = lastMessage.getSenderPerson(); + if (senderPerson == null) { + return true; } + Person user = extras.getParcelable(Notification.EXTRA_MESSAGING_PERSON); + return Objects.equals(user, senderPerson); } } return false; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java index 12d537d3c646..0f6ce2153488 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java @@ -520,7 +520,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView public boolean getIsNonblockable() { boolean isNonblockable = Dependency.get(NotificationBlockingHelperManager.class) .isNonblockable(mStatusBarNotification.getPackageName(), - mEntry.channel.getId()); + mEntry.getChannel().getId()); // If the SystemNotifAsyncTask hasn't finished running or retrieved a value, we'll try once // again, but in-place on the main thread this time. This should rarely ever get called. @@ -532,13 +532,13 @@ public class ExpandableNotificationRow extends ActivatableNotificationView mEntry.mIsSystemNotification = isSystemNotification(mContext, mStatusBarNotification); } - isNonblockable |= mEntry.channel.isImportanceLockedByOEM(); - isNonblockable |= mEntry.channel.isImportanceLockedByCriticalDeviceFunction(); + isNonblockable |= mEntry.getChannel().isImportanceLockedByOEM(); + isNonblockable |= mEntry.getChannel().isImportanceLockedByCriticalDeviceFunction(); if (!isNonblockable && mEntry != null && mEntry.mIsSystemNotification != null) { if (mEntry.mIsSystemNotification) { - if (mEntry.channel != null - && !mEntry.channel.isBlockableSystem()) { + if (mEntry.getChannel() != null + && !mEntry.getChannel().isBlockableSystem()) { isNonblockable = true; } } @@ -2389,7 +2389,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView public ArraySet<NotificationChannel> getUniqueChannels() { ArraySet<NotificationChannel> channels = new ArraySet<>(); - channels.add(mEntry.channel); + channels.add(mEntry.getChannel()); // If this is a summary, then add in the children notification channels for the // same user and pkg. @@ -2398,7 +2398,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView final int numChildren = childrenRows.size(); for (int i = 0; i < numChildren; i++) { final ExpandableNotificationRow childRow = childrenRows.get(i); - final NotificationChannel childChannel = childRow.getEntry().channel; + final NotificationChannel childChannel = childRow.getEntry().getChannel(); final StatusBarNotification childSbn = childRow.getStatusBarNotification(); if (childSbn.getUser().equals(mStatusBarNotification.getUser()) && childSbn.getPackageName().equals(mStatusBarNotification.getPackageName())) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java index 8f7671a5dd96..3e8825d735da 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java @@ -316,7 +316,7 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx iNotificationManager, mVisualStabilityManager, packageName, - row.getEntry().channel, + row.getEntry().getChannel(), row.getUniqueChannels(), sbn, mCheckSaveListener, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NPVPluginManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NPVPluginManager.kt new file mode 100644 index 000000000000..7dcc2fcfe2b2 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NPVPluginManager.kt @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.phone + +import android.content.Context +import android.view.View +import android.widget.FrameLayout +import com.android.systemui.plugins.NPVPlugin +import com.android.systemui.plugins.PluginListener +import com.android.systemui.qs.TouchAnimator +import com.android.systemui.shared.plugins.PluginManager + +/** + * Manages the NPVPlugin view and state + * + * Abstracts NPVPlugin from NPV and helps animate on expansion and respond to changes in Config. + */ +class NPVPluginManager( + var parent: FrameLayout, + val pluginManager: PluginManager +) : PluginListener<NPVPlugin> { + + private var plugin: NPVPlugin? = null + private var animator = createAnimator() + + private fun createAnimator() = TouchAnimator.Builder() + .addFloat(parent, "alpha", 1f, 0f) + .addFloat(parent, "scaleY", 1f, 0f) + .build() + + init { + pluginManager.addPluginListener(NPVPlugin.ACTION, this, NPVPlugin::class.java, false) + parent.pivotY = 0f + } + + override fun onPluginConnected(plugin: NPVPlugin, pluginContext: Context) { + parent.removeAllViews() + plugin.attachToRoot(parent) + this.plugin = plugin + parent.visibility = View.VISIBLE + } + + fun changeVisibility(visibility: Int) { + parent.visibility = if (plugin != null) visibility else View.GONE + } + + fun destroy() { + plugin?.onDestroy() + pluginManager.removePluginListener(this) + } + + override fun onPluginDisconnected(plugin: NPVPlugin) { + if (this.plugin == plugin) { + this.plugin = null + parent.removeAllViews() + parent.visibility = View.GONE + } + } + + fun setListening(listening: Boolean) { + plugin?.setListening(listening) + } + + fun setExpansion(expansion: Float, headerTranslation: Float, heightDiff: Float) { + parent.setTranslationY(expansion * heightDiff + headerTranslation) + if (!expansion.isNaN()) animator.setPosition(expansion) + } + + fun replaceFrameLayout(newParent: FrameLayout) { + newParent.visibility = parent.visibility + parent.removeAllViews() + plugin?.attachToRoot(newParent) + parent = newParent + animator = createAnimator() + } + + fun getHeight() = if (plugin != null) parent.height else 0 +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java index 256c8e4e264f..f91b03ed087d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java @@ -393,6 +393,10 @@ public class NotificationPanelView extends PanelView implements private boolean mAllowExpandForSmallExpansion; private Runnable mExpandAfterLayoutRunnable; + private PluginManager mPluginManager; + private FrameLayout mPluginFrame; + private NPVPluginManager mNPVPluginManager; + @Inject public NotificationPanelView(@Named(VIEW_CONTEXT) Context context, AttributeSet attrs, InjectionInflationController injectionInflationController, @@ -400,7 +404,8 @@ public class NotificationPanelView extends PanelView implements PulseExpansionHandler pulseExpansionHandler, DynamicPrivacyController dynamicPrivacyController, KeyguardBypassController bypassController, - FalsingManager falsingManager) { + FalsingManager falsingManager, + PluginManager pluginManager) { super(context, attrs); setWillNotDraw(!DEBUG); mInjectionInflationController = injectionInflationController; @@ -431,6 +436,7 @@ public class NotificationPanelView extends PanelView implements }); mBottomAreaShadeAlphaAnimator.setDuration(160); mBottomAreaShadeAlphaAnimator.setInterpolator(Interpolators.ALPHA_OUT); + mPluginManager = pluginManager; } /** @@ -465,6 +471,9 @@ public class NotificationPanelView extends PanelView implements mKeyguardBottomArea = findViewById(R.id.keyguard_bottom_area); mQsNavbarScrim = findViewById(R.id.qs_navbar_scrim); mLastOrientation = getResources().getConfiguration().orientation; + mPluginFrame = findViewById(R.id.plugin_frame); + mNPVPluginManager = new NPVPluginManager(mPluginFrame, mPluginManager); + initBottomArea(); @@ -584,6 +593,19 @@ public class NotificationPanelView extends PanelView implements lp.gravity = panelGravity; mNotificationStackScroller.setLayoutParams(lp); } + int sideMargin = res.getDimensionPixelOffset(R.dimen.notification_side_paddings); + int topMargin = + res.getDimensionPixelOffset(com.android.internal.R.dimen.quick_qs_total_height); + lp = (FrameLayout.LayoutParams) mPluginFrame.getLayoutParams(); + if (lp.width != qsWidth || lp.gravity != panelGravity || lp.leftMargin != sideMargin + || lp.rightMargin != sideMargin || lp.topMargin != topMargin) { + lp.width = qsWidth; + lp.gravity = panelGravity; + lp.leftMargin = sideMargin; + lp.rightMargin = sideMargin; + lp.topMargin = topMargin; + mPluginFrame.setLayoutParams(lp); + } } @Override @@ -650,6 +672,43 @@ public class NotificationPanelView extends PanelView implements if (mOnReinflationListener != null) { mOnReinflationListener.run(); } + reinflatePluginContainer(); + } + + @Override + public void onUiModeChanged() { + reinflatePluginContainer(); + } + + private void reinflatePluginContainer() { + int index = indexOfChild(mPluginFrame); + removeView(mPluginFrame); + mPluginFrame = (FrameLayout) mInjectionInflationController + .injectable(LayoutInflater.from(mContext)).inflate( + R.layout.status_bar_expanded_plugin_frame, + this, + false); + addView(mPluginFrame, index); + + Resources res = getResources(); + int qsWidth = res.getDimensionPixelSize(R.dimen.qs_panel_width); + int panelGravity = getResources().getInteger(R.integer.notification_panel_layout_gravity); + FrameLayout.LayoutParams lp; + int sideMargin = res.getDimensionPixelOffset(R.dimen.notification_side_paddings); + int topMargin = + res.getDimensionPixelOffset(com.android.internal.R.dimen.quick_qs_total_height); + lp = (FrameLayout.LayoutParams) mPluginFrame.getLayoutParams(); + if (lp.width != qsWidth || lp.gravity != panelGravity || lp.leftMargin != sideMargin + || lp.rightMargin != sideMargin || lp.topMargin != topMargin) { + lp.width = qsWidth; + lp.gravity = panelGravity; + lp.leftMargin = sideMargin; + lp.rightMargin = sideMargin; + lp.topMargin = topMargin; + mPluginFrame.setLayoutParams(lp); + } + + mNPVPluginManager.replaceFrameLayout(mPluginFrame); } private void initBottomArea() { @@ -679,6 +738,7 @@ public class NotificationPanelView extends PanelView implements int oldMaxHeight = mQsMaxExpansionHeight; if (mQs != null) { mQsMinExpansionHeight = mKeyguardShowing ? 0 : mQs.getQsMinExpansionHeight(); + mQsMinExpansionHeight += mNPVPluginManager.getHeight(); mQsMaxExpansionHeight = mQs.getDesiredHeight(); mNotificationStackScroller.setMaxTopPadding( mQsMaxExpansionHeight + mQsNotificationTopPadding); @@ -1784,6 +1844,9 @@ public class NotificationPanelView extends PanelView implements mBarState != StatusBarState.KEYGUARD && (!mQsExpanded || mQsExpansionFromOverscroll)); updateEmptyShadeView(); + mNPVPluginManager.changeVisibility((mBarState != StatusBarState.KEYGUARD) + ? View.VISIBLE + : View.INVISIBLE); mQsNavbarScrim.setVisibility(mBarState == StatusBarState.SHADE && mQsExpanded && !mStackScrollerOverscrolling && mQsScrimEnabled ? View.VISIBLE @@ -1840,6 +1903,8 @@ public class NotificationPanelView extends PanelView implements if (mQs == null) return; float qsExpansionFraction = getQsExpansionFraction(); mQs.setQsExpansion(qsExpansionFraction, getHeaderTranslation()); + int heightDiff = mQs.getDesiredHeight() - mQs.getQsMinExpansionHeight(); + mNPVPluginManager.setExpansion(qsExpansionFraction, getHeaderTranslation(), heightDiff); mNotificationStackScroller.setQsExpansionFraction(qsExpansionFraction); } @@ -2260,6 +2325,7 @@ public class NotificationPanelView extends PanelView implements appearAmount = mNotificationStackScroller.calculateAppearFractionBypass(); } startHeight = -mQs.getQsMinExpansionHeight(); + startHeight -= mNPVPluginManager.getHeight(); } float translation = MathUtils.lerp(startHeight, 0, Math.min(1.0f, appearAmount)) @@ -2400,6 +2466,7 @@ public class NotificationPanelView extends PanelView implements mKeyguardStatusBar.setListening(listening); if (mQs == null) return; mQs.setListening(listening); + mNPVPluginManager.setListening(listening); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index fe96ef764875..6b12c6158948 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -1263,7 +1263,7 @@ public class StatusBar extends SystemUI implements DemoMode, mStatusBarKeyguardViewManager = keyguardViewMediator.registerStatusBar(this, getBouncerContainer(), mNotificationPanel, mBiometricUnlockController, mStatusBarWindow.findViewById(R.id.lock_icon_container), mStackScroller, - mKeyguardBypassController, mFalsingManager); + mKeyguardBypassController); mKeyguardIndicationController .setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager); mBiometricUnlockController.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager); diff --git a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java index 94ca9e9c9b51..819a7f6fde1a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java +++ b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java @@ -29,6 +29,7 @@ import android.util.Log; import androidx.test.InstrumentationRegistry; +import com.android.keyguard.KeyguardUpdateMonitor; import com.android.systemui.classifier.FalsingManagerFake; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.util.Assert; @@ -78,6 +79,7 @@ public abstract class SysuiTestCase { // A lot of tests get the FalsingManager, often via several layers of indirection. // None of them actually need it. mDependency.injectTestDependency(FalsingManager.class, new FalsingManagerFake()); + mDependency.injectMockDependency(KeyguardUpdateMonitor.class); } @After diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFaceViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFaceViewTest.java index 128e819ccedd..b907cdb54bbf 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFaceViewTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFaceViewTest.java @@ -63,7 +63,7 @@ public class AuthBiometricFaceViewTest extends SysuiTestCase { mFaceView.mNegativeButton = mNegativeButton; mFaceView.mPositiveButton = mPositiveButton; mFaceView.mTryAgainButton = mTryAgainButton; - mFaceView.mErrorView = mErrorView; + mFaceView.mIndicatorView = mErrorView; } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricViewTest.java index ffcb293ba398..fc1870738375 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricViewTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricViewTest.java @@ -17,12 +17,15 @@ package com.android.systemui.biometrics; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import android.content.Context; +import android.hardware.biometrics.BiometricPrompt; +import android.os.Bundle; import android.test.suitebuilder.annotation.SmallTest; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper.RunWithLooper; @@ -55,10 +58,10 @@ public class AuthBiometricViewTest extends SysuiTestCase { @Mock private TextView mTitleView; @Mock private TextView mSubtitleView; @Mock private TextView mDescriptionView; - @Mock private TextView mErrorView; + @Mock private TextView mIndicatorView; @Mock private ImageView mIconView; - TestableBiometricView mBiometricView; + private TestableBiometricView mBiometricView; @Before public void setup() { @@ -87,8 +90,8 @@ public class AuthBiometricViewTest extends SysuiTestCase { verify(mCallback, never()).onAction(anyInt()); verify(mBiometricView.mNegativeButton).setText(eq(R.string.cancel)); verify(mBiometricView.mPositiveButton).setEnabled(eq(true)); - verify(mErrorView).setText(eq(R.string.biometric_dialog_tap_confirm)); - verify(mErrorView).setVisibility(eq(View.VISIBLE)); + verify(mIndicatorView).setText(eq(R.string.biometric_dialog_tap_confirm)); + verify(mIndicatorView).setVisibility(eq(View.VISIBLE)); } @Test @@ -193,11 +196,88 @@ public class AuthBiometricViewTest extends SysuiTestCase { verify(mCallback, never()).onAction(eq(AuthBiometricView.Callback.ACTION_USER_CANCELED)); } + @Test + public void testRestoresState() { + final boolean requireConfirmation = true; // set/init from AuthController + + Button tryAgainButton = new Button(mContext); + TextView indicatorView = new TextView(mContext); + initDialog(mContext, mCallback, new MockInjector() { + @Override + public Button getTryAgainButton() { + return tryAgainButton; + } + @Override + public TextView getIndicatorView() { + return indicatorView; + } + }); + + final String failureMessage = "testFailureMessage"; + mBiometricView.setRequireConfirmation(requireConfirmation); + mBiometricView.onAuthenticationFailed(failureMessage); + waitForIdleSync(); + + Bundle state = new Bundle(); + mBiometricView.onSaveState(state); + + assertEquals(View.VISIBLE, tryAgainButton.getVisibility()); + assertEquals(View.VISIBLE, state.getInt(AuthDialog.KEY_BIOMETRIC_TRY_AGAIN_VISIBILITY)); + + assertEquals(AuthBiometricView.STATE_ERROR, mBiometricView.mState); + assertEquals(AuthBiometricView.STATE_ERROR, state.getInt(AuthDialog.KEY_BIOMETRIC_STATE)); + + assertEquals(View.VISIBLE, mBiometricView.mIndicatorView.getVisibility()); + assertTrue(state.getBoolean(AuthDialog.KEY_BIOMETRIC_INDICATOR_ERROR_SHOWING)); + + assertEquals(failureMessage, mBiometricView.mIndicatorView.getText()); + assertEquals(failureMessage, state.getString(AuthDialog.KEY_BIOMETRIC_INDICATOR_STRING)); + + // TODO: Test dialog size. Should move requireConfirmation to buildBiometricPromptBundle + + // Create new dialog and restore the previous state into it + Button tryAgainButton2 = new Button(mContext); + TextView indicatorView2 = new TextView(mContext); + initDialog(mContext, mCallback, state, new MockInjector() { + @Override + public Button getTryAgainButton() { + return tryAgainButton2; + } + @Override + public TextView getIndicatorView() { + return indicatorView2; + } + }); + mBiometricView.setRequireConfirmation(requireConfirmation); + waitForIdleSync(); + + // Test restored state + assertEquals(View.VISIBLE, tryAgainButton.getVisibility()); + assertEquals(AuthBiometricView.STATE_ERROR, mBiometricView.mState); + assertEquals(View.VISIBLE, mBiometricView.mIndicatorView.getVisibility()); + assertEquals(failureMessage, mBiometricView.mIndicatorView.getText()); + } + + private Bundle buildBiometricPromptBundle() { + Bundle bundle = new Bundle(); + bundle.putCharSequence(BiometricPrompt.KEY_TITLE, "Title"); + bundle.putCharSequence(BiometricPrompt.KEY_NEGATIVE_TEXT, "Negative"); + return bundle; + } + private void initDialog(Context context, AuthBiometricView.Callback callback, - MockInjector injector) { + Bundle savedState, MockInjector injector) { mBiometricView = new TestableBiometricView(context, null, injector); + mBiometricView.setBiometricPromptBundle(buildBiometricPromptBundle()); mBiometricView.setCallback(callback); - mBiometricView.initializeViews(); + mBiometricView.restoreState(savedState); + mBiometricView.onFinishInflateInternal(); + mBiometricView.onAttachedToWindowInternal(); + } + + private void initDialog(Context context, AuthBiometricView.Callback callback, + MockInjector injector) { + initDialog(context, callback, null /* savedState */, injector); } private class MockInjector extends AuthBiometricView.Injector { @@ -232,8 +312,8 @@ public class AuthBiometricViewTest extends SysuiTestCase { } @Override - public TextView getErrorView() { - return mErrorView; + public TextView getIndicatorView() { + return mIndicatorView; } @Override diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java index a5e468e0545d..eb7be4fa6332 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java @@ -147,7 +147,7 @@ public class AuthControllerTest extends SysuiTestCase { public void testShowInvoked_whenSystemRequested() throws Exception { showDialog(BiometricPrompt.TYPE_FACE); - verify(mDialog1).show(any()); + verify(mDialog1).show(any(), any()); } @Test @@ -215,7 +215,7 @@ public class AuthControllerTest extends SysuiTestCase { @Test public void testShowNewDialog_beforeOldDialogDismissed_SkipsAnimations() throws Exception { showDialog(BiometricPrompt.TYPE_FACE); - verify(mDialog1).show(any()); + verify(mDialog1).show(any(), any()); showDialog(BiometricPrompt.TYPE_FACE); @@ -223,13 +223,13 @@ public class AuthControllerTest extends SysuiTestCase { verify(mDialog1).dismissWithoutCallback(eq(false) /* animate */); // Second dialog should be shown without animation - verify(mDialog2).show(any()); + verify(mDialog2).show(any(), any()); } @Test public void testConfigurationPersists_whenOnConfigurationChanged() throws Exception { showDialog(BiometricPrompt.TYPE_FACE); - verify(mDialog1).show(any()); + verify(mDialog1).show(any(), any()); mBiometricDialogImpl.onConfigurationChanged(new Configuration()); @@ -241,10 +241,7 @@ public class AuthControllerTest extends SysuiTestCase { // Saved state is restored into new dialog ArgumentCaptor<Bundle> captor2 = ArgumentCaptor.forClass(Bundle.class); - verify(mDialog2).restoreState(captor2.capture()); - - // Dialog for new configuration skips intro - verify(mDialog2).show(any()); + verify(mDialog2).show(any(), captor2.capture()); // TODO: This should check all values we want to save/restore assertEquals(captor.getValue(), captor2.getValue()); diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java index ba434d4fd0bd..448c80ef3c57 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java @@ -71,8 +71,8 @@ import com.android.systemui.statusbar.notification.collection.NotificationData; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.phone.DozeParameters; -import com.android.systemui.statusbar.phone.NotificationGroupManager; import com.android.systemui.statusbar.phone.KeyguardBypassController; +import com.android.systemui.statusbar.phone.NotificationGroupManager; import com.android.systemui.statusbar.phone.StatusBarWindowController; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.HeadsUpManager; @@ -165,7 +165,8 @@ public class BubbleControllerTest extends SysuiTestCase { // Return non-null notification data from the NEM when(mNotificationEntryManager.getNotificationData()).thenReturn(mNotificationData); when(mNotificationData.get(mRow.getEntry().key)).thenReturn(mRow.getEntry()); - when(mNotificationData.getChannel(mRow.getEntry().key)).thenReturn(mRow.getEntry().channel); + when(mNotificationData.getChannel(mRow.getEntry().key)).thenReturn( + mRow.getEntry().getChannel()); mZenModeConfig.suppressedVisualEffects = 0; when(mZenModeController.getConfig()).thenReturn(mZenModeConfig); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java index 264a5400f1a5..7cd58193a3e7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java @@ -306,12 +306,21 @@ public class NotificationTestHelper { userHandle, null /* overrideGroupKey */, System.currentTimeMillis()); - NotificationEntry entry = NotificationEntry.buildForTest(sbn); + final NotificationChannel channel = + new NotificationChannel( + notification.getChannelId(), + notification.getChannelId(), + importance); + channel.setBlockableSystem(true); + + NotificationEntry entry = new NotificationEntry( + sbn, + new RankingBuilder() + .setKey(sbn.getKey()) + .setChannel(channel) + .build()); entry.setRow(row); entry.createIcons(mContext, sbn); - entry.channel = new NotificationChannel( - notification.getChannelId(), notification.getChannelId(), importance); - entry.channel.setBlockableSystem(true); row.setEntry(entry); row.getNotificationInflater().addInflationFlags(extraInflationFlags); NotificationContentInflaterTest.runThenWaitForInflation( diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/RankingBuilder.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/RankingBuilder.java new file mode 100644 index 000000000000..bbdc4b7fc360 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/RankingBuilder.java @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar; + +import android.app.Notification; +import android.app.NotificationChannel; +import android.service.notification.NotificationListenerService.Ranking; +import android.service.notification.SnoozeCriterion; + +import java.util.ArrayList; + +/** + * Standard builder class for Ranking objects. For use in tests that need to craft the underlying + * Ranking object of a NotificationEntry. + */ +public class RankingBuilder { + private String mKey = "test_key"; + private int mRank = 0; + private boolean mMatchesInterruptionFilter = false; + private int mVisibilityOverride = 0; + private int mSuppressedVisualEffects = 0; + private int mImportance = 0; + private CharSequence mExplanation = "test_explanation"; + private String mOverrideGroupKey = null; + private NotificationChannel mChannel = null; + private ArrayList<String> mOverridePeople = null; + private ArrayList<SnoozeCriterion> mSnoozeCriteria = null; + private boolean mShowBadge = false; + private int mUserSentiment = 0; + private boolean mHidden = false; + private long mLastAudiblyAlertedMs = 0; + private boolean mNoisy = false; + private ArrayList<Notification.Action> mSmartActions = null; + private ArrayList<CharSequence> mSmartReplies = null; + private boolean mCanBubble = false; + + public RankingBuilder setKey(String key) { + mKey = key; + return this; + } + + public RankingBuilder setImportance(int importance) { + mImportance = importance; + return this; + } + + public RankingBuilder setUserSentiment(int userSentiment) { + mUserSentiment = userSentiment; + return this; + } + + public RankingBuilder setChannel(NotificationChannel channel) { + mChannel = channel; + return this; + } + + public RankingBuilder setSmartActions(ArrayList<Notification.Action> smartActions) { + mSmartActions = smartActions; + return this; + } + + public RankingBuilder setSmartReplies(ArrayList<CharSequence> smartReplies) { + mSmartReplies = smartReplies; + return this; + } + + public Ranking build() { + final Ranking ranking = new Ranking(); + ranking.populate( + mKey, + mRank, + mMatchesInterruptionFilter, + mVisibilityOverride, + mSuppressedVisualEffects, + mImportance, + mExplanation, + mOverrideGroupKey, + mChannel, + mOverridePeople, + mSnoozeCriteria, + mShowBadge, + mUserSentiment, + mHidden, + mLastAudiblyAlertedMs, + mNoisy, + mSmartActions, + mSmartReplies, + mCanBubble); + return ranking; + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationDataTest.java index ed719d99a980..45173a2ef797 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationDataTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationDataTest.java @@ -145,7 +145,7 @@ public class NotificationDataTest extends SysuiTestCase { override.putParcelable(OVERRIDE_CHANNEL, NOTIFICATION_CHANNEL); mNotificationData.rankingOverrides.put(mRow.getEntry().key, override); mNotificationData.add(mRow.getEntry()); - assertEquals(NOTIFICATION_CHANNEL, mRow.getEntry().channel); + assertEquals(NOTIFICATION_CHANNEL, mRow.getEntry().getChannel()); } @Test @@ -343,7 +343,7 @@ public class NotificationDataTest extends SysuiTestCase { new NotificationEntry(mMockStatusBarNotification, ranking); assertEquals(systemGeneratedSmartActions, entry.systemGeneratedSmartActions); - assertEquals(NOTIFICATION_CHANNEL, entry.channel); + assertEquals(NOTIFICATION_CHANNEL, entry.getChannel()); assertEquals(Ranking.USER_SENTIMENT_NEGATIVE, entry.userSentiment); assertEquals(snoozeCriterions, entry.snoozeCriteria); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java index d526d104630e..a14557bd9684 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java @@ -51,6 +51,7 @@ import com.android.systemui.SysuiTestCase; import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.NotificationTestHelper; +import com.android.systemui.statusbar.RankingBuilder; import com.android.systemui.statusbar.notification.AboveShelfChangedListener; import com.android.systemui.statusbar.notification.stack.NotificationChildrenContainer; @@ -327,8 +328,11 @@ public class ExpandableNotificationRowTest extends SysuiTestCase { // Give each child a unique channel id/name. int i = 0; for (ExpandableNotificationRow childRow : childRows) { - childRow.getEntry().channel = - new NotificationChannel("id" + i, "dinnertime" + i, IMPORTANCE_DEFAULT); + childRow.getEntry().setRanking(new RankingBuilder() + .setChannel( + new NotificationChannel( + "id" + i, "dinnertime" + i, IMPORTANCE_DEFAULT)) + .build()); i++; } @@ -364,7 +368,7 @@ public class ExpandableNotificationRowTest extends SysuiTestCase { public void testGetIsNonblockable_oemLocked() throws Exception { ExpandableNotificationRow row = mNotificationTestHelper.createRow(mNotificationTestHelper.createNotification()); - row.getEntry().channel.setImportanceLockedByOEM(true); + row.getEntry().getChannel().setImportanceLockedByOEM(true); assertTrue(row.getIsNonblockable()); } @@ -373,7 +377,7 @@ public class ExpandableNotificationRowTest extends SysuiTestCase { public void testGetIsNonblockable_criticalDeviceFunction() throws Exception { ExpandableNotificationRow row = mNotificationTestHelper.createRow(mNotificationTestHelper.createNotification()); - row.getEntry().channel.setImportanceLockedByCriticalDeviceFunction(true); + row.getEntry().getChannel().setImportanceLockedByCriticalDeviceFunction(true); assertTrue(row.getIsNonblockable()); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManagerTest.java index 3c91b3f1bdd3..a26cdbd30b47 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManagerTest.java @@ -41,8 +41,10 @@ import androidx.test.filters.FlakyTest; import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; +import com.android.systemui.bubbles.BubbleController; import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin; import com.android.systemui.statusbar.NotificationTestHelper; +import com.android.systemui.statusbar.RankingBuilder; import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.util.Assert; @@ -73,6 +75,7 @@ public class NotificationBlockingHelperManagerTest extends SysuiTestCase { public void setUp() { Assert.sMainLooper = TestableLooper.get(this).getLooper(); MockitoAnnotations.initMocks(this); + mDependency.injectMockDependency(BubbleController.class); when(mGutsManager.openGuts( any(View.class), anyInt(), @@ -82,6 +85,7 @@ public class NotificationBlockingHelperManagerTest extends SysuiTestCase { when(mMenuRow.getLongpressMenuItem(any(Context.class))).thenReturn(mMenuItem); mDependency.injectTestDependency(NotificationGutsManager.class, mGutsManager); mDependency.injectTestDependency(NotificationEntryManager.class, mEntryManager); + mDependency.injectMockDependency(BubbleController.class); mHelper = new NotificationTestHelper(mContext); @@ -138,8 +142,11 @@ public class NotificationBlockingHelperManagerTest extends SysuiTestCase { ExpandableNotificationRow groupRow = createBlockableGroupRowSpy(10); int i = 0; for (ExpandableNotificationRow childRow : groupRow.getNotificationChildren()) { - childRow.getEntry().channel = - new NotificationChannel(Integer.toString(i++), "", IMPORTANCE_DEFAULT); + childRow.getEntry().setRanking(new RankingBuilder() + .setChannel( + new NotificationChannel( + Integer.toString(i++), "", IMPORTANCE_DEFAULT)) + .build()); } groupRow.getEntry().userSentiment = USER_SENTIMENT_NEGATIVE; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java index 795948470295..09c4179185fc 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java @@ -62,6 +62,7 @@ import com.android.systemui.SysuiTestCase; import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin; import com.android.systemui.statusbar.NotificationPresenter; import com.android.systemui.statusbar.NotificationTestHelper; +import com.android.systemui.statusbar.RankingBuilder; import com.android.systemui.statusbar.notification.NotificationActivityStarter; import com.android.systemui.statusbar.notification.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; @@ -498,7 +499,10 @@ public class NotificationGutsManagerTest extends SysuiTestCase { try { ExpandableNotificationRow row = mHelper.createRow(nb.build()); - row.getEntry().channel = mTestNotificationChannel; + row.getEntry().setRanking( + new RankingBuilder() + .setChannel(mTestNotificationChannel) + .build()); return row; } catch (Exception e) { fail(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationMenuRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationMenuRowTest.java index 98e1692c2368..096acf9d9ce4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationMenuRowTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationMenuRowTest.java @@ -40,6 +40,7 @@ import android.view.ViewGroup; import androidx.test.filters.SmallTest; import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin; +import com.android.systemui.statusbar.RankingBuilder; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.utils.leaks.LeakCheckedTest; @@ -60,9 +61,11 @@ public class NotificationMenuRowTest extends LeakCheckedTest { public void setup() { injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES); mRow = mock(ExpandableNotificationRow.class); - NotificationEntry entry = NotificationEntry.buildForTest( - mock(StatusBarNotification.class)); - entry.channel = mock(NotificationChannel.class); + NotificationEntry entry = new NotificationEntry( + mock(StatusBarNotification.class), + new RankingBuilder() + .setChannel(mock(NotificationChannel.class)) + .build()); when(mRow.getEntry()).thenReturn(entry); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java index a96efd7d2fc2..86ab3a70c3ac 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java @@ -38,6 +38,7 @@ import com.android.systemui.SystemUIFactory; import com.android.systemui.SysuiTestCase; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.statusbar.StatusBarStateController; +import com.android.systemui.shared.plugins.PluginManager; import com.android.systemui.statusbar.KeyguardAffordanceView; import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.NotificationShelf; @@ -195,7 +196,7 @@ public class NotificationPanelViewTest extends SysuiTestCase { SystemUIFactory.getInstance().getRootComponent()), coordinator, expansionHandler, mock(DynamicPrivacyController.class), bypassController, - mFalsingManager); + mFalsingManager, mock(PluginManager.class)); mNotificationStackScroller = mNotificationStackScrollLayout; mKeyguardStatusView = NotificationPanelViewTest.this.mKeyguardStatusView; mKeyguardStatusBar = NotificationPanelViewTest.this.mKeyguardStatusBar; diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ru/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ru/strings.xml index 0ff85fe39c99..dc77981e6c95 100644 --- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ru/strings.xml +++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ru/strings.xml @@ -17,5 +17,5 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"В правом углу"</string> + <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Сделать вырез в углу"</string> </resources> diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ru/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ru/strings.xml index 2493da34af1f..a02eaf7bdc26 100644 --- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ru/strings.xml +++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ru/strings.xml @@ -17,5 +17,5 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Сверху и снизу"</string> + <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Увеличить вырез вдвое"</string> </resources> diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ru/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ru/strings.xml index 89ac1c3e1b11..1d1656d2862e 100644 --- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ru/strings.xml +++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ru/strings.xml @@ -17,5 +17,5 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Сверху"</string> + <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Сделать вырез выше"</string> </resources> diff --git a/services/accessibility/java/com/android/server/accessibility/GlobalActionPerformer.java b/services/accessibility/java/com/android/server/accessibility/GlobalActionPerformer.java index 672518cc17ed..b9b2654b93cc 100644 --- a/services/accessibility/java/com/android/server/accessibility/GlobalActionPerformer.java +++ b/services/accessibility/java/com/android/server/accessibility/GlobalActionPerformer.java @@ -24,10 +24,7 @@ import android.os.Binder; import android.os.Handler; import android.os.Looper; import android.os.PowerManager; -import android.os.RemoteException; -import android.os.ServiceManager; import android.os.SystemClock; -import android.view.IWindowManager; import android.view.InputDevice; import android.view.KeyCharacterMap; import android.view.KeyEvent; @@ -191,7 +188,7 @@ public class GlobalActionPerformer { ScreenshotHelper screenshotHelper = (mScreenshotHelperSupplier != null) ? mScreenshotHelperSupplier.get() : new ScreenshotHelper(mContext); screenshotHelper.takeScreenshot(android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN, - true, true, new Handler(Looper.getMainLooper())); + true, true, new Handler(Looper.getMainLooper()), null); return true; } } diff --git a/services/core/java/com/android/server/PackageWatchdog.java b/services/core/java/com/android/server/PackageWatchdog.java index e194f721b8d2..5672a13991d8 100644 --- a/services/core/java/com/android/server/PackageWatchdog.java +++ b/services/core/java/com/android/server/PackageWatchdog.java @@ -284,28 +284,6 @@ public class PackageWatchdog { } /** - * Returns packages observed by {@code observer} - * - * @return an empty set if {@code observer} has some packages observerd from a previous boot - * but has not registered itself in the current boot to receive notifications. Returns null - * if there are no active packages monitored from any boot. - */ - @Nullable - public Set<String> getPackages(PackageHealthObserver observer) { - synchronized (mLock) { - for (int i = 0; i < mAllObservers.size(); i++) { - if (observer.getName().equals(mAllObservers.keyAt(i))) { - if (observer.equals(mAllObservers.valueAt(i).mRegisteredObserver)) { - return mAllObservers.valueAt(i).mPackages.keySet(); - } - return Collections.emptySet(); - } - } - } - return null; - } - - /** * Called when a process fails either due to a crash or ANR. * * <p>For each package contained in the process, one registered observer with the least user diff --git a/services/core/java/com/android/server/SystemService.java b/services/core/java/com/android/server/SystemService.java index 4151c7269934..5e659b64dbbe 100644 --- a/services/core/java/com/android/server/SystemService.java +++ b/services/core/java/com/android/server/SystemService.java @@ -168,7 +168,7 @@ public abstract class SystemService { * calls this method). */ @Deprecated - public void onStartUser(@UserIdInt int userHandle) {} + public void onStartUser(@UserIdInt int userId) {} /** * Called when a new user is starting, for system services to initialize any per-user @@ -189,7 +189,7 @@ public abstract class SystemService { * default calls this method). */ @Deprecated - public void onUnlockUser(@UserIdInt int userHandle) {} + public void onUnlockUser(@UserIdInt int userId) {} /** * Called when an existing user is in the process of being unlocked. This @@ -218,7 +218,7 @@ public abstract class SystemService { * (which by default calls this method). */ @Deprecated - public void onSwitchUser(@UserIdInt int userHandle) {} + public void onSwitchUser(@UserIdInt int userId) {} /** * Called when switching to a different foreground user, for system services that have @@ -243,7 +243,7 @@ public abstract class SystemService { * calls this method). */ @Deprecated - public void onStopUser(@UserIdInt int userHandle) {} + public void onStopUser(@UserIdInt int userId) {} /** * Called when an existing user is stopping, for system services to finalize any per-user @@ -268,7 +268,7 @@ public abstract class SystemService { * default calls this method). */ @Deprecated - public void onCleanupUser(@UserIdInt int userHandle) {} + public void onCleanupUser(@UserIdInt int userId) {} /** * Called when an existing user is stopping, for system services to finalize any per-user diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 9b1eb3a62185..09bfb7a1adca 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -6098,16 +6098,16 @@ public class ActivityManagerService extends IActivityManager.Stub return ptw != null ? ptw.tag : null; } - private ProviderInfo getProviderInfoLocked(String authority, int userHandle, int pmFlags) { + private ProviderInfo getProviderInfoLocked(String authority, @UserIdInt int userId, + int pmFlags) { ProviderInfo pi = null; - ContentProviderRecord cpr = mProviderMap.getProviderByName(authority, userHandle); + ContentProviderRecord cpr = mProviderMap.getProviderByName(authority, userId); if (cpr != null) { pi = cpr.info; } else { try { pi = AppGlobals.getPackageManager().resolveContentProvider( - authority, PackageManager.GET_URI_PERMISSION_PATTERNS | pmFlags, - userHandle); + authority, PackageManager.GET_URI_PERMISSION_PATTERNS | pmFlags, userId); } catch (RemoteException ex) { } } @@ -6324,13 +6324,6 @@ public class ActivityManagerService extends IActivityManager.Stub } @Override - public void resizeStack(int stackId, Rect destBounds, boolean allowResizeInDockedMode, - boolean preserveWindows, boolean animate, int animationDuration) { - mActivityTaskManager.resizeStack(stackId, destBounds, allowResizeInDockedMode, - preserveWindows, animate, animationDuration); - } - - @Override public ParceledListSlice<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum, int flags, int userId) { return mActivityTaskManager.getRecentTasks(maxNum, flags, userId); @@ -9170,7 +9163,16 @@ public class ActivityManagerService extends IActivityManager.Stub Integer.toString(currentUserId), currentUserId); mBatteryStatsService.noteEvent(BatteryStats.HistoryItem.EVENT_USER_FOREGROUND_START, Integer.toString(currentUserId), currentUserId); - mSystemServiceManager.startUser(t, currentUserId); + + // On Automotive, at this point the system user has already been started and unlocked, + // and some of the tasks we do here have already been done. So skip those in that case. + // TODO(b/132262830): this workdound shouldn't be necessary once we move the + // headless-user start logic to UserManager-land + final boolean bootingSystemUser = currentUserId == UserHandle.USER_SYSTEM; + + if (bootingSystemUser) { + mSystemServiceManager.startUser(t, currentUserId); + } synchronized (this) { // Only start up encryption-aware persistent apps; once user is @@ -9199,12 +9201,6 @@ public class ActivityManagerService extends IActivityManager.Stub t.traceEnd(); } - // On Automotive, at this point the system user has already been started and unlocked, - // and some of the tasks we do here have already been done. So skip those in that case. - // TODO(b/132262830): this workdound shouldn't be necessary once we move the - // headless-user start logic to UserManager-land - final boolean bootingSystemUser = currentUserId == UserHandle.USER_SYSTEM; - if (bootingSystemUser) { t.traceBegin("startHomeOnAllDisplays"); mAtmInternal.startHomeOnAllDisplays(currentUserId, "systemReady"); @@ -15345,11 +15341,11 @@ public class ActivityManagerService extends IActivityManager.Stub intent.getAction()); final String[] packageNames = intent.getStringArrayExtra( Intent.EXTRA_CHANGED_PACKAGE_LIST); - final int userHandle = intent.getIntExtra( + final int userIdExtra = intent.getIntExtra( Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL); mAtmInternal.onPackagesSuspendedChanged(packageNames, suspended, - userHandle); + userIdExtra); break; } break; @@ -18068,7 +18064,7 @@ public class ActivityManagerService extends IActivityManager.Stub } @Override - public void killForegroundAppsForUser(int userHandle) { + public void killForegroundAppsForUser(@UserIdInt int userId) { synchronized (ActivityManagerService.this) { final ArrayList<ProcessRecord> procs = new ArrayList<>(); final int NP = mProcessList.mProcessNames.getMap().size(); @@ -18083,7 +18079,7 @@ public class ActivityManagerService extends IActivityManager.Stub continue; } if (app.removed - || (app.userId == userHandle && app.hasForegroundActivities())) { + || (app.userId == userId && app.hasForegroundActivities())) { procs.add(app); } } diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java index 8b8c40e1346b..d46c62662faf 100644 --- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java +++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java @@ -2481,8 +2481,6 @@ final class ActivityManagerShellCommand extends ShellCommand { switch (op) { case "move-task": return runStackMoveTask(pw); - case "resize": - return runStackResize(pw); case "resize-animated": return runStackResizeAnimated(pw); case "resize-docked-stack": @@ -2561,17 +2559,6 @@ final class ActivityManagerShellCommand extends ShellCommand { return 0; } - int runStackResize(PrintWriter pw) throws RemoteException { - String stackIdStr = getNextArgRequired(); - int stackId = Integer.parseInt(stackIdStr); - final Rect bounds = getBounds(); - if (bounds == null) { - getErrPrintWriter().println("Error: invalid input bounds"); - return -1; - } - return resizeStack(stackId, bounds, 0); - } - int runStackResizeAnimated(PrintWriter pw) throws RemoteException { String stackIdStr = getNextArgRequired(); int stackId = Integer.parseInt(stackIdStr); @@ -2585,16 +2572,7 @@ final class ActivityManagerShellCommand extends ShellCommand { return -1; } } - return resizeStackUnchecked(stackId, bounds, 0, true); - } - - int resizeStackUnchecked(int stackId, Rect bounds, int delayMs, boolean animate) - throws RemoteException { - try { - mTaskInterface.resizeStack(stackId, bounds, false, false, animate, -1); - Thread.sleep(delayMs); - } catch (InterruptedException e) { - } + mTaskInterface.animateResizePinnedStack(stackId, bounds, -1); return 0; } @@ -2609,14 +2587,6 @@ final class ActivityManagerShellCommand extends ShellCommand { return 0; } - int resizeStack(int stackId, Rect bounds, int delayMs) throws RemoteException { - if (bounds == null) { - getErrPrintWriter().println("Error: invalid input bounds"); - return -1; - } - return resizeStackUnchecked(stackId, bounds, delayMs, false); - } - int runStackPositionTask(PrintWriter pw) throws RemoteException { String taskIdStr = getNextArgRequired(); int taskId = Integer.parseInt(taskIdStr); @@ -3195,8 +3165,6 @@ final class ActivityManagerShellCommand extends ShellCommand { pw.println(" move-task <TASK_ID> <STACK_ID> [true|false]"); pw.println(" Move <TASK_ID> from its current stack to the top (true) or"); pw.println(" bottom (false) of <STACK_ID>."); - pw.println(" resize <STACK_ID> <LEFT,TOP,RIGHT,BOTTOM>"); - pw.println(" Change <STACK_ID> size and position to <LEFT,TOP,RIGHT,BOTTOM>."); pw.println(" resize-animated <STACK_ID> <LEFT,TOP,RIGHT,BOTTOM>"); pw.println(" Same as resize, but allow animation."); pw.println(" resize-docked-stack <LEFT,TOP,RIGHT,BOTTOM> [<TASK_LEFT,TASK_TOP,TASK_RIGHT,TASK_BOTTOM>]"); diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java index 5fe72ddfaf91..5c8e530faf70 100644 --- a/services/core/java/com/android/server/am/UserController.java +++ b/services/core/java/com/android/server/am/UserController.java @@ -841,7 +841,7 @@ class UserController implements Handler.Callback { * @return user id to lock. UserHandler.USER_NULL will be returned if no user should be locked. */ @GuardedBy("mLock") - private int updateUserToLockLU(int userId) { + private int updateUserToLockLU(@UserIdInt int userId) { int userIdToLock = userId; if (mDelayUserDataLocking && !getUserInfo(userId).isEphemeral() && !hasUserRestriction(UserManager.DISALLOW_RUN_IN_BACKGROUND, userId)) { @@ -869,7 +869,7 @@ class UserController implements Handler.Callback { * {@code userId}. The returned list includes {@code userId}. */ @GuardedBy("mLock") - private @NonNull int[] getUsersToStopLU(int userId) { + private @NonNull int[] getUsersToStopLU(@UserIdInt int userId) { int startedUsersSize = mStartedUsers.size(); IntArray userIds = new IntArray(); userIds.add(userId); @@ -892,7 +892,7 @@ class UserController implements Handler.Callback { return userIds.toArray(); } - private void forceStopUser(int userId, String reason) { + private void forceStopUser(@UserIdInt int userId, String reason) { mInjector.activityManagerForceStopPackage(userId, reason); Intent intent = new Intent(Intent.ACTION_USER_STOPPED); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY @@ -965,7 +965,7 @@ class UserController implements Handler.Callback { } } - boolean startUser(final int userId, final boolean foreground) { + boolean startUser(final @UserIdInt int userId, final boolean foreground) { return startUser(userId, foreground, null); } @@ -1002,7 +1002,7 @@ class UserController implements Handler.Callback { * @return true if the user has been successfully started */ boolean startUser( - final int userId, + final @UserIdInt int userId, final boolean foreground, @Nullable IProgressListener unlockListener) { @@ -1018,7 +1018,7 @@ class UserController implements Handler.Callback { } } - private boolean startUserInternal(int userId, boolean foreground, + private boolean startUserInternal(@UserIdInt int userId, boolean foreground, @Nullable IProgressListener unlockListener, @NonNull TimingsTraceAndSlog t) { Slog.i(TAG, "Starting userid:" + userId + " fg:" + foreground); @@ -1257,7 +1257,8 @@ class UserController implements Handler.Callback { } } - boolean unlockUser(final int userId, byte[] token, byte[] secret, IProgressListener listener) { + boolean unlockUser(final @UserIdInt int userId, byte[] token, byte[] secret, + IProgressListener listener) { checkCallingPermission(INTERACT_ACROSS_USERS_FULL, "unlockUser"); final long binderToken = Binder.clearCallingIdentity(); try { @@ -1273,12 +1274,12 @@ class UserController implements Handler.Callback { * when the credential-encrypted storage isn't tied to a user-provided * PIN or pattern. */ - private boolean maybeUnlockUser(final int userId) { + private boolean maybeUnlockUser(final @UserIdInt int userId) { // Try unlocking storage using empty token return unlockUserCleared(userId, null, null, null); } - private static void notifyFinished(int userId, IProgressListener listener) { + private static void notifyFinished(@UserIdInt int userId, IProgressListener listener) { if (listener == null) return; try { listener.onFinished(userId, null); @@ -1286,7 +1287,7 @@ class UserController implements Handler.Callback { } } - private boolean unlockUserCleared(final int userId, byte[] token, byte[] secret, + private boolean unlockUserCleared(final @UserIdInt int userId, byte[] token, byte[] secret, IProgressListener listener) { UserState uss; if (!StorageManager.isUserKeyUnlocked(userId)) { @@ -1384,7 +1385,7 @@ class UserController implements Handler.Callback { getSwitchingFromSystemUserMessage(), getSwitchingToSystemUserMessage()); } - private void dispatchForegroundProfileChanged(int userId) { + private void dispatchForegroundProfileChanged(@UserIdInt int userId) { final int observerCount = mUserSwitchObservers.beginBroadcast(); for (int i = 0; i < observerCount; i++) { try { @@ -1397,7 +1398,7 @@ class UserController implements Handler.Callback { } /** Called on handler thread */ - void dispatchUserSwitchComplete(int userId) { + void dispatchUserSwitchComplete(@UserIdInt int userId) { mInjector.getWindowManager().setSwitchingUser(false); final int observerCount = mUserSwitchObservers.beginBroadcast(); for (int i = 0; i < observerCount; i++) { @@ -1409,7 +1410,7 @@ class UserController implements Handler.Callback { mUserSwitchObservers.finishBroadcast(); } - private void dispatchLockedBootComplete(int userId) { + private void dispatchLockedBootComplete(@UserIdInt int userId) { final int observerCount = mUserSwitchObservers.beginBroadcast(); for (int i = 0; i < observerCount; i++) { try { @@ -1596,7 +1597,7 @@ class UserController implements Handler.Callback { } - int handleIncomingUser(int callingPid, int callingUid, int userId, boolean allowAll, + int handleIncomingUser(int callingPid, int callingUid, @UserIdInt int userId, boolean allowAll, int allowMode, String name, String callerPackage) { final int callingUserId = UserHandle.getUserId(callingUid); if (callingUserId == userId) { @@ -1682,12 +1683,12 @@ class UserController implements Handler.Callback { return targetUserId; } - int unsafeConvertIncomingUser(int userId) { + int unsafeConvertIncomingUser(@UserIdInt int userId) { return (userId == UserHandle.USER_CURRENT || userId == UserHandle.USER_CURRENT_OR_SELF) ? getCurrentUserId(): userId; } - void ensureNotSpecialUser(int userId) { + void ensureNotSpecialUser(@UserIdInt int userId) { if (userId >= 0) { return; } @@ -1700,7 +1701,7 @@ class UserController implements Handler.Callback { mUserSwitchObservers.register(observer, name); } - void sendForegroundProfileChanged(int userId) { + void sendForegroundProfileChanged(@UserIdInt int userId) { mHandler.removeMessages(FOREGROUND_PROFILE_CHANGED_MSG); mHandler.obtainMessage(FOREGROUND_PROFILE_CHANGED_MSG, userId, 0).sendToTarget(); } @@ -1709,13 +1710,13 @@ class UserController implements Handler.Callback { mUserSwitchObservers.unregister(observer); } - UserState getStartedUserState(int userId) { + UserState getStartedUserState(@UserIdInt int userId) { synchronized (mLock) { return mStartedUsers.get(userId); } } - boolean hasStartedUserState(int userId) { + boolean hasStartedUserState(@UserIdInt int userId) { synchronized (mLock) { return mStartedUsers.get(userId) != null; } @@ -1804,7 +1805,7 @@ class UserController implements Handler.Callback { } } - boolean isUserRunning(int userId, int flags) { + boolean isUserRunning(@UserIdInt int userId, int flags) { UserState state = getStartedUserState(userId); if (state == null) { return false; @@ -1920,7 +1921,7 @@ class UserController implements Handler.Callback { } @GuardedBy("mLock") - private boolean isCurrentUserLU(int userId) { + private boolean isCurrentUserLU(@UserIdInt int userId) { return userId == getCurrentOrTargetUserIdLU(); } @@ -1929,7 +1930,7 @@ class UserController implements Handler.Callback { return ums != null ? ums.getUserIds() : new int[] { 0 }; } - private UserInfo getUserInfo(int userId) { + private UserInfo getUserInfo(@UserIdInt int userId) { return mInjector.getUserManager().getUserInfo(userId); } @@ -1943,7 +1944,7 @@ class UserController implements Handler.Callback { * * It doesn't handle other special user IDs such as {@link UserHandle#USER_CURRENT}. */ - int[] expandUserId(int userId) { + int[] expandUserId(@UserIdInt int userId) { if (userId != UserHandle.USER_ALL) { return new int[] {userId}; } else { @@ -1951,7 +1952,7 @@ class UserController implements Handler.Callback { } } - boolean exists(int userId) { + boolean exists(@UserIdInt int userId) { return mInjector.getUserManager().exists(userId); } @@ -1967,16 +1968,16 @@ class UserController implements Handler.Callback { } } - private void enforceShellRestriction(String restriction, int userHandle) { + private void enforceShellRestriction(String restriction, @UserIdInt int userId) { if (Binder.getCallingUid() == SHELL_UID) { - if (userHandle < 0 || hasUserRestriction(restriction, userHandle)) { + if (userId < 0 || hasUserRestriction(restriction, userId)) { throw new SecurityException("Shell does not have permission to access user " - + userHandle); + + userId); } } } - boolean hasUserRestriction(String restriction, int userId) { + boolean hasUserRestriction(String restriction, @UserIdInt int userId) { return mInjector.getUserManager().hasUserRestriction(restriction, userId); } @@ -1994,7 +1995,7 @@ class UserController implements Handler.Callback { } } - boolean isUserOrItsParentRunning(int userId) { + boolean isUserOrItsParentRunning(@UserIdInt int userId) { synchronized (mLock) { if (isUserRunning(userId, 0)) { return true; @@ -2007,7 +2008,7 @@ class UserController implements Handler.Callback { } } - boolean isCurrentProfile(int userId) { + boolean isCurrentProfile(@UserIdInt int userId) { synchronized (mLock) { return ArrayUtils.contains(mCurrentProfileIds, userId); } @@ -2019,7 +2020,7 @@ class UserController implements Handler.Callback { } } - void onUserRemoved(int userId) { + void onUserRemoved(@UserIdInt int userId) { synchronized (mLock) { int size = mUserProfileGroupIds.size(); for (int i = size - 1; i >= 0; i--) { @@ -2037,7 +2038,7 @@ class UserController implements Handler.Callback { * Returns whether the given user requires credential entry at this time. This is used to * intercept activity launches for work apps when the Work Challenge is present. */ - protected boolean shouldConfirmCredentials(int userId) { + protected boolean shouldConfirmCredentials(@UserIdInt int userId) { synchronized (mLock) { if (mStartedUsers.get(userId) == null) { return false; @@ -2265,7 +2266,7 @@ class UserController implements Handler.Callback { IIntentReceiver resultTo, int resultCode, String resultData, Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle bOptions, boolean ordered, boolean sticky, int callingPid, int callingUid, int realCallingUid, - int realCallingPid, int userId) { + int realCallingPid, @UserIdInt int userId) { // TODO b/64165549 Verify that mLock is not held before calling AMS methods synchronized (mService) { return mService.broadcastIntentLocked(null, null, intent, resolvedType, resultTo, @@ -2282,11 +2283,11 @@ class UserController implements Handler.Callback { WindowManagerService getWindowManager() { return mService.mWindowManager; } - void activityManagerOnUserStopped(int userId) { + void activityManagerOnUserStopped(@UserIdInt int userId) { LocalServices.getService(ActivityTaskManagerInternal.class).onUserStopped(userId); } - void systemServiceManagerCleanupUser(int userId) { + void systemServiceManagerCleanupUser(@UserIdInt int userId) { mService.mSystemServiceManager.cleanupUser(userId); } @@ -2330,7 +2331,7 @@ class UserController implements Handler.Callback { } } - void sendPreBootBroadcast(int userId, boolean quiet, final Runnable onFinish) { + void sendPreBootBroadcast(@UserIdInt int userId, boolean quiet, final Runnable onFinish) { new PreBootBroadcaster(mService, userId, null, quiet) { @Override public void onFinished() { @@ -2339,7 +2340,7 @@ class UserController implements Handler.Callback { }.sendNext(); } - void activityManagerForceStopPackage(int userId, String reason) { + void activityManagerForceStopPackage(@UserIdInt int userId, String reason) { synchronized (mService) { mService.forceStopPackageLocked(null, -1, false, false, true, false, false, userId, reason); @@ -2351,11 +2352,11 @@ class UserController implements Handler.Callback { return mService.checkComponentPermission(permission, pid, uid, owningUid, exported); } - protected void startHomeActivity(int userId, String reason) { + protected void startHomeActivity(@UserIdInt int userId, String reason) { mService.mAtmInternal.startHomeActivity(userId, reason); } - void startUserWidgets(int userId) { + void startUserWidgets(@UserIdInt int userId) { AppWidgetManagerInternal awm = LocalServices.getService(AppWidgetManagerInternal.class); if (awm != null) { // Out of band, because this is called during a sequence with @@ -2370,13 +2371,13 @@ class UserController implements Handler.Callback { mService.mAtmInternal.updateUserConfiguration(); } - void clearBroadcastQueueForUser(int userId) { + void clearBroadcastQueueForUser(@UserIdInt int userId) { synchronized (mService) { mService.clearBroadcastQueueForUserLocked(userId); } } - void loadUserRecents(int userId) { + void loadUserRecents(@UserIdInt int userId) { mService.mAtmInternal.loadRecentTasksForUser(userId); } @@ -2384,7 +2385,7 @@ class UserController implements Handler.Callback { mService.startPersistentApps(matchFlags); } - void installEncryptionUnawareProviders(int userId) { + void installEncryptionUnawareProviders(@UserIdInt int userId) { mService.installEncryptionUnawareProviders(userId); } @@ -2417,11 +2418,11 @@ class UserController implements Handler.Callback { } } - void stackSupervisorRemoveUser(int userId) { + void stackSupervisorRemoveUser(@UserIdInt int userId) { mService.mAtmInternal.removeUser(userId); } - protected boolean stackSupervisorSwitchUser(int userId, UserState uss) { + protected boolean stackSupervisorSwitchUser(@UserIdInt int userId, UserState uss) { return mService.mAtmInternal.switchUser(userId, uss); } diff --git a/services/core/java/com/android/server/camera/CameraServiceProxy.java b/services/core/java/com/android/server/camera/CameraServiceProxy.java index 8de259516890..09f52860e069 100644 --- a/services/core/java/com/android/server/camera/CameraServiceProxy.java +++ b/services/core/java/com/android/server/camera/CameraServiceProxy.java @@ -36,6 +36,7 @@ import android.os.UserManager; import android.util.ArrayMap; import android.util.ArraySet; import android.util.Slog; +import android.util.StatsLog; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; @@ -44,6 +45,9 @@ import com.android.server.ServiceThread; import com.android.server.SystemService; import com.android.server.wm.WindowManagerInternal; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.TimeUnit; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -102,6 +106,9 @@ public class CameraServiceProxy extends SystemService private final boolean mNotifyNfc; + private ScheduledThreadPoolExecutor mLogWriterService = new ScheduledThreadPoolExecutor( + /*corePoolSize*/ 1); + /** * Structure to track camera usage */ @@ -204,6 +211,9 @@ public class CameraServiceProxy extends SystemService mNotifyNfc = SystemProperties.getInt(NFC_NOTIFICATION_PROP, 0) > 0; if (DEBUG) Slog.v(TAG, "Notify NFC behavior is " + (mNotifyNfc ? "active" : "disabled")); + // Don't keep any extra logging threads if not needed + mLogWriterService.setKeepAliveTime(1, TimeUnit.SECONDS); + mLogWriterService.allowCoreThreadTimeOut(true); } @Override @@ -279,6 +289,51 @@ public class CameraServiceProxy extends SystemService } } + private class EventWriterTask implements Runnable { + private ArrayList<CameraUsageEvent> mEventList; + private static final long WRITER_SLEEP_MS = 100; + + public EventWriterTask(ArrayList<CameraUsageEvent> eventList) { + mEventList = eventList; + } + + @Override + public void run() { + if (mEventList != null) { + for (CameraUsageEvent event : mEventList) { + logCameraUsageEvent(event); + try { + Thread.sleep(WRITER_SLEEP_MS); + } catch (InterruptedException e) {} + } + mEventList.clear(); + } + } + + /** + * Write camera usage events to stats log. + * Package-private + */ + private void logCameraUsageEvent(CameraUsageEvent e) { + int facing = StatsLog.CAMERA_ACTION_EVENT__FACING__UNKNOWN; + switch(e.mCameraFacing) { + case ICameraServiceProxy.CAMERA_FACING_BACK: + facing = StatsLog.CAMERA_ACTION_EVENT__FACING__BACK; + break; + case ICameraServiceProxy.CAMERA_FACING_FRONT: + facing = StatsLog.CAMERA_ACTION_EVENT__FACING__FRONT; + break; + case ICameraServiceProxy.CAMERA_FACING_EXTERNAL: + facing = StatsLog.CAMERA_ACTION_EVENT__FACING__EXTERNAL; + break; + default: + Slog.w(TAG, "Unknown camera facing: " + e.mCameraFacing); + } + StatsLog.write(StatsLog.CAMERA_ACTION_EVENT, e.getDuration(), e.mAPILevel, + e.mClientName, facing); + } + } + /** * Dump camera usage events to log. * Package-private @@ -315,6 +370,10 @@ public class CameraServiceProxy extends SystemService .setPackageName(e.mClientName); mLogger.write(l); } + + mLogWriterService.execute(new EventWriterTask( + new ArrayList<CameraUsageEvent>(mCameraUsageHistory))); + mCameraUsageHistory.clear(); } final long ident = Binder.clearCallingIdentity(); diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index db8d0988e75c..f71b3627135d 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -457,7 +457,7 @@ public class NotificationManagerService extends SystemService { private static final int MY_UID = Process.myUid(); private static final int MY_PID = Process.myPid(); private static final IBinder WHITELIST_TOKEN = new Binder(); - private RankingHandler mRankingHandler; + protected RankingHandler mRankingHandler; private long mLastOverRateLogTime; private float mMaxPackageEnqueueRate = DEFAULT_MAX_NOTIFICATION_ENQUEUE_RATE; @@ -1550,10 +1550,12 @@ public class NotificationManagerService extends SystemService { @VisibleForTesting void clearNotifications() { - mEnqueuedNotifications.clear(); - mNotificationList.clear(); - mNotificationsByKey.clear(); - mSummaryByGroupKey.clear(); + synchronized (mNotificationList) { + mEnqueuedNotifications.clear(); + mNotificationList.clear(); + mNotificationsByKey.clear(); + mSummaryByGroupKey.clear(); + } } @VisibleForTesting @@ -1605,11 +1607,6 @@ public class NotificationManagerService extends SystemService { void setPreferencesHelper(PreferencesHelper prefHelper) { mPreferencesHelper = prefHelper; } @VisibleForTesting - void setRankingHandler(RankingHandler rankingHandler) { - mRankingHandler = rankingHandler; - } - - @VisibleForTesting void setZenHelper(ZenModeHelper zenHelper) { mZenModeHelper = zenHelper; } @@ -1641,7 +1638,7 @@ public class NotificationManagerService extends SystemService { // TODO: All tests should use this init instead of the one-off setters above. @VisibleForTesting - void init(Looper looper, IPackageManager packageManager, + void init(Looper looper, RankingHandler rankingHandler, IPackageManager packageManager, PackageManager packageManagerClient, LightsManager lightsManager, NotificationListeners notificationListeners, NotificationAssistants notificationAssistants, ConditionProviders conditionProviders, @@ -1675,7 +1672,6 @@ public class NotificationManagerService extends SystemService { mUm = userManager; mHandler = new WorkerHandler(looper); - mRankingThread.start(); String[] extractorNames; try { extractorNames = resources.getStringArray(R.array.config_notificationSignalExtractors); @@ -1684,7 +1680,7 @@ public class NotificationManagerService extends SystemService { } mUsageStats = usageStats; mMetricsLogger = new MetricsLogger(); - mRankingHandler = new RankingHandlerWorker(mRankingThread.getLooper()); + mRankingHandler = rankingHandler; mConditionProviders = conditionProviders; mZenModeHelper = new ZenModeHelper(getContext(), mHandler.getLooper(), mConditionProviders); mZenModeHelper.addCallback(new ZenModeHelper.Callback() { @@ -1829,8 +1825,9 @@ public class NotificationManagerService extends SystemService { }, mUserProfiles); final File systemDir = new File(Environment.getDataDirectory(), "system"); + mRankingThread.start(); - init(Looper.myLooper(), + init(Looper.myLooper(), new RankingHandlerWorker(mRankingThread.getLooper()), AppGlobals.getPackageManager(), getContext().getPackageManager(), getLocalService(LightsManager.class), new NotificationListeners(AppGlobals.getPackageManager()), diff --git a/services/core/java/com/android/server/notification/ZenLog.java b/services/core/java/com/android/server/notification/ZenLog.java index c6af7566a8bd..8f05636eed9c 100644 --- a/services/core/java/com/android/server/notification/ZenLog.java +++ b/services/core/java/com/android/server/notification/ZenLog.java @@ -179,6 +179,7 @@ public class ZenLog { case TYPE_SUPPRESSOR_CHANGED: return "suppressor_changed"; case TYPE_LISTENER_HINTS_CHANGED: return "listener_hints_changed"; case TYPE_SET_NOTIFICATION_POLICY: return "set_notification_policy"; + case TYPE_SET_CONSOLIDATED_ZEN_POLICY: return "set_consolidated_policy"; default: return "unknown"; } } diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java index ee948b28e546..f63aa5256078 100644 --- a/services/core/java/com/android/server/notification/ZenModeHelper.java +++ b/services/core/java/com/android/server/notification/ZenModeHelper.java @@ -954,12 +954,11 @@ public class ZenModeHelper { } private void applyCustomPolicy(ZenPolicy policy, ZenRule rule) { - if (rule.zenMode == NotificationManager.INTERRUPTION_FILTER_NONE) { + if (rule.zenMode == Global.ZEN_MODE_NO_INTERRUPTIONS) { policy.apply(new ZenPolicy.Builder() .disallowAllSounds() .build()); - } else if (rule.zenMode - == NotificationManager.INTERRUPTION_FILTER_ALARMS) { + } else if (rule.zenMode == Global.ZEN_MODE_ALARMS) { policy.apply(new ZenPolicy.Builder() .disallowAllSounds() .allowAlarms(true) diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index ab77cc6de819..b124c4b18efa 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -113,6 +113,7 @@ import static com.android.server.pm.PackageManagerServiceUtils.logCriticalInfo; import static com.android.server.pm.PackageManagerServiceUtils.verifySignatures; import android.Manifest; +import android.annotation.AppIdInt; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; @@ -12059,11 +12060,12 @@ public class PackageManagerService extends IPackageManager.Stub | IntentFilter.MATCH_ADJUSTMENT_NORMAL; } - private void killApplication(String pkgName, int appId, String reason) { + private void killApplication(String pkgName, @AppIdInt int appId, String reason) { killApplication(pkgName, appId, UserHandle.USER_ALL, reason); } - private void killApplication(String pkgName, int appId, int userId, String reason) { + private void killApplication(String pkgName, @AppIdInt int appId, + @UserIdInt int userId, String reason) { // Request the ActivityManager to kill the process(only for existing packages) // so that we do not end up in a confused state while the user is still using the older // version of the application while the new one gets installed. @@ -12438,7 +12440,7 @@ public class PackageManagerService extends IPackageManager.Stub @Override public void sendPackageAddedForNewUsers(String packageName, boolean sendBootCompleted, - boolean includeStopped, int appId, int[] userIds, int[] instantUserIds) { + boolean includeStopped, @AppIdInt int appId, int[] userIds, int[] instantUserIds) { if (ArrayUtils.isEmpty(userIds) && ArrayUtils.isEmpty(instantUserIds)) { return; } @@ -18903,7 +18905,8 @@ public class PackageManagerService extends IPackageManager.Stub * Remove entries from the keystore daemon. Will only remove it if the * {@code appId} is valid. */ - private static void removeKeystoreDataIfNeeded(UserManagerInternal um, int userId, int appId) { + private static void removeKeystoreDataIfNeeded(UserManagerInternal um, @UserIdInt int userId, + @AppIdInt int appId) { if (appId < 0) { return; } @@ -18989,7 +18992,7 @@ public class PackageManagerService extends IPackageManager.Stub } @Override - public void getPackageSizeInfo(final String packageName, int userHandle, + public void getPackageSizeInfo(final String packageName, int userId, final IPackageStatsObserver observer) { throw new UnsupportedOperationException( "Shame on you for calling the hidden API getPackageSizeInfo(). Shame!"); @@ -22494,24 +22497,24 @@ public class PackageManagerService extends IPackageManager.Stub } /** Called by UserManagerService */ - void cleanUpUser(UserManagerService userManager, int userHandle) { + void cleanUpUser(UserManagerService userManager, @UserIdInt int userId) { synchronized (mLock) { - mDirtyUsers.remove(userHandle); - mUserNeedsBadging.delete(userHandle); - mSettings.removeUserLPw(userHandle); - mPendingBroadcasts.remove(userHandle); - mInstantAppRegistry.onUserRemovedLPw(userHandle); - removeUnusedPackagesLPw(userManager, userHandle); + mDirtyUsers.remove(userId); + mUserNeedsBadging.delete(userId); + mSettings.removeUserLPw(userId); + mPendingBroadcasts.remove(userId); + mInstantAppRegistry.onUserRemovedLPw(userId); + removeUnusedPackagesLPw(userManager, userId); } } /** - * We're removing userHandle and would like to remove any downloaded packages + * We're removing userId and would like to remove any downloaded packages * that are no longer in use by any other user. - * @param userHandle the user being removed + * @param userId the user being removed */ @GuardedBy("mLock") - private void removeUnusedPackagesLPw(UserManagerService userManager, final int userHandle) { + private void removeUnusedPackagesLPw(UserManagerService userManager, final int userId) { final boolean DEBUG_CLEAN_APKS = false; int [] users = userManager.getUserIds(); Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator(); @@ -22535,7 +22538,7 @@ public class PackageManagerService extends IPackageManager.Stub } } else { for (int i = 0; i < users.length; i++) { - if (users[i] != userHandle && ps.getInstalled(users[i])) { + if (users[i] != userId && ps.getInstalled(users[i])) { keep = true; if (DEBUG_CLEAN_APKS) { Slog.i(TAG, " Keeping package " + packageName + " for user " @@ -22551,7 +22554,7 @@ public class PackageManagerService extends IPackageManager.Stub } //end run mHandler.post(() -> deletePackageX(packageName, PackageManager.VERSION_CODE_HIGHEST, - userHandle, 0)); + userId, 0)); } } } diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java index af1a095c6871..fe529a152364 100644 --- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java +++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java @@ -276,7 +276,7 @@ class PackageManagerShellCommand extends ShellCommand { case "get-harmful-app-warning": return runGetHarmfulAppWarning(); case "get-stagedsessions": - return getStagedSessions(); + return runListStagedSessions(); case "uninstall-system-updates": return uninstallSystemUpdates(); case "rollback-app": @@ -348,53 +348,6 @@ class PackageManagerShellCommand extends ShellCommand { return 1; } - private int getStagedSessions() { - final IndentingPrintWriter pw = new IndentingPrintWriter( - getOutPrintWriter(), /* singleIndent */ " ", /* wrapLength */ 120); - try { - List<SessionInfo> stagedSessions = - mInterface.getPackageInstaller().getStagedSessions().getList(); - final SparseArray<SessionInfo> sessionById = new SparseArray<>(stagedSessions.size()); - for (SessionInfo session : stagedSessions) { - sessionById.put(session.getSessionId(), session); - } - for (SessionInfo session: stagedSessions) { - if (session.getParentSessionId() != SessionInfo.INVALID_ID) { - continue; - } - printStagedSession(session, pw); - if (session.isMultiPackage()) { - pw.increaseIndent(); - final int[] childIds = session.getChildSessionIds(); - for (int i = 0; i < childIds.length; i++) { - final SessionInfo childSession = sessionById.get(childIds[i]); - if (childSession == null) { - pw.println("sessionId = " + childIds[i] + "; not found"); - } else { - printStagedSession(childSession, pw); - } - } - pw.decreaseIndent(); - } - } - } catch (RemoteException e) { - pw.println("Failure [" - + e.getClass().getName() + " - " - + e.getMessage() + "]"); - return 0; - } - return 1; - } - - private static void printStagedSession(SessionInfo session, PrintWriter pw) { - pw.println("sessionId = " + session.getSessionId() - + "; appPackageName = " + session.getAppPackageName() - + "; isStaged = " + session.isStaged() - + "; isReady = " + session.isStagedSessionReady() - + "; isApplied = " + session.isStagedSessionApplied() - + "; isFailed = " + session.isStagedSessionFailed() + ";"); - } - private int uninstallSystemUpdates() { final PrintWriter pw = getOutPrintWriter(); List<String> failedUninstalls = new LinkedList<>(); @@ -567,6 +520,8 @@ class PackageManagerShellCommand extends ShellCommand { return runListPermissionGroups(); case "permissions": return runListPermissions(); + case "staged-sessions": + return runListStagedSessions(); case "users": ServiceManager.getService("user").shellCommand( getInFileDescriptor(), getOutFileDescriptor(), getErrFileDescriptor(), @@ -904,6 +859,103 @@ class PackageManagerShellCommand extends ShellCommand { return 0; } + private static class SessionDump { + boolean onlyParent; // Show parent sessions only + boolean onlyReady; // Show only staged sessions that are in ready state + boolean onlySessionId; // Show sessionId only + } + + // Returns true if the provided flag is a session flag and given SessionDump was updated + private boolean setSessionFlag(String flag, SessionDump sessionDump) { + switch (flag) { + case "--only-parent": + sessionDump.onlyParent = true; + break; + case "--only-ready": + sessionDump.onlyReady = true; + break; + case "--only-sessionid": + sessionDump.onlySessionId = true; + break; + default: + return false; + } + return true; + } + + private int runListStagedSessions() { + final IndentingPrintWriter pw = new IndentingPrintWriter( + getOutPrintWriter(), /* singleIndent */ " ", /* wrapLength */ 120); + + SessionDump sessionDump = new SessionDump(); + String opt; + while ((opt = getNextOption()) != null) { + if (!setSessionFlag(opt, sessionDump)) { + pw.println("Error: Unknown option: " + opt); + return -1; + } + } + + try { + List<SessionInfo> stagedSessions = + mInterface.getPackageInstaller().getStagedSessions().getList(); + printSessionList(pw, stagedSessions, sessionDump); + } catch (RemoteException e) { + pw.println("Failure [" + + e.getClass().getName() + " - " + + e.getMessage() + "]"); + return -1; + } + return 1; + } + + private void printSessionList(IndentingPrintWriter pw, List<SessionInfo> stagedSessions, + SessionDump sessionDump) { + final SparseArray<SessionInfo> sessionById = new SparseArray<>(stagedSessions.size()); + for (SessionInfo session : stagedSessions) { + sessionById.put(session.getSessionId(), session); + } + for (SessionInfo session: stagedSessions) { + if (sessionDump.onlyReady && !session.isStagedSessionReady()) { + continue; + } + if (session.getParentSessionId() != SessionInfo.INVALID_ID) { + continue; + } + printSession(pw, session, sessionDump); + if (session.isMultiPackage() && !sessionDump.onlyParent) { + pw.increaseIndent(); + final int[] childIds = session.getChildSessionIds(); + for (int i = 0; i < childIds.length; i++) { + final SessionInfo childSession = sessionById.get(childIds[i]); + if (childSession == null) { + if (sessionDump.onlySessionId) { + pw.println(childIds[i]); + } else { + pw.println("sessionId = " + childIds[i] + "; not found"); + } + } else { + printSession(pw, childSession, sessionDump); + } + } + pw.decreaseIndent(); + } + } + } + + private static void printSession(PrintWriter pw, SessionInfo session, SessionDump sessionDump) { + if (sessionDump.onlySessionId) { + pw.println(session.getSessionId()); + return; + } + pw.println("sessionId = " + session.getSessionId() + + "; appPackageName = " + session.getAppPackageName() + + "; isStaged = " + session.isStaged() + + "; isReady = " + session.isStagedSessionReady() + + "; isApplied = " + session.isStagedSessionApplied() + + "; isFailed = " + session.isStagedSessionFailed() + ";"); + } + private Intent parseIntentAndUser() throws URISyntaxException { mTargetUser = UserHandle.USER_CURRENT; mBrief = false; @@ -3108,6 +3160,12 @@ class PackageManagerShellCommand extends ShellCommand { pw.println(" -d: only list dangerous permissions"); pw.println(" -u: list only the permissions users will see"); pw.println(""); + pw.println(" list staged-sessions [--only-ready] [--only-sessionid] [--only-parent]"); + pw.println(" Displays list of all staged sessions on device."); + pw.println(" --only-ready: show only staged sessions that are ready"); + pw.println(" --only-sessionid: show only sessionId of each session"); + pw.println(" --only-parent: hide all children sessions"); + pw.println(""); pw.println(" resolve-activity [--brief] [--components] [--query-flags FLAGS]"); pw.println(" [--user USER_ID] INTENT"); pw.println(" Prints the activity that resolves to the given INTENT."); @@ -3345,7 +3403,7 @@ class PackageManagerShellCommand extends ShellCommand { pw.println(" uninstall-system-updates"); pw.println(" Remove updates to all system applications and fall back to their /system " + "version."); - pw.println(); + pw.println(""); pw.println(" get-moduleinfo [--all | --installed] [module-name]"); pw.println(" Displays module info. If module-name is specified only that info is shown"); pw.println(" By default, without any argument only installed modules are shown."); diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index 65fb35d34c01..81723cbe22c5 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -404,10 +404,10 @@ public class UserManagerService extends IUserManager.Stub { return; } final IntentSender target = intent.getParcelableExtra(Intent.EXTRA_INTENT); - final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_ID, UserHandle.USER_NULL); + final int userId = intent.getIntExtra(Intent.EXTRA_USER_ID, UserHandle.USER_NULL); // Call setQuietModeEnabled on bg thread to avoid ANR BackgroundThread.getHandler().post(() -> - setQuietModeEnabled(userHandle, false, target, /* callingPackage */ null)); + setQuietModeEnabled(userId, false, target, /* callingPackage */ null)); } }; @@ -482,9 +482,9 @@ public class UserManagerService extends IUserManager.Stub { } @Override - public void onStartUser(int userHandle) { + public void onStartUser(@UserIdInt int userId) { synchronized (mUms.mUsersLock) { - final UserData user = mUms.getUserDataLU(userHandle); + final UserData user = mUms.getUserDataLU(userId); if (user != null) { user.startRealtime = SystemClock.elapsedRealtime(); } @@ -492,9 +492,9 @@ public class UserManagerService extends IUserManager.Stub { } @Override - public void onUnlockUser(int userHandle) { + public void onUnlockUser(@UserIdInt int userId) { synchronized (mUms.mUsersLock) { - final UserData user = mUms.getUserDataLU(userHandle); + final UserData user = mUms.getUserDataLU(userId); if (user != null) { user.unlockRealtime = SystemClock.elapsedRealtime(); } @@ -502,9 +502,9 @@ public class UserManagerService extends IUserManager.Stub { } @Override - public void onStopUser(int userHandle) { + public void onStopUser(@UserIdInt int userId) { synchronized (mUms.mUsersLock) { - final UserData user = mUms.getUserDataLU(userHandle); + final UserData user = mUms.getUserDataLU(userId); if (user != null) { user.startRealtime = 0; user.unlockRealtime = 0; @@ -610,7 +610,7 @@ public class UserManagerService extends IUserManager.Stub { } @Override - public String getUserAccount(int userId) { + public String getUserAccount(@UserIdInt int userId) { checkManageUserAndAcrossUsersFullPermission("get user account"); synchronized (mUsersLock) { return mUsers.get(userId).account; @@ -618,7 +618,7 @@ public class UserManagerService extends IUserManager.Stub { } @Override - public void setUserAccount(int userId, String accountName) { + public void setUserAccount(@UserIdInt int userId, String accountName) { checkManageUserAndAcrossUsersFullPermission("set user account"); UserData userToUpdate = null; synchronized (mPackagesLock) { @@ -676,7 +676,7 @@ public class UserManagerService extends IUserManager.Stub { } @Override - public List<UserInfo> getProfiles(int userId, boolean enabledOnly) { + public List<UserInfo> getProfiles(@UserIdInt int userId, boolean enabledOnly) { boolean returnFullInfo = true; if (userId != UserHandle.getCallingUserId()) { checkManageOrCreateUsersPermission("getting profiles related to user " + userId); @@ -694,7 +694,7 @@ public class UserManagerService extends IUserManager.Stub { } @Override - public int[] getProfileIds(int userId, boolean enabledOnly) { + public int[] getProfileIds(@UserIdInt int userId, boolean enabledOnly) { if (userId != UserHandle.getCallingUserId()) { checkManageOrCreateUsersPermission("getting profiles related to user " + userId); } @@ -710,7 +710,8 @@ public class UserManagerService extends IUserManager.Stub { /** Assume permissions already checked and caller's identity cleared */ @GuardedBy("mUsersLock") - private List<UserInfo> getProfilesLU(int userId, boolean enabledOnly, boolean fullInfo) { + private List<UserInfo> getProfilesLU(@UserIdInt int userId, boolean enabledOnly, + boolean fullInfo) { IntArray profileIds = getProfileIdsLU(userId, enabledOnly); ArrayList<UserInfo> users = new ArrayList<>(profileIds.size()); for (int i = 0; i < profileIds.size(); i++) { @@ -733,7 +734,7 @@ public class UserManagerService extends IUserManager.Stub { * Assume permissions already checked and caller's identity cleared */ @GuardedBy("mUsersLock") - private IntArray getProfileIdsLU(int userId, boolean enabledOnly) { + private IntArray getProfileIdsLU(@UserIdInt int userId, boolean enabledOnly) { UserInfo user = getUserInfoLU(userId); IntArray result = new IntArray(mUsers.size()); if (user == null) { @@ -761,28 +762,28 @@ public class UserManagerService extends IUserManager.Stub { } @Override - public int getCredentialOwnerProfile(int userHandle) { + public int getCredentialOwnerProfile(@UserIdInt int userId) { checkManageUsersPermission("get the credential owner"); - if (!mLockPatternUtils.isSeparateProfileChallengeEnabled(userHandle)) { + if (!mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)) { synchronized (mUsersLock) { - UserInfo profileParent = getProfileParentLU(userHandle); + UserInfo profileParent = getProfileParentLU(userId); if (profileParent != null) { return profileParent.id; } } } - return userHandle; + return userId; } @Override - public boolean isSameProfileGroup(int userId, int otherUserId) { + public boolean isSameProfileGroup(@UserIdInt int userId, int otherUserId) { if (userId == otherUserId) return true; checkManageUsersPermission("check if in the same profile group"); return isSameProfileGroupNoChecks(userId, otherUserId); } - private boolean isSameProfileGroupNoChecks(int userId, int otherUserId) { + private boolean isSameProfileGroupNoChecks(@UserIdInt int userId, int otherUserId) { synchronized (mUsersLock) { UserInfo userInfo = getUserInfoLU(userId); if (userInfo == null || userInfo.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID) { @@ -798,27 +799,27 @@ public class UserManagerService extends IUserManager.Stub { } @Override - public UserInfo getProfileParent(int userHandle) { + public UserInfo getProfileParent(@UserIdInt int userId) { checkManageUsersPermission("get the profile parent"); synchronized (mUsersLock) { - return getProfileParentLU(userHandle); + return getProfileParentLU(userId); } } @Override - public int getProfileParentId(int userHandle) { + public int getProfileParentId(@UserIdInt int userId) { checkManageUsersPermission("get the profile parent"); - return mLocalService.getProfileParentId(userHandle); + return mLocalService.getProfileParentId(userId); } @GuardedBy("mUsersLock") - private UserInfo getProfileParentLU(int userHandle) { - UserInfo profile = getUserInfoLU(userHandle); + private UserInfo getProfileParentLU(@UserIdInt int userId) { + UserInfo profile = getUserInfoLU(userId); if (profile == null) { return null; } int parentUserId = profile.profileGroupId; - if (parentUserId == userHandle || parentUserId == UserInfo.NO_PROFILE_GROUP_ID) { + if (parentUserId == userId || parentUserId == UserInfo.NO_PROFILE_GROUP_ID) { return null; } else { return getUserInfoLU(parentUserId); @@ -848,7 +849,7 @@ public class UserManagerService extends IUserManager.Stub { @Override public boolean requestQuietModeEnabled(@NonNull String callingPackage, boolean enableQuietMode, - int userHandle, @Nullable IntentSender target) { + @UserIdInt int userId, @Nullable IntentSender target) { Preconditions.checkNotNull(callingPackage); if (enableQuietMode && target != null) { @@ -862,17 +863,17 @@ public class UserManagerService extends IUserManager.Stub { boolean result = false; if (enableQuietMode) { setQuietModeEnabled( - userHandle, true /* enableQuietMode */, target, callingPackage); + userId, true /* enableQuietMode */, target, callingPackage); result = true; } else { boolean needToShowConfirmCredential = - mLockPatternUtils.isSecure(userHandle) - && !StorageManager.isUserKeyUnlocked(userHandle); + mLockPatternUtils.isSecure(userId) + && !StorageManager.isUserKeyUnlocked(userId); if (needToShowConfirmCredential) { - showConfirmCredentialToDisableQuietMode(userHandle, target); + showConfirmCredentialToDisableQuietMode(userId, target); } else { setQuietModeEnabled( - userHandle, false /* enableQuietMode */, target, callingPackage); + userId, false /* enableQuietMode */, target, callingPackage); result = true; } } @@ -922,16 +923,16 @@ public class UserManagerService extends IUserManager.Stub { + "default launcher nor has MANAGE_USERS/MODIFY_QUIET_MODE permission"); } - private void setQuietModeEnabled(int userHandle, boolean enableQuietMode, + private void setQuietModeEnabled(@UserIdInt int userId, boolean enableQuietMode, IntentSender target, @Nullable String callingPackage) { final UserInfo profile, parent; final UserData profileUserData; synchronized (mUsersLock) { - profile = getUserInfoLU(userHandle); - parent = getProfileParentLU(userHandle); + profile = getUserInfoLU(userId); + parent = getProfileParentLU(userId); if (profile == null || !profile.isManagedProfile()) { - throw new IllegalArgumentException("User " + userHandle + " is not a profile"); + throw new IllegalArgumentException("User " + userId + " is not a profile"); } if (profile.isQuietModeEnabled() == enableQuietMode) { Slog.i(LOG_TAG, "Quiet mode is already " + enableQuietMode); @@ -945,17 +946,17 @@ public class UserManagerService extends IUserManager.Stub { } try { if (enableQuietMode) { - ActivityManager.getService().stopUser(userHandle, /* force */true, null); + ActivityManager.getService().stopUser(userId, /* force */true, null); LocalServices.getService(ActivityManagerInternal.class) - .killForegroundAppsForUser(userHandle); + .killForegroundAppsForUser(userId); } else { IProgressListener callback = target != null ? new DisableQuietModeUserUnlockedCallback(target) : null; ActivityManager.getService().startUserInBackgroundWithListener( - userHandle, callback); + userId, callback); } - logQuietModeEnabled(userHandle, enableQuietMode, callingPackage); + logQuietModeEnabled(userId, enableQuietMode, callingPackage); } catch (RemoteException e) { // Should not happen, same process. e.rethrowAsRuntimeException(); @@ -964,11 +965,11 @@ public class UserManagerService extends IUserManager.Stub { enableQuietMode); } - private void logQuietModeEnabled(int userHandle, boolean enableQuietMode, + private void logQuietModeEnabled(@UserIdInt int userId, boolean enableQuietMode, @Nullable String callingPackage) { UserData userData; synchronized (mUsersLock) { - userData = getUserDataLU(userHandle); + userData = getUserDataLU(userId); } if (userData == null) { return; @@ -987,11 +988,11 @@ public class UserManagerService extends IUserManager.Stub { } @Override - public boolean isQuietModeEnabled(int userHandle) { + public boolean isQuietModeEnabled(@UserIdInt int userId) { synchronized (mPackagesLock) { UserInfo info; synchronized (mUsersLock) { - info = getUserInfoLU(userHandle); + info = getUserInfoLU(userId); } if (info == null || !info.isManagedProfile()) { return false; @@ -1004,15 +1005,14 @@ public class UserManagerService extends IUserManager.Stub { * Show confirm credential screen to unlock user in order to turn off quiet mode. */ private void showConfirmCredentialToDisableQuietMode( - @UserIdInt int userHandle, @Nullable IntentSender target) { + @UserIdInt int userId, @Nullable IntentSender target) { // otherwise, we show a profile challenge to trigger decryption of the user final KeyguardManager km = (KeyguardManager) mContext.getSystemService( Context.KEYGUARD_SERVICE); - // We should use userHandle not credentialOwnerUserId here, as even if it is unified + // We should use userId not credentialOwnerUserId here, as even if it is unified // lock, confirm screenlock page will know and show personal challenge, and unlock // work profile when personal challenge is correct - final Intent unlockIntent = km.createConfirmDeviceCredentialIntent(null, null, - userHandle); + final Intent unlockIntent = km.createConfirmDeviceCredentialIntent(null, null, userId); if (unlockIntent == null) { return; } @@ -1021,7 +1021,7 @@ public class UserManagerService extends IUserManager.Stub { if (target != null) { callBackIntent.putExtra(Intent.EXTRA_INTENT, target); } - callBackIntent.putExtra(Intent.EXTRA_USER_ID, userHandle); + callBackIntent.putExtra(Intent.EXTRA_USER_ID, userId); callBackIntent.setPackage(mContext.getPackageName()); callBackIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); final PendingIntent pendingIntent = PendingIntent.getBroadcast( @@ -1039,7 +1039,7 @@ public class UserManagerService extends IUserManager.Stub { } @Override - public void setUserEnabled(int userId) { + public void setUserEnabled(@UserIdInt int userId) { checkManageUsersPermission("enable user"); synchronized (mPackagesLock) { UserInfo info; @@ -1054,7 +1054,7 @@ public class UserManagerService extends IUserManager.Stub { } @Override - public void setUserAdmin(int userId) { + public void setUserAdmin(@UserIdInt int userId) { checkManageUserAndAcrossUsersFullPermission("set user admin"); synchronized (mPackagesLock) { @@ -1097,7 +1097,7 @@ public class UserManagerService extends IUserManager.Stub { } @Override - public UserInfo getUserInfo(int userId) { + public UserInfo getUserInfo(@UserIdInt int userId) { checkManageOrCreateUsersPermission("query user"); synchronized (mUsersLock) { return userWithName(getUserInfoLU(userId)); @@ -1128,7 +1128,7 @@ public class UserManagerService extends IUserManager.Stub { } @Override - public boolean isManagedProfile(int userId) { + public boolean isManagedProfile(@UserIdInt int userId) { checkManageOrInteractPermIfCallerInOtherProfileGroup(userId, "isManagedProfile"); synchronized (mUsersLock) { UserInfo userInfo = getUserInfoLU(userId); @@ -1137,19 +1137,19 @@ public class UserManagerService extends IUserManager.Stub { } @Override - public boolean isUserUnlockingOrUnlocked(int userId) { + public boolean isUserUnlockingOrUnlocked(@UserIdInt int userId) { checkManageOrInteractPermIfCallerInOtherProfileGroup(userId, "isUserUnlockingOrUnlocked"); return mLocalService.isUserUnlockingOrUnlocked(userId); } @Override - public boolean isUserUnlocked(int userId) { + public boolean isUserUnlocked(@UserIdInt int userId) { checkManageOrInteractPermIfCallerInOtherProfileGroup(userId, "isUserUnlocked"); return mLocalService.isUserUnlocked(userId); } @Override - public boolean isUserRunning(int userId) { + public boolean isUserRunning(@UserIdInt int userId) { checkManageOrInteractPermIfCallerInOtherProfileGroup(userId, "isUserRunning"); return mLocalService.isUserRunning(userId); } @@ -1190,7 +1190,8 @@ public class UserManagerService extends IUserManager.Stub { } } - private void checkManageOrInteractPermIfCallerInOtherProfileGroup(int userId, String name) { + private void checkManageOrInteractPermIfCallerInOtherProfileGroup(@UserIdInt int userId, + String name) { int callingUserId = UserHandle.getCallingUserId(); if (callingUserId == userId || isSameProfileGroupNoChecks(callingUserId, userId) || hasManageUsersPermission()) { @@ -1204,7 +1205,7 @@ public class UserManagerService extends IUserManager.Stub { } @Override - public boolean isDemoUser(int userId) { + public boolean isDemoUser(@UserIdInt int userId) { int callingUserId = UserHandle.getCallingUserId(); if (callingUserId != userId && !hasManageUsersPermission()) { throw new SecurityException("You need MANAGE_USERS permission to query if u=" + userId @@ -1224,7 +1225,7 @@ public class UserManagerService extends IUserManager.Stub { } @Override - public boolean canHaveRestrictedProfile(int userId) { + public boolean canHaveRestrictedProfile(@UserIdInt int userId) { checkManageUsersPermission("canHaveRestrictedProfile"); synchronized (mUsersLock) { final UserInfo userInfo = getUserInfoLU(userId); @@ -1260,7 +1261,7 @@ public class UserManagerService extends IUserManager.Stub { * Should be locked on mUsers before calling this. */ @GuardedBy("mUsersLock") - private UserInfo getUserInfoLU(int userId) { + private UserInfo getUserInfoLU(@UserIdInt int userId) { final UserData userData = mUsers.get(userId); // If it is partial and not in the process of being removed, return as unknown user. if (userData != null && userData.info.partial && !mRemovingUserIds.get(userId)) { @@ -1271,7 +1272,7 @@ public class UserManagerService extends IUserManager.Stub { } @GuardedBy("mUsersLock") - private UserData getUserDataLU(int userId) { + private UserData getUserDataLU(@UserIdInt int userId) { final UserData userData = mUsers.get(userId); // If it is partial and not in the process of being removed, return as unknown user. if (userData != null && userData.info.partial && !mRemovingUserIds.get(userId)) { @@ -1284,7 +1285,7 @@ public class UserManagerService extends IUserManager.Stub { * Obtains {@link #mUsersLock} and return UserInfo from mUsers. * <p>No permissions checking or any addition checks are made</p> */ - private UserInfo getUserInfoNoChecks(int userId) { + private UserInfo getUserInfoNoChecks(@UserIdInt int userId) { synchronized (mUsersLock) { final UserData userData = mUsers.get(userId); return userData != null ? userData.info : null; @@ -1295,19 +1296,19 @@ public class UserManagerService extends IUserManager.Stub { * Obtains {@link #mUsersLock} and return UserData from mUsers. * <p>No permissions checking or any addition checks are made</p> */ - private UserData getUserDataNoChecks(int userId) { + private UserData getUserDataNoChecks(@UserIdInt int userId) { synchronized (mUsersLock) { return mUsers.get(userId); } } /** Called by PackageManagerService */ - public boolean exists(int userId) { + public boolean exists(@UserIdInt int userId) { return mLocalService.exists(userId); } @Override - public void setUserName(int userId, String name) { + public void setUserName(@UserIdInt int userId, String name) { checkManageUsersPermission("rename users"); boolean changed = false; synchronized (mPackagesLock) { @@ -1333,7 +1334,7 @@ public class UserManagerService extends IUserManager.Stub { } @Override - public void setUserIcon(int userId, Bitmap bitmap) { + public void setUserIcon(@UserIdInt int userId, Bitmap bitmap) { checkManageUsersPermission("update users"); if (hasUserRestriction(UserManager.DISALLOW_SET_USER_ICON, userId)) { Log.w(LOG_TAG, "Cannot set user icon. DISALLOW_SET_USER_ICON is enabled."); @@ -1344,7 +1345,7 @@ public class UserManagerService extends IUserManager.Stub { - private void sendUserInfoChangedBroadcast(int userId) { + private void sendUserInfoChangedBroadcast(@UserIdInt int userId) { Intent changedIntent = new Intent(Intent.ACTION_USER_INFO_CHANGED); changedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId); changedIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); @@ -1389,7 +1390,7 @@ public class UserManagerService extends IUserManager.Stub { return null; } - public void makeInitialized(int userId) { + public void makeInitialized(@UserIdInt int userId) { checkManageUsersPermission("makeInitialized"); boolean scheduleWriteUser = false; UserData userData; @@ -1447,8 +1448,8 @@ public class UserManagerService extends IUserManager.Stub { /** * See {@link UserManagerInternal#setDevicePolicyUserRestrictions} */ - private void setDevicePolicyUserRestrictionsInner(int userId, @Nullable Bundle restrictions, - boolean isDeviceOwner, int cameraRestrictionScope) { + private void setDevicePolicyUserRestrictionsInner(@UserIdInt int userId, + @Nullable Bundle restrictions, boolean isDeviceOwner, int cameraRestrictionScope) { final Bundle global = new Bundle(); final Bundle local = new Bundle(); @@ -1505,8 +1506,8 @@ public class UserManagerService extends IUserManager.Stub { * empty, record is removed from the array. * @return whether restrictions bundle is different from the old one. */ - private boolean updateRestrictionsIfNeededLR(int userId, @Nullable Bundle restrictions, - SparseArray<Bundle> restrictionsArray) { + private boolean updateRestrictionsIfNeededLR(@UserIdInt int userId, + @Nullable Bundle restrictions, SparseArray<Bundle> restrictionsArray) { final boolean changed = !UserRestrictionsUtils.areEqual(restrictionsArray.get(userId), restrictions); if (changed) { @@ -1520,7 +1521,7 @@ public class UserManagerService extends IUserManager.Stub { } @GuardedBy("mRestrictionsLock") - private Bundle computeEffectiveUserRestrictionsLR(int userId) { + private Bundle computeEffectiveUserRestrictionsLR(@UserIdInt int userId) { final Bundle baseRestrictions = UserRestrictionsUtils.nonNull(mBaseUserRestrictions.get(userId)); final Bundle global = UserRestrictionsUtils.mergeAll(mDevicePolicyGlobalUserRestrictions); @@ -1538,14 +1539,14 @@ public class UserManagerService extends IUserManager.Stub { } @GuardedBy("mRestrictionsLock") - private void invalidateEffectiveUserRestrictionsLR(int userId) { + private void invalidateEffectiveUserRestrictionsLR(@UserIdInt int userId) { if (DBG) { Log.d(LOG_TAG, "invalidateEffectiveUserRestrictions userId=" + userId); } mCachedEffectiveUserRestrictions.remove(userId); } - private Bundle getEffectiveUserRestrictions(int userId) { + private Bundle getEffectiveUserRestrictions(@UserIdInt int userId) { synchronized (mRestrictionsLock) { Bundle restrictions = mCachedEffectiveUserRestrictions.get(userId); if (restrictions == null) { @@ -1558,7 +1559,7 @@ public class UserManagerService extends IUserManager.Stub { /** @return a specific user restriction that's in effect currently. */ @Override - public boolean hasUserRestriction(String restrictionKey, int userId) { + public boolean hasUserRestriction(String restrictionKey, @UserIdInt int userId) { return mLocalService.hasUserRestriction(restrictionKey, userId); } @@ -1593,7 +1594,7 @@ public class UserManagerService extends IUserManager.Stub { * and {@link UserManager#RESTRICTION_SOURCE_PROFILE_OWNER} */ @Override - public int getUserRestrictionSource(String restrictionKey, int userId) { + public int getUserRestrictionSource(String restrictionKey, @UserIdInt int userId) { List<EnforcingUser> enforcingUsers = getUserRestrictionSources(restrictionKey, userId); // Get "bitwise or" of restriction sources for all enforcing users. int result = UserManager.RESTRICTION_NOT_SET; @@ -1652,12 +1653,12 @@ public class UserManagerService extends IUserManager.Stub { * {@link Bundle}. */ @Override - public Bundle getUserRestrictions(int userId) { + public Bundle getUserRestrictions(@UserIdInt int userId) { return UserRestrictionsUtils.clone(getEffectiveUserRestrictions(userId)); } @Override - public boolean hasBaseUserRestriction(String restrictionKey, int userId) { + public boolean hasBaseUserRestriction(String restrictionKey, @UserIdInt int userId) { checkManageUsersPermission("hasBaseUserRestriction"); if (!UserRestrictionsUtils.isValidRestriction(restrictionKey)) { return false; @@ -1669,7 +1670,7 @@ public class UserManagerService extends IUserManager.Stub { } @Override - public void setUserRestriction(String key, boolean value, int userId) { + public void setUserRestriction(String key, boolean value, @UserIdInt int userId) { checkManageUsersPermission("setUserRestriction"); if (!UserRestrictionsUtils.isValidRestriction(key)) { return; @@ -1695,7 +1696,7 @@ public class UserManagerService extends IUserManager.Stub { */ @GuardedBy("mRestrictionsLock") private void updateUserRestrictionsInternalLR( - @Nullable Bundle newBaseRestrictions, int userId) { + @Nullable Bundle newBaseRestrictions, @UserIdInt int userId) { final Bundle prevAppliedRestrictions = UserRestrictionsUtils.nonNull( mAppliedUserRestrictions.get(userId)); @@ -1779,7 +1780,7 @@ public class UserManagerService extends IUserManager.Stub { // Package private for the inner class. @GuardedBy("mRestrictionsLock") - void applyUserRestrictionsLR(int userId) { + void applyUserRestrictionsLR(@UserIdInt int userId) { updateUserRestrictionsInternalLR(null, userId); } @@ -1831,7 +1832,7 @@ public class UserManagerService extends IUserManager.Stub { } @Override - public boolean canAddMoreManagedProfiles(int userId, boolean allowedToRemoveOne) { + public boolean canAddMoreManagedProfiles(@UserIdInt int userId, boolean allowedToRemoveOne) { checkManageUsersPermission("check if more managed profiles can be added."); if (ActivityManager.isLowRamDeviceStatic()) { return false; @@ -2661,7 +2662,7 @@ public class UserManagerService extends IUserManager.Stub { /** * Removes the app restrictions file for a specific package and user id, if it exists. */ - private static void cleanAppRestrictionsForPackageLAr(String pkg, int userId) { + private static void cleanAppRestrictionsForPackageLAr(String pkg, @UserIdInt int userId) { File dir = Environment.getUserSystemDirectory(userId); File resFile = new File(dir, packageToRestrictionsFileName(pkg)); if (resFile.exists()) { @@ -2670,23 +2671,23 @@ public class UserManagerService extends IUserManager.Stub { } @Override - public UserInfo createProfileForUser(String name, int flags, int userId, + public UserInfo createProfileForUser(String name, int flags, @UserIdInt int userId, String[] disallowedPackages) { checkManageOrCreateUsersPermission(flags); return createUserInternal(name, flags, userId, disallowedPackages); } @Override - public UserInfo createProfileForUserEvenWhenDisallowed(String name, int flags, int userId, - String[] disallowedPackages) { + public UserInfo createProfileForUserEvenWhenDisallowed(String name, int flags, + @UserIdInt int userId, String[] disallowedPackages) { checkManageOrCreateUsersPermission(flags); return createUserInternalUnchecked(name, flags, userId, disallowedPackages); } @Override - public boolean removeUserEvenWhenDisallowed(@UserIdInt int userHandle) { + public boolean removeUserEvenWhenDisallowed(@UserIdInt int userId) { checkManageOrCreateUsersPermission("Only the system can remove users"); - return removeUserUnchecked(userHandle); + return removeUserUnchecked(userId); } @Override @@ -2871,7 +2872,7 @@ public class UserManagerService extends IUserManager.Stub { } @VisibleForTesting - void removeUserInfo(int userId) { + void removeUserInfo(@UserIdInt int userId) { synchronized (mUsers) { mUsers.remove(userId); } @@ -2923,11 +2924,11 @@ public class UserManagerService extends IUserManager.Stub { /** * Mark this guest user for deletion to allow us to create another guest * and switch to that user before actually removing this guest. - * @param userHandle the userid of the current guest + * @param userId the userid of the current guest * @return whether the user could be marked for deletion */ @Override - public boolean markGuestForDeletion(int userHandle) { + public boolean markGuestForDeletion(@UserIdInt int userId) { checkManageUsersPermission("Only the system can remove users"); if (getUserRestrictions(UserHandle.getCallingUserId()).getBoolean( UserManager.DISALLOW_REMOVE_USER, false)) { @@ -2940,8 +2941,8 @@ public class UserManagerService extends IUserManager.Stub { final UserData userData; synchronized (mPackagesLock) { synchronized (mUsersLock) { - userData = mUsers.get(userHandle); - if (userHandle == 0 || userData == null || mRemovingUserIds.get(userHandle)) { + userData = mUsers.get(userId); + if (userId == 0 || userData == null || mRemovingUserIds.get(userId)) { return false; } } @@ -2968,16 +2969,16 @@ public class UserManagerService extends IUserManager.Stub { /** * Removes a user and all data directories created for that user. This method should be called * after the user's processes have been terminated. - * @param userHandle the user's id + * @param userId the user's id */ @Override - public boolean removeUser(int userHandle) { - Slog.i(LOG_TAG, "removeUser u" + userHandle); + public boolean removeUser(@UserIdInt int userId) { + Slog.i(LOG_TAG, "removeUser u" + userId); checkManageOrCreateUsersPermission("Only the system can remove users"); final boolean isManagedProfile; synchronized (mUsersLock) { - UserInfo userInfo = getUserInfoLU(userHandle); + UserInfo userInfo = getUserInfoLU(userId); isManagedProfile = userInfo != null && userInfo.isManagedProfile(); } String restriction = isManagedProfile @@ -2986,39 +2987,39 @@ public class UserManagerService extends IUserManager.Stub { Log.w(LOG_TAG, "Cannot remove user. " + restriction + " is enabled."); return false; } - return removeUserUnchecked(userHandle); + return removeUserUnchecked(userId); } - private boolean removeUserUnchecked(int userHandle) { + private boolean removeUserUnchecked(@UserIdInt int userId) { long ident = Binder.clearCallingIdentity(); try { final UserData userData; int currentUser = ActivityManager.getCurrentUser(); - if (currentUser == userHandle) { + if (currentUser == userId) { Log.w(LOG_TAG, "Current user cannot be removed."); return false; } synchronized (mPackagesLock) { synchronized (mUsersLock) { - userData = mUsers.get(userHandle); - if (userHandle == UserHandle.USER_SYSTEM) { + userData = mUsers.get(userId); + if (userId == UserHandle.USER_SYSTEM) { Log.e(LOG_TAG, "System user cannot be removed."); return false; } if (userData == null) { Log.e(LOG_TAG, String.format( - "Cannot remove user %d, invalid user id provided.", userHandle)); + "Cannot remove user %d, invalid user id provided.", userId)); return false; } - if (mRemovingUserIds.get(userHandle)) { + if (mRemovingUserIds.get(userId)) { Log.e(LOG_TAG, String.format( - "User %d is already scheduled for removal.", userHandle)); + "User %d is already scheduled for removal.", userId)); return false; } - addRemovingUserIdLocked(userHandle); + addRemovingUserIdLocked(userId); } // Set this to a partially created user, so that the user will be purged @@ -3031,7 +3032,7 @@ public class UserManagerService extends IUserManager.Stub { writeUserLP(userData); } try { - mAppOpsService.removeUser(userHandle); + mAppOpsService.removeUser(userId); } catch (RemoteException e) { Log.w(LOG_TAG, "Unable to notify AppOpsService of removing user.", e); } @@ -3043,17 +3044,17 @@ public class UserManagerService extends IUserManager.Stub { sendProfileRemovedBroadcast(userData.info.profileGroupId, userData.info.id); } - if (DBG) Slog.i(LOG_TAG, "Stopping user " + userHandle); + if (DBG) Slog.i(LOG_TAG, "Stopping user " + userId); int res; try { - res = ActivityManager.getService().stopUser(userHandle, /* force= */ true, + res = ActivityManager.getService().stopUser(userId, /* force= */ true, new IStopUserCallback.Stub() { @Override - public void userStopped(int userId) { - finishRemoveUser(userId); + public void userStopped(int userIdParam) { + finishRemoveUser(userIdParam); } @Override - public void userStopAborted(int userId) { + public void userStopAborted(int userIdParam) { } }); } catch (RemoteException e) { @@ -3068,7 +3069,7 @@ public class UserManagerService extends IUserManager.Stub { @GuardedBy("mUsersLock") @VisibleForTesting - void addRemovingUserIdLocked(int userId) { + void addRemovingUserIdLocked(@UserIdInt int userId) { // We remember deleted user IDs to prevent them from being // reused during the current boot; they can still be reused // after a reboot or recycling of userIds. @@ -3080,14 +3081,14 @@ public class UserManagerService extends IUserManager.Stub { } } - void finishRemoveUser(final int userHandle) { - if (DBG) Slog.i(LOG_TAG, "finishRemoveUser " + userHandle); + void finishRemoveUser(final @UserIdInt int userId) { + if (DBG) Slog.i(LOG_TAG, "finishRemoveUser " + userId); // Let other services shutdown any activity and clean up their state before completely // wiping the user's system directory and removing from the user list long ident = Binder.clearCallingIdentity(); try { Intent addedIntent = new Intent(Intent.ACTION_USER_REMOVED); - addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userHandle); + addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId); mContext.sendOrderedBroadcastAsUser(addedIntent, UserHandle.ALL, android.Manifest.permission.MANAGE_USERS, @@ -3097,15 +3098,15 @@ public class UserManagerService extends IUserManager.Stub { if (DBG) { Slog.i(LOG_TAG, "USER_REMOVED broadcast sent, cleaning up user data " - + userHandle); + + userId); } new Thread() { @Override public void run() { // Clean up any ActivityTaskManager state LocalServices.getService(ActivityTaskManagerInternal.class) - .onUserStopped(userHandle); - removeUserState(userHandle); + .onUserStopped(userId); + removeUserState(userId); } }.start(); } @@ -3117,47 +3118,46 @@ public class UserManagerService extends IUserManager.Stub { } } - private void removeUserState(final int userHandle) { + private void removeUserState(final @UserIdInt int userId) { try { - mContext.getSystemService(StorageManager.class).destroyUserKey(userHandle); + mContext.getSystemService(StorageManager.class).destroyUserKey(userId); } catch (IllegalStateException e) { // This may be simply because the user was partially created. - Slog.i(LOG_TAG, - "Destroying key for user " + userHandle + " failed, continuing anyway", e); + Slog.i(LOG_TAG, "Destroying key for user " + userId + " failed, continuing anyway", e); } // Cleanup gatekeeper secure user id try { final IGateKeeperService gk = GateKeeper.getService(); if (gk != null) { - gk.clearSecureUserId(userHandle); + gk.clearSecureUserId(userId); } } catch (Exception ex) { Slog.w(LOG_TAG, "unable to clear GK secure user id"); } // Cleanup package manager settings - mPm.cleanUpUser(this, userHandle); + mPm.cleanUpUser(this, userId); // Clean up all data before removing metadata - mUserDataPreparer.destroyUserData(userHandle, + mUserDataPreparer.destroyUserData(userId, StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE); // Remove this user from the list synchronized (mUsersLock) { - mUsers.remove(userHandle); - mIsUserManaged.delete(userHandle); + mUsers.remove(userId); + mIsUserManaged.delete(userId); } synchronized (mUserStates) { - mUserStates.delete(userHandle); + mUserStates.delete(userId); } synchronized (mRestrictionsLock) { - mBaseUserRestrictions.remove(userHandle); - mAppliedUserRestrictions.remove(userHandle); - mCachedEffectiveUserRestrictions.remove(userHandle); - mDevicePolicyLocalUserRestrictions.remove(userHandle); - if (mDevicePolicyGlobalUserRestrictions.get(userHandle) != null) { - mDevicePolicyGlobalUserRestrictions.remove(userHandle); + mBaseUserRestrictions.remove(userId); + mAppliedUserRestrictions.remove(userId); + mCachedEffectiveUserRestrictions.remove(userId); + mDevicePolicyLocalUserRestrictions.remove(userId); + if (mDevicePolicyGlobalUserRestrictions.get(userId) != null) { + mDevicePolicyGlobalUserRestrictions.remove(userId); applyUserRestrictionsForAllUsersLR(); } } @@ -3166,12 +3166,12 @@ public class UserManagerService extends IUserManager.Stub { writeUserListLP(); } // Remove user file - AtomicFile userFile = new AtomicFile(new File(mUsersDir, userHandle + XML_SUFFIX)); + AtomicFile userFile = new AtomicFile(new File(mUsersDir, userId + XML_SUFFIX)); userFile.delete(); updateUserIds(); if (RELEASE_DELETED_USER_ID) { synchronized (mUsers) { - mRemovingUserIds.delete(userHandle); + mRemovingUserIds.delete(userId); } } } @@ -3191,7 +3191,7 @@ public class UserManagerService extends IUserManager.Stub { } @Override - public Bundle getApplicationRestrictionsForUser(String packageName, int userId) { + public Bundle getApplicationRestrictionsForUser(String packageName, @UserIdInt int userId) { if (UserHandle.getCallingUserId() != userId || !UserHandle.isSameApp(Binder.getCallingUid(), getUidForPackage(packageName))) { checkSystemOrRoot("get application restrictions for other user/app " + packageName); @@ -3204,7 +3204,7 @@ public class UserManagerService extends IUserManager.Stub { @Override public void setApplicationRestrictions(String packageName, Bundle restrictions, - int userId) { + @UserIdInt int userId) { checkSystemOrRoot("set application restrictions"); if (restrictions != null) { restrictions.setDefusable(true); @@ -3238,7 +3238,8 @@ public class UserManagerService extends IUserManager.Stub { } @GuardedBy("mAppRestrictionsLock") - private static Bundle readApplicationRestrictionsLAr(String packageName, int userId) { + private static Bundle readApplicationRestrictionsLAr(String packageName, + @UserIdInt int userId) { AtomicFile restrictionsFile = new AtomicFile(new File(Environment.getUserSystemDirectory(userId), packageToRestrictionsFileName(packageName))); @@ -3332,7 +3333,7 @@ public class UserManagerService extends IUserManager.Stub { @GuardedBy("mAppRestrictionsLock") private static void writeApplicationRestrictionsLAr(String packageName, - Bundle restrictions, int userId) { + Bundle restrictions, @UserIdInt int userId) { AtomicFile restrictionsFile = new AtomicFile( new File(Environment.getUserSystemDirectory(userId), packageToRestrictionsFileName(packageName))); @@ -3410,17 +3411,17 @@ public class UserManagerService extends IUserManager.Stub { } @Override - public int getUserSerialNumber(int userHandle) { + public int getUserSerialNumber(@UserIdInt int userId) { synchronized (mUsersLock) { - final UserInfo userInfo = getUserInfoLU(userHandle); + final UserInfo userInfo = getUserInfoLU(userId); return userInfo != null ? userInfo.serialNumber : -1; } } @Override - public boolean isUserNameSet(int userHandle) { + public boolean isUserNameSet(@UserIdInt int userId) { synchronized (mUsersLock) { - final UserInfo userInfo = getUserInfoLU(userHandle); + final UserInfo userInfo = getUserInfoLU(userId); return userInfo != null && userInfo.name != null; } } @@ -3438,21 +3439,21 @@ public class UserManagerService extends IUserManager.Stub { } @Override - public long getUserCreationTime(int userHandle) { + public long getUserCreationTime(@UserIdInt int userId) { int callingUserId = UserHandle.getCallingUserId(); UserInfo userInfo = null; synchronized (mUsersLock) { - if (callingUserId == userHandle) { - userInfo = getUserInfoLU(userHandle); + if (callingUserId == userId) { + userInfo = getUserInfoLU(userId); } else { - UserInfo parent = getProfileParentLU(userHandle); + UserInfo parent = getProfileParentLU(userId); if (parent != null && parent.id == callingUserId) { - userInfo = getUserInfoLU(userHandle); + userInfo = getUserInfoLU(userId); } } } if (userInfo == null) { - throw new SecurityException("userHandle can only be the calling user or a managed " + throw new SecurityException("userId can only be the calling user or a managed " + "profile associated with this user"); } return userInfo.creationTime; @@ -3485,7 +3486,7 @@ public class UserManagerService extends IUserManager.Stub { * Called right before a user is started. This gives us a chance to prepare * app storage and apply any user restrictions. */ - public void onBeforeStartUser(int userId) { + public void onBeforeStartUser(@UserIdInt int userId) { UserInfo userInfo = getUserInfo(userId); if (userInfo == null) { return; @@ -3600,7 +3601,7 @@ public class UserManagerService extends IUserManager.Stub { } @Override - public void setSeedAccountData(int userId, String accountName, String accountType, + public void setSeedAccountData(@UserIdInt int userId, String accountName, String accountType, PersistableBundle accountOptions, boolean persist) { checkManageUsersPermission("Require MANAGE_USERS permission to set user seed data"); synchronized (mPackagesLock) { @@ -3881,20 +3882,20 @@ public class UserManagerService extends IUserManager.Stub { * @param userId * @return whether the user has been initialized yet */ - boolean isUserInitialized(int userId) { + boolean isUserInitialized(@UserIdInt int userId) { return mLocalService.isUserInitialized(userId); } private class LocalService extends UserManagerInternal { @Override - public void setDevicePolicyUserRestrictions(int userId, @Nullable Bundle restrictions, - boolean isDeviceOwner, int cameraRestrictionScope) { + public void setDevicePolicyUserRestrictions(@UserIdInt int userId, + @Nullable Bundle restrictions, boolean isDeviceOwner, int cameraRestrictionScope) { UserManagerService.this.setDevicePolicyUserRestrictionsInner(userId, restrictions, isDeviceOwner, cameraRestrictionScope); } @Override - public Bundle getBaseUserRestrictions(int userId) { + public Bundle getBaseUserRestrictions(@UserIdInt int userId) { synchronized (mRestrictionsLock) { return mBaseUserRestrictions.get(userId); } @@ -3902,7 +3903,7 @@ public class UserManagerService extends IUserManager.Stub { @Override public void setBaseUserRestrictionsByDpmsForMigration( - int userId, Bundle baseRestrictions) { + @UserIdInt int userId, Bundle baseRestrictions) { synchronized (mRestrictionsLock) { if (updateRestrictionsIfNeededLR( userId, new Bundle(baseRestrictions), mBaseUserRestrictions)) { @@ -3921,7 +3922,7 @@ public class UserManagerService extends IUserManager.Stub { } @Override - public boolean getUserRestriction(int userId, String key) { + public boolean getUserRestriction(@UserIdInt int userId, String key) { return getUserRestrictions(userId).getBoolean(key); } @@ -3947,14 +3948,14 @@ public class UserManagerService extends IUserManager.Stub { } @Override - public void setUserManaged(int userId, boolean isManaged) { + public void setUserManaged(@UserIdInt int userId, boolean isManaged) { synchronized (mUsersLock) { mIsUserManaged.put(userId, isManaged); } } @Override - public void setUserIcon(int userId, Bitmap bitmap) { + public void setUserIcon(@UserIdInt int userId, Bitmap bitmap) { long ident = Binder.clearCallingIdentity(); try { synchronized (mPackagesLock) { @@ -4011,7 +4012,7 @@ public class UserManagerService extends IUserManager.Stub { } @Override - public void onEphemeralUserStop(int userId) { + public void onEphemeralUserStop(@UserIdInt int userId) { synchronized (mUsersLock) { UserInfo userInfo = getUserInfoLU(userId); if (userInfo != null && userInfo.isEphemeral()) { @@ -4040,26 +4041,26 @@ public class UserManagerService extends IUserManager.Stub { } @Override - public boolean removeUserEvenWhenDisallowed(int userId) { + public boolean removeUserEvenWhenDisallowed(@UserIdInt int userId) { return removeUserUnchecked(userId); } @Override - public boolean isUserRunning(int userId) { + public boolean isUserRunning(@UserIdInt int userId) { synchronized (mUserStates) { return mUserStates.get(userId, -1) >= 0; } } @Override - public void setUserState(int userId, int userState) { + public void setUserState(@UserIdInt int userId, int userState) { synchronized (mUserStates) { mUserStates.put(userId, userState); } } @Override - public void removeUserState(int userId) { + public void removeUserState(@UserIdInt int userId) { synchronized (mUserStates) { mUserStates.delete(userId); } @@ -4071,7 +4072,7 @@ public class UserManagerService extends IUserManager.Stub { } @Override - public boolean isUserUnlockingOrUnlocked(int userId) { + public boolean isUserUnlockingOrUnlocked(@UserIdInt int userId) { int state; synchronized (mUserStates) { state = mUserStates.get(userId, -1); @@ -4085,7 +4086,7 @@ public class UserManagerService extends IUserManager.Stub { } @Override - public boolean isUserUnlocked(int userId) { + public boolean isUserUnlocked(@UserIdInt int userId) { int state; synchronized (mUserStates) { state = mUserStates.get(userId, -1); @@ -4098,12 +4099,12 @@ public class UserManagerService extends IUserManager.Stub { } @Override - public boolean isUserInitialized(int userId) { + public boolean isUserInitialized(@UserIdInt int userId) { return (getUserInfo(userId).flags & UserInfo.FLAG_INITIALIZED) != 0; } @Override - public boolean exists(int userId) { + public boolean exists(@UserIdInt int userId) { return getUserInfoNoChecks(userId) != null; } @@ -4147,7 +4148,7 @@ public class UserManagerService extends IUserManager.Stub { } @Override - public int getProfileParentId(int userId) { + public int getProfileParentId(@UserIdInt int userId) { synchronized (mUsersLock) { UserInfo profileParent = getProfileParentLU(userId); if (profileParent == null) { @@ -4165,7 +4166,7 @@ public class UserManagerService extends IUserManager.Stub { } @Override - public boolean hasUserRestriction(String restrictionKey, int userId) { + public boolean hasUserRestriction(String restrictionKey, @UserIdInt int userId) { if (!UserRestrictionsUtils.isValidRestriction(restrictionKey)) { return false; } @@ -4274,7 +4275,7 @@ public class UserManagerService extends IUserManager.Stub { * @param userId The parent user * @return */ - boolean hasManagedProfile(int userId) { + boolean hasManagedProfile(@UserIdInt int userId) { synchronized (mUsersLock) { UserInfo userInfo = getUserInfoLU(userId); final int userSize = mUsers.size(); diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java index 83aa07d446e8..a9e3f046e425 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java @@ -57,6 +57,7 @@ import android.app.AppOpsManager; import android.app.ApplicationPackageManager; import android.app.IActivityManager; import android.content.Context; +import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.PermissionGroupInfoFlags; import android.content.pm.PackageManager.PermissionInfoFlags; @@ -3750,7 +3751,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { // Make sure all dynamic permissions have been assigned to a package, // and make sure there are no dangling permissions. boolean permissionSourcePackageChanged = updatePermissionSourcePackage(changingPkgName, - changingPkg); + changingPkg, callback); if (permissionTreesSourcePackageChanged | permissionSourcePackageChanged) { // Permission ownership has changed. This e.g. changes which packages can get signature @@ -3803,7 +3804,8 @@ public class PermissionManagerService extends IPermissionManager.Stub { * @return {@code true} if a permission source package might have changed */ private boolean updatePermissionSourcePackage(@Nullable String packageName, - @Nullable PackageParser.Package pkg) { + @Nullable PackageParser.Package pkg, + final @Nullable PermissionCallback callback) { boolean changed = false; Set<BasePermission> needsUpdate = null; @@ -3819,6 +3821,45 @@ public class PermissionManagerService extends IPermissionManager.Stub { && (pkg == null || !hasPermission(pkg, bp.getName()))) { Slog.i(TAG, "Removing permission " + bp.getName() + " that used to be declared by " + bp.getSourcePackageName()); + if (bp.isRuntime()) { + final int[] userIds = mUserManagerInt.getUserIds(); + final int numUserIds = userIds.length; + for (int userIdNum = 0; userIdNum < numUserIds; userIdNum++) { + final int userId = userIds[userIdNum]; + + mPackageManagerInt.forEachPackage((Package p) -> { + final String pName = p.packageName; + final ApplicationInfo appInfo = + mPackageManagerInt.getApplicationInfo(pName, 0, + Process.SYSTEM_UID, UserHandle.USER_SYSTEM); + if (appInfo != null + && appInfo.targetSdkVersion < Build.VERSION_CODES.M) { + return; + } + + final String permissionName = bp.getName(); + if (checkPermissionImpl(permissionName, pName, userId) + == PackageManager.PERMISSION_GRANTED) { + try { + revokeRuntimePermissionInternal( + permissionName, + pName, + false, + Process.SYSTEM_UID, + userId, + callback); + } catch (IllegalArgumentException e) { + Slog.e(TAG, + "Failed to revoke " + + permissionName + + " from " + + pName, + e); + } + } + }); + } + } changed = true; it.remove(); } diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java index a671e5f9a150..3147bc629ffa 100644 --- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java +++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java @@ -568,6 +568,10 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { } void onUnlockUser(int userId) { + // In order to ensure that no package begins running while a backup or restore is taking + // place, onUnlockUser must remain blocked until all pending backups and restores have + // completed. + CountDownLatch latch = new CountDownLatch(1); getHandler().post(() -> { final List<Rollback> rollbacks; synchronized (mLock) { @@ -580,7 +584,14 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { for (Rollback rollback : changed) { saveRollback(rollback); } + latch.countDown(); }); + + try { + latch.await(); + } catch (InterruptedException ie) { + throw new IllegalStateException("RollbackManagerHandlerThread interrupted"); + } } private void updateRollbackLifetimeDurationInMillis() { diff --git a/services/core/java/com/android/server/webkit/WebViewUpdater.java b/services/core/java/com/android/server/webkit/WebViewUpdater.java index a460040d0a60..3b58af2a200f 100644 --- a/services/core/java/com/android/server/webkit/WebViewUpdater.java +++ b/services/core/java/com/android/server/webkit/WebViewUpdater.java @@ -87,19 +87,6 @@ class WebViewUpdater { newPackage = findPreferredWebViewPackage(); if (mCurrentWebViewPackage != null) { oldProviderName = mCurrentWebViewPackage.packageName; - if (changedState == WebViewUpdateService.PACKAGE_CHANGED - && newPackage.packageName.equals(oldProviderName)) { - // If we don't change package name we should only rerun the - // preparation phase if the current package has been replaced - // (not if it has been enabled/disabled). - return; - } - if (newPackage.packageName.equals(oldProviderName) - && (newPackage.lastUpdateTime - == mCurrentWebViewPackage.lastUpdateTime)) { - // If the chosen package hasn't been updated, then early-out - return; - } } // Only trigger update actions if the updated package is the one // that will be used, or the one that was in use before the diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java index f5f6625c8728..b92625fe14af 100644 --- a/services/core/java/com/android/server/wm/ActivityStack.java +++ b/services/core/java/com/android/server/wm/ActivityStack.java @@ -33,6 +33,7 @@ import static android.app.WindowConfiguration.windowingModeToString; import static android.content.pm.ActivityInfo.CONFIG_SCREEN_LAYOUT; import static android.content.pm.ActivityInfo.FLAG_RESUME_WHILE_PAUSING; import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS; +import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD; import static android.view.Display.INVALID_DISPLAY; @@ -134,6 +135,7 @@ import android.os.Looper; import android.os.Message; import android.os.RemoteException; import android.os.SystemClock; +import android.os.Trace; import android.os.UserHandle; import android.service.voice.IVoiceInteractionSession; import android.util.ArraySet; @@ -635,11 +637,15 @@ class ActivityStack extends ConfigurationContainer { display.onStackWindowingModeChanged(this); } if (hasNewOverrideBounds) { - // Note the resizeStack may enter onConfigurationChanged recursively, so we make a copy - // of the temporary bounds (newBounds is mTmpRect) to avoid it being modified. - mRootActivityContainer.resizeStack(this, new Rect(newBounds), null /* tempTaskBounds */, - null /* tempTaskInsetBounds */, PRESERVE_WINDOWS, - true /* allowResizeInDockedMode */, true /* deferResume */); + if (inSplitScreenPrimaryWindowingMode()) { + mStackSupervisor.resizeDockedStackLocked(new Rect(newBounds), + null /* tempTaskBounds */, null /* tempTaskInsetBounds */, + null /* tempOtherTaskBounds */, null /* tempOtherTaskInsetBounds */, + PRESERVE_WINDOWS, true /* deferResume */); + } else { + resize(new Rect(newBounds), null /* tempTaskBounds */, + null /* tempTaskInsetBounds */, PRESERVE_WINDOWS, true /* deferResume */); + } } if (prevIsAlwaysOnTop != isAlwaysOnTop()) { // Since always on top is only on when the stack is freeform or pinned, the state @@ -818,7 +824,8 @@ class ActivityStack extends ConfigurationContainer { } if (!Objects.equals(getRequestedOverrideBounds(), mTmpRect2)) { - resize(mTmpRect2, null /* tempTaskBounds */, null /* tempTaskInsetBounds */); + resize(mTmpRect2, null /* tempTaskBounds */, null /* tempTaskInsetBounds */, + false /* preserveWindows */, true /* deferResume */); } } finally { if (showRecents && !alreadyInSplitScreenMode && mDisplayId == DEFAULT_DISPLAY @@ -2208,7 +2215,7 @@ class ActivityStack extends ConfigurationContainer { * Returns true if this stack should be resized to match the bounds specified by * {@link ActivityOptions#setLaunchBounds} when launching an activity into the stack. */ - boolean resizeStackWithLaunchBounds() { + boolean shouldResizeStackWithLaunchBounds() { return inPinnedWindowingMode(); } @@ -4344,31 +4351,42 @@ class ActivityStack extends ConfigurationContainer { } } - // TODO: Figure-out a way to consolidate with resize() method below. - void requestResize(Rect bounds) { - mService.resizeStack(mStackId, bounds, - true /* allowResizeInDockedMode */, false /* preserveWindows */, - false /* animate */, -1 /* animationDuration */); - } - // TODO: Can only be called from special methods in ActivityStackSupervisor. // Need to consolidate those calls points into this resize method so anyone can call directly. - void resize(Rect bounds, Rect tempTaskBounds, Rect tempTaskInsetBounds) { + void resize(Rect bounds, Rect tempTaskBounds, Rect tempTaskInsetBounds, + boolean preserveWindows, boolean deferResume) { if (!updateBoundsAllowed(bounds)) { return; } - // Update override configurations of all tasks in the stack. - final Rect taskBounds = tempTaskBounds != null ? tempTaskBounds : bounds; + Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "stack.resize_" + mStackId); + mWindowManager.deferSurfaceLayout(); + try { + // Update override configurations of all tasks in the stack. + final Rect taskBounds = tempTaskBounds != null ? tempTaskBounds : bounds; + for (int i = mTaskHistory.size() - 1; i >= 0; i--) { + final TaskRecord task = mTaskHistory.get(i); + if (task.isResizeable()) { + if (tempTaskInsetBounds != null && !tempTaskInsetBounds.isEmpty()) { + task.setDisplayedBounds(taskBounds); + task.setBounds(tempTaskInsetBounds); + } else { + task.setDisplayedBounds(null); + task.setBounds(taskBounds); + } + } + } - for (int i = mTaskHistory.size() - 1; i >= 0; i--) { - final TaskRecord task = mTaskHistory.get(i); - if (task.isResizeable()) { - task.updateOverrideConfiguration(taskBounds, tempTaskInsetBounds); + setBounds(bounds); + + if (!deferResume) { + ensureVisibleActivitiesConfigurationLocked( + topRunningActivityLocked(), preserveWindows); } + } finally { + mWindowManager.continueSurfaceLayout(); + Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); } - - setBounds(bounds); } void onPipAnimationEndResize() { @@ -4497,18 +4515,27 @@ class ActivityStack extends ConfigurationContainer { * then skip running tasks that match those types. */ void getRunningTasks(List<TaskRecord> tasksOut, @ActivityType int ignoreActivityType, - @WindowingMode int ignoreWindowingMode, int callingUid, boolean allowed) { + @WindowingMode int ignoreWindowingMode, int callingUid, boolean allowed, + boolean crossUser) { boolean focusedStack = mRootActivityContainer.getTopDisplayFocusedStack() == this; boolean topTask = true; + int userId = UserHandle.getUserId(callingUid); for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { final TaskRecord task = mTaskHistory.get(taskNdx); if (task.getTopActivity() == null) { // Skip if there are no activities in the task continue; } - if (!allowed && !task.isActivityTypeHome() && task.effectiveUid != callingUid) { - // Skip if the caller can't fetch this task - continue; + if (task.effectiveUid != callingUid) { + if (task.userId != userId && !crossUser) { + // Skip if the caller does not have cross user permission + continue; + } + if (!allowed && !task.isActivityTypeHome()) { + // Skip if the caller isn't allowed to fetch this task, except for the home + // task which we always return. + continue; + } } if (ignoreActivityType != ACTIVITY_TYPE_UNDEFINED && task.getActivityType() == ignoreActivityType) { @@ -4774,7 +4801,7 @@ class ActivityStack extends ConfigurationContainer { if (!mStackSupervisor.getLaunchParamsController() .layoutTask(task, info.windowLayout, activity, source, options) && !matchParentBounds() && task.isResizeable() && !isLockscreenShown) { - task.updateOverrideConfiguration(getRequestedOverrideBounds()); + task.setBounds(getRequestedOverrideBounds()); } task.createTask(toTop, (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0); return task; diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java index a480fb8f110f..7a3f022d60bf 100644 --- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java @@ -1398,7 +1398,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { boolean reparented = false; if (task.isResizeable() && canUseActivityOptionsLaunchBounds(options)) { final Rect bounds = options.getLaunchBounds(); - task.updateOverrideConfiguration(bounds); + task.setBounds(bounds); ActivityStack stack = mRootActivityContainer.getLaunchStack(null, options, task, ON_TOP); @@ -1412,10 +1412,9 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { // task.reparent() should already placed the task on top, // still need moveTaskToFrontLocked() below for any transition settings. } - if (stack.resizeStackWithLaunchBounds()) { - mRootActivityContainer.resizeStack(stack, bounds, null /* tempTaskBounds */, - null /* tempTaskInsetBounds */, !PRESERVE_WINDOWS, - true /* allowResizeInDockedMode */, !DEFER_RESUME); + if (stack.shouldResizeStackWithLaunchBounds()) { + stack.resize(bounds, null /* tempTaskBounds */, null /* tempTaskInsetBounds */, + !PRESERVE_WINDOWS, !DEFER_RESUME); } else { // WM resizeTask must be done after the task is moved to the correct stack, // because Task's setBounds() also updates dim layer's bounds, but that has @@ -1636,7 +1635,8 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { // Don't allow re-entry while resizing. E.g. due to docked stack detaching. mAllowDockedStackResize = false; ActivityRecord r = stack.topRunningActivityLocked(); - stack.resize(dockedBounds, tempDockedTaskBounds, tempDockedTaskInsetBounds); + stack.resize(dockedBounds, tempDockedTaskBounds, tempDockedTaskInsetBounds, + !PRESERVE_WINDOWS, DEFER_RESUME); // TODO: Checking for isAttached might not be needed as if the user passes in null // dockedBounds then they want the docked stack to be dismissed. @@ -1674,11 +1674,19 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { tempRect /* outStackBounds */, otherTaskRect /* outTempTaskBounds */); - mRootActivityContainer.resizeStack(current, - !tempRect.isEmpty() ? tempRect : null, + if (tempRect.isEmpty()) { + // If this scenario is hit, it means something is not working right. + // Empty/null bounds implies fullscreen. In the event that this stack + // *should* be fullscreen, its mode should be set explicitly in a form + // of setWindowingMode so that other parts of the system are updated + // properly. + throw new IllegalArgumentException("Trying to set null bounds on a" + + " non-fullscreen stack"); + } + + current.resize(tempRect, !otherTaskRect.isEmpty() ? otherTaskRect : tempOtherTaskBounds, - tempOtherTaskInsetBounds, preserveWindows, - true /* allowResizeInDockedMode */, deferResume); + tempOtherTaskInsetBounds, preserveWindows, deferResume); } } if (!deferResume) { @@ -1728,8 +1736,8 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { // transitioning it from fullscreen into a floating state. stack.onPipAnimationEndResize(); } - stack.resize(pinnedBounds, tempPinnedTaskBounds, insetBounds); - stack.ensureVisibleActivitiesConfigurationLocked(r, false); + stack.resize(pinnedBounds, tempPinnedTaskBounds, insetBounds, !PRESERVE_WINDOWS, + !DEFER_RESUME); } finally { mWindowManager.continueSurfaceLayout(); Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java index 5717e2fa02d2..641b00aeb70b 100644 --- a/services/core/java/com/android/server/wm/ActivityStarter.java +++ b/services/core/java/com/android/server/wm/ActivityStarter.java @@ -2400,11 +2400,10 @@ class ActivityStarter { } final ActivityStack stack = task.getStack(); - if (stack != null && stack.resizeStackWithLaunchBounds()) { - mService.resizeStack( - stack.mStackId, bounds, true, !PRESERVE_WINDOWS, ANIMATE, -1); + if (stack != null && stack.inPinnedWindowingMode()) { + mService.animateResizePinnedStack(stack.mStackId, bounds, -1); } else { - task.updateOverrideConfiguration(bounds); + task.setBounds(bounds); } } diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index ee56c0902e78..d97f0f5041a4 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -19,6 +19,8 @@ package com.android.server.wm; import static android.Manifest.permission.BIND_VOICE_INTERACTION; import static android.Manifest.permission.CHANGE_CONFIGURATION; import static android.Manifest.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS; +import static android.Manifest.permission.INTERACT_ACROSS_USERS; +import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL; import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW; import static android.Manifest.permission.MANAGE_ACTIVITY_STACKS; import static android.Manifest.permission.READ_FRAME_BUFFER; @@ -2508,15 +2510,16 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { @WindowConfiguration.ActivityType int ignoreActivityType, @WindowConfiguration.WindowingMode int ignoreWindowingMode) { final int callingUid = Binder.getCallingUid(); + final int callingPid = Binder.getCallingPid(); + final boolean crossUser = isCrossUserAllowed(callingPid, callingUid); ArrayList<ActivityManager.RunningTaskInfo> list = new ArrayList<>(); synchronized (mGlobalLock) { if (DEBUG_ALL) Slog.v(TAG, "getTasks: max=" + maxNum); - final boolean allowed = isGetTasksAllowed("getTasks", Binder.getCallingPid(), - callingUid); + final boolean allowed = isGetTasksAllowed("getTasks", callingPid, callingUid); mRootActivityContainer.getRunningTasks(maxNum, list, ignoreActivityType, - ignoreWindowingMode, callingUid, allowed); + ignoreWindowingMode, callingUid, allowed, crossUser); } return list; @@ -2582,35 +2585,23 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } @Override - public void resizeStack(int stackId, Rect destBounds, boolean allowResizeInDockedMode, - boolean preserveWindows, boolean animate, int animationDuration) { - enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "resizeStack()"); + public void animateResizePinnedStack(int stackId, Rect destBounds, int animationDuration) { + enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "animateResizePinnedStack()"); final long ident = Binder.clearCallingIdentity(); try { synchronized (mGlobalLock) { - if (animate) { - final ActivityStack stack = mRootActivityContainer.getStack(stackId); - if (stack == null) { - Slog.w(TAG, "resizeStack: stackId " + stackId + " not found."); - return; - } - if (stack.getWindowingMode() != WINDOWING_MODE_PINNED) { - throw new IllegalArgumentException("Stack: " + stackId - + " doesn't support animated resize."); - } - stack.animateResizePinnedStack(null /* sourceHintBounds */, destBounds, - animationDuration, false /* fromFullscreen */); - } else { - final ActivityStack stack = mRootActivityContainer.getStack(stackId); - if (stack == null) { - Slog.w(TAG, "resizeStack: stackId " + stackId + " not found."); - return; - } - mRootActivityContainer.resizeStack(stack, destBounds, - null /* tempTaskBounds */, null /* tempTaskInsetBounds */, - preserveWindows, allowResizeInDockedMode, !DEFER_RESUME); + final ActivityStack stack = mRootActivityContainer.getStack(stackId); + if (stack == null) { + Slog.w(TAG, "resizeStack: stackId " + stackId + " not found."); + return; + } + if (stack.getWindowingMode() != WINDOWING_MODE_PINNED) { + throw new IllegalArgumentException("Stack: " + stackId + + " doesn't support animated resize."); } + stack.animateResizePinnedStack(null /* sourceHintBounds */, destBounds, + animationDuration, false /* fromFullscreen */); } } finally { Binder.restoreCallingIdentity(ident); @@ -3546,6 +3537,11 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { return allowed; } + boolean isCrossUserAllowed(int pid, int uid) { + return checkPermission(INTERACT_ACROSS_USERS, pid, uid) == PERMISSION_GRANTED + || checkPermission(INTERACT_ACROSS_USERS_FULL, pid, uid) == PERMISSION_GRANTED; + } + private PendingAssistExtras enqueueAssistContext(int requestType, Intent intent, String hint, IAssistDataReceiver receiver, Bundle receiverExtras, IBinder activityToken, boolean focused, boolean newSessionId, int userHandle, Bundle args, long timeout, diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java index aecbca391735..b502bd54bfc5 100644 --- a/services/core/java/com/android/server/wm/DisplayPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayPolicy.java @@ -3551,7 +3551,8 @@ public class DisplayPolicy { if (mScreenshotHelper != null) { mScreenshotHelper.takeScreenshot(screenshotType, mStatusBar != null && mStatusBar.isVisibleLw(), - mNavigationBar != null && mNavigationBar.isVisibleLw(), mHandler); + mNavigationBar != null && mNavigationBar.isVisibleLw(), + mHandler, null /* completionConsumer */); } } diff --git a/services/core/java/com/android/server/wm/LaunchParamsController.java b/services/core/java/com/android/server/wm/LaunchParamsController.java index 59c02f736513..59df09be1ff5 100644 --- a/services/core/java/com/android/server/wm/LaunchParamsController.java +++ b/services/core/java/com/android/server/wm/LaunchParamsController.java @@ -152,7 +152,7 @@ class LaunchParamsController { if (task.getStack().inFreeformWindowingMode()) { // Only set bounds if it's in freeform mode. - task.updateOverrideConfiguration(mTmpParams.mBounds); + task.setBounds(mTmpParams.mBounds); return true; } diff --git a/services/core/java/com/android/server/wm/RootActivityContainer.java b/services/core/java/com/android/server/wm/RootActivityContainer.java index eb5d096aa781..50b5902e17d4 100644 --- a/services/core/java/com/android/server/wm/RootActivityContainer.java +++ b/services/core/java/com/android/server/wm/RootActivityContainer.java @@ -27,12 +27,10 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; -import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE; import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK; -import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.INVALID_DISPLAY; import static android.view.WindowManager.TRANSIT_SHOW_SINGLE_TASK_DISPLAY; @@ -93,7 +91,6 @@ import android.os.FactoryTest; import android.os.IBinder; import android.os.RemoteException; import android.os.SystemClock; -import android.os.Trace; import android.os.UserHandle; import android.os.storage.StorageManager; import android.provider.Settings; @@ -881,48 +878,6 @@ class RootActivityContainer extends ConfigurationContainer } } - void resizeStack(ActivityStack stack, Rect bounds, Rect tempTaskBounds, - Rect tempTaskInsetBounds, boolean preserveWindows, boolean allowResizeInDockedMode, - boolean deferResume) { - - if (stack.inSplitScreenPrimaryWindowingMode()) { - mStackSupervisor.resizeDockedStackLocked(bounds, tempTaskBounds, - tempTaskInsetBounds, null, null, preserveWindows, deferResume); - return; - } - - final boolean splitScreenActive = getDefaultDisplay().hasSplitScreenPrimaryStack(); - if (!allowResizeInDockedMode - && !stack.getWindowConfiguration().tasksAreFloating() && splitScreenActive) { - // If the docked stack exists, don't resize non-floating stacks independently of the - // size computed from the docked stack size (otherwise they will be out of sync) - return; - } - - Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "am.resizeStack_" + stack.mStackId); - mWindowManager.deferSurfaceLayout(); - try { - if (stack.affectedBySplitScreenResize()) { - if (bounds == null && stack.inSplitScreenWindowingMode()) { - // null bounds = fullscreen windowing mode...at least for now. - stack.setWindowingMode(WINDOWING_MODE_FULLSCREEN); - } else if (splitScreenActive) { - // If we are in split-screen mode and this stack support split-screen, then - // it should be split-screen secondary mode. i.e. adjacent to the docked stack. - stack.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY); - } - } - stack.resize(bounds, tempTaskBounds, tempTaskInsetBounds); - if (!deferResume) { - stack.ensureVisibleActivitiesConfigurationLocked( - stack.topRunningActivityLocked(), preserveWindows); - } - } finally { - mWindowManager.continueSurfaceLayout(); - Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); - } - } - /** * Move stack with all its existing content to specified display. * @param stackId Id of stack to move. @@ -1014,9 +969,8 @@ class RootActivityContainer extends ConfigurationContainer // Resize the pinned stack to match the current size of the task the activity we are // going to be moving is currently contained in. We do this to have the right starting // animation bounds for the pinned stack to the desired bounds the caller wants. - resizeStack(stack, task.getRequestedOverrideBounds(), null /* tempTaskBounds */, - null /* tempTaskInsetBounds */, !PRESERVE_WINDOWS, - true /* allowResizeInDockedMode */, !DEFER_RESUME); + stack.resize(task.getRequestedOverrideBounds(), null /* tempTaskBounds */, + null /* tempTaskInsetBounds */, !PRESERVE_WINDOWS, !DEFER_RESUME); if (task.mActivities.size() == 1) { // Defer resume until below, and do not schedule PiP changes until we animate below @@ -2260,9 +2214,9 @@ class RootActivityContainer extends ConfigurationContainer void getRunningTasks(int maxNum, List<ActivityManager.RunningTaskInfo> list, @WindowConfiguration.ActivityType int ignoreActivityType, @WindowConfiguration.WindowingMode int ignoreWindowingMode, int callingUid, - boolean allowed) { + boolean allowed, boolean crossUser) { mStackSupervisor.getRunningTasks().getTasks(maxNum, list, ignoreActivityType, - ignoreWindowingMode, mActivityDisplays, callingUid, allowed); + ignoreWindowingMode, mActivityDisplays, callingUid, allowed, crossUser); } void sendPowerHintForLaunchStartIfNeeded(boolean forceSend, ActivityRecord targetActivity) { diff --git a/services/core/java/com/android/server/wm/RunningTasks.java b/services/core/java/com/android/server/wm/RunningTasks.java index 3bf437d38bcc..22a9c32a830f 100644 --- a/services/core/java/com/android/server/wm/RunningTasks.java +++ b/services/core/java/com/android/server/wm/RunningTasks.java @@ -40,7 +40,7 @@ class RunningTasks { void getTasks(int maxNum, List<RunningTaskInfo> list, @ActivityType int ignoreActivityType, @WindowingMode int ignoreWindowingMode, ArrayList<ActivityDisplay> activityDisplays, - int callingUid, boolean allowed) { + int callingUid, boolean allowed, boolean crossUser) { // Return early if there are no tasks to fetch if (maxNum <= 0) { return; @@ -55,7 +55,7 @@ class RunningTasks { final ActivityStack stack = display.getChildAt(stackNdx); mTmpStackTasks.clear(); stack.getRunningTasks(mTmpStackTasks, ignoreActivityType, ignoreWindowingMode, - callingUid, allowed); + callingUid, allowed, crossUser); mTmpSortedSet.addAll(mTmpStackTasks); } } diff --git a/services/core/java/com/android/server/wm/TaskRecord.java b/services/core/java/com/android/server/wm/TaskRecord.java index e25ca73e457d..d3f3981625d9 100644 --- a/services/core/java/com/android/server/wm/TaskRecord.java +++ b/services/core/java/com/android/server/wm/TaskRecord.java @@ -512,7 +512,7 @@ class TaskRecord extends ConfigurationContainer { if (!getWindowConfiguration().persistTaskBounds()) { // Reset current bounds for task whose bounds shouldn't be persisted so it uses // default configuration the next time it launches. - updateOverrideConfiguration(null); + setBounds(null); } mService.getTaskChangeNotificationController().notifyTaskRemoved(taskId); } @@ -565,7 +565,7 @@ class TaskRecord extends ConfigurationContainer { // Task doesn't exist in window manager yet (e.g. was restored from recents). // All we can do for now is update the bounds so it can be used when the task is // added to window manager. - updateOverrideConfiguration(bounds); + setBounds(bounds); if (!inFreeformWindowingMode()) { // re-restore the task so it can have the proper stack association. mService.mStackSupervisor.restoreRecentTaskLocked(this, null, !ON_TOP); @@ -584,7 +584,11 @@ class TaskRecord extends ConfigurationContainer { Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "am.resizeTask_" + taskId); - final boolean updatedConfig = updateOverrideConfiguration(bounds); + boolean updatedConfig = false; + mTmpConfig.setTo(getResolvedOverrideConfiguration()); + if (setBounds(bounds) != BOUNDS_CHANGE_NONE) { + updatedConfig = !mTmpConfig.equals(getResolvedOverrideConfiguration()); + } // This variable holds information whether the configuration didn't change in a significant // way and the activity was kept the way it was. If it's false, it means the activity @@ -1803,15 +1807,6 @@ class TaskRecord extends ConfigurationContainer { } } - /** - * Update task's override configuration based on the bounds. - * @param bounds The bounds of the task. - * @return True if the override configuration was updated. - */ - boolean updateOverrideConfiguration(Rect bounds) { - return updateOverrideConfiguration(bounds, null /* insetBounds */); - } - void setLastNonFullscreenBounds(Rect bounds) { if (mLastNonFullscreenBounds == null) { mLastNonFullscreenBounds = new Rect(bounds); @@ -1821,32 +1816,6 @@ class TaskRecord extends ConfigurationContainer { } /** - * Update task's override configuration based on the bounds. - * @param bounds The bounds of the task. - * @param insetBounds The bounds used to calculate the system insets, which is used here to - * subtract the navigation bar/status bar size from the screen size reported - * to the application. See {@link IActivityTaskManager#resizeDockedStack}. - * @return True if the override configuration was updated. - */ - boolean updateOverrideConfiguration(Rect bounds, @Nullable Rect insetBounds) { - final boolean hasSetDisplayedBounds = (insetBounds != null && !insetBounds.isEmpty()); - if (hasSetDisplayedBounds) { - setDisplayedBounds(bounds); - } else { - setDisplayedBounds(null); - } - // "steady" bounds do not include any temporary offsets from animation or interaction. - Rect steadyBounds = hasSetDisplayedBounds ? insetBounds : bounds; - if (equivalentRequestedOverrideBounds(steadyBounds)) { - return false; - } - - mTmpConfig.setTo(getResolvedOverrideConfiguration()); - setBounds(steadyBounds); - return !mTmpConfig.equals(getResolvedOverrideConfiguration()); - } - - /** * This should be called when an child activity changes state. This should only * be called from * {@link ActivityRecord#setState(ActivityState, String)} . @@ -2297,7 +2266,7 @@ class TaskRecord extends ConfigurationContainer { Rect updateOverrideConfigurationFromLaunchBounds() { final Rect bounds = getLaunchBounds(); - updateOverrideConfiguration(bounds); + setBounds(bounds); if (bounds != null && !bounds.isEmpty()) { // TODO: Review if we actually want to do this - we are setting the launch bounds // directly here. @@ -2322,12 +2291,12 @@ class TaskRecord extends ConfigurationContainer { return; } if (mLastNonFullscreenBounds != null) { - updateOverrideConfiguration(mLastNonFullscreenBounds); + setBounds(mLastNonFullscreenBounds); } else { mService.mStackSupervisor.getLaunchParamsController().layoutTask(this, null); } } else { - updateOverrideConfiguration(inStack.getRequestedOverrideBounds()); + setBounds(inStack.getRequestedOverrideBounds()); } } diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java index 814bec671750..bef6a37a1ebe 100644 --- a/services/core/java/com/android/server/wm/TaskStack.java +++ b/services/core/java/com/android/server/wm/TaskStack.java @@ -859,7 +859,7 @@ public class TaskStack extends WindowContainer<Task> implements // When the home stack is resizable, should always have the same stack and task bounds if (isActivityTypeHome()) { final Task homeTask = findHomeTask(); - if (homeTask != null && homeTask.isResizeable()) { + if (homeTask == null || homeTask.isResizeable()) { // Calculate the home stack bounds when in docked mode and the home stack is // resizeable. getDisplayContent().mDividerControllerLocked @@ -965,7 +965,7 @@ public class TaskStack extends WindowContainer<Task> implements } void resetDockedStackToMiddle() { - if (inSplitScreenPrimaryWindowingMode()) { + if (!inSplitScreenPrimaryWindowingMode()) { throw new IllegalStateException("Not a docked stack=" + this); } @@ -973,12 +973,12 @@ public class TaskStack extends WindowContainer<Task> implements final Rect bounds = new Rect(); final Rect tempBounds = new Rect(); - TaskStack dockedStack = mDisplayContent.getSplitScreenPrimaryStackIgnoringVisibility(); - Rect dockedBounds = - (dockedStack == null || dockedStack == this) ? null : dockedStack.getRawBounds(); - getStackDockedModeBoundsLocked(mDisplayContent.getConfiguration(), dockedBounds, + getStackDockedModeBoundsLocked(mDisplayContent.getConfiguration(), null /* dockedBounds */, null /* currentTempTaskBounds */, bounds, tempBounds); - mActivityStack.requestResize(bounds); + mActivityStack.mStackSupervisor.resizeDockedStackLocked(bounds, null /* tempTaskBounds */, + null /* tempTaskInsetBounds */, null /* tempOtherTaskBounds */, + null /* tempOtherTaskInsetBounds */, false /* preserveWindows */, + false /* deferResume */); } @Override diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java index 8c51452075b7..d7116d8bbd87 100644 --- a/services/core/java/com/android/server/wm/WindowProcessController.java +++ b/services/core/java/com/android/server/wm/WindowProcessController.java @@ -23,7 +23,6 @@ import static android.view.Display.INVALID_DISPLAY; import static com.android.server.am.ActivityManagerService.MY_PID; import static com.android.server.wm.ActivityStack.ActivityState.DESTROYED; import static com.android.server.wm.ActivityStack.ActivityState.DESTROYING; -import static com.android.server.wm.ActivityStack.ActivityState.INITIALIZING; import static com.android.server.wm.ActivityStack.ActivityState.PAUSED; import static com.android.server.wm.ActivityStack.ActivityState.PAUSING; import static com.android.server.wm.ActivityStack.ActivityState.RESUMED; @@ -556,14 +555,7 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio continue; } ActivityRecord topActivity = task.getTopActivity(); - if (topActivity == null) { - continue; - } - // If an activity has just been started it will not yet be visible, but - // is expected to be soon. We treat this as if it were already visible. - // This ensures a subsequent activity can be started even before this one - // becomes visible. - if (topActivity.visible || topActivity.isState(INITIALIZING)) { + if (topActivity != null && topActivity.visible) { return true; } } diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java index 8e679d44fe05..6dfbc36ce6f7 100644 --- a/services/core/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java @@ -1050,7 +1050,7 @@ class WindowStateAnimator { // to prevent further updates until buffer latch. // We also need to freeze the Surface geometry until a buffer // comes in at the new size (normally position and crop are unfrozen). - // setGeometryAppliesWithResizeInTransaction accomplishes this for us. + // deferTransactionUntil accomplishes this for us. if (wasForceScaled && !mForceScaleUntilResize) { mSurfaceController.deferTransactionUntil(mSurfaceController.mSurfaceControl, mWin.getFrameNumber()); diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java index 8cede6c52914..6d813d106345 100644 --- a/services/core/java/com/android/server/wm/WindowSurfaceController.java +++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java @@ -245,10 +245,6 @@ class WindowSurfaceController { } } - void setGeometryAppliesWithResizeInTransaction(boolean recoveringMemory) { - mSurfaceControl.setGeometryAppliesWithResize(); - } - void setMatrixInTransaction(float dsdx, float dtdx, float dtdy, float dsdy, boolean recoveringMemory) { setMatrix(null, dsdx, dtdx, dtdy, dsdy, false); diff --git a/services/tests/servicestests/src/com/android/server/accessibility/GlobalActionPerformerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/GlobalActionPerformerTest.java index e72e4601bbe8..c73be6f100cd 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/GlobalActionPerformerTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/GlobalActionPerformerTest.java @@ -35,6 +35,8 @@ import org.junit.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import java.util.function.Consumer; + /** * Tests for GlobalActionPerformer */ @@ -84,6 +86,6 @@ public class GlobalActionPerformerTest { AccessibilityService.GLOBAL_ACTION_TAKE_SCREENSHOT); verify(mMockScreenshotHelper).takeScreenshot( eq(android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN), anyBoolean(), - anyBoolean(), any(Handler.class)); + anyBoolean(), any(Handler.class), any()); } } diff --git a/services/tests/uiservicestests/AndroidManifest.xml b/services/tests/uiservicestests/AndroidManifest.xml index 7453c489ecc8..180deb5c4dcc 100644 --- a/services/tests/uiservicestests/AndroidManifest.xml +++ b/services/tests/uiservicestests/AndroidManifest.xml @@ -31,6 +31,7 @@ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.OBSERVE_ROLE_HOLDERS" /> <uses-permission android:name="android.permission.GET_INTENT_SENDER_INTENT"/> + <uses-permission android:name="android.permission.WRITE_DEVICE_CONFIG" /> <application android:debuggable="true"> <uses-library android:name="android.test.runner" /> diff --git a/services/tests/uiservicestests/src/com/android/server/UiServiceTestCase.java b/services/tests/uiservicestests/src/com/android/server/UiServiceTestCase.java index 14b71ec526a8..3c2d55058c3e 100644 --- a/services/tests/uiservicestests/src/com/android/server/UiServiceTestCase.java +++ b/services/tests/uiservicestests/src/com/android/server/UiServiceTestCase.java @@ -27,9 +27,11 @@ import androidx.test.InstrumentationRegistry; import com.android.server.uri.UriGrantsManagerInternal; +import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.mockito.Mock; +import org.mockito.Mockito; import org.mockito.MockitoAnnotations; public class UiServiceTestCase { @@ -77,4 +79,9 @@ public class UiServiceTestCase { when(mUgmInternal.checkGrantUriPermission( anyInt(), anyString(), any(Uri.class), anyInt(), anyInt())).thenReturn(-1); } + + @After + public final void cleanUpMockito() { + Mockito.framework().clearInlineMocks(); + } } diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java index be638a9d9755..d11995a82229 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java @@ -62,6 +62,7 @@ import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyInt; +import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.mock; @@ -209,9 +210,10 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { private AudioManager mAudioManager; @Mock ActivityManager mActivityManager; - NotificationManagerService.WorkerHandler mHandler; @Mock Resources mResources; + @Mock + RankingHandler mRankingHandler; private NotificationChannel mTestNotificationChannel = new NotificationChannel( TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT); @@ -342,7 +344,6 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { // Use this testable looper. mTestableLooper = TestableLooper.get(this); - mHandler = mService.new WorkerHandler(mTestableLooper.getLooper()); // MockPackageManager - default returns ApplicationInfo with matching calling UID mContext.setMockPackageManager(mPackageManagerClient); @@ -391,7 +392,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { when(mAssistants.isAdjustmentAllowed(anyString())).thenReturn(true); - mService.init(mTestableLooper.getLooper(), + mService.init(mTestableLooper.getLooper(), mRankingHandler, mPackageManager, mPackageManagerClient, mockLightsManager, mListeners, mAssistants, mConditionProviders, mCompanionMgr, mSnoozeHelper, mUsageStats, mPolicyFile, mActivityManager, @@ -410,6 +411,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { PKG, new ParceledListSlice(Arrays.asList(mTestNotificationChannel))); assertNotNull(mBinderService.getNotificationChannel( PKG, mContext.getUserId(), PKG, TEST_CHANNEL_ID)); + clearInvocations(mRankingHandler); } @After @@ -461,7 +463,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { Notification.Builder nb = new Notification.Builder(mContext, "a") .setContentTitle("foo") .setSmallIcon(android.R.drawable.sym_def_app_icon); - StatusBarNotification sbn = new StatusBarNotification(pkg, pkg, uid, "tag", uid, 0, + StatusBarNotification sbn = new StatusBarNotification(pkg, pkg, uid, + "tag" + System.currentTimeMillis(), uid, 0, nb.build(), new UserHandle(userId), null, postTime); return sbn; } @@ -482,7 +485,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { if (isBubble) { nb.setBubbleMetadata(getBasicBubbleMetadataBuilder().build()); } - StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, id, "tag", mUid, 0, + + StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, id, + "tag" + System.currentTimeMillis(), mUid, 0, nb.build(), new UserHandle(mUid), null, 0); return new NotificationRecord(mContext, sbn, channel); } @@ -510,7 +515,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { if (isBubble) { nb.setBubbleMetadata(getBasicBubbleMetadataBuilder().build()); } - StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0, + StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, nb.build(), new UserHandle(mUid), null, 0); return new NotificationRecord(mContext, sbn, channel); } @@ -588,7 +593,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { when(mActivityManager.getPackageImportance(nrBubble.sbn.getPackageName())).thenReturn( IMPORTANCE_FOREGROUND); - mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", + mBinderService.enqueueNotificationWithTag(PKG, PKG, nrBubble.sbn.getTag(), nrBubble.sbn.getId(), nrBubble.sbn.getNotification(), nrBubble.sbn.getUserId()); waitForIdle(); @@ -600,7 +605,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { // Plain notification without bubble metadata NotificationRecord nrPlain = generateNotificationRecord(mTestNotificationChannel, 2, "BUBBLE_GROUP", false /* isSummary */, false /* isBubble */); - mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", + mBinderService.enqueueNotificationWithTag(PKG, PKG, nrPlain.sbn.getTag(), nrPlain.sbn.getId(), nrPlain.sbn.getNotification(), nrPlain.sbn.getUserId()); waitForIdle(); @@ -613,7 +618,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { if (summaryAutoCancel) { nrSummary.getNotification().flags |= FLAG_AUTO_CANCEL; } - mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", + mBinderService.enqueueNotificationWithTag(PKG, PKG, nrSummary.sbn.getTag(), nrSummary.sbn.getId(), nrSummary.sbn.getNotification(), nrSummary.sbn.getUserId()); waitForIdle(); @@ -757,7 +762,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { mBinderService.createNotificationChannels( PKG, new ParceledListSlice(Arrays.asList(channel))); final StatusBarNotification sbn = generateNotificationRecord(channel).sbn; - mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", + mBinderService.enqueueNotificationWithTag(PKG, PKG, + "testBlockedNotifications_blockedChannel", sbn.getId(), sbn.getNotification(), sbn.getUserId()); waitForIdle(); assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length); @@ -775,7 +781,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { final StatusBarNotification sbn = generateNotificationRecord(channel).sbn; sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; - mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", + mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(), sbn.getId(), sbn.getNotification(), sbn.getUserId()); waitForIdle(); assertEquals(1, mBinderService.getActiveNotifications(sbn.getPackageName()).length); @@ -804,7 +810,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { StatusBarNotification sbn = generateNotificationRecord(channel).sbn; sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; - mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", + mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(), sbn.getId(), sbn.getNotification(), sbn.getUserId()); waitForIdle(); // The first time a foreground service notification is shown, we allow the channel @@ -826,7 +832,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { sbn = generateNotificationRecord(channel).sbn; sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; - mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", + mBinderService.enqueueNotificationWithTag(PKG, PKG, + "testEnqueuedBlockedNotifications_userBlockedChannelForegroundService", sbn.getId(), sbn.getNotification(), sbn.getUserId()); waitForIdle(); // The second time it is shown, we keep the user's preference. @@ -840,7 +847,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { public void testBlockedNotifications_blockedChannelGroup() throws Exception { when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); mService.setPreferencesHelper(mPreferencesHelper); - when(mPreferencesHelper.isGroupBlocked(anyString(), anyInt(), anyString())).thenReturn(true); + when(mPreferencesHelper.isGroupBlocked(anyString(), anyInt(), anyString())). + thenReturn(true); NotificationChannel channel = new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_HIGH); @@ -857,7 +865,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { mBinderService.setNotificationsEnabledForPackage(PKG, mUid, false); final StatusBarNotification sbn = generateNotificationRecord(null).sbn; - mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", + mBinderService.enqueueNotificationWithTag(PKG, PKG, + "testEnqueuedBlockedNotifications_blockedApp", sbn.getId(), sbn.getNotification(), sbn.getUserId()); waitForIdle(); assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length); @@ -871,7 +880,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { final StatusBarNotification sbn = generateNotificationRecord(null).sbn; sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; - mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", + mBinderService.enqueueNotificationWithTag(PKG, PKG, + "testEnqueuedBlockedNotifications_blockedAppForegroundService", sbn.getId(), sbn.getNotification(), sbn.getUserId()); waitForIdle(); assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length); @@ -893,7 +903,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { final StatusBarNotification sbn = generateNotificationRecord(mTestNotificationChannel, ++id, "", false).sbn; sbn.getNotification().category = category; - mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", + mBinderService.enqueueNotificationWithTag(PKG, PKG, + "testEnqueuedRestrictedNotifications_asSystem", sbn.getId(), sbn.getNotification(), sbn.getUserId()); } waitForIdle(); @@ -917,7 +928,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { final StatusBarNotification sbn = generateNotificationRecord(mTestNotificationChannel, ++id, "", false).sbn; sbn.getNotification().category = category; - mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", + mBinderService.enqueueNotificationWithTag(PKG, PKG, + "testEnqueuedRestrictedNotifications_notAutomotive", sbn.getId(), sbn.getNotification(), sbn.getUserId()); } waitForIdle(); @@ -940,7 +952,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { final StatusBarNotification sbn = generateNotificationRecord(null).sbn; sbn.getNotification().category = category; try { - mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", + mBinderService.enqueueNotificationWithTag(PKG, PKG, + "testEnqueuedRestrictedNotifications_badUser", sbn.getId(), sbn.getNotification(), sbn.getUserId()); fail("Calls from non system apps should not allow use of restricted categories"); } catch (SecurityException e) { @@ -977,7 +990,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { @Test public void testEnqueueNotificationWithTag_PopulatesGetActiveNotifications() throws Exception { - mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0, + mBinderService.enqueueNotificationWithTag(PKG, PKG, + "testEnqueueNotificationWithTag_PopulatesGetActiveNotifications", 0, generateNotificationRecord(null).getNotification(), 0); waitForIdle(); StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG); @@ -987,9 +1001,11 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { @Test public void testCancelNotificationImmediatelyAfterEnqueue() throws Exception { - mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0, + mBinderService.enqueueNotificationWithTag(PKG, PKG, + "testCancelNotificationImmediatelyAfterEnqueue", 0, generateNotificationRecord(null).getNotification(), 0); - mBinderService.cancelNotificationWithTag(PKG, PKG, "tag", 0, 0); + mBinderService.cancelNotificationWithTag(PKG, PKG, + "testCancelNotificationImmediatelyAfterEnqueue", 0, 0); waitForIdle(); StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG); @@ -999,12 +1015,15 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { @Test public void testCancelNotificationWhilePostedAndEnqueued() throws Exception { - mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0, + mBinderService.enqueueNotificationWithTag(PKG, PKG, + "testCancelNotificationWhilePostedAndEnqueued", 0, generateNotificationRecord(null).getNotification(), 0); waitForIdle(); - mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0, + mBinderService.enqueueNotificationWithTag(PKG, PKG, + "testCancelNotificationWhilePostedAndEnqueued", 0, generateNotificationRecord(null).getNotification(), 0); - mBinderService.cancelNotificationWithTag(PKG, PKG, "tag", 0, 0); + mBinderService.cancelNotificationWithTag(PKG, PKG, + "testCancelNotificationWhilePostedAndEnqueued", 0, 0); waitForIdle(); StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG); @@ -1019,7 +1038,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { public void testCancelNotificationsFromListenerImmediatelyAfterEnqueue() throws Exception { NotificationRecord r = generateNotificationRecord(null); final StatusBarNotification sbn = r.sbn; - mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", + mBinderService.enqueueNotificationWithTag(PKG, PKG, + "testCancelNotificationsFromListenerImmediatelyAfterEnqueue", sbn.getId(), sbn.getNotification(), sbn.getUserId()); mBinderService.cancelNotificationsFromListener(null, null); waitForIdle(); @@ -1032,7 +1052,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { @Test public void testCancelAllNotificationsImmediatelyAfterEnqueue() throws Exception { final StatusBarNotification sbn = generateNotificationRecord(null).sbn; - mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", + mBinderService.enqueueNotificationWithTag(PKG, PKG, + "testCancelAllNotificationsImmediatelyAfterEnqueue", sbn.getId(), sbn.getNotification(), sbn.getUserId()); mBinderService.cancelAllNotifications(PKG, sbn.getUserId()); waitForIdle(); @@ -1047,7 +1068,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { final NotificationRecord n = generateNotificationRecord( mTestNotificationChannel, 1, "group", true); - mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", + mBinderService.enqueueNotificationWithTag(PKG, PKG, + "testUserInitiatedClearAll_noLeak", n.sbn.getId(), n.sbn.getNotification(), n.sbn.getUserId()); waitForIdle(); @@ -1070,9 +1092,11 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { final NotificationRecord child = generateNotificationRecord( mTestNotificationChannel, 2, "group1", false); - mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", + mBinderService.enqueueNotificationWithTag(PKG, PKG, + "testCancelAllNotificationsCancelsChildren", parent.sbn.getId(), parent.sbn.getNotification(), parent.sbn.getUserId()); - mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", + mBinderService.enqueueNotificationWithTag(PKG, PKG, + "testCancelAllNotificationsCancelsChildren", child.sbn.getId(), child.sbn.getNotification(), child.sbn.getUserId()); waitForIdle(); @@ -1085,7 +1109,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { public void testCancelAllNotificationsMultipleEnqueuedDoesNotCrash() throws Exception { final StatusBarNotification sbn = generateNotificationRecord(null).sbn; for (int i = 0; i < 10; i++) { - mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", + mBinderService.enqueueNotificationWithTag(PKG, PKG, + "testCancelAllNotificationsMultipleEnqueuedDoesNotCrash", sbn.getId(), sbn.getNotification(), sbn.getUserId()); } mBinderService.cancelAllNotifications(PKG, sbn.getUserId()); @@ -1104,17 +1129,20 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { mTestNotificationChannel, 2, "group1", false); // fully post parent notification - mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", + mBinderService.enqueueNotificationWithTag(PKG, PKG, + "testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash", parent.sbn.getId(), parent.sbn.getNotification(), parent.sbn.getUserId()); waitForIdle(); // enqueue the child several times for (int i = 0; i < 10; i++) { - mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", + mBinderService.enqueueNotificationWithTag(PKG, PKG, + "testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash", child.sbn.getId(), child.sbn.getNotification(), child.sbn.getUserId()); } // make the parent a child, which will cancel the child notification - mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", + mBinderService.enqueueNotificationWithTag(PKG, PKG, + "testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash", parentAsChild.sbn.getId(), parentAsChild.sbn.getNotification(), parentAsChild.sbn.getUserId()); waitForIdle(); @@ -1126,7 +1154,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { public void testCancelAllNotifications_IgnoreForegroundService() throws Exception { final StatusBarNotification sbn = generateNotificationRecord(null).sbn; sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; - mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", + mBinderService.enqueueNotificationWithTag(PKG, PKG, + "testCancelAllNotifications_IgnoreForegroundService", sbn.getId(), sbn.getNotification(), sbn.getUserId()); mBinderService.cancelAllNotifications(PKG, sbn.getUserId()); waitForIdle(); @@ -1140,7 +1169,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { public void testCancelAllNotifications_IgnoreOtherPackages() throws Exception { final StatusBarNotification sbn = generateNotificationRecord(null).sbn; sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; - mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", + mBinderService.enqueueNotificationWithTag(PKG, PKG, + "testCancelAllNotifications_IgnoreOtherPackages", sbn.getId(), sbn.getNotification(), sbn.getUserId()); mBinderService.cancelAllNotifications("other_pkg_name", sbn.getUserId()); waitForIdle(); @@ -1153,7 +1183,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { @Test public void testCancelAllNotifications_NullPkgRemovesAll() throws Exception { final StatusBarNotification sbn = generateNotificationRecord(null).sbn; - mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", + mBinderService.enqueueNotificationWithTag(PKG, PKG, + "testCancelAllNotifications_NullPkgRemovesAll", sbn.getId(), sbn.getNotification(), sbn.getUserId()); mBinderService.cancelAllNotifications(null, sbn.getUserId()); waitForIdle(); @@ -1166,7 +1197,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { @Test public void testCancelAllNotifications_NullPkgIgnoresUserAllNotifications() throws Exception { final StatusBarNotification sbn = generateNotificationRecord(null).sbn; - mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", + mBinderService.enqueueNotificationWithTag(PKG, PKG, + "testCancelAllNotifications_NullPkgIgnoresUserAllNotifications", sbn.getId(), sbn.getNotification(), UserHandle.USER_ALL); // Null pkg is how we signal a user switch. mBinderService.cancelAllNotifications(null, sbn.getUserId()); @@ -1181,7 +1213,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { public void testAppInitiatedCancelAllNotifications_CancelsNoClearFlag() throws Exception { final StatusBarNotification sbn = generateNotificationRecord(null).sbn; sbn.getNotification().flags |= Notification.FLAG_NO_CLEAR; - mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", + mBinderService.enqueueNotificationWithTag(PKG, PKG, + "testAppInitiatedCancelAllNotifications_CancelsNoClearFlag", sbn.getId(), sbn.getNotification(), sbn.getUserId()); mBinderService.cancelAllNotifications(PKG, sbn.getUserId()); waitForIdle(); @@ -1266,7 +1299,12 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { @Test public void testRemoveForegroundServiceFlag_ImmediatelyAfterEnqueue() throws Exception { - final StatusBarNotification sbn = generateNotificationRecord(null).sbn; + Notification n = + new Notification.Builder(mContext, mTestNotificationChannel.getId()) + .setSmallIcon(android.R.drawable.sym_def_app_icon) + .build(); + StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, null, mUid, 0, + n, new UserHandle(mUid), null, 0); sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; mBinderService.enqueueNotificationWithTag(PKG, PKG, null, sbn.getId(), sbn.getNotification(), sbn.getUserId()); @@ -1283,12 +1321,13 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { final StatusBarNotification sbn = generateNotificationRecord(null).sbn; sbn.getNotification().flags = Notification.FLAG_ONGOING_EVENT | FLAG_FOREGROUND_SERVICE; - mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", + mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(), sbn.getId(), sbn.getNotification(), sbn.getUserId()); sbn.getNotification().flags = Notification.FLAG_ONGOING_EVENT; - mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", + mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(), sbn.getId(), sbn.getNotification(), sbn.getUserId()); - mBinderService.cancelNotificationWithTag(PKG, PKG, "tag", sbn.getId(), sbn.getUserId()); + mBinderService.cancelNotificationWithTag(PKG, PKG, sbn.getTag(), sbn.getId(), + sbn.getUserId()); waitForIdle(); assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length); assertEquals(0, mService.getNotificationRecordCount()); @@ -1376,21 +1415,22 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { // should not be returned final NotificationRecord group2 = generateNotificationRecord( mTestNotificationChannel, 2, "group2", true); - mBinderService.enqueueNotificationWithTag(PKG, PKG, null, + mBinderService.enqueueNotificationWithTag(PKG, PKG, "testFindGroupNotificationsLocked", group2.sbn.getId(), group2.sbn.getNotification(), group2.sbn.getUserId()); waitForIdle(); // should not be returned final NotificationRecord nonGroup = generateNotificationRecord( mTestNotificationChannel, 3, null, false); - mBinderService.enqueueNotificationWithTag(PKG, PKG, null, + mBinderService.enqueueNotificationWithTag(PKG, PKG, "testFindGroupNotificationsLocked", nonGroup.sbn.getId(), nonGroup.sbn.getNotification(), nonGroup.sbn.getUserId()); waitForIdle(); // same group, child, should be returned final NotificationRecord group1Child = generateNotificationRecord( mTestNotificationChannel, 4, "group1", false); - mBinderService.enqueueNotificationWithTag(PKG, PKG, null, group1Child.sbn.getId(), + mBinderService.enqueueNotificationWithTag(PKG, PKG, "testFindGroupNotificationsLocked", + group1Child.sbn.getId(), group1Child.sbn.getNotification(), group1Child.sbn.getUserId()); waitForIdle(); @@ -1447,7 +1487,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { public void testAppInitiatedCancelAllNotifications_CancelsOnGoingFlag() throws Exception { final StatusBarNotification sbn = generateNotificationRecord(null).sbn; sbn.getNotification().flags |= Notification.FLAG_ONGOING_EVENT; - mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", + mBinderService.enqueueNotificationWithTag(PKG, PKG, + "testAppInitiatedCancelAllNotifications_CancelsOnGoingFlag", sbn.getId(), sbn.getNotification(), sbn.getUserId()); mBinderService.cancelAllNotifications(PKG, sbn.getUserId()); waitForIdle(); @@ -1564,7 +1605,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { new NotificationChannel("foo", "foo", IMPORTANCE_HIGH)); Notification.TvExtender tv = new Notification.TvExtender().setChannelId("foo"); - mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0, + mBinderService.enqueueNotificationWithTag(PKG, PKG, "testTvExtenderChannelOverride_onTv", 0, generateNotificationRecord(null, tv).getNotification(), 0); verify(mPreferencesHelper, times(1)).getNotificationChannel( anyString(), anyInt(), eq("foo"), anyBoolean()); @@ -1579,8 +1620,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { mTestNotificationChannel); Notification.TvExtender tv = new Notification.TvExtender().setChannelId("foo"); - mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", 0, - generateNotificationRecord(null, tv).getNotification(), 0); + mBinderService.enqueueNotificationWithTag(PKG, PKG, "testTvExtenderChannelOverride_notOnTv", + 0, generateNotificationRecord(null, tv).getNotification(), 0); verify(mPreferencesHelper, times(1)).getNotificationChannel( anyString(), anyInt(), eq(mTestNotificationChannel.getId()), anyBoolean()); } @@ -2220,7 +2261,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { final NotificationRecord child = generateNotificationRecord( mTestNotificationChannel, 2, "group", false); - mBinderService.enqueueNotificationWithTag(PKG, PKG, null, + mBinderService.enqueueNotificationWithTag(PKG, PKG, "testPostNonGroup_noUnsnoozing", child.sbn.getId(), child.sbn.getNotification(), child.sbn.getUserId()); waitForIdle(); @@ -2233,7 +2274,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { final NotificationRecord record = generateNotificationRecord( mTestNotificationChannel, 2, null, false); - mBinderService.enqueueNotificationWithTag(PKG, PKG, null, + mBinderService.enqueueNotificationWithTag(PKG, PKG, "testPostNonGroup_noUnsnoozing", record.sbn.getId(), record.sbn.getNotification(), record.sbn.getUserId()); waitForIdle(); @@ -2245,7 +2286,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { final NotificationRecord parent = generateNotificationRecord( mTestNotificationChannel, 2, "group", true); - mBinderService.enqueueNotificationWithTag(PKG, PKG, null, + mBinderService.enqueueNotificationWithTag(PKG, PKG, "testPostGroupSummary_noUnsnoozing", parent.sbn.getId(), parent.sbn.getNotification(), parent.sbn.getUserId()); waitForIdle(); @@ -2659,31 +2700,37 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { .setColorized(true) .setFlag(Notification.FLAG_CAN_COLORIZE, true) .setSmallIcon(android.R.drawable.sym_def_app_icon); - StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0, + StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, + "testNoFakeColorizedPermission", mUid, 0, nb.build(), new UserHandle(mUid), null, 0); NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); - mBinderService.enqueueNotificationWithTag(PKG, PKG, null, + mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(), nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId()); waitForIdle(); NotificationRecord posted = mService.findNotificationLocked( - PKG, null, nr.sbn.getId(), nr.sbn.getUserId()); + PKG, nr.sbn.getTag(), nr.sbn.getId(), nr.sbn.getUserId()); assertFalse(posted.getNotification().isColorized()); } @Test - public void testGetNotificationCountLocked() throws Exception { + public void testGetNotificationCountLocked() { + String sampleTagToExclude = null; + int sampleIdToExclude = 0; for (int i = 0; i < 20; i++) { NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, i, null, false); mService.addEnqueuedNotification(r); + } for (int i = 0; i < 20; i++) { NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, i, null, false); mService.addNotification(r); + sampleTagToExclude = r.sbn.getTag(); + sampleIdToExclude = i; } // another package @@ -2700,55 +2747,49 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { mService.addNotification(otherPackage); // Same notifications are enqueued as posted, everything counts b/c id and tag don't match + // anything that's currently enqueued or posted int userId = new UserHandle(mUid).getIdentifier(); assertEquals(40, mService.getNotificationCountLocked(PKG, userId, 0, null)); assertEquals(40, mService.getNotificationCountLocked(PKG, userId, 0, "tag2")); + + // return all for package "a" - "banana" tag isn't used assertEquals(2, mService.getNotificationCountLocked("a", userId, 0, "banana")); // exclude a known notification - it's excluded from only the posted list, not enqueued - assertEquals(39, - mService.getNotificationCountLocked(PKG, userId, 0, "tag")); + assertEquals(39, mService.getNotificationCountLocked( + PKG, userId, sampleIdToExclude, sampleTagToExclude)); } @Test public void testAddAutogroup_requestsSort() throws Exception { - RankingHandler rh = mock(RankingHandler.class); - mService.setRankingHandler(rh); - final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); mService.addNotification(r); mService.addAutogroupKeyLocked(r.getKey()); - verify(rh, times(1)).requestSort(); + verify(mRankingHandler, times(1)).requestSort(); } @Test public void testRemoveAutogroup_requestsSort() throws Exception { - RankingHandler rh = mock(RankingHandler.class); - mService.setRankingHandler(rh); - final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); r.setOverrideGroupKey("TEST"); mService.addNotification(r); mService.removeAutogroupKeyLocked(r.getKey()); - verify(rh, times(1)).requestSort(); + verify(mRankingHandler, times(1)).requestSort(); } @Test public void testReaddAutogroup_noSort() throws Exception { - RankingHandler rh = mock(RankingHandler.class); - mService.setRankingHandler(rh); - final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); r.setOverrideGroupKey("TEST"); mService.addNotification(r); mService.addAutogroupKeyLocked(r.getKey()); - verify(rh, never()).requestSort(); + verify(mRankingHandler, never()).requestSort(); } @Test @@ -2922,7 +2963,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { .setFlag(FLAG_FOREGROUND_SERVICE, true) .setPriority(Notification.PRIORITY_MIN); - StatusBarNotification sbn = new StatusBarNotification(preOPkg, preOPkg, 9, "tag", + StatusBarNotification sbn = new StatusBarNotification(preOPkg, preOPkg, 9, + "testBumpFGImportance_noChannelChangePreOApp", Binder.getCallingUid(), 0, nb.build(), new UserHandle(Binder.getCallingUid()), null, 0); mBinderService.enqueueNotificationWithTag(sbn.getPackageName(), sbn.getOpPkg(), @@ -2938,10 +2980,12 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { .setFlag(FLAG_FOREGROUND_SERVICE, true) .setPriority(Notification.PRIORITY_MIN); - sbn = new StatusBarNotification(preOPkg, preOPkg, 9, "tag", Binder.getCallingUid(), + sbn = new StatusBarNotification(preOPkg, preOPkg, 9, + "testBumpFGImportance_noChannelChangePreOApp", Binder.getCallingUid(), 0, nb.build(), new UserHandle(Binder.getCallingUid()), null, 0); - mBinderService.enqueueNotificationWithTag(preOPkg, preOPkg, "tag", + mBinderService.enqueueNotificationWithTag(preOPkg, preOPkg, + "testBumpFGImportance_noChannelChangePreOApp", sbn.getId(), sbn.getNotification(), sbn.getUserId()); waitForIdle(); assertEquals(IMPORTANCE_LOW, @@ -3154,9 +3198,6 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { public void testUserSentimentChangeTriggersUpdate() throws Exception { final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); mService.addNotification(r); - NotificationManagerService.WorkerHandler handler = mock( - NotificationManagerService.WorkerHandler.class); - mService.setHandler(handler); when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true); Bundle signals = new Bundle(); @@ -3168,16 +3209,13 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { waitForIdle(); - verify(handler, timeout(300).times(1)).scheduleSendRankingUpdate(); + verify(mRankingHandler, timeout(300).times(1)).requestSort(); } @Test public void testTooLateAdjustmentTriggersUpdate() throws Exception { final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); mService.addNotification(r); - NotificationManagerService.WorkerHandler handler = mock( - NotificationManagerService.WorkerHandler.class); - mService.setHandler(handler); when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true); Bundle signals = new Bundle(); @@ -3189,16 +3227,13 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { waitForIdle(); - verify(handler, timeout(300).times(1)).scheduleSendRankingUpdate(); + verify(mRankingHandler, times(1)).requestSort(); } @Test public void testEnqueuedAdjustmentAppliesAdjustments() throws Exception { final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); mService.addEnqueuedNotification(r); - NotificationManagerService.WorkerHandler handler = mock( - NotificationManagerService.WorkerHandler.class); - mService.setHandler(handler); when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true); Bundle signals = new Bundle(); @@ -3208,8 +3243,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { r.sbn.getPackageName(), r.getKey(), signals, "", r.getUser().getIdentifier()); mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment); - assertEquals(USER_SENTIMENT_NEGATIVE, - r.getUserSentiment()); + assertEquals(USER_SENTIMENT_NEGATIVE, r.getUserSentiment()); } @Test @@ -4099,7 +4133,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { final StatusBarNotification sbn = generateNotificationRecord(null).sbn; try { - mInternalService.enqueueNotification(notReal, "android", 0, 0, "tag", + mInternalService.enqueueNotification(notReal, "android", 0, 0, + "testPostFromAndroidForNonExistentPackage", sbn.getId(), sbn.getNotification(), sbn.getUserId()); fail("can't post notifications for nonexistent packages, even if you exist"); } catch (SecurityException e) { @@ -4373,7 +4408,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); mService.addNotification(r); - StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0, + StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, r.sbn.getId(), + r.sbn.getTag(), mUid, 0, new Notification.Builder(mContext, mTestNotificationChannel.getId()).build(), new UserHandle(mUid), null, 0); NotificationRecord update = new NotificationRecord(mContext, sbn, mTestNotificationChannel); @@ -4502,7 +4538,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn( IMPORTANCE_FOREGROUND); - mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", + mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(), nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId()); waitForIdle(); @@ -4526,7 +4562,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn( IMPORTANCE_FOREGROUND); - mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", + mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(), nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId()); waitForIdle(); @@ -4550,8 +4586,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn( IMPORTANCE_FOREGROUND); - mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", - nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId()); + mBinderService.enqueueNotificationWithTag(PKG, PKG, + nr.sbn.getTag(), nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId()); waitForIdle(); // yes allowed, yes foreground, yes bubble @@ -4572,7 +4608,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn( IMPORTANCE_VISIBLE); - mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", + mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(), nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId()); waitForIdle(); @@ -4593,7 +4629,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { // Send notif when we're foreground when(mActivityManager.getPackageImportance(nr1.sbn.getPackageName())).thenReturn( IMPORTANCE_FOREGROUND); - mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", + mBinderService.enqueueNotificationWithTag(PKG, PKG, nr1.sbn.getTag(), nr1.sbn.getId(), nr1.sbn.getNotification(), nr1.sbn.getUserId()); waitForIdle(); @@ -4607,7 +4643,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { when(mActivityManager.getPackageImportance(nr2.sbn.getPackageName())).thenReturn( IMPORTANCE_VISIBLE); - mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", + mBinderService.enqueueNotificationWithTag(PKG, PKG, nr2.sbn.getTag(), nr2.sbn.getId(), nr2.sbn.getNotification(), nr2.sbn.getUserId()); waitForIdle(); @@ -4633,7 +4669,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { // Send notif when we're foreground when(mActivityManager.getPackageImportance(nr1.sbn.getPackageName())).thenReturn( IMPORTANCE_FOREGROUND); - mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", + mBinderService.enqueueNotificationWithTag(PKG, PKG, nr1.sbn.getTag(), nr1.sbn.getId(), nr1.sbn.getNotification(), nr1.sbn.getUserId()); waitForIdle(); @@ -4642,7 +4678,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { nr1.sbn.getKey()).getNotification().isBubbleNotification()); // Remove the bubble - mBinderService.cancelNotificationWithTag(PKG, PKG, "tag", nr1.sbn.getId(), + mBinderService.cancelNotificationWithTag(PKG, PKG, nr1.sbn.getTag(), nr1.sbn.getId(), nr1.sbn.getUserId()); waitForIdle(); @@ -4656,7 +4692,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { when(mActivityManager.getPackageImportance(nr2.sbn.getPackageName())).thenReturn( IMPORTANCE_VISIBLE); - mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", + mBinderService.enqueueNotificationWithTag(PKG, PKG, nr2.sbn.getTag(), nr2.sbn.getId(), nr2.sbn.getNotification(), nr2.sbn.getUserId()); waitForIdle(); @@ -4702,11 +4738,12 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { .setActions(replyAction) .setSmallIcon(android.R.drawable.sym_def_app_icon); - StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0, + StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, + "testFlagBubbleNotifs_flag_messaging", mUid, 0, nb.build(), new UserHandle(mUid), null, 0); NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); - mBinderService.enqueueNotificationWithTag(PKG, PKG, null, + mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(), nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId()); waitForIdle(); @@ -4735,13 +4772,14 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { .setBubbleMetadata(data) .setSmallIcon(android.R.drawable.sym_def_app_icon); - StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0, + StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, + "testFlagBubbleNotifs_flag_phonecall", mUid, 0, nb.build(), new UserHandle(mUid), null, 0); // Make sure it has foreground service sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); - mBinderService.enqueueNotificationWithTag(PKG, PKG, null, + mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(), nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId()); waitForIdle(); @@ -4774,7 +4812,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { nb.build(), new UserHandle(mUid), null, 0); NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); - mBinderService.enqueueNotificationWithTag(PKG, PKG, null, + mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(), nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId()); waitForIdle(); @@ -4798,13 +4836,14 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { .setBubbleMetadata(data) .setSmallIcon(android.R.drawable.sym_def_app_icon); - StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0, + StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, + "testFlagBubbleNotifs_noFlag_phonecall_noPerson", mUid, 0, nb.build(), new UserHandle(mUid), null, 0); // Make sure it has foreground service sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); - mBinderService.enqueueNotificationWithTag(PKG, PKG, null, + mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(), nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId()); waitForIdle(); @@ -4832,13 +4871,14 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { .setBubbleMetadata(data) .setSmallIcon(android.R.drawable.sym_def_app_icon); - StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0, + StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, + "testFlagBubbleNotifs_noFlag_phonecall_noCategory", mUid, 0, nb.build(), new UserHandle(mUid), null, 0); // Make sure it has foreground service sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); - mBinderService.enqueueNotificationWithTag(PKG, PKG, null, + mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(), nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId()); waitForIdle(); @@ -4872,12 +4912,13 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { ) .setSmallIcon(android.R.drawable.sym_def_app_icon); - StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0, + StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, + "testFlagBubbleNotifs_noFlag_messaging_appNotAllowed", mUid, 0, nb.build(), new UserHandle(mUid), null, 0); NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); // Post the notification - mBinderService.enqueueNotificationWithTag(PKG, PKG, null, + mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(), nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId()); waitForIdle(); @@ -4895,7 +4936,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel); // Post the notification - mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", + mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(), nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId()); waitForIdle(); @@ -4929,12 +4970,13 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { ) .setSmallIcon(android.R.drawable.sym_def_app_icon); - StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0, + StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, + "testFlagBubbleNotifs_noFlag_messaging_channelNotAllowed", mUid, 0, nb.build(), new UserHandle(mUid), null, 0); NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); // Post the notification - mBinderService.enqueueNotificationWithTag(PKG, PKG, null, + mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(), nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId()); waitForIdle(); @@ -4963,13 +5005,14 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { .setBubbleMetadata(data) .setSmallIcon(android.R.drawable.sym_def_app_icon); - StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0, + StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, + "testFlagBubbleNotifs_noFlag_phonecall_notAllowed", mUid, 0, nb.build(), new UserHandle(mUid), null, 0); // Make sure it has foreground service sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); - mBinderService.enqueueNotificationWithTag(PKG, PKG, null, + mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(), nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId()); waitForIdle(); @@ -4998,13 +5041,14 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { .setBubbleMetadata(data) .setSmallIcon(android.R.drawable.sym_def_app_icon); - StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, null, mUid, 0, + StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, + "testFlagBubbleNotifs_noFlag_phonecall_channelNotAllowed", mUid, 0, nb.build(), new UserHandle(mUid), null, 0); // Make sure it has foreground service sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE; NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel); - mBinderService.enqueueNotificationWithTag(PKG, PKG, null, + mBinderService.enqueueNotificationWithTag(PKG, PKG, sbn.getTag(), nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId()); waitForIdle(); @@ -5033,7 +5077,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { nrBubble.sbn.getNotification().flags |= FLAG_BUBBLE; // Post the notification - mBinderService.enqueueNotificationWithTag(PKG, PKG, null, + mBinderService.enqueueNotificationWithTag(PKG, PKG, + "testAppCancelNotifications_cancelsBubbles", nrBubble.sbn.getId(), nrBubble.sbn.getNotification(), nrBubble.sbn.getUserId()); waitForIdle(); @@ -5041,7 +5086,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { assertEquals(1, notifs.length); assertEquals(1, mService.getNotificationRecordCount()); - mBinderService.cancelNotificationWithTag(PKG, PKG, null, nrBubble.sbn.getId(), + mBinderService.cancelNotificationWithTag(PKG, PKG, + "testAppCancelNotifications_cancelsBubbles", nrBubble.sbn.getId(), nrBubble.sbn.getUserId()); waitForIdle(); @@ -5196,7 +5242,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn( IMPORTANCE_FOREGROUND); - mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", + mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(), nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId()); waitForIdle(); @@ -5226,7 +5272,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { // Plain notification that has bubble metadata NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, null /* tvExtender */, true /* isBubble */); - mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", + mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(), nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId()); waitForIdle(); @@ -5260,7 +5306,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { // Notif that is not a bubble NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, null /* tvExtender */, true /* isBubble */); - mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", + mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(), nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId()); waitForIdle(); @@ -5290,7 +5336,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { // Plain notification that has bubble metadata NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, null /* tvExtender */, true /* isBubble */); - mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag", + mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(), nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId()); waitForIdle(); diff --git a/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java b/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java index f37ff1177fe9..7f9f489c509a 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/RoleObserverTest.java @@ -129,7 +129,7 @@ public class RoleObserverTest extends UiServiceTestCase { mRoleObserver = mService.new RoleObserver(mRoleManager, mPm, mExecutor); try { - mService.init(mock(Looper.class), + mService.init(mock(Looper.class), mock(RankingHandler.class), mock(IPackageManager.class), mock(PackageManager.class), mock(LightsManager.class), mock(NotificationListeners.class), mock(NotificationAssistants.class), diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java index d2af18e5f10b..34cc0c742005 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java @@ -147,8 +147,8 @@ public class ActivityStarterTests extends ActivityTestsBase { assertThat((Object) task2.getStack()).isInstanceOf(ActivityStack.class); mStarter.updateBounds(task2, bounds); - verify(mService, times(1)).resizeStack(eq(task2.getStack().mStackId), - eq(bounds), anyBoolean(), anyBoolean(), anyBoolean(), anyInt()); + verify(mService, times(1)).animateResizePinnedStack(eq(task2.getStack().mStackId), + eq(bounds), anyInt()); // In the case of no animation, the stack and task bounds should be set immediately. if (!ANIMATE) { diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java index fb4e330f06ed..55011fb0aa04 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java @@ -1031,7 +1031,7 @@ public class RecentTasksTest extends ActivityTestsBase { assertSecurityException(expectCallable, () -> mService.moveTopActivityToPinnedStack(INVALID_STACK_ID, new Rect())); assertSecurityException(expectCallable, - () -> mService.resizeStack(INVALID_STACK_ID, new Rect(), true, true, true, 0)); + () -> mService.animateResizePinnedStack(INVALID_STACK_ID, new Rect(), -1)); assertSecurityException(expectCallable, () -> mService.resizeDockedStack(new Rect(), new Rect(), new Rect(), new Rect(), new Rect())); @@ -1289,10 +1289,10 @@ public class RecentTasksTest extends ActivityTestsBase { @Override void getTasks(int maxNum, List<RunningTaskInfo> list, int ignoreActivityType, int ignoreWindowingMode, ArrayList<ActivityDisplay> activityDisplays, - int callingUid, boolean allowed) { + int callingUid, boolean allowed, boolean crossUser) { mLastAllowed = allowed; super.getTasks(maxNum, list, ignoreActivityType, ignoreWindowingMode, activityDisplays, - callingUid, allowed); + callingUid, allowed, crossUser); } } } diff --git a/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java index dc964806b7a9..cdd4c2424421 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java @@ -77,7 +77,7 @@ public class RunningTasksTest extends ActivityTestsBase { final int numFetchTasks = 5; ArrayList<RunningTaskInfo> tasks = new ArrayList<>(); mRunningTasks.getTasks(5, tasks, ACTIVITY_TYPE_UNDEFINED, WINDOWING_MODE_UNDEFINED, - displays, -1 /* callingUid */, true /* allowed */); + displays, -1 /* callingUid */, true /* allowed */, true /*crossUser */); assertThat(tasks).hasSize(numFetchTasks); for (int i = 0; i < numFetchTasks; i++) { assertEquals(numTasks - i - 1, tasks.get(i).id); @@ -87,7 +87,7 @@ public class RunningTasksTest extends ActivityTestsBase { // and does not crash tasks.clear(); mRunningTasks.getTasks(100, tasks, ACTIVITY_TYPE_UNDEFINED, WINDOWING_MODE_UNDEFINED, - displays, -1 /* callingUid */, true /* allowed */); + displays, -1 /* callingUid */, true /* allowed */, true /* crossUser */); assertThat(tasks).hasSize(numTasks); for (int i = 0; i < numTasks; i++) { assertEquals(numTasks - i - 1, tasks.get(i).id); diff --git a/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java b/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java index 83dd69a24295..8d2a79b6b5db 100644 --- a/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java +++ b/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java @@ -185,11 +185,6 @@ public class StubTransaction extends SurfaceControl.Transaction { } @Override - public SurfaceControl.Transaction setGeometryAppliesWithResize(SurfaceControl sc) { - return this; - } - - @Override public SurfaceControl.Transaction setSecure(SurfaceControl sc, boolean isSecure) { return this; } diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java index fc464a1f4393..090623e2f767 100644 --- a/services/usage/java/com/android/server/usage/UsageStatsService.java +++ b/services/usage/java/com/android/server/usage/UsageStatsService.java @@ -121,7 +121,7 @@ public class UsageStatsService extends SystemService implements private static final long TEN_SECONDS = 10 * 1000; private static final long TWENTY_MINUTES = 20 * 60 * 1000; private static final long FLUSH_INTERVAL = COMPRESS_TIME ? TEN_SECONDS : TWENTY_MINUTES; - private static final long TIME_CHANGE_THRESHOLD_MILLIS = 2 * 1000; // Two seconds. + static final long TIME_CHANGE_THRESHOLD_MILLIS = 2 * 1000; // Two seconds. private static final boolean ENABLE_KERNEL_UPDATES = true; private static final File KERNEL_COUNTER_FILE = new File("/proc/uid_procstat/set"); @@ -156,8 +156,6 @@ public class UsageStatsService extends SystemService implements private final SparseArray<UserUsageStatsService> mUserState = new SparseArray<>(); private final SparseBooleanArray mUserUnlockedStates = new SparseBooleanArray(); private final SparseIntArray mUidToKernelCounter = new SparseIntArray(); - long mRealTimeSnapshot; - long mSystemTimeSnapshot; int mUsageSource; /** Manages the standby state of apps. */ @@ -253,9 +251,6 @@ public class UsageStatsService extends SystemService implements getContext().registerReceiverAsUser(new UserActionsReceiver(), UserHandle.ALL, filter, null, mHandler); - mRealTimeSnapshot = SystemClock.elapsedRealtime(); - mSystemTimeSnapshot = System.currentTimeMillis(); - publishLocalService(UsageStatsManagerInternal.class, new LocalService()); publishBinderService(Context.USAGE_STATS_SERVICE, new BinderService()); } @@ -345,7 +340,7 @@ public class UsageStatsService extends SystemService implements mUserUnlockedStates.put(userId, true); final UserUsageStatsService userService = getUserDataAndInitializeIfNeededLocked( userId, System.currentTimeMillis()); - userService.userUnlocked(checkAndGetTimeLocked()); + userService.userUnlocked(System.currentTimeMillis()); // Process all the pending reported events while (pendingEvents.peek() != null) { reportEvent(pendingEvents.poll(), userId); @@ -569,37 +564,6 @@ public class UsageStatsService extends SystemService implements } /** - * This should be the only way to get the time from the system. - */ - private long checkAndGetTimeLocked() { - final long actualSystemTime = System.currentTimeMillis(); - final long actualRealtime = SystemClock.elapsedRealtime(); - final long expectedSystemTime = (actualRealtime - mRealTimeSnapshot) + mSystemTimeSnapshot; - final long diffSystemTime = actualSystemTime - expectedSystemTime; - if (Math.abs(diffSystemTime) > TIME_CHANGE_THRESHOLD_MILLIS - && ENABLE_TIME_CHANGE_CORRECTION) { - // The time has changed. - Slog.i(TAG, "Time changed in UsageStats by " + (diffSystemTime / 1000) + " seconds"); - final int userCount = mUserState.size(); - for (int i = 0; i < userCount; i++) { - final UserUsageStatsService service = mUserState.valueAt(i); - service.onTimeChanged(expectedSystemTime, actualSystemTime); - } - mRealTimeSnapshot = actualRealtime; - mSystemTimeSnapshot = actualSystemTime; - } - return actualSystemTime; - } - - /** - * Assuming the event's timestamp is measured in milliseconds since boot, - * convert it to a system wall time. - */ - private void convertToSystemTimeLocked(Event event) { - event.mTimeStamp = Math.max(0, event.mTimeStamp - mRealTimeSnapshot) + mSystemTimeSnapshot; - } - - /** * Called by the Binder stub */ void shutdown() { @@ -718,9 +682,8 @@ public class UsageStatsService extends SystemService implements return; } - final long timeNow = checkAndGetTimeLocked(); + final long timeNow = System.currentTimeMillis(); final long elapsedRealtime = SystemClock.elapsedRealtime(); - convertToSystemTimeLocked(event); if (event.mPackage != null && mPackageManagerInternal.isPackageEphemeral(userId, event.mPackage)) { @@ -876,13 +839,8 @@ public class UsageStatsService extends SystemService implements return null; } - final long timeNow = checkAndGetTimeLocked(); - if (!validRange(timeNow, beginTime, endTime)) { - return null; - } - final UserUsageStatsService service = - getUserDataAndInitializeIfNeededLocked(userId, timeNow); + getUserDataAndInitializeIfNeededLocked(userId, System.currentTimeMillis()); List<UsageStats> list = service.queryUsageStats(bucketType, beginTime, endTime); if (list == null) { return null; @@ -913,13 +871,8 @@ public class UsageStatsService extends SystemService implements return null; } - final long timeNow = checkAndGetTimeLocked(); - if (!validRange(timeNow, beginTime, endTime)) { - return null; - } - final UserUsageStatsService service = - getUserDataAndInitializeIfNeededLocked(userId, timeNow); + getUserDataAndInitializeIfNeededLocked(userId, System.currentTimeMillis()); return service.queryConfigurationStats(bucketType, beginTime, endTime); } } @@ -935,13 +888,8 @@ public class UsageStatsService extends SystemService implements return null; } - final long timeNow = checkAndGetTimeLocked(); - if (!validRange(timeNow, beginTime, endTime)) { - return null; - } - final UserUsageStatsService service = - getUserDataAndInitializeIfNeededLocked(userId, timeNow); + getUserDataAndInitializeIfNeededLocked(userId, System.currentTimeMillis()); return service.queryEventStats(bucketType, beginTime, endTime); } } @@ -957,13 +905,8 @@ public class UsageStatsService extends SystemService implements return null; } - final long timeNow = checkAndGetTimeLocked(); - if (!validRange(timeNow, beginTime, endTime)) { - return null; - } - final UserUsageStatsService service = - getUserDataAndInitializeIfNeededLocked(userId, timeNow); + getUserDataAndInitializeIfNeededLocked(userId, System.currentTimeMillis()); return service.queryEvents(beginTime, endTime, shouldObfuscateInstantApps); } } @@ -979,21 +922,12 @@ public class UsageStatsService extends SystemService implements return null; } - final long timeNow = checkAndGetTimeLocked(); - if (!validRange(timeNow, beginTime, endTime)) { - return null; - } - final UserUsageStatsService service = - getUserDataAndInitializeIfNeededLocked(userId, timeNow); + getUserDataAndInitializeIfNeededLocked(userId, System.currentTimeMillis()); return service.queryEventsForPackage(beginTime, endTime, packageName, includeTaskRoot); } } - private static boolean validRange(long currentTime, long beginTime, long endTime) { - return beginTime <= currentTime && beginTime < endTime; - } - private String buildFullToken(String packageName, String token) { final StringBuilder sb = new StringBuilder(packageName.length() + token.length() + 1); sb.append(packageName); @@ -2050,8 +1984,8 @@ public class UsageStatsService extends SystemService implements // Check to ensure that only user 0's data is b/r for now if (user == UserHandle.USER_SYSTEM) { - final UserUsageStatsService userStats = - getUserDataAndInitializeIfNeededLocked(user, checkAndGetTimeLocked()); + final UserUsageStatsService userStats = getUserDataAndInitializeIfNeededLocked( + user, System.currentTimeMillis()); return userStats.getBackupPayload(key); } else { return null; @@ -2068,8 +2002,8 @@ public class UsageStatsService extends SystemService implements } if (user == UserHandle.USER_SYSTEM) { - final UserUsageStatsService userStats = - getUserDataAndInitializeIfNeededLocked(user, checkAndGetTimeLocked()); + final UserUsageStatsService userStats = getUserDataAndInitializeIfNeededLocked( + user, System.currentTimeMillis()); userStats.applyRestoredPayload(key, payload); } } diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java index 6fbd88227f9b..1560b9e708e3 100644 --- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java +++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java @@ -76,6 +76,8 @@ class UserUsageStatsService { private final String mLogPrefix; private String mLastBackgroundedPackage; private final int mUserId; + private long mRealTimeSnapshot; + private long mSystemTimeSnapshot; private static final long[] INTERVAL_LENGTH = new long[] { UnixCalendar.DAY_IN_MILLIS, UnixCalendar.WEEK_IN_MILLIS, @@ -101,6 +103,8 @@ class UserUsageStatsService { mListener = listener; mLogPrefix = "User[" + Integer.toString(userId) + "] "; mUserId = userId; + mRealTimeSnapshot = SystemClock.elapsedRealtime(); + mSystemTimeSnapshot = System.currentTimeMillis(); } void init(final long currentTimeMillis) { @@ -165,12 +169,41 @@ class UserUsageStatsService { persistActiveStats(); } - void onTimeChanged(long oldTime, long newTime) { + private void onTimeChanged(long oldTime, long newTime) { persistActiveStats(); mDatabase.onTimeChanged(newTime - oldTime); loadActiveStats(newTime); } + /** + * This should be the only way to get the time from the system. + */ + private long checkAndGetTimeLocked() { + final long actualSystemTime = System.currentTimeMillis(); + if (!UsageStatsService.ENABLE_TIME_CHANGE_CORRECTION) { + return actualSystemTime; + } + final long actualRealtime = SystemClock.elapsedRealtime(); + final long expectedSystemTime = (actualRealtime - mRealTimeSnapshot) + mSystemTimeSnapshot; + final long diffSystemTime = actualSystemTime - expectedSystemTime; + if (Math.abs(diffSystemTime) > UsageStatsService.TIME_CHANGE_THRESHOLD_MILLIS) { + // The time has changed. + Slog.i(TAG, mLogPrefix + "Time changed in by " + (diffSystemTime / 1000) + " seconds"); + onTimeChanged(expectedSystemTime, actualSystemTime); + mRealTimeSnapshot = actualRealtime; + mSystemTimeSnapshot = actualSystemTime; + } + return actualSystemTime; + } + + /** + * Assuming the event's timestamp is measured in milliseconds since boot, + * convert it to a system wall time. + */ + private void convertToSystemTimeLocked(Event event) { + event.mTimeStamp = Math.max(0, event.mTimeStamp - mRealTimeSnapshot) + mSystemTimeSnapshot; + } + void reportEvent(Event event) { if (DEBUG) { Slog.d(TAG, mLogPrefix + "Got usage event for " + event.mPackage @@ -178,6 +211,9 @@ class UserUsageStatsService { + eventToString(event.mEventType)); } + checkAndGetTimeLocked(); + convertToSystemTimeLocked(event); + if (event.mTimeStamp >= mDailyExpiryDate.getTimeInMillis()) { // Need to rollover rolloverStats(event.mTimeStamp); @@ -298,6 +334,10 @@ class UserUsageStatsService { } }; + private static boolean validRange(long currentTime, long beginTime, long endTime) { + return beginTime <= currentTime && beginTime < endTime; + } + /** * Generic query method that selects the appropriate IntervalStats for the specified time range * and bucket, then calls the {@link com.android.server.usage.UsageStatsDatabase.StatCombiner} @@ -370,19 +410,31 @@ class UserUsageStatsService { } List<UsageStats> queryUsageStats(int bucketType, long beginTime, long endTime) { + if (!validRange(checkAndGetTimeLocked(), beginTime, endTime)) { + return null; + } return queryStats(bucketType, beginTime, endTime, sUsageStatsCombiner); } List<ConfigurationStats> queryConfigurationStats(int bucketType, long beginTime, long endTime) { + if (!validRange(checkAndGetTimeLocked(), beginTime, endTime)) { + return null; + } return queryStats(bucketType, beginTime, endTime, sConfigStatsCombiner); } List<EventStats> queryEventStats(int bucketType, long beginTime, long endTime) { + if (!validRange(checkAndGetTimeLocked(), beginTime, endTime)) { + return null; + } return queryStats(bucketType, beginTime, endTime, sEventStatsCombiner); } UsageEvents queryEvents(final long beginTime, final long endTime, boolean obfuscateInstantApps) { + if (!validRange(checkAndGetTimeLocked(), beginTime, endTime)) { + return null; + } final ArraySet<String> names = new ArraySet<>(); List<Event> results = queryStats(INTERVAL_DAILY, beginTime, endTime, new StatCombiner<Event>() { @@ -428,6 +480,9 @@ class UserUsageStatsService { UsageEvents queryEventsForPackage(final long beginTime, final long endTime, final String packageName, boolean includeTaskRoot) { + if (!validRange(checkAndGetTimeLocked(), beginTime, endTime)) { + return null; + } final ArraySet<String> names = new ArraySet<>(); names.add(packageName); final List<Event> results = queryStats(INTERVAL_DAILY, @@ -1030,10 +1085,12 @@ class UserUsageStatsService { } byte[] getBackupPayload(String key){ + checkAndGetTimeLocked(); return mDatabase.getBackupPayload(key); } void applyRestoredPayload(String key, byte[] payload){ + checkAndGetTimeLocked(); mDatabase.applyRestoredPayload(key, payload); } } diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbConfigDescriptor.java b/services/usb/java/com/android/server/usb/descriptors/UsbConfigDescriptor.java index de2dd101acfd..3f2d8c8ef47c 100644 --- a/services/usb/java/com/android/server/usb/descriptors/UsbConfigDescriptor.java +++ b/services/usb/java/com/android/server/usb/descriptors/UsbConfigDescriptor.java @@ -41,6 +41,8 @@ public final class UsbConfigDescriptor extends UsbDescriptor { // D4..0 Reserved, set to 0. private int mMaxPower; // 8:1 Maximum Power Consumption in 2mA units + private boolean mBlockAudio; // leave it off for now. We be replace with a "Developer Option" + private ArrayList<UsbInterfaceDescriptor> mInterfaceDescriptors = new ArrayList<UsbInterfaceDescriptor>(); @@ -77,21 +79,35 @@ public final class UsbConfigDescriptor extends UsbDescriptor { mInterfaceDescriptors.add(interfaceDesc); } + private boolean isAudioInterface(UsbInterfaceDescriptor descriptor) { + return descriptor.getUsbClass() == UsbDescriptor.CLASSID_AUDIO + && descriptor.getUsbSubclass() == UsbDescriptor.AUDIO_AUDIOSTREAMING; + } + UsbConfiguration toAndroid(UsbDescriptorParser parser) { if (UsbDescriptorParser.DEBUG) { Log.d(TAG, " toAndroid()"); } + + // NOTE - This code running in the server process. + //TODO (pmclean@) - remove this +// int pid = android.os.Process.myPid(); +// int uid = android.os.Process.myUid(); +// Log.d(TAG, " ---- pid:" + pid + " uid:" + uid); + String name = parser.getDescriptorString(mConfigIndex); UsbConfiguration config = new UsbConfiguration(mConfigValue, name, mAttribs, mMaxPower); - UsbInterface[] interfaces = new UsbInterface[mInterfaceDescriptors.size()]; - if (UsbDescriptorParser.DEBUG) { - Log.d(TAG, " " + mInterfaceDescriptors.size() + " interfaces."); - } - for (int index = 0; index < mInterfaceDescriptors.size(); index++) { - interfaces[index] = mInterfaceDescriptors.get(index).toAndroid(parser); + + ArrayList<UsbInterface> filteredInterfaces = new ArrayList<UsbInterface>(); + for (UsbInterfaceDescriptor descriptor : mInterfaceDescriptors) { + if (!mBlockAudio || !isAudioInterface(descriptor)) { + filteredInterfaces.add(descriptor.toAndroid(parser)); + } } - config.setInterfaces(interfaces); + UsbInterface[] interfaceArray = new UsbInterface[0]; + interfaceArray = filteredInterfaces.toArray(interfaceArray); + config.setInterfaces(interfaceArray); return config; } diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbDescriptorParser.java b/services/usb/java/com/android/server/usb/descriptors/UsbDescriptorParser.java index 4f62d5a5c967..6ffbd43a7b1a 100644 --- a/services/usb/java/com/android/server/usb/descriptors/UsbDescriptorParser.java +++ b/services/usb/java/com/android/server/usb/descriptors/UsbDescriptorParser.java @@ -26,7 +26,7 @@ import java.util.ArrayList; */ public final class UsbDescriptorParser { private static final String TAG = "UsbDescriptorParser"; - public static final boolean DEBUG = false; + public static final boolean DEBUG = true; private final String mDeviceAddr; diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbEndpointDescriptor.java b/services/usb/java/com/android/server/usb/descriptors/UsbEndpointDescriptor.java index 5eb0a2f75ded..4d0cfea98630 100644 --- a/services/usb/java/com/android/server/usb/descriptors/UsbEndpointDescriptor.java +++ b/services/usb/java/com/android/server/usb/descriptors/UsbEndpointDescriptor.java @@ -31,7 +31,7 @@ public class UsbEndpointDescriptor extends UsbDescriptor { public static final int MASK_ENDPOINT_ADDRESS = 0b000000000001111; public static final int MASK_ENDPOINT_DIRECTION = (byte) 0b0000000010000000; public static final int DIRECTION_OUTPUT = 0x0000; - public static final int DIRECTION_INPUT = (byte) 0x0080; + public static final int DIRECTION_INPUT = 0x0080; public static final int MASK_ATTRIBS_TRANSTYPE = 0b00000011; public static final int TRANSTYPE_CONTROL = 0x00; @@ -85,7 +85,7 @@ public class UsbEndpointDescriptor extends UsbDescriptor { } public int getEndpointAddress() { - return mEndpointAddress; + return mEndpointAddress & MASK_ENDPOINT_ADDRESS; } public int getAttributes() { @@ -108,6 +108,10 @@ public class UsbEndpointDescriptor extends UsbDescriptor { return mSyncAddress; } + public int getDirection() { + return mEndpointAddress & UsbEndpointDescriptor.MASK_ENDPOINT_DIRECTION; + } + /* package */ UsbEndpoint toAndroid(UsbDescriptorParser parser) { if (UsbDescriptorParser.DEBUG) { Log.d(TAG, "toAndroid() type:" @@ -137,11 +141,9 @@ public class UsbEndpointDescriptor extends UsbDescriptor { canvas.openList(); - int address = getEndpointAddress(); canvas.writeListItem("Address: " - + ReportCanvas.getHexString(address & UsbEndpointDescriptor.MASK_ENDPOINT_ADDRESS) - + ((address & UsbEndpointDescriptor.MASK_ENDPOINT_DIRECTION) - == UsbEndpointDescriptor.DIRECTION_OUTPUT ? " [out]" : " [in]")); + + ReportCanvas.getHexString(getEndpointAddress()) + + (getDirection() == UsbEndpointDescriptor.DIRECTION_OUTPUT ? " [out]" : " [in]")); int attributes = getAttributes(); canvas.openListItem(); diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbInterfaceDescriptor.java b/services/usb/java/com/android/server/usb/descriptors/UsbInterfaceDescriptor.java index 1dc6069bbb0a..64dbd971cc67 100644 --- a/services/usb/java/com/android/server/usb/descriptors/UsbInterfaceDescriptor.java +++ b/services/usb/java/com/android/server/usb/descriptors/UsbInterfaceDescriptor.java @@ -31,7 +31,6 @@ import java.util.ArrayList; */ public class UsbInterfaceDescriptor extends UsbDescriptor { private static final String TAG = "UsbInterfaceDescriptor"; - protected int mInterfaceNumber; // 2:1 Number of Interface protected byte mAlternateSetting; // 3:1 Value used to select alternative setting protected byte mNumEndpoints; // 4:1 Number of Endpoints used for this interface @@ -73,6 +72,19 @@ public class UsbInterfaceDescriptor extends UsbDescriptor { return mNumEndpoints; } + /** + * @param index Index of desired UsbEndpointDescriptor. + * @return the UsbEndpointDescriptor descriptor at the specified index, or + * null if an invalid index. + */ + public UsbEndpointDescriptor getEndpointDescriptor(int index) { + if (index < 0 || index >= mEndpointDescriptors.size()) { + return null; + } + + return mEndpointDescriptors.get(index); + } + public int getUsbClass() { return mUsbClass; } diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java index f16dec6fb670..0ff92739f8b6 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java @@ -194,7 +194,7 @@ final class VoiceInteractionSessionConnection implements ServiceConnection, if (!mFullyBound) { mFullyBound = mContext.bindServiceAsUser(mBindIntent, mFullConnection, Context.BIND_AUTO_CREATE | Context.BIND_TREAT_LIKE_ACTIVITY - | Context.BIND_FOREGROUND_SERVICE + | Context.BIND_SCHEDULE_LIKE_TOP_APP | Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS, new UserHandle(mUser)); } diff --git a/startop/iorap/src/com/google/android/startop/iorap/IorapForwardingService.java b/startop/iorap/src/com/google/android/startop/iorap/IorapForwardingService.java index 31bd34199784..902da4c0f72e 100644 --- a/startop/iorap/src/com/google/android/startop/iorap/IorapForwardingService.java +++ b/startop/iorap/src/com/google/android/startop/iorap/IorapForwardingService.java @@ -275,7 +275,8 @@ public class IorapForwardingService extends SystemService { Log.e(TAG, "connectToRemoteAndConfigure - null iorap remote. check for Log.wtf?"); return false; } - invokeRemote( () -> mIorapRemote.setTaskListener(new RemoteTaskListener()) ); + invokeRemote(mIorapRemote, + (IIorap remote) -> remote.setTaskListener(new RemoteTaskListener()) ); registerInProcessListenersLocked(); return true; @@ -323,8 +324,9 @@ public class IorapForwardingService extends SystemService { mSequenceId, intent)); } - invokeRemote(() -> - mIorapRemote.onAppLaunchEvent(RequestId.nextValueForSequence(), + invokeRemote(mIorapRemote, + (IIorap remote) -> + remote.onAppLaunchEvent(RequestId.nextValueForSequence(), new AppLaunchEvent.IntentStarted(mSequenceId, intent)) ); } @@ -335,8 +337,9 @@ public class IorapForwardingService extends SystemService { Log.v(TAG, String.format("AppLaunchObserver#onIntentFailed(%d)", mSequenceId)); } - invokeRemote(() -> - mIorapRemote.onAppLaunchEvent(RequestId.nextValueForSequence(), + invokeRemote(mIorapRemote, + (IIorap remote) -> + remote.onAppLaunchEvent(RequestId.nextValueForSequence(), new AppLaunchEvent.IntentFailed(mSequenceId)) ); } @@ -349,8 +352,9 @@ public class IorapForwardingService extends SystemService { mSequenceId, activity, temperature)); } - invokeRemote(() -> - mIorapRemote.onAppLaunchEvent(RequestId.nextValueForSequence(), + invokeRemote(mIorapRemote, + (IIorap remote) -> + remote.onAppLaunchEvent(RequestId.nextValueForSequence(), new AppLaunchEvent.ActivityLaunched(mSequenceId, activity, temperature)) ); } @@ -362,8 +366,9 @@ public class IorapForwardingService extends SystemService { mSequenceId, activity)); } - invokeRemote(() -> - mIorapRemote.onAppLaunchEvent(RequestId.nextValueForSequence(), + invokeRemote(mIorapRemote, + (IIorap remote) -> + remote.onAppLaunchEvent(RequestId.nextValueForSequence(), new AppLaunchEvent.ActivityLaunchCancelled(mSequenceId, activity))); } @@ -375,8 +380,9 @@ public class IorapForwardingService extends SystemService { mSequenceId, activity)); } - invokeRemote(() -> - mIorapRemote.onAppLaunchEvent(RequestId.nextValueForSequence(), + invokeRemote(mIorapRemote, + (IIorap remote) -> + remote.onAppLaunchEvent(RequestId.nextValueForSequence(), new AppLaunchEvent.ActivityLaunchFinished(mSequenceId, activity)) ); } @@ -501,8 +507,8 @@ public class IorapForwardingService extends SystemService { mRunningJobs.put(request, params); } - if (!invokeRemote( () -> - mIorapRemote.onJobScheduledEvent(request, + if (!invokeRemote(mIorapRemote, (IIorap remote) -> + remote.onJobScheduledEvent(request, JobScheduledEvent.createIdleMaintenance( JobScheduledEvent.TYPE_START_JOB, params)) @@ -539,8 +545,8 @@ public class IorapForwardingService extends SystemService { // Notify iorapd to stop (abort) the job. if (wasTracking) { - invokeRemote(() -> - mIorapRemote.onJobScheduledEvent(RequestId.nextValueForSequence(), + invokeRemote(mIorapRemote, (IIorap remote) -> + remote.onJobScheduledEvent(RequestId.nextValueForSequence(), JobScheduledEvent.createIdleMaintenance( JobScheduledEvent.TYPE_STOP_JOB, params)) @@ -632,12 +638,17 @@ public class IorapForwardingService extends SystemService { /** Allow passing lambdas to #invokeRemote */ private interface RemoteRunnable { // TODO: run(RequestId) ? - void run() throws RemoteException; + void run(IIorap iorap) throws RemoteException; } - private static boolean invokeRemote(RemoteRunnable r) { + // Always pass in the iorap directly here to avoid data race. + private static boolean invokeRemote(IIorap iorap, RemoteRunnable r) { + if (iorap == null) { + Log.w(TAG, "IIorap went to null in this thread, drop invokeRemote."); + return false; + } try { - r.run(); + r.run(iorap); return true; } catch (RemoteException e) { // This could be a logic error (remote side returning error), which we need to fix. diff --git a/startop/view_compiler/dex_builder_test/Android.bp b/startop/view_compiler/dex_builder_test/Android.bp index 1214538e8f0d..f783aa68fe92 100644 --- a/startop/view_compiler/dex_builder_test/Android.bp +++ b/startop/view_compiler/dex_builder_test/Android.bp @@ -37,15 +37,21 @@ genrule { android_test { name: "dex-builder-test", srcs: [ + "src/android/startop/test/ApkLayoutCompilerTest.java", "src/android/startop/test/DexBuilderTest.java", "src/android/startop/test/LayoutCompilerTest.java", "src/android/startop/test/TestClass.java", ], sdk_version: "current", - data: [":generate_dex_testcases", ":generate_compiled_layout1", ":generate_compiled_layout2"], + data: [ + ":generate_dex_testcases", + ":generate_compiled_layout1", + ":generate_compiled_layout2", + ], static_libs: [ - "androidx.test.rules", - "guava", + "androidx.test.core", + "androidx.test.runner", + "junit", ], manifest: "AndroidManifest.xml", resource_dirs: ["res"], diff --git a/startop/view_compiler/dex_builder_test/src/android/startop/test/ApkLayoutCompilerTest.java b/startop/view_compiler/dex_builder_test/src/android/startop/test/ApkLayoutCompilerTest.java new file mode 100644 index 000000000000..230e8df1e687 --- /dev/null +++ b/startop/view_compiler/dex_builder_test/src/android/startop/test/ApkLayoutCompilerTest.java @@ -0,0 +1,57 @@ +/* + * 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.startop.test; + +import android.content.Context; +import androidx.test.InstrumentationRegistry; +import android.view.View; +import dalvik.system.PathClassLoader; +import java.lang.reflect.Method; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +public class ApkLayoutCompilerTest { + static ClassLoader loadDexFile() throws Exception { + Context context = InstrumentationRegistry.getTargetContext(); + return new PathClassLoader(context.getCodeCacheDir() + "/compiled_view.dex", + ClassLoader.getSystemClassLoader()); + } + + @BeforeClass + public static void setup() throws Exception { + // ensure PackageManager has compiled the layouts. + Process pm = Runtime.getRuntime().exec("pm compile --compile-layouts android.startop.test"); + pm.waitFor(); + } + + @Test + public void loadAndInflateLayout1() throws Exception { + ClassLoader dex_file = loadDexFile(); + Class compiled_view = dex_file.loadClass("android.startop.test.CompiledView"); + Method layout1 = compiled_view.getMethod("layout1", Context.class, int.class); + Context context = InstrumentationRegistry.getTargetContext(); + layout1.invoke(null, context, R.layout.layout1); + } + + @Test + public void loadAndInflateLayout2() throws Exception { + ClassLoader dex_file = loadDexFile(); + Class compiled_view = dex_file.loadClass("android.startop.test.CompiledView"); + Method layout2 = compiled_view.getMethod("layout2", Context.class, int.class); + Context context = InstrumentationRegistry.getTargetContext(); + layout2.invoke(null, context, R.layout.layout2); + } +} diff --git a/startop/view_compiler/dex_builder_test/src/android/startop/test/DexBuilderTest.java b/startop/view_compiler/dex_builder_test/src/android/startop/test/DexBuilderTest.java index d1fe58800bbf..6af01f6f3292 100644 --- a/startop/view_compiler/dex_builder_test/src/android/startop/test/DexBuilderTest.java +++ b/startop/view_compiler/dex_builder_test/src/android/startop/test/DexBuilderTest.java @@ -14,8 +14,11 @@ package android.startop.test; +import android.content.Context; +import androidx.test.InstrumentationRegistry; import dalvik.system.PathClassLoader; - +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import org.junit.Assert; import org.junit.Test; diff --git a/startop/view_compiler/dex_builder_test/src/android/startop/test/LayoutCompilerTest.java b/startop/view_compiler/dex_builder_test/src/android/startop/test/LayoutCompilerTest.java index 3dfb20c2e524..b0cf91d5fb97 100644 --- a/startop/view_compiler/dex_builder_test/src/android/startop/test/LayoutCompilerTest.java +++ b/startop/view_compiler/dex_builder_test/src/android/startop/test/LayoutCompilerTest.java @@ -15,11 +15,11 @@ package android.startop.test; import android.content.Context; - import androidx.test.InstrumentationRegistry; - +import android.view.View; import dalvik.system.PathClassLoader; - +import java.lang.reflect.Method; +import org.junit.Assert; import org.junit.Test; import java.lang.reflect.Method; diff --git a/telephony/java/android/provider/Telephony.java b/telephony/java/android/provider/Telephony.java index c1b8479a7f56..67b252e52db9 100644 --- a/telephony/java/android/provider/Telephony.java +++ b/telephony/java/android/provider/Telephony.java @@ -3962,6 +3962,13 @@ public final class Telephony { public static final Uri CONTENT_URI = Uri.parse("content://cellbroadcasts"); /** + * The id of the subscription which received this cell broadcast message. + * <P>Type: INTEGER</P> + * @hide + */ + public static final String SUB_ID = "sub_id"; + + /** * Message geographical scope. Valid values are: * <ul> * <li>{@link android.telephony.SmsCbMessage#GEOGRAPHICAL_SCOPE_CELL_WIDE}. meaning the @@ -4183,6 +4190,18 @@ public final class Telephony { public static final String GEOMETRIES = "geometries"; /** + * Geo-Fencing Maximum Wait Time in second. The range of the time is [0, 255]. A device + * shall allow to determine its position meeting operator policy. If the device is unable to + * determine its position meeting operator policy within the GeoFencing Maximum Wait Time, + * it shall present the alert to the user and discontinue further positioning determination + * for the alert. + * + * <P>Type: INTEGER</P> + * @hide + */ + public static final String MAXIMUM_WAIT_TIME = "maximum_wait_time"; + + /** * Query columns for instantiating {@link android.telephony.CellBroadcastMessage} objects. * @hide */ @@ -4235,7 +4254,8 @@ public final class Telephony { CMAS_CERTAINTY, RECEIVED_TIME, MESSAGE_BROADCASTED, - GEOMETRIES + GEOMETRIES, + MAXIMUM_WAIT_TIME }; } diff --git a/telephony/java/android/telephony/SmsCbMessage.java b/telephony/java/android/telephony/SmsCbMessage.java index 77231d107c6a..c078764cfa24 100644 --- a/telephony/java/android/telephony/SmsCbMessage.java +++ b/telephony/java/android/telephony/SmsCbMessage.java @@ -139,6 +139,12 @@ public final class SmsCbMessage implements Parcelable { @Retention(RetentionPolicy.SOURCE) public @interface MessagePriority {} + /** + * ATIS-0700041 Section 5.2.8 WAC Geo-Fencing Maximum Wait Time Table 12. + * @hide + */ + public static final int MAXIMUM_WAIT_TIME_NOT_SET = 255; + /** Format of this message (for interpretation of service category values). */ private final int mMessageFormat; @@ -187,6 +193,14 @@ public final class SmsCbMessage implements Parcelable { @Nullable private final SmsCbCmasInfo mCmasWarningInfo; + /** + * Geo-Fencing Maximum Wait Time in second, a device shall allow to determine its position + * meeting operator policy. If the device is unable to determine its position meeting operator + * policy within the GeoFencing Maximum Wait Time, it shall present the alert to the user and + * discontinue further positioning determination for the alert. + */ + private final int mMaximumWaitTimeSec; + /** UNIX timestamp of when the message was received. */ private final long mReceivedTimeMillis; @@ -202,8 +216,8 @@ public final class SmsCbMessage implements Parcelable { @Nullable SmsCbCmasInfo cmasWarningInfo) { this(messageFormat, geographicalScope, serialNumber, location, serviceCategory, language, - body, priority, etwsWarningInfo, cmasWarningInfo, null /* geometries */, - System.currentTimeMillis()); + body, priority, etwsWarningInfo, cmasWarningInfo, 0 /* maximumWaitingTime */, + null /* geometries */, System.currentTimeMillis()); } /** @@ -213,7 +227,7 @@ public final class SmsCbMessage implements Parcelable { public SmsCbMessage(int messageFormat, int geographicalScope, int serialNumber, SmsCbLocation location, int serviceCategory, String language, String body, int priority, SmsCbEtwsInfo etwsWarningInfo, SmsCbCmasInfo cmasWarningInfo, - List<Geometry> geometries, long receivedTimeMillis) { + int maximumWaitTimeSec, List<Geometry> geometries, long receivedTimeMillis) { mMessageFormat = messageFormat; mGeographicalScope = geographicalScope; mSerialNumber = serialNumber; @@ -226,6 +240,7 @@ public final class SmsCbMessage implements Parcelable { mCmasWarningInfo = cmasWarningInfo; mReceivedTimeMillis = receivedTimeMillis; mGeometries = geometries; + mMaximumWaitTimeSec = maximumWaitTimeSec; } /** @@ -262,6 +277,7 @@ public final class SmsCbMessage implements Parcelable { mReceivedTimeMillis = in.readLong(); String geoStr = in.readString(); mGeometries = geoStr != null ? CbGeoUtils.parseGeometriesFromString(geoStr) : null; + mMaximumWaitTimeSec = in.readInt(); } /** @@ -295,6 +311,7 @@ public final class SmsCbMessage implements Parcelable { dest.writeLong(mReceivedTimeMillis); dest.writeString( mGeometries != null ? CbGeoUtils.encodeGeometriesToString(mGeometries) : null); + dest.writeInt(mMaximumWaitTimeSec); } @NonNull @@ -389,6 +406,15 @@ public final class SmsCbMessage implements Parcelable { } /** + * Get the Geo-Fencing Maximum Wait Time. + * @return the time in second. + * @hide + */ + public int getMaximumWaitingTime() { + return mMaximumWaitTimeSec; + } + + /** * Get the time when this message was received. * @return the time in millisecond */ @@ -475,6 +501,7 @@ public final class SmsCbMessage implements Parcelable { + ", priority=" + mPriority + (mEtwsWarningInfo != null ? (", " + mEtwsWarningInfo.toString()) : "") + (mCmasWarningInfo != null ? (", " + mCmasWarningInfo.toString()) : "") + + ", maximumWaitingTime = " + mMaximumWaitTimeSec + ", geo=" + (mGeometries != null ? CbGeoUtils.encodeGeometriesToString(mGeometries) : "null") + '}'; @@ -535,6 +562,8 @@ public final class SmsCbMessage implements Parcelable { cv.put(CellBroadcasts.GEOMETRIES, (String) null); } + cv.put(CellBroadcasts.MAXIMUM_WAIT_TIME, mMaximumWaitTimeSec); + return cv; } @@ -644,17 +673,21 @@ public final class SmsCbMessage implements Parcelable { List<Geometry> geometries = geoStr != null ? CbGeoUtils.parseGeometriesFromString(geoStr) : null; - long receivedTimeSec = cursor.getLong( + long receivedTimeMillis = cursor.getLong( cursor.getColumnIndexOrThrow(CellBroadcasts.RECEIVED_TIME)); + int maximumWaitTimeSec = cursor.getInt( + cursor.getColumnIndexOrThrow(CellBroadcasts.MAXIMUM_WAIT_TIME)); + return new SmsCbMessage(format, geoScope, serialNum, location, category, - language, body, priority, etwsInfo, cmasInfo, geometries, receivedTimeSec); + language, body, priority, etwsInfo, cmasInfo, maximumWaitTimeSec, geometries, + receivedTimeMillis); } /** * @return {@code True} if this message needs geo-fencing check. */ public boolean needGeoFencingCheck() { - return mGeometries != null; + return mMaximumWaitTimeSec > 0 && mGeometries != null; } } diff --git a/telephony/java/android/telephony/ims/feature/ImsFeature.java b/telephony/java/android/telephony/ims/feature/ImsFeature.java index 3a9979d78a55..356288047e15 100644 --- a/telephony/java/android/telephony/ims/feature/ImsFeature.java +++ b/telephony/java/android/telephony/ims/feature/ImsFeature.java @@ -201,15 +201,20 @@ public abstract class ImsFeature { } /** - * Contains the capabilities defined and supported by an ImsFeature in the form of a bit mask. - * <p> - * Typically this class is not used directly, but rather extended in subclasses of + * Contains the IMS capabilities defined and supported by an ImsFeature in the form of a + * bit-mask. + * + * @deprecated This class is not used directly, but rather extended in subclasses of * {@link ImsFeature} to provide service specific capabilities. + * @see MmTelFeature.MmTelCapabilities * @hide */ - @SystemApi + // Not Actually deprecated, but we need to remove it from the @SystemApi surface. + @Deprecated + @SystemApi // SystemApi only because it was leaked through type usage in a previous release. public static class Capabilities { /** @deprecated Use getters and accessors instead. */ + // Not actually deprecated, but we need to remove it from the @SystemApi surface eventually. protected int mCapabilities = 0; /** diff --git a/telephony/java/android/telephony/ims/feature/MmTelFeature.java b/telephony/java/android/telephony/ims/feature/MmTelFeature.java index 20c191da0550..ceb470491dc5 100644 --- a/telephony/java/android/telephony/ims/feature/MmTelFeature.java +++ b/telephony/java/android/telephony/ims/feature/MmTelFeature.java @@ -242,8 +242,8 @@ public class MmTelFeature extends ImsFeature { * @param capabilities The capabilities that are supported for MmTel in the form of a * bitfield. */ - public MmTelCapabilities(int capabilities) { - mCapabilities = capabilities; + public MmTelCapabilities(@MmTelCapability int capabilities) { + super(capabilities); } @IntDef(flag = true, diff --git a/telephony/java/com/android/internal/telephony/CbGeoUtils.java b/telephony/java/com/android/internal/telephony/CbGeoUtils.java index 73dd822903f5..0b73252a1e1b 100644 --- a/telephony/java/com/android/internal/telephony/CbGeoUtils.java +++ b/telephony/java/com/android/internal/telephony/CbGeoUtils.java @@ -299,7 +299,8 @@ public class CbGeoUtils { * @return the encoded string. */ @NonNull - public static String encodeGeometriesToString(@NonNull List<Geometry> geometries) { + public static String encodeGeometriesToString(List<Geometry> geometries) { + if (geometries == null || geometries.isEmpty()) return ""; return geometries.stream() .map(geometry -> encodeGeometryToString(geometry)) .filter(encodedStr -> !TextUtils.isEmpty(encodedStr)) diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java b/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java index dca4e6b13b90..6eea118787a7 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java +++ b/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java @@ -104,7 +104,7 @@ public class GsmSmsCbMessage { header.getSerialNumber(), location, header.getServiceCategory(), null, getEtwsPrimaryMessage(context, header.getEtwsInfo().getWarningType()), SmsCbMessage.MESSAGE_PRIORITY_EMERGENCY, header.getEtwsInfo(), - header.getCmasInfo(), null /* geometries */, receivedTimeMillis); + header.getCmasInfo(), 0, null /* geometries */, receivedTimeMillis); } else if (header.isUmtsFormat()) { // UMTS format has only 1 PDU byte[] pdu = pdus[0]; @@ -120,9 +120,13 @@ public class GsmSmsCbMessage { // Has Warning Area Coordinates information List<Geometry> geometries = null; + int maximumWaitingTimeSec = 255; if (pdu.length > wacDataOffset) { try { - geometries = parseWarningAreaCoordinates(pdu, wacDataOffset); + Pair<Integer, List<Geometry>> wac = parseWarningAreaCoordinates(pdu, + wacDataOffset); + maximumWaitingTimeSec = wac.first; + geometries = wac.second; } catch (Exception ex) { // Catch the exception here, the message will be considered as having no WAC // information which means the message will be broadcasted directly. @@ -133,7 +137,8 @@ public class GsmSmsCbMessage { return new SmsCbMessage(SmsCbMessage.MESSAGE_FORMAT_3GPP, header.getGeographicalScope(), header.getSerialNumber(), location, header.getServiceCategory(), language, body, priority, - header.getEtwsInfo(), header.getCmasInfo(), geometries, receivedTimeMillis); + header.getEtwsInfo(), header.getCmasInfo(), maximumWaitingTimeSec, geometries, + receivedTimeMillis); } else { String language = null; StringBuilder sb = new StringBuilder(); @@ -148,7 +153,7 @@ public class GsmSmsCbMessage { return new SmsCbMessage(SmsCbMessage.MESSAGE_FORMAT_3GPP, header.getGeographicalScope(), header.getSerialNumber(), location, header.getServiceCategory(), language, sb.toString(), priority, - header.getEtwsInfo(), header.getCmasInfo(), null /* geometries */, + header.getEtwsInfo(), header.getCmasInfo(), 0, null /* geometries */, receivedTimeMillis); } } @@ -197,7 +202,17 @@ public class GsmSmsCbMessage { } } - private static List<Geometry> parseWarningAreaCoordinates(byte[] pdu, int wacOffset) { + /** + * Parse the broadcast area and maximum wait time from the Warning Area Coordinates TLV. + * + * @param pdu Warning Area Coordinates TLV. + * @param wacOffset the offset of Warning Area Coordinates TLV. + * @return a pair with the first element is maximum wait time and the second is the broadcast + * area. The default value of the maximum wait time is 255 which means use the device default + * value. + */ + private static Pair<Integer, List<Geometry>> parseWarningAreaCoordinates( + byte[] pdu, int wacOffset) { // little-endian int wacDataLength = (pdu[wacOffset + 1] << 8) | pdu[wacOffset]; int offset = wacOffset + 2; @@ -209,6 +224,8 @@ public class GsmSmsCbMessage { BitStreamReader bitReader = new BitStreamReader(pdu, offset); + int maximumWaitTimeSec = SmsCbMessage.MAXIMUM_WAIT_TIME_NOT_SET; + List<Geometry> geo = new ArrayList<>(); int remainedBytes = wacDataLength; while (remainedBytes > 0) { @@ -220,8 +237,7 @@ public class GsmSmsCbMessage { switch (type) { case CbGeoUtils.GEO_FENCING_MAXIMUM_WAIT_TIME: - // TODO: handle the maximum wait time in cell broadcast provider. - int maximumWaitTimeSec = bitReader.read(8); + maximumWaitTimeSec = bitReader.read(8); break; case CbGeoUtils.GEOMETRY_TYPE_POLYGON: List<LatLng> latLngs = new ArrayList<>(); @@ -247,7 +263,7 @@ public class GsmSmsCbMessage { throw new IllegalArgumentException("Unsupported geoType = " + type); } } - return geo; + return new Pair(maximumWaitTimeSec, geo); } /** diff --git a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java index 4c5abf9fc6a6..2d867f9d754f 100644 --- a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java +++ b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java @@ -20,7 +20,6 @@ import static android.service.watchdog.ExplicitHealthCheckService.PackageConfig; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.anyInt; @@ -65,8 +64,6 @@ import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.function.Consumer; -// TODO: Write test without using PackageWatchdog#getPackages. Just rely on -// behavior of observers receiving crash notifications or not to determine if it's registered // TODO: Use Truth in tests. /** * Test PackageWatchdog. @@ -115,76 +112,109 @@ public class PackageWatchdogTest { dropShellPermissions(); } - /** - * Test registration, unregistration, package expiry and duration reduction - */ @Test - public void testRegistration() throws Exception { + public void testRegistration_singleObserver() { + PackageWatchdog watchdog = createWatchdog(); + TestObserver observer = new TestObserver(OBSERVER_NAME_1); + + watchdog.startObservingHealth(observer, Arrays.asList(APP_A), SHORT_DURATION); + raiseFatalFailure(watchdog, Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE))); + mTestLooper.dispatchAll(); + + // The failed packages should be the same as the registered ones to ensure registration is + // done successfully + assertEquals(1, observer.mHealthCheckFailedPackages.size()); + assertTrue(observer.mHealthCheckFailedPackages.contains(APP_A)); + } + + @Test + public void testRegistration_multiObservers() { PackageWatchdog watchdog = createWatchdog(); TestObserver observer1 = new TestObserver(OBSERVER_NAME_1); TestObserver observer2 = new TestObserver(OBSERVER_NAME_2); - TestObserver observer3 = new TestObserver(OBSERVER_NAME_3); - // Start observing for observer1 which will be unregistered watchdog.startObservingHealth(observer1, Arrays.asList(APP_A), SHORT_DURATION); - // Start observing for observer2 which will expire watchdog.startObservingHealth(observer2, Arrays.asList(APP_A, APP_B), SHORT_DURATION); - // Start observing for observer3 which will have expiry duration reduced - watchdog.startObservingHealth(observer3, Arrays.asList(APP_A), LONG_DURATION); - - // Verify packages observed at start - // 1 - assertEquals(1, watchdog.getPackages(observer1).size()); - assertTrue(watchdog.getPackages(observer1).contains(APP_A)); - // 2 - assertEquals(2, watchdog.getPackages(observer2).size()); - assertTrue(watchdog.getPackages(observer2).contains(APP_A)); - assertTrue(watchdog.getPackages(observer2).contains(APP_B)); - // 3 - assertEquals(1, watchdog.getPackages(observer3).size()); - assertTrue(watchdog.getPackages(observer3).contains(APP_A)); - - // Then unregister observer1 - watchdog.unregisterHealthObserver(observer1); - - // Verify observer2 and observer3 left - // 1 - assertNull(watchdog.getPackages(observer1)); - // 2 - assertEquals(2, watchdog.getPackages(observer2).size()); - assertTrue(watchdog.getPackages(observer2).contains(APP_A)); - assertTrue(watchdog.getPackages(observer2).contains(APP_B)); - // 3 - assertEquals(1, watchdog.getPackages(observer3).size()); - assertTrue(watchdog.getPackages(observer3).contains(APP_A)); - - // Then advance time a little and run messages in Handlers so observer2 expires + raiseFatalFailure(watchdog, Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE), + new VersionedPackage(APP_B, VERSION_CODE))); + mTestLooper.dispatchAll(); + + // The failed packages should be the same as the registered ones to ensure registration is + // done successfully + assertEquals(1, observer1.mHealthCheckFailedPackages.size()); + assertEquals(2, observer2.mHealthCheckFailedPackages.size()); + assertTrue(observer1.mHealthCheckFailedPackages.contains(APP_A)); + assertTrue(observer2.mHealthCheckFailedPackages.contains(APP_A)); + assertTrue(observer2.mHealthCheckFailedPackages.contains(APP_B)); + } + + @Test + public void testUnregistration_singleObserver() { + PackageWatchdog watchdog = createWatchdog(); + TestObserver observer = new TestObserver(OBSERVER_NAME_1); + + watchdog.startObservingHealth(observer, Arrays.asList(APP_A), SHORT_DURATION); + watchdog.unregisterHealthObserver(observer); + raiseFatalFailure(watchdog, Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE))); + mTestLooper.dispatchAll(); + + // We should have no failed packages to ensure unregistration is done successfully + assertEquals(0, observer.mHealthCheckFailedPackages.size()); + } + + @Test + public void testUnregistration_multiObservers() { + PackageWatchdog watchdog = createWatchdog(); + TestObserver observer1 = new TestObserver(OBSERVER_NAME_1); + TestObserver observer2 = new TestObserver(OBSERVER_NAME_2); + + watchdog.startObservingHealth(observer1, Arrays.asList(APP_A), SHORT_DURATION); + watchdog.startObservingHealth(observer2, Arrays.asList(APP_A), SHORT_DURATION); + watchdog.unregisterHealthObserver(observer2); + raiseFatalFailure(watchdog, Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE))); + mTestLooper.dispatchAll(); + + // observer1 should receive failed packages as intended. + assertEquals(1, observer1.mHealthCheckFailedPackages.size()); + // observer2 should have no failed packages to ensure unregistration is done successfully + assertEquals(0, observer2.mHealthCheckFailedPackages.size()); + } + + @Test + public void testExpiration_singleObserver() { + PackageWatchdog watchdog = createWatchdog(); + TestObserver observer = new TestObserver(OBSERVER_NAME_1); + + watchdog.startObservingHealth(observer, Arrays.asList(APP_A), SHORT_DURATION); moveTimeForwardAndDispatch(SHORT_DURATION); + raiseFatalFailure(watchdog, Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE))); + mTestLooper.dispatchAll(); - // Verify observer3 left with reduced expiry duration - // 1 - assertNull(watchdog.getPackages(observer1)); - // 2 - assertNull(watchdog.getPackages(observer2)); - // 3 - assertEquals(1, watchdog.getPackages(observer3).size()); - assertTrue(watchdog.getPackages(observer3).contains(APP_A)); - - // Then advance time some more and run messages in Handlers so observer3 expires - moveTimeForwardAndDispatch(LONG_DURATION); - - // Verify observer3 expired - // 1 - assertNull(watchdog.getPackages(observer1)); - // 2 - assertNull(watchdog.getPackages(observer2)); - // 3 - assertNull(watchdog.getPackages(observer3)); + // We should have no failed packages for the fatal failure is raised after expiration + assertEquals(0, observer.mHealthCheckFailedPackages.size()); + } + + @Test + public void testExpiration_multiObservers() { + PackageWatchdog watchdog = createWatchdog(); + TestObserver observer1 = new TestObserver(OBSERVER_NAME_1); + TestObserver observer2 = new TestObserver(OBSERVER_NAME_2); + + watchdog.startObservingHealth(observer1, Arrays.asList(APP_A), SHORT_DURATION); + watchdog.startObservingHealth(observer2, Arrays.asList(APP_A), LONG_DURATION); + moveTimeForwardAndDispatch(SHORT_DURATION); + raiseFatalFailure(watchdog, Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE))); + mTestLooper.dispatchAll(); + + // We should have no failed packages for the fatal failure is raised after expiration + assertEquals(0, observer1.mHealthCheckFailedPackages.size()); + // We should have failed packages since observer2 hasn't expired + assertEquals(1, observer2.mHealthCheckFailedPackages.size()); } /** Observing already observed package extends the observation time. */ @Test - public void testObserveAlreadyObservedPackage() throws Exception { + public void testObserveAlreadyObservedPackage() { PackageWatchdog watchdog = createWatchdog(); TestObserver observer = new TestObserver(OBSERVER_NAME_1); @@ -200,56 +230,43 @@ public class PackageWatchdogTest { // Then advance time such that it should have expired were it not for the second observation moveTimeForwardAndDispatch((SHORT_DURATION / 2) + 1); - // Verify that APP_A not expired since second observation extended the time - assertEquals(1, watchdog.getPackages(observer).size()); - assertTrue(watchdog.getPackages(observer).contains(APP_A)); + raiseFatalFailure(watchdog, Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE))); + mTestLooper.dispatchAll(); + + // Verify that we receive failed packages as expected for APP_A not expired + assertEquals(1, observer.mHealthCheckFailedPackages.size()); + assertTrue(observer.mHealthCheckFailedPackages.contains(APP_A)); } /** * Test package observers are persisted and loaded on startup */ @Test - public void testPersistence() throws Exception { + public void testPersistence() { PackageWatchdog watchdog1 = createWatchdog(); TestObserver observer1 = new TestObserver(OBSERVER_NAME_1); TestObserver observer2 = new TestObserver(OBSERVER_NAME_2); watchdog1.startObservingHealth(observer1, Arrays.asList(APP_A), SHORT_DURATION); watchdog1.startObservingHealth(observer2, Arrays.asList(APP_A, APP_B), SHORT_DURATION); - - // Verify 2 observers are registered and saved internally - // 1 - assertEquals(1, watchdog1.getPackages(observer1).size()); - assertTrue(watchdog1.getPackages(observer1).contains(APP_A)); - // 2 - assertEquals(2, watchdog1.getPackages(observer2).size()); - assertTrue(watchdog1.getPackages(observer2).contains(APP_A)); - assertTrue(watchdog1.getPackages(observer2).contains(APP_B)); - // Then advance time and run IO Handler so file is saved mTestLooper.dispatchAll(); - // Then start a new watchdog PackageWatchdog watchdog2 = createWatchdog(); - - // Verify the new watchdog loads observers on startup but nothing registered - assertEquals(0, watchdog2.getPackages(observer1).size()); - assertEquals(0, watchdog2.getPackages(observer2).size()); - // Verify random observer not saved returns null - assertNull(watchdog2.getPackages(new TestObserver(OBSERVER_NAME_3))); - - // Then register observer1 + // Then resume observer1 and observer2 watchdog2.registerHealthObserver(observer1); watchdog2.registerHealthObserver(observer2); + raiseFatalFailure(watchdog2, Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE), + new VersionedPackage(APP_B, VERSION_CODE))); + mTestLooper.dispatchAll(); - // Verify 2 observers are registered after reload - // 1 - assertEquals(1, watchdog1.getPackages(observer1).size()); - assertTrue(watchdog1.getPackages(observer1).contains(APP_A)); - // 2 - assertEquals(2, watchdog1.getPackages(observer2).size()); - assertTrue(watchdog1.getPackages(observer2).contains(APP_A)); - assertTrue(watchdog1.getPackages(observer2).contains(APP_B)); + // We should receive failed packages as expected to ensure observers are persisted and + // resumed correctly + assertEquals(1, observer1.mHealthCheckFailedPackages.size()); + assertEquals(2, observer2.mHealthCheckFailedPackages.size()); + assertTrue(observer1.mHealthCheckFailedPackages.contains(APP_A)); + assertTrue(observer1.mHealthCheckFailedPackages.contains(APP_A)); + assertTrue(observer2.mHealthCheckFailedPackages.contains(APP_B)); } /** @@ -273,8 +290,8 @@ public class PackageWatchdogTest { mTestLooper.dispatchAll(); // Verify that observers are not notified - assertEquals(0, observer1.mFailedPackages.size()); - assertEquals(0, observer2.mFailedPackages.size()); + assertEquals(0, observer1.mMitigatedPackages.size()); + assertEquals(0, observer2.mMitigatedPackages.size()); } /** @@ -292,16 +309,14 @@ public class PackageWatchdogTest { watchdog.startObservingHealth(observer1, Arrays.asList(APP_B), SHORT_DURATION); // Then fail APP_C (not observed) above the threshold - for (int i = 0; i < watchdog.getTriggerFailureCount(); i++) { - watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_C, VERSION_CODE))); - } + raiseFatalFailure(watchdog, Arrays.asList(new VersionedPackage(APP_C, VERSION_CODE))); // Run handler so package failures are dispatched to observers mTestLooper.dispatchAll(); // Verify that observers are not notified - assertEquals(0, observer1.mFailedPackages.size()); - assertEquals(0, observer2.mFailedPackages.size()); + assertEquals(0, observer1.mMitigatedPackages.size()); + assertEquals(0, observer2.mMitigatedPackages.size()); } /** @@ -326,16 +341,14 @@ public class PackageWatchdogTest { watchdog.startObservingHealth(observer, Arrays.asList(APP_A), SHORT_DURATION); // Then fail APP_A (different version) above the threshold - for (int i = 0; i < watchdog.getTriggerFailureCount(); i++) { - watchdog.onPackageFailure(Arrays.asList( - new VersionedPackage(APP_A, differentVersionCode))); - } + raiseFatalFailure(watchdog, + Arrays.asList(new VersionedPackage(APP_A, differentVersionCode))); // Run handler so package failures are dispatched to observers mTestLooper.dispatchAll(); // Verify that observers are not notified - assertEquals(0, observer.mFailedPackages.size()); + assertEquals(0, observer.mMitigatedPackages.size()); } @@ -365,21 +378,19 @@ public class PackageWatchdogTest { SHORT_DURATION); // Then fail all apps above the threshold - for (int i = 0; i < watchdog.getTriggerFailureCount(); i++) { - watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE), - new VersionedPackage(APP_B, VERSION_CODE), - new VersionedPackage(APP_C, VERSION_CODE), - new VersionedPackage(APP_D, VERSION_CODE))); - } + raiseFatalFailure(watchdog, Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE), + new VersionedPackage(APP_B, VERSION_CODE), + new VersionedPackage(APP_C, VERSION_CODE), + new VersionedPackage(APP_D, VERSION_CODE))); // Run handler so package failures are dispatched to observers mTestLooper.dispatchAll(); // Verify least impact observers are notifed of package failures - List<String> observerNonePackages = observerNone.mFailedPackages; - List<String> observerHighPackages = observerHigh.mFailedPackages; - List<String> observerMidPackages = observerMid.mFailedPackages; - List<String> observerLowPackages = observerLow.mFailedPackages; + List<String> observerNonePackages = observerNone.mMitigatedPackages; + List<String> observerHighPackages = observerHigh.mMitigatedPackages; + List<String> observerMidPackages = observerMid.mMitigatedPackages; + List<String> observerLowPackages = observerLow.mMitigatedPackages; // APP_D failure observed by only observerNone is not caught cos its impact is none assertEquals(0, observerNonePackages.size()); @@ -418,66 +429,58 @@ public class PackageWatchdogTest { watchdog.startObservingHealth(observerSecond, Arrays.asList(APP_A), LONG_DURATION); // Then fail APP_A above the threshold - for (int i = 0; i < watchdog.getTriggerFailureCount(); i++) { - watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE))); - } + raiseFatalFailure(watchdog, Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE))); // Run handler so package failures are dispatched to observers mTestLooper.dispatchAll(); // Verify only observerFirst is notifed - assertEquals(1, observerFirst.mFailedPackages.size()); - assertEquals(APP_A, observerFirst.mFailedPackages.get(0)); - assertEquals(0, observerSecond.mFailedPackages.size()); + assertEquals(1, observerFirst.mMitigatedPackages.size()); + assertEquals(APP_A, observerFirst.mMitigatedPackages.get(0)); + assertEquals(0, observerSecond.mMitigatedPackages.size()); // After observerFirst handles failure, next action it has is high impact observerFirst.mImpact = PackageHealthObserverImpact.USER_IMPACT_HIGH; - observerFirst.mFailedPackages.clear(); - observerSecond.mFailedPackages.clear(); + observerFirst.mMitigatedPackages.clear(); + observerSecond.mMitigatedPackages.clear(); // Then fail APP_A again above the threshold - for (int i = 0; i < watchdog.getTriggerFailureCount(); i++) { - watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE))); - } + raiseFatalFailure(watchdog, Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE))); // Run handler so package failures are dispatched to observers mTestLooper.dispatchAll(); // Verify only observerSecond is notifed cos it has least impact - assertEquals(1, observerSecond.mFailedPackages.size()); - assertEquals(APP_A, observerSecond.mFailedPackages.get(0)); - assertEquals(0, observerFirst.mFailedPackages.size()); + assertEquals(1, observerSecond.mMitigatedPackages.size()); + assertEquals(APP_A, observerSecond.mMitigatedPackages.get(0)); + assertEquals(0, observerFirst.mMitigatedPackages.size()); // After observerSecond handles failure, it has no further actions observerSecond.mImpact = PackageHealthObserverImpact.USER_IMPACT_NONE; - observerFirst.mFailedPackages.clear(); - observerSecond.mFailedPackages.clear(); + observerFirst.mMitigatedPackages.clear(); + observerSecond.mMitigatedPackages.clear(); // Then fail APP_A again above the threshold - for (int i = 0; i < watchdog.getTriggerFailureCount(); i++) { - watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE))); - } + raiseFatalFailure(watchdog, Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE))); // Run handler so package failures are dispatched to observers mTestLooper.dispatchAll(); // Verify only observerFirst is notifed cos it has the only action - assertEquals(1, observerFirst.mFailedPackages.size()); - assertEquals(APP_A, observerFirst.mFailedPackages.get(0)); - assertEquals(0, observerSecond.mFailedPackages.size()); + assertEquals(1, observerFirst.mMitigatedPackages.size()); + assertEquals(APP_A, observerFirst.mMitigatedPackages.get(0)); + assertEquals(0, observerSecond.mMitigatedPackages.size()); // After observerFirst handles failure, it too has no further actions observerFirst.mImpact = PackageHealthObserverImpact.USER_IMPACT_NONE; - observerFirst.mFailedPackages.clear(); - observerSecond.mFailedPackages.clear(); + observerFirst.mMitigatedPackages.clear(); + observerSecond.mMitigatedPackages.clear(); // Then fail APP_A again above the threshold - for (int i = 0; i < watchdog.getTriggerFailureCount(); i++) { - watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE))); - } + raiseFatalFailure(watchdog, Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE))); // Run handler so package failures are dispatched to observers mTestLooper.dispatchAll(); // Verify no observer is notified cos no actions left - assertEquals(0, observerFirst.mFailedPackages.size()); - assertEquals(0, observerSecond.mFailedPackages.size()); + assertEquals(0, observerFirst.mMitigatedPackages.size()); + assertEquals(0, observerSecond.mMitigatedPackages.size()); } /** @@ -496,17 +499,15 @@ public class PackageWatchdogTest { watchdog.startObservingHealth(observer1, Arrays.asList(APP_A), SHORT_DURATION); // Then fail APP_A above the threshold - for (int i = 0; i < watchdog.getTriggerFailureCount(); i++) { - watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE))); - } + raiseFatalFailure(watchdog, Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE))); // Run handler so package failures are dispatched to observers mTestLooper.dispatchAll(); // Verify only one observer is notifed - assertEquals(1, observer1.mFailedPackages.size()); - assertEquals(APP_A, observer1.mFailedPackages.get(0)); - assertEquals(0, observer2.mFailedPackages.size()); + assertEquals(1, observer1.mMitigatedPackages.size()); + assertEquals(APP_A, observer1.mMitigatedPackages.get(0)); + assertEquals(0, observer2.mMitigatedPackages.size()); } /** @@ -555,15 +556,15 @@ public class PackageWatchdogTest { assertEquals(0, controller.getRequestedPackages().size()); // Verify observer1 is not notified - assertEquals(0, observer1.mFailedPackages.size()); + assertEquals(0, observer1.mMitigatedPackages.size()); // Verify observer2 is notifed because health checks for APP_B never passed - assertEquals(1, observer2.mFailedPackages.size()); - assertEquals(APP_B, observer2.mFailedPackages.get(0)); + assertEquals(1, observer2.mMitigatedPackages.size()); + assertEquals(APP_B, observer2.mMitigatedPackages.get(0)); // Verify observer3 is notifed because health checks for APP_A did not pass before expiry - assertEquals(1, observer3.mFailedPackages.size()); - assertEquals(APP_A, observer3.mFailedPackages.get(0)); + assertEquals(1, observer3.mMitigatedPackages.size()); + assertEquals(APP_A, observer3.mMitigatedPackages.get(0)); } /** @@ -607,7 +608,7 @@ public class PackageWatchdogTest { moveTimeForwardAndDispatch(SHORT_DURATION); // Verify APP_A is not failed (APP_B) is not expired yet - assertEquals(0, observer.mFailedPackages.size()); + assertEquals(0, observer.mMitigatedPackages.size()); // Re-enable explicit health checks setExplicitHealthCheckEnabled(true); @@ -635,8 +636,8 @@ public class PackageWatchdogTest { moveTimeForwardAndDispatch(SHORT_DURATION); // Verify only APP_C is failed because explicit health checks was not supported for APP_A - assertEquals(1, observer.mFailedPackages.size()); - assertEquals(APP_C, observer.mFailedPackages.get(0)); + assertEquals(1, observer.mMitigatedPackages.size()); + assertEquals(APP_C, observer.mMitigatedPackages.get(0)); } /** @@ -660,17 +661,17 @@ public class PackageWatchdogTest { moveTimeForwardAndDispatch(SHORT_DURATION); // Verify that health check is failed - assertEquals(1, observer.mFailedPackages.size()); - assertEquals(APP_A, observer.mFailedPackages.get(0)); + assertEquals(1, observer.mMitigatedPackages.size()); + assertEquals(APP_A, observer.mMitigatedPackages.get(0)); // Then clear failed packages and start observing a random package so requests are synced // and PackageWatchdog#onSupportedPackages is called and APP_A has a chance to fail again // this time due to package expiry. - observer.mFailedPackages.clear(); + observer.mMitigatedPackages.clear(); watchdog.startObservingHealth(observer, Arrays.asList(APP_B), LONG_DURATION); // Verify that health check failure is not notified again - assertTrue(observer.mFailedPackages.isEmpty()); + assertTrue(observer.mMitigatedPackages.isEmpty()); } /** Tests {@link MonitoredPackage} health check state transitions. */ @@ -734,8 +735,8 @@ public class PackageWatchdogTest { mTestLooper.dispatchAll(); // Verify the NetworkStack observer is notified - assertEquals(1, observer.mFailedPackages.size()); - assertEquals(APP_A, observer.mFailedPackages.get(0)); + assertEquals(1, observer.mMitigatedPackages.size()); + assertEquals(APP_A, observer.mMitigatedPackages.get(0)); } private void adoptShellPermissions(String... permissions) { @@ -770,6 +771,13 @@ public class PackageWatchdogTest { mTestLooper.dispatchAll(); } + /** Trigger package failures above the threshold. */ + private void raiseFatalFailure(PackageWatchdog watchdog, List<VersionedPackage> packages) { + for (int i = 0; i < watchdog.getTriggerFailureCount(); i++) { + watchdog.onPackageFailure(packages); + } + } + private PackageWatchdog createWatchdog() { return createWatchdog(new TestController(), true /* withPackagesReady */); } @@ -799,7 +807,8 @@ public class PackageWatchdogTest { private static class TestObserver implements PackageHealthObserver { private final String mName; private int mImpact; - final List<String> mFailedPackages = new ArrayList<>(); + final List<String> mHealthCheckFailedPackages = new ArrayList<>(); + final List<String> mMitigatedPackages = new ArrayList<>(); TestObserver(String name) { mName = name; @@ -812,11 +821,12 @@ public class PackageWatchdogTest { } public int onHealthCheckFailed(VersionedPackage versionedPackage) { + mHealthCheckFailedPackages.add(versionedPackage.getPackageName()); return mImpact; } public boolean execute(VersionedPackage versionedPackage) { - mFailedPackages.add(versionedPackage.getPackageName()); + mMitigatedPackages.add(versionedPackage.getPackageName()); return true; } diff --git a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java index b2e5a62849e7..bc98f06ebc56 100644 --- a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java +++ b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java @@ -28,6 +28,8 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import java.util.concurrent.TimeUnit; + /** * Runs the staged rollback tests. */ @@ -99,9 +101,15 @@ public class StagedRollbackTest extends BaseHostJUnit4Test { // crash system_server enough times to trigger a rollback crashProcess("system_server", NATIVE_CRASHES_THRESHOLD); - // Rollback should be committed automatically now - // Give time for rollback to be committed - assertTrue(getDevice().waitForDeviceNotAvailable(60000)); + // Rollback should be committed automatically now. + // Give time for rollback to be committed. This could take a while, + // because we need all of the following to happen: + // 1. system_server comes back up and boot completes. + // 2. Rollback health observer detects updatable crashing signal. + // 3. Staged rollback session becomes ready. + // 4. Device actually reboots. + // So we give a generous timeout here. + assertTrue(getDevice().waitForDeviceNotAvailable(TimeUnit.MINUTES.toMillis(5))); getDevice().waitForDeviceAvailable(); // verify rollback committed diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java index 9d4b837ce2d1..f8c20111d79b 100644 --- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java +++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java @@ -15,6 +15,7 @@ */ package android.net.wifi; +import android.annotation.IntDef; import android.annotation.Nullable; import android.annotation.UnsupportedAppUsage; import android.os.Parcel; @@ -23,6 +24,8 @@ import android.security.Credentials; import android.text.TextUtils; import android.util.Log; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.nio.charset.StandardCharsets; import java.security.PrivateKey; import java.security.cert.X509Certificate; @@ -111,6 +114,48 @@ public class WifiEnterpriseConfig implements Parcelable { /** @hide */ public static final String CA_CERT_ALIAS_DELIMITER = " "; + /** + * Do not use OCSP stapling (TLS certificate status extension) + * @hide + */ + public static final int OCSP_NONE = 0; + + /** + * Try to use OCSP stapling, but not require response + * @hide + */ + public static final int OCSP_REQUEST_CERT_STATUS = 1; + + /** + * Require valid OCSP stapling response + * @hide + */ + public static final int OCSP_REQUIRE_CERT_STATUS = 2; + + /** + * Require valid OCSP stapling response for all not-trusted certificates in the server + * certificate chain + * @hide + */ + public static final int OCSP_REQUIRE_ALL_NON_TRUSTED_CERTS_STATUS = 3; + + /** @hide */ + @IntDef(prefix = {"OCSP_"}, value = { + OCSP_NONE, + OCSP_REQUEST_CERT_STATUS, + OCSP_REQUIRE_CERT_STATUS, + OCSP_REQUIRE_ALL_NON_TRUSTED_CERTS_STATUS + }) + @Retention(RetentionPolicy.SOURCE) + public @interface Ocsp { + } + + /** + * Whether to use/require OCSP (Online Certificate Status Protocol) to check server certificate. + * @hide + */ + private @Ocsp int mOcsp = OCSP_NONE; + // Fields to copy verbatim from wpa_supplicant. private static final String[] SUPPLICANT_CONFIG_KEYS = new String[] { IDENTITY_KEY, @@ -185,6 +230,7 @@ public class WifiEnterpriseConfig implements Parcelable { mPhase2Method = source.mPhase2Method; mIsAppInstalledDeviceKeyAndCert = source.mIsAppInstalledDeviceKeyAndCert; mIsAppInstalledCaCert = source.mIsAppInstalledCaCert; + mOcsp = source.mOcsp; } /** @@ -230,6 +276,7 @@ public class WifiEnterpriseConfig implements Parcelable { ParcelUtil.writeCertificates(dest, mClientCertificateChain); dest.writeBoolean(mIsAppInstalledDeviceKeyAndCert); dest.writeBoolean(mIsAppInstalledCaCert); + dest.writeInt(mOcsp); } public static final @android.annotation.NonNull Creator<WifiEnterpriseConfig> CREATOR = @@ -251,6 +298,7 @@ public class WifiEnterpriseConfig implements Parcelable { enterpriseConfig.mClientCertificateChain = ParcelUtil.readCertificates(in); enterpriseConfig.mIsAppInstalledDeviceKeyAndCert = in.readBoolean(); enterpriseConfig.mIsAppInstalledCaCert = in.readBoolean(); + enterpriseConfig.mOcsp = in.readInt(); return enterpriseConfig; } @@ -1141,6 +1189,7 @@ public class WifiEnterpriseConfig implements Parcelable { if (mPhase2Method > 0 && mPhase2Method < Phase2.strings.length) { sb.append("phase2_method: ").append(Phase2.strings[mPhase2Method]).append("\n"); } + sb.append(" ocsp: ").append(mOcsp).append("\n"); return sb.toString(); } @@ -1190,4 +1239,28 @@ public class WifiEnterpriseConfig implements Parcelable { public boolean isAppInstalledCaCert() { return mIsAppInstalledCaCert; } + + /** + * Set the ocsp type. + * @param ocsp is one {@link ##OCSP_NONE}, {@link #OCSP_REQUEST_CERT_STATUS}, + * {@link #OCSP_REQUIRE_CERT_STATUS} or + * {@link #OCSP_REQUIRE_ALL_NON_TRUSTED_CERTS_STATUS} + * @hide + */ + public void setOcsp(@Ocsp int ocsp) { + if (ocsp >= OCSP_NONE && ocsp <= OCSP_REQUIRE_ALL_NON_TRUSTED_CERTS_STATUS) { + mOcsp = ocsp; + } else { + throw new IllegalArgumentException("Invalid OCSP type."); + } + } + + /** + * Get the ocsp type. + * @return ocsp type + * @hide + */ + public @Ocsp int getOcsp() { + return mOcsp; + } } diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index 6bf7bfb9b4a1..a37de00ce7de 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -52,12 +52,14 @@ import android.os.Messenger; import android.os.RemoteException; import android.os.ServiceManager; import android.os.WorkSource; +import android.text.TextUtils; import android.util.Log; import android.util.Pair; import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.util.ArrayUtils; import com.android.internal.util.AsyncChannel; import com.android.internal.util.Protocol; import com.android.server.net.NetworkPinner; @@ -1821,6 +1823,7 @@ public class WifiManager { try { IWifiManager iWifiManager = getIWifiManager(); if (iWifiManager == null) { + if (config == null) return; throw new RemoteException("Wifi service is not running"); } if (!iWifiManager.addOrUpdatePasspointConfiguration( @@ -1849,6 +1852,7 @@ public class WifiManager { try { IWifiManager iWifiManager = getIWifiManager(); if (iWifiManager == null) { + if (TextUtils.isEmpty(fqdn)) return; throw new RemoteException("Wifi service is not running"); } if (!iWifiManager.removePasspointConfiguration( @@ -1899,6 +1903,7 @@ public class WifiManager { try { IWifiManager iWifiManager = getIWifiManager(); if (iWifiManager == null) { + if (bssid == 0L || TextUtils.isEmpty(fileName)) return; throw new RemoteException("Wifi service is not running"); } iWifiManager.queryPasspointIcon(bssid, fileName); @@ -1928,6 +1933,8 @@ public class WifiManager { * @param holdoff hold off time in milliseconds * @param ess set if the hold off pertains to an ESS rather than a BSS * @hide + * + * TODO (140167680): This needs to be removed, the implementation is empty! */ public void deauthenticateNetwork(long holdoff, boolean ess) { try { @@ -2504,6 +2511,7 @@ public class WifiManager { try { IWifiManager iWifiManager = getIWifiManager(); if (iWifiManager == null) { + if (TextUtils.isEmpty(country)) return; throw new RemoteException("Wifi service is not running"); } iWifiManager.setCountryCode(country); @@ -2692,6 +2700,7 @@ public class WifiManager { try { IWifiManager iWifiManager = getIWifiManager(); if (iWifiManager == null) { + if (TextUtils.isEmpty(ifaceName) || mode == IFACE_IP_MODE_UNSPECIFIED) return; throw new RemoteException("Wifi service is not running"); } iWifiManager.updateInterfaceIpState(ifaceName, mode); @@ -3044,6 +3053,7 @@ public class WifiManager { try { IWifiManager iWifiManager = getIWifiManager(); if (iWifiManager == null) { + if (remoteIPAddress == null || !enable) return; throw new RemoteException("Wifi service is not running"); } iWifiManager.enableTdls(remoteIPAddress.getHostAddress(), enable); @@ -3062,6 +3072,7 @@ public class WifiManager { try { IWifiManager iWifiManager = getIWifiManager(); if (iWifiManager == null) { + if (TextUtils.isEmpty(remoteMacAddress) || !enable) return; throw new RemoteException("Wifi service is not running"); } iWifiManager.enableTdlsWithMacAddress(remoteMacAddress, enable); @@ -3956,7 +3967,7 @@ public class WifiManager { android.Manifest.permission.NETWORK_STACK }) public void disableEphemeralNetwork(String SSID) { - if (SSID == null) throw new IllegalArgumentException("SSID cannot be null"); + if (TextUtils.isEmpty(SSID)) throw new IllegalArgumentException("SSID cannot be null"); try { IWifiManager iWifiManager = getIWifiManager(); if (iWifiManager == null) { @@ -4495,6 +4506,7 @@ public class WifiManager { try { IWifiManager iWifiManager = getIWifiManager(); if (iWifiManager == null) { + if (verbose == 0) return; throw new RemoteException("Wifi service is not running"); } iWifiManager.enableVerboseLogging(verbose); @@ -4581,6 +4593,7 @@ public class WifiManager { try { IWifiManager iWifiManager = getIWifiManager(); if (iWifiManager == null) { + if (enabled) return; throw new RemoteException("Wifi service is not running"); } iWifiManager.enableWifiConnectivityManager(enabled); @@ -4611,6 +4624,7 @@ public class WifiManager { try { IWifiManager iWifiManager = getIWifiManager(); if (iWifiManager == null) { + if (ArrayUtils.isEmpty(data)) return; throw new RemoteException("Wifi service is not running"); } iWifiManager.restoreBackupData(data); @@ -4631,6 +4645,7 @@ public class WifiManager { try { IWifiManager iWifiManager = getIWifiManager(); if (iWifiManager == null) { + if (ArrayUtils.isEmpty(supplicantData) && ArrayUtils.isEmpty(ipConfigData)) return; throw new RemoteException("Wifi service is not running"); } iWifiManager.restoreSupplicantBackupData(supplicantData, ipConfigData); @@ -4937,6 +4952,7 @@ public class WifiManager { try { IWifiManager iWifiManager = getIWifiManager(); if (iWifiManager == null) { + if (state == DEVICE_MOBILITY_STATE_UNKNOWN) return; throw new RemoteException("Wifi service is not running"); } iWifiManager.setDeviceMobilityState(state); diff --git a/wifi/tests/src/android/net/wifi/WifiEnterpriseConfigTest.java b/wifi/tests/src/android/net/wifi/WifiEnterpriseConfigTest.java index beed6666f28f..d8db4ceb6e9c 100644 --- a/wifi/tests/src/android/net/wifi/WifiEnterpriseConfigTest.java +++ b/wifi/tests/src/android/net/wifi/WifiEnterpriseConfigTest.java @@ -23,6 +23,7 @@ import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import android.net.wifi.WifiEnterpriseConfig.Eap; import android.net.wifi.WifiEnterpriseConfig.Phase2; @@ -343,11 +344,13 @@ public class WifiEnterpriseConfigTest { enterpriseConfig.setPassword("*"); enterpriseConfig.setEapMethod(Eap.TTLS); enterpriseConfig.setPhase2Method(Phase2.GTC); + enterpriseConfig.setOcsp(WifiEnterpriseConfig.OCSP_REQUIRE_CERT_STATUS); mEnterpriseConfig = new WifiEnterpriseConfig(); mEnterpriseConfig.copyFromExternal(enterpriseConfig, "*"); assertEquals("TTLS", getSupplicantEapMethod()); assertEquals("\"autheap=GTC\"", getSupplicantPhase2Method()); assertNotEquals("*", mEnterpriseConfig.getPassword()); + assertEquals(enterpriseConfig.getOcsp(), mEnterpriseConfig.getOcsp()); } /** Verfies that parceling a WifiEnterpriseConfig preseves method information. */ @@ -487,4 +490,35 @@ public class WifiEnterpriseConfigTest { assertFalse(mEnterpriseConfig.isAppInstalledDeviceKeyAndCert()); assertTrue(mEnterpriseConfig.isAppInstalledCaCert()); } + + /** Verifies that OCSP value is set correctly. */ + @Test + public void testOcspSetGet() throws Exception { + WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig(); + + enterpriseConfig.setOcsp(WifiEnterpriseConfig.OCSP_NONE); + assertEquals(WifiEnterpriseConfig.OCSP_NONE, enterpriseConfig.getOcsp()); + + enterpriseConfig.setOcsp(WifiEnterpriseConfig.OCSP_REQUIRE_CERT_STATUS); + assertEquals(WifiEnterpriseConfig.OCSP_REQUIRE_CERT_STATUS, enterpriseConfig.getOcsp()); + + enterpriseConfig.setOcsp(WifiEnterpriseConfig.OCSP_REQUEST_CERT_STATUS); + assertEquals(WifiEnterpriseConfig.OCSP_REQUEST_CERT_STATUS, enterpriseConfig.getOcsp()); + + enterpriseConfig.setOcsp(WifiEnterpriseConfig.OCSP_REQUIRE_ALL_NON_TRUSTED_CERTS_STATUS); + assertEquals(WifiEnterpriseConfig.OCSP_REQUIRE_ALL_NON_TRUSTED_CERTS_STATUS, + enterpriseConfig.getOcsp()); + } + + /** Verifies that an exception is thrown when invalid OCSP is set. */ + @Test + public void testInvalidOcspValue() { + WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig(); + try { + enterpriseConfig.setOcsp(-1); + fail("Should raise an IllegalArgumentException here."); + } catch (IllegalArgumentException e) { + // expected exception. + } + } } |