Merge "Remove libhwbinder/libhidltransport deps" am: 32f968b767 am: 350e380ced
am: 90640230f8
Change-Id: If6ef601b91084579dcb0138afc7ed21b915d240c
diff --git a/cmds/incidentd/src/WorkDirectory.cpp b/cmds/incidentd/src/WorkDirectory.cpp
index e826061..7e7c642 100644
--- a/cmds/incidentd/src/WorkDirectory.cpp
+++ b/cmds/incidentd/src/WorkDirectory.cpp
@@ -664,7 +664,7 @@
nanosleep(&spec, nullptr);
}
clock_gettime(CLOCK_REALTIME, &spec);
- timestampNs = (spec.tv_sec) * 1000 + spec.tv_nsec;
+ timestampNs = int64_t(spec.tv_sec) * 1000 + spec.tv_nsec;
} while (file_exists_locked(timestampNs));
return timestampNs;
}
diff --git a/cmds/statsd/src/main.cpp b/cmds/statsd/src/main.cpp
index 68082c2..42132ee 100644
--- a/cmds/statsd/src/main.cpp
+++ b/cmds/statsd/src/main.cpp
@@ -78,7 +78,7 @@
ps->giveThreadPoolName();
IPCThreadState::self()->disableBackgroundScheduling(true);
- ::android::hardware::configureRpcThreadpool(1 /*threads*/, false /*willJoin*/);
+ ::android::hardware::configureRpcThreadpool(4 /*threads*/, false /*willJoin*/);
std::shared_ptr<LogEventQueue> eventQueue =
std::make_shared<LogEventQueue>(2000 /*buffer limit. Buffer is NOT pre-allocated*/);
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index f5b0b59..a0d0b30 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -146,6 +146,7 @@
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -3656,6 +3657,22 @@
return false;
}
+ private static final class RequestFinishCallback extends IRequestFinishCallback.Stub {
+ private final WeakReference<Activity> mActivityRef;
+
+ RequestFinishCallback(WeakReference<Activity> activityRef) {
+ mActivityRef = activityRef;
+ }
+
+ @Override
+ public void requestFinish() {
+ Activity activity = mActivityRef.get();
+ if (activity != null) {
+ activity.mHandler.post(activity::finishAfterTransition);
+ }
+ }
+ }
+
/**
* Called when the activity has detected the user's press of the back
* key. The default implementation simply finishes the current activity,
@@ -3681,11 +3698,7 @@
// while at the root of the task. This call allows ActivityTaskManager
// to intercept or defer finishing.
ActivityTaskManager.getService().onBackPressedOnTaskRoot(mToken,
- new IRequestFinishCallback.Stub() {
- public void requestFinish() {
- mHandler.post(() -> finishAfterTransition());
- }
- });
+ new RequestFinishCallback(new WeakReference<>(this)));
} catch (RemoteException e) {
finishAfterTransition();
}
diff --git a/core/java/android/app/ActivityView.java b/core/java/android/app/ActivityView.java
index 3bf659b..2b4ff01 100644
--- a/core/java/android/app/ActivityView.java
+++ b/core/java/android/app/ActivityView.java
@@ -120,7 +120,10 @@
mActivityTaskManager = ActivityTaskManager.getService();
mSurfaceView = new SurfaceView(context);
- mSurfaceView.setAlpha(0f);
+ // Since ActivityView#getAlpha has been overridden, we should use parent class's alpha
+ // as master to synchronize surface view's alpha value.
+ mSurfaceView.setAlpha(super.getAlpha());
+ mSurfaceView.setUseAlpha();
mSurfaceCallback = new SurfaceCallback();
mSurfaceView.getHolder().addCallback(mSurfaceCallback);
addView(mSurfaceView);
@@ -347,9 +350,20 @@
mSurfaceView.layout(0 /* left */, 0 /* top */, r - l /* right */, b - t /* bottom */);
}
+ /**
+ * Sets the alpha value when the content of {@link SurfaceView} needs to show or hide.
+ * <p>Note: The surface view may ignore the alpha value in some cases. Refer to
+ * {@link SurfaceView#setAlpha} for more details.
+ *
+ * @param alpha The opacity of the view.
+ */
@Override
public void setAlpha(float alpha) {
- mSurfaceView.setAlpha(alpha);
+ super.setAlpha(alpha);
+
+ if (mSurfaceView != null) {
+ mSurfaceView.setAlpha(alpha);
+ }
}
@Override
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index e57738f..9f51db8 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -108,6 +108,8 @@
ParceledListSlice getNotificationChannelsBypassingDnd(String pkg, int userId);
boolean isPackagePaused(String pkg);
+ void silenceNotificationSound();
+
// TODO: Remove this when callers have been migrated to the equivalent
// INotificationListener method.
@UnsupportedAppUsage
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index dd39376..b13a34f 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -1095,6 +1095,25 @@
}
/**
+ * Silences the current notification sound, if ones currently playing.
+ * <p>
+ * It is intended to handle use-cases such as silencing a ringing call
+ * when the user presses the volume button during ringing.
+ * <p>
+ * If this method is called prior to when the notification begins playing, the sound will not be
+ * silenced. As such it is not intended as a means to avoid playing of a sound.
+ * @hide
+ */
+ public void silenceNotificationSound() {
+ INotificationManager service = getService();
+ try {
+ service.silenceNotificationSound();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Returns whether notifications from this package are temporarily hidden. This
* could be done because the package was marked as distracting to the user via
* {@code PackageManager#setDistractingPackageRestrictions(String[], int)} or because the
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index cfe2cf0..d29cf80 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -1162,7 +1162,8 @@
@Override
public AppPredictionManager createService(ContextImpl ctx)
throws ServiceNotFoundException {
- return new AppPredictionManager(ctx);
+ IBinder b = ServiceManager.getService(Context.APP_PREDICTION_SERVICE);
+ return b == null ? null : new AppPredictionManager(ctx);
}
});
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 4a5ea03..1bc922d 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -4117,6 +4117,9 @@
/**
* Official published name of the app prediction service.
*
+ * <p><b>NOTE: </b> this service is optional; callers of
+ * {@code Context.getSystemServiceName(APP_PREDICTION_SERVICE)} should check for {@code null}.
+ *
* @hide
* @see #getSystemService(String)
*/
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index a7eecd7..abcf77b 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -44,6 +44,7 @@
import android.content.pm.PermissionInfo;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
+import android.content.pm.permission.SplitPermissionInfoParcelable;
import android.content.pm.SuspendDialogInfo;
import android.content.pm.UserInfo;
import android.content.pm.VerifierDeviceIdentity;
@@ -772,4 +773,6 @@
void setRuntimePermissionsVersion(int version, int userId);
void notifyPackagesReplacedReceived(in String[] packages);
+
+ List<SplitPermissionInfoParcelable> getSplitPermissions();
}
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 643cb3e..f682ebb 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -57,6 +57,7 @@
import android.content.IntentFilter;
import android.content.pm.PackageParserCacheHelper.ReadHelper;
import android.content.pm.PackageParserCacheHelper.WriteHelper;
+import android.content.pm.permission.SplitPermissionInfoParcelable;
import android.content.pm.split.DefaultSplitAssetLoader;
import android.content.pm.split.SplitAssetDependencyLoader;
import android.content.pm.split.SplitAssetLoader;
@@ -103,6 +104,7 @@
import com.android.internal.os.ClassLoaderFactory;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.XmlUtils;
+import com.android.server.SystemConfig;
import libcore.io.IoUtils;
import libcore.util.EmptyArray;
@@ -2482,11 +2484,10 @@
Slog.i(TAG, newPermsMsg.toString());
}
-
- final int NS = PermissionManager.SPLIT_PERMISSIONS.size();
- for (int is=0; is<NS; is++) {
- final PermissionManager.SplitPermissionInfo spi =
- PermissionManager.SPLIT_PERMISSIONS.get(is);
+ List<SplitPermissionInfoParcelable> splitPermissions = getSplitPermissions();
+ final int listSize = splitPermissions.size();
+ for (int is = 0; is < listSize; is++) {
+ final SplitPermissionInfoParcelable spi = splitPermissions.get(is);
if (pkg.applicationInfo.targetSdkVersion >= spi.getTargetSdk()
|| !pkg.requestedPermissions.contains(spi.getSplitPermission())) {
continue;
@@ -2540,6 +2541,23 @@
return pkg;
}
+ private List<SplitPermissionInfoParcelable> getSplitPermissions() {
+ // PackageManager runs this code during initialization prior to registering with
+ // ServiceManager, so we can't use the PackageManager API. Instead, just read from
+ // SystemConfig directly when in any SystemProcess and only use PackageManager when not in
+ // one.
+ if (ActivityThread.isSystem()) {
+ return PermissionManager.splitPermissionInfoListToParcelableList(
+ SystemConfig.getInstance().getSplitPermissions());
+ } else {
+ try {
+ return ActivityThread.getPackageManager().getSplitPermissions();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ }
+
private boolean checkOverlayRequiredSystemProperty(String propName, String propValue) {
if (TextUtils.isEmpty(propName) || TextUtils.isEmpty(propValue)) {
diff --git a/core/java/android/content/pm/permission/SplitPermissionInfoParcelable.aidl b/core/java/android/content/pm/permission/SplitPermissionInfoParcelable.aidl
new file mode 100644
index 0000000..d84454c
--- /dev/null
+++ b/core/java/android/content/pm/permission/SplitPermissionInfoParcelable.aidl
@@ -0,0 +1,19 @@
+/**
+ * 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.content.pm.permission;
+
+ parcelable SplitPermissionInfoParcelable;
\ No newline at end of file
diff --git a/core/java/android/content/pm/permission/SplitPermissionInfoParcelable.java b/core/java/android/content/pm/permission/SplitPermissionInfoParcelable.java
new file mode 100644
index 0000000..6537fbc
--- /dev/null
+++ b/core/java/android/content/pm/permission/SplitPermissionInfoParcelable.java
@@ -0,0 +1,178 @@
+/*
+ * 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.content.pm.permission;
+
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.Preconditions;
+
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Parcelable version of {@link android.permission.PermissionManager.SplitPermissionInfo}
+ * @hide
+ */
+public class SplitPermissionInfoParcelable implements Parcelable {
+
+ /**
+ * The permission that is split.
+ */
+ @NonNull
+ private final String mSplitPermission;
+
+ /**
+ * The permissions that are added.
+ */
+ @NonNull
+ private final List<String> mNewPermissions;
+
+ /**
+ * The target API level when the permission was split.
+ */
+ @IntRange(from = 0)
+ private final int mTargetSdk;
+
+ private void onConstructed() {
+ Preconditions.checkCollectionElementsNotNull(mNewPermissions, "newPermissions");
+ }
+
+
+
+ // Code below generated by codegen v1.0.0.
+ //
+ // DO NOT MODIFY!
+ //
+ // To regenerate run:
+ // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/content/pm/SplitPermissionInfoParcelable.java
+ //
+ // CHECKSTYLE:OFF Generated code
+
+ /**
+ * Creates a new SplitPermissionInfoParcelable.
+ *
+ * @param splitPermission
+ * The permission that is split.
+ * @param newPermissions
+ * The permissions that are added.
+ * @param targetSdk
+ * The target API level when the permission was split.
+ */
+ public SplitPermissionInfoParcelable(
+ @NonNull String splitPermission,
+ @NonNull List<String> newPermissions,
+ @IntRange(from = 0) int targetSdk) {
+ this.mSplitPermission = splitPermission;
+ Preconditions.checkNotNull(mSplitPermission);
+ this.mNewPermissions = newPermissions;
+ Preconditions.checkNotNull(mNewPermissions);
+ this.mTargetSdk = targetSdk;
+ Preconditions.checkArgumentNonnegative(mTargetSdk);
+
+ onConstructed();
+ }
+
+ /**
+ * The permission that is split.
+ */
+ public @NonNull String getSplitPermission() {
+ return mSplitPermission;
+ }
+
+ /**
+ * The permissions that are added.
+ */
+ public @NonNull List<String> getNewPermissions() {
+ return mNewPermissions;
+ }
+
+ /**
+ * The target API level when the permission was split.
+ */
+ public @IntRange(from = 0) int getTargetSdk() {
+ return mTargetSdk;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ // You can override field equality logic by defining either of the methods like:
+ // boolean fieldNameEquals(SplitPermissionInfoParcelable other) { ... }
+ // boolean fieldNameEquals(FieldType otherValue) { ... }
+
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ @SuppressWarnings("unchecked")
+ SplitPermissionInfoParcelable that = (SplitPermissionInfoParcelable) o;
+ //noinspection PointlessBooleanExpression
+ return true
+ && Objects.equals(mSplitPermission, that.mSplitPermission)
+ && Objects.equals(mNewPermissions, that.mNewPermissions)
+ && mTargetSdk == that.mTargetSdk;
+ }
+
+ @Override
+ public int hashCode() {
+ // You can override field hashCode logic by defining methods like:
+ // int fieldNameHashCode() { ... }
+
+ int _hash = 1;
+ _hash = 31 * _hash + Objects.hashCode(mSplitPermission);
+ _hash = 31 * _hash + Objects.hashCode(mNewPermissions);
+ _hash = 31 * _hash + mTargetSdk;
+ return _hash;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ // You can override field parcelling by defining methods like:
+ // void parcelFieldName(Parcel dest, int flags) { ... }
+
+ dest.writeString(mSplitPermission);
+ dest.writeStringList(mNewPermissions);
+ dest.writeInt(mTargetSdk);
+ }
+
+ @Override
+ public int describeContents() { return 0; }
+
+ public static final @NonNull Parcelable.Creator<SplitPermissionInfoParcelable> CREATOR
+ = new Parcelable.Creator<SplitPermissionInfoParcelable>() {
+ @Override
+ public SplitPermissionInfoParcelable[] newArray(int size) {
+ return new SplitPermissionInfoParcelable[size];
+ }
+
+ @Override
+ @SuppressWarnings({"unchecked", "RedundantCast"})
+ public SplitPermissionInfoParcelable createFromParcel(Parcel in) {
+ // You can override field unparcelling by defining methods like:
+ // static FieldType unparcelFieldName(Parcel in) { ... }
+
+ String splitPermission = in.readString();
+ List<String> newPermissions = new java.util.ArrayList<>();
+ in.readStringList(newPermissions);
+ int targetSdk = in.readInt();
+ return new SplitPermissionInfoParcelable(
+ splitPermission,
+ newPermissions,
+ targetSdk);
+ }
+ };
+}
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index 5ac13d8..a0170da 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -206,10 +206,16 @@
continue;
}
- if (filterTags == null || Arrays.binarySearch(filterTags,
- CameraMetadataNative.getTag(keyName, vendorId)) >= 0) {
+
+ if (filterTags != null && Arrays.binarySearch(filterTags,
+ CameraMetadataNative.getTag(keyName, vendorId)) < 0) {
+ // ignore vendor keys not in filterTags
+ continue;
+ }
+ if (instance == null || instance.getProtected(k) != null) {
keyList.add(k);
}
+
}
}
diff --git a/core/java/android/hardware/radio/TunerAdapter.java b/core/java/android/hardware/radio/TunerAdapter.java
index be2846f..aa5480a 100644
--- a/core/java/android/hardware/radio/TunerAdapter.java
+++ b/core/java/android/hardware/radio/TunerAdapter.java
@@ -271,6 +271,8 @@
mCallback.setProgramListObserver(list, () -> {
try {
mTuner.stopProgramListUpdates();
+ } catch (IllegalStateException ex) {
+ // it's fine to not stop updates if tuner is already closed
} catch (RemoteException ex) {
Log.e(TAG, "Couldn't stop program list updates", ex);
}
diff --git a/core/java/android/hardware/radio/TunerCallbackAdapter.java b/core/java/android/hardware/radio/TunerCallbackAdapter.java
index 0fb93e5..beff0f7 100644
--- a/core/java/android/hardware/radio/TunerCallbackAdapter.java
+++ b/core/java/android/hardware/radio/TunerCallbackAdapter.java
@@ -211,10 +211,12 @@
@Override
public void onProgramListUpdated(ProgramList.Chunk chunk) {
- synchronized (mLock) {
- if (mProgramList == null) return;
- mProgramList.apply(Objects.requireNonNull(chunk));
- }
+ mHandler.post(() -> {
+ synchronized (mLock) {
+ if (mProgramList == null) return;
+ mProgramList.apply(Objects.requireNonNull(chunk));
+ }
+ });
}
@Override
diff --git a/core/java/android/inputmethodservice/SoftInputWindow.java b/core/java/android/inputmethodservice/SoftInputWindow.java
index 0513fee..356b344 100644
--- a/core/java/android/inputmethodservice/SoftInputWindow.java
+++ b/core/java/android/inputmethodservice/SoftInputWindow.java
@@ -21,6 +21,7 @@
import android.annotation.IntDef;
import android.app.Dialog;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.graphics.Rect;
import android.os.Debug;
import android.os.IBinder;
@@ -50,6 +51,7 @@
final int mWindowType;
final int mGravity;
final boolean mTakesFocus;
+ final boolean mAutomotiveHideNavBarForKeyboard;
private final Rect mBounds = new Rect();
@Retention(SOURCE)
@@ -134,6 +136,8 @@
mWindowType = windowType;
mGravity = gravity;
mTakesFocus = takesFocus;
+ mAutomotiveHideNavBarForKeyboard = context.getResources().getBoolean(
+ com.android.internal.R.bool.config_automotiveHideNavBarForKeyboard);
initDockWindow();
}
@@ -247,6 +251,11 @@
windowModFlags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
}
+ if (isAutomotive() && mAutomotiveHideNavBarForKeyboard) {
+ windowSetFlags |= WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
+ windowModFlags |= WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
+ }
+
getWindow().setFlags(windowSetFlags, windowModFlags);
}
@@ -338,6 +347,10 @@
mWindowState = newState;
}
+ private boolean isAutomotive() {
+ return getContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
+ }
+
private static String stateToString(@SoftInputWindowState int state) {
switch (state) {
case SoftInputWindowState.TOKEN_PENDING:
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 00d522b..ecd16dd 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -266,8 +266,11 @@
* - Fixed bug in min learned capacity updating process.
* New in version 34:
* - Deprecated STATS_SINCE_UNPLUGGED and STATS_CURRENT.
+ * New in version 35:
+ * - Fixed bug that was not reporting high cellular tx power correctly
+ * - Added out of service and emergency service modes to data connection types
*/
- static final int CHECKIN_VERSION = 34;
+ static final int CHECKIN_VERSION = 35;
/**
* Old version, we hit 9 and ran out of room, need to remove.
@@ -2371,18 +2374,21 @@
*/
public abstract int getMobileRadioActiveUnknownCount(int which);
- public static final int DATA_CONNECTION_NONE = 0;
- public static final int DATA_CONNECTION_OTHER = TelephonyManager.MAX_NETWORK_TYPE + 1;
+ public static final int DATA_CONNECTION_OUT_OF_SERVICE = 0;
+ public static final int DATA_CONNECTION_EMERGENCY_SERVICE =
+ TelephonyManager.MAX_NETWORK_TYPE + 1;
+ public static final int DATA_CONNECTION_OTHER = DATA_CONNECTION_EMERGENCY_SERVICE + 1;
+
static final String[] DATA_CONNECTION_NAMES = {
- "none", "gprs", "edge", "umts", "cdma", "evdo_0", "evdo_A",
+ "oos", "gprs", "edge", "umts", "cdma", "evdo_0", "evdo_A",
"1xrtt", "hsdpa", "hsupa", "hspa", "iden", "evdo_b", "lte",
"ehrpd", "hspap", "gsm", "td_scdma", "iwlan", "lte_ca", "nr",
- "other"
+ "emngcy", "other"
};
@UnsupportedAppUsage
- public static final int NUM_DATA_CONNECTION_TYPES = DATA_CONNECTION_OTHER+1;
+ public static final int NUM_DATA_CONNECTION_TYPES = DATA_CONNECTION_OTHER + 1;
/**
* Returns the time in microseconds that the phone has been running with
@@ -6564,6 +6570,10 @@
}
oldState = rec.states;
oldState2 = rec.states2;
+ // Clear High Tx Power Flag for volta positioning
+ if ((rec.states2 & HistoryItem.STATE2_CELLULAR_HIGH_TX_POWER_FLAG) != 0) {
+ rec.states2 &= ~HistoryItem.STATE2_CELLULAR_HIGH_TX_POWER_FLAG;
+ }
}
return item.toString();
@@ -7865,9 +7875,9 @@
// Phone data connection (DATA_CONNECTION_TIME_DATA and DATA_CONNECTION_COUNT_DATA)
for (int i = 0; i < NUM_DATA_CONNECTION_TYPES; ++i) {
// Map OTHER to TelephonyManager.NETWORK_TYPE_UNKNOWN and mark NONE as a boolean.
- boolean isNone = (i == DATA_CONNECTION_NONE);
+ boolean isNone = (i == DATA_CONNECTION_OUT_OF_SERVICE);
int telephonyNetworkType = i;
- if (i == DATA_CONNECTION_OTHER) {
+ if (i == DATA_CONNECTION_OTHER || i == DATA_CONNECTION_EMERGENCY_SERVICE) {
telephonyNetworkType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
}
final long pdcToken = proto.start(SystemProto.DATA_CONNECTION);
diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java
index ce1942c..7a70e93 100644
--- a/core/java/android/os/GraphicsEnvironment.java
+++ b/core/java/android/os/GraphicsEnvironment.java
@@ -67,6 +67,8 @@
private static final String PROPERTY_GFX_DRIVER_PRERELEASE = "ro.gfx.driver.1";
private static final String PROPERTY_GFX_DRIVER_BUILD_TIME = "ro.gfx.driver_build_time";
private static final String METADATA_DRIVER_BUILD_TIME = "com.android.gamedriver.build_time";
+ private static final String METADATA_DEVELOPER_DRIVER_ENABLE =
+ "com.android.graphics.developerdriver.enable";
private static final String ANGLE_RULES_FILE = "a4a_rules.json";
private static final String ANGLE_TEMP_RULES = "debug.angle.rules";
private static final String ACTION_ANGLE_FOR_ANDROID = "android.app.action.ANGLE_FOR_ANDROID";
@@ -691,7 +693,8 @@
/**
* Return the driver package name to use. Return null for system driver.
*/
- private static String chooseDriverInternal(Context context, Bundle coreSettings) {
+ private static String chooseDriverInternal(
+ Context context, Bundle coreSettings, PackageManager pm, String packageName) {
final String gameDriver = SystemProperties.get(PROPERTY_GFX_DRIVER);
final boolean hasGameDriver = gameDriver != null && !gameDriver.isEmpty();
@@ -706,12 +709,24 @@
// To minimize risk of driver updates crippling the device beyond user repair, never use an
// updated driver for privileged or non-updated system apps. Presumably pre-installed apps
// were tested thoroughly with the pre-installed driver.
- final ApplicationInfo ai = context.getApplicationInfo();
+ ApplicationInfo ai;
+ try {
+ // Get the ApplicationInfo from PackageManager so that metadata fields present.
+ ai = pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA);
+ } catch (PackageManager.NameNotFoundException e) {
+ // Unlikely to fail for applications, but in case of failure, fall back to use the
+ // ApplicationInfo from context directly.
+ ai = context.getApplicationInfo();
+ }
if (ai.isPrivilegedApp() || (ai.isSystemApp() && !ai.isUpdatedSystemApp())) {
if (DEBUG) Log.v(TAG, "Ignoring driver package for privileged/non-updated system app.");
return null;
}
+ final boolean enablePrereleaseDriver =
+ (ai.metaData != null && ai.metaData.getBoolean(METADATA_DEVELOPER_DRIVER_ENABLE))
+ || getCanLoadSystemLibraries() == 1;
+
// Priority for Game Driver settings global on confliction (Higher priority comes first):
// 1. GAME_DRIVER_ALL_APPS
// 2. GAME_DRIVER_OPT_OUT_APPS
@@ -728,7 +743,7 @@
return hasGameDriver ? gameDriver : null;
case GAME_DRIVER_GLOBAL_OPT_IN_PRERELEASE_DRIVER:
if (DEBUG) Log.v(TAG, "All apps opt in to use prerelease driver.");
- return hasPrereleaseDriver ? prereleaseDriver : null;
+ return hasPrereleaseDriver && enablePrereleaseDriver ? prereleaseDriver : null;
case GAME_DRIVER_GLOBAL_OPT_IN_DEFAULT:
default:
break;
@@ -745,7 +760,7 @@
null, coreSettings, Settings.Global.GAME_DRIVER_PRERELEASE_OPT_IN_APPS)
.contains(appPackageName)) {
if (DEBUG) Log.v(TAG, "App opts in for prerelease Game Driver.");
- return hasPrereleaseDriver ? prereleaseDriver : null;
+ return hasPrereleaseDriver && enablePrereleaseDriver ? prereleaseDriver : null;
}
// Early return here since the rest logic is only for Game Driver.
@@ -783,7 +798,8 @@
*/
private static boolean chooseDriver(
Context context, Bundle coreSettings, PackageManager pm, String packageName) {
- final String driverPackageName = chooseDriverInternal(context, coreSettings);
+ final String driverPackageName = chooseDriverInternal(context, coreSettings, pm,
+ packageName);
if (driverPackageName == null) {
return false;
}
diff --git a/core/java/android/permission/PermissionManager.java b/core/java/android/permission/PermissionManager.java
index a2ab0c1..3c45b0c 100644
--- a/core/java/android/permission/PermissionManager.java
+++ b/core/java/android/permission/PermissionManager.java
@@ -26,14 +26,15 @@
import android.annotation.TestApi;
import android.content.Context;
import android.content.pm.IPackageManager;
+import android.content.pm.permission.SplitPermissionInfoParcelable;
import android.os.RemoteException;
+import android.util.Log;
import com.android.internal.annotations.Immutable;
-import com.android.server.SystemConfig;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
-import java.util.Objects;
/**
* System level service for accessing the permission capabilities of the platform.
@@ -44,18 +45,14 @@
@SystemApi
@SystemService(Context.PERMISSION_SERVICE)
public final class PermissionManager {
- /**
- * {@link android.content.pm.PackageParser} needs access without having a {@link Context}.
- *
- * @hide
- */
- public static final ArrayList<SplitPermissionInfo> SPLIT_PERMISSIONS =
- SystemConfig.getInstance().getSplitPermissions();
+ private static final String TAG = PermissionManager.class.getName();
private final @NonNull Context mContext;
private final IPackageManager mPackageManager;
+ private List<SplitPermissionInfo> mSplitPermissionInfos;
+
/**
* Creates a new instance.
*
@@ -123,7 +120,48 @@
* @return All permissions that are split.
*/
public @NonNull List<SplitPermissionInfo> getSplitPermissions() {
- return SPLIT_PERMISSIONS;
+ if (mSplitPermissionInfos != null) {
+ return mSplitPermissionInfos;
+ }
+
+ List<SplitPermissionInfoParcelable> parcelableList;
+ try {
+ parcelableList = mPackageManager.getSplitPermissions();
+ } catch (RemoteException e) {
+ Log.w(TAG, "Error getting split permissions", e);
+ return Collections.emptyList();
+ }
+
+ mSplitPermissionInfos = splitPermissionInfoListToNonParcelableList(parcelableList);
+
+ return mSplitPermissionInfos;
+ }
+
+ private List<SplitPermissionInfo> splitPermissionInfoListToNonParcelableList(
+ List<SplitPermissionInfoParcelable> parcelableList) {
+ final int size = parcelableList.size();
+ List<SplitPermissionInfo> list = new ArrayList<>(size);
+ for (int i = 0; i < size; i++) {
+ list.add(new SplitPermissionInfo(parcelableList.get(i)));
+ }
+ return list;
+ }
+
+ /**
+ * Converts a {@link List} of {@link SplitPermissionInfo} into a List of
+ * {@link SplitPermissionInfoParcelable} and returns it.
+ * @hide
+ */
+ public static List<SplitPermissionInfoParcelable> splitPermissionInfoListToParcelableList(
+ List<SplitPermissionInfo> splitPermissionsList) {
+ final int size = splitPermissionsList.size();
+ List<SplitPermissionInfoParcelable> outList = new ArrayList<>(size);
+ for (int i = 0; i < size; i++) {
+ SplitPermissionInfo info = splitPermissionsList.get(i);
+ outList.add(new SplitPermissionInfoParcelable(
+ info.getSplitPermission(), info.getNewPermissions(), info.getTargetSdk()));
+ }
+ return outList;
}
/**
@@ -132,44 +170,40 @@
*/
@Immutable
public static final class SplitPermissionInfo {
- private final @NonNull String mSplitPerm;
- private final @NonNull List<String> mNewPerms;
- private final int mTargetSdk;
+ private @NonNull final SplitPermissionInfoParcelable mSplitPermissionInfoParcelable;
@Override
public boolean equals(@Nullable Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
SplitPermissionInfo that = (SplitPermissionInfo) o;
- return mTargetSdk == that.mTargetSdk
- && mSplitPerm.equals(that.mSplitPerm)
- && mNewPerms.equals(that.mNewPerms);
+ return mSplitPermissionInfoParcelable.equals(that.mSplitPermissionInfoParcelable);
}
@Override
public int hashCode() {
- return Objects.hash(mSplitPerm, mNewPerms, mTargetSdk);
+ return mSplitPermissionInfoParcelable.hashCode();
}
/**
* Get the permission that is split.
*/
public @NonNull String getSplitPermission() {
- return mSplitPerm;
+ return mSplitPermissionInfoParcelable.getSplitPermission();
}
/**
* Get the permissions that are added.
*/
public @NonNull List<String> getNewPermissions() {
- return mNewPerms;
+ return mSplitPermissionInfoParcelable.getNewPermissions();
}
/**
* Get the target API level when the permission was split.
*/
public int getTargetSdk() {
- return mTargetSdk;
+ return mSplitPermissionInfoParcelable.getTargetSdk();
}
/**
@@ -183,9 +217,11 @@
*/
public SplitPermissionInfo(@NonNull String splitPerm, @NonNull List<String> newPerms,
int targetSdk) {
- mSplitPerm = splitPerm;
- mNewPerms = newPerms;
- mTargetSdk = targetSdk;
+ this(new SplitPermissionInfoParcelable(splitPerm, newPerms, targetSdk));
+ }
+
+ private SplitPermissionInfo(@NonNull SplitPermissionInfoParcelable parcelable) {
+ mSplitPermissionInfoParcelable = parcelable;
}
}
}
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index cb7d41b..93bcdbf 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -1639,7 +1639,7 @@
@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/service/textclassifier/TextClassifierService.java b/core/java/android/service/textclassifier/TextClassifierService.java
index 30c4e90..bb39be2 100644
--- a/core/java/android/service/textclassifier/TextClassifierService.java
+++ b/core/java/android/service/textclassifier/TextClassifierService.java
@@ -51,7 +51,6 @@
import com.android.internal.util.Preconditions;
-import java.lang.ref.WeakReference;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@@ -431,23 +430,18 @@
* Forwards the callback result to a wrapped binder callback.
*/
private static final class ProxyCallback<T extends Parcelable> implements Callback<T> {
- private WeakReference<ITextClassifierCallback> mTextClassifierCallback;
+ private ITextClassifierCallback mTextClassifierCallback;
private ProxyCallback(ITextClassifierCallback textClassifierCallback) {
- mTextClassifierCallback =
- new WeakReference<>(Preconditions.checkNotNull(textClassifierCallback));
+ mTextClassifierCallback = Preconditions.checkNotNull(textClassifierCallback);
}
@Override
public void onSuccess(T result) {
- ITextClassifierCallback callback = mTextClassifierCallback.get();
- if (callback == null) {
- return;
- }
try {
Bundle bundle = new Bundle(1);
bundle.putParcelable(KEY_RESULT, result);
- callback.onSuccess(bundle);
+ mTextClassifierCallback.onSuccess(bundle);
} catch (RemoteException e) {
Slog.d(LOG_TAG, "Error calling callback");
}
@@ -455,12 +449,8 @@
@Override
public void onFailure(CharSequence error) {
- ITextClassifierCallback callback = mTextClassifierCallback.get();
- if (callback == null) {
- return;
- }
try {
- callback.onFailure();
+ mTextClassifierCallback.onFailure();
} catch (RemoteException e) {
Slog.d(LOG_TAG, "Error calling callback");
}
diff --git a/core/java/android/view/GestureExclusionTracker.java b/core/java/android/view/GestureExclusionTracker.java
index 6fcdd71..fffb323e 100644
--- a/core/java/android/view/GestureExclusionTracker.java
+++ b/core/java/android/view/GestureExclusionTracker.java
@@ -44,7 +44,7 @@
while (i.hasNext()) {
final GestureExclusionViewInfo info = i.next();
final View v = info.getView();
- if (v == null || !v.isAttachedToWindow()) {
+ if (v == null || !v.isAttachedToWindow() || !v.isAggregatedVisible()) {
mGestureExclusionViewsChanged = true;
i.remove();
continue;
@@ -122,7 +122,8 @@
public int update() {
final View excludedView = getView();
- if (excludedView == null || !excludedView.isAttachedToWindow()) return GONE;
+ if (excludedView == null || !excludedView.isAttachedToWindow()
+ || !excludedView.isAggregatedVisible()) return GONE;
final List<Rect> localRects = excludedView.getSystemGestureExclusionRects();
final List<Rect> newRects = new ArrayList<>(localRects.size());
for (Rect src : localRects) {
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 254d04e..85ea3d3 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -100,6 +100,7 @@
public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallback {
private static final String TAG = "SurfaceView";
private static final boolean DEBUG = false;
+ private static final boolean DEBUG_POSITION = false;
@UnsupportedAppUsage
final ArrayList<SurfaceHolder.Callback> mCallbacks
@@ -126,6 +127,7 @@
// we need to preserve the old one until the new one has drawn.
SurfaceControl mDeferredDestroySurfaceControl;
SurfaceControl mBackgroundControl;
+ final Object mSurfaceControlLock = new Object();
final Rect mTmpRect = new Rect();
final Configuration mConfiguration = new Configuration();
@@ -173,6 +175,9 @@
@UnsupportedAppUsage
int mRequestedFormat = PixelFormat.RGB_565;
+ boolean mUseAlpha = false;
+ float mSurfaceAlpha = 1f;
+
@UnsupportedAppUsage
boolean mHaveFrame = false;
boolean mSurfaceCreated = false;
@@ -200,6 +205,7 @@
private int mPendingReportDraws;
private SurfaceControl.Transaction mRtTransaction = new SurfaceControl.Transaction();
+ private SurfaceControl.Transaction mTmpTransaction = new SurfaceControl.Transaction();
public SurfaceView(Context context) {
this(context, null);
@@ -288,6 +294,152 @@
updateSurface();
}
+ /**
+ * Make alpha value of this view reflect onto the surface. This can only be called from at most
+ * one SurfaceView within a view tree.
+ *
+ * <p class="note"><strong>Note:</strong> Alpha value of the view is ignored and the underlying
+ * surface is rendered opaque by default.</p>
+ *
+ * @hide
+ */
+ public void setUseAlpha() {
+ if (!mUseAlpha) {
+ mUseAlpha = true;
+ updateSurfaceAlpha();
+ }
+ }
+
+ @Override
+ public void setAlpha(float alpha) {
+ // Sets the opacity of the view to a value, where 0 means the view is completely transparent
+ // and 1 means the view is completely opaque.
+ //
+ // Note: Alpha value of this view is ignored by default. To enable alpha blending, you need
+ // to call setUseAlpha() as well.
+ // This view doesn't support translucent opacity if the view is located z-below, since the
+ // logic to punch a hole in the view hierarchy cannot handle such case. See also
+ // #clearSurfaceViewPort(Canvas)
+ if (DEBUG) {
+ Log.d(TAG, System.identityHashCode(this)
+ + " setAlpha: mUseAlpha = " + mUseAlpha + " alpha=" + alpha);
+ }
+ super.setAlpha(alpha);
+ updateSurfaceAlpha();
+ }
+
+ private float getFixedAlpha() {
+ // Compute alpha value to be set on the underlying surface.
+ final float alpha = getAlpha();
+ return mUseAlpha && (mSubLayer > 0 || alpha == 0f) ? alpha : 1f;
+ }
+
+ private void updateSurfaceAlpha() {
+ if (!mUseAlpha) {
+ if (DEBUG) {
+ Log.d(TAG, System.identityHashCode(this)
+ + " updateSurfaceAlpha: setUseAlpha() is not called, ignored.");
+ }
+ return;
+ }
+ final float viewAlpha = getAlpha();
+ if (mSubLayer < 0 && 0f < viewAlpha && viewAlpha < 1f) {
+ Log.w(TAG, System.identityHashCode(this)
+ + " updateSurfaceAlpha:"
+ + " translucent color is not supported for a surface placed z-below.");
+ }
+ if (!mHaveFrame) {
+ if (DEBUG) {
+ Log.d(TAG, System.identityHashCode(this)
+ + " updateSurfaceAlpha: has no surface.");
+ }
+ return;
+ }
+ final ViewRootImpl viewRoot = getViewRootImpl();
+ if (viewRoot == null) {
+ if (DEBUG) {
+ Log.d(TAG, System.identityHashCode(this)
+ + " updateSurfaceAlpha: ViewRootImpl not available.");
+ }
+ return;
+ }
+ if (mSurfaceControl == null) {
+ if (DEBUG) {
+ Log.d(TAG, System.identityHashCode(this)
+ + "updateSurfaceAlpha:"
+ + " surface is not yet created, or already released.");
+ }
+ return;
+ }
+ final Surface parent = viewRoot.mSurface;
+ if (parent == null || !parent.isValid()) {
+ if (DEBUG) {
+ Log.d(TAG, System.identityHashCode(this)
+ + " updateSurfaceAlpha: ViewRootImpl has no valid surface");
+ }
+ return;
+ }
+ final float alpha = getFixedAlpha();
+ if (alpha != mSurfaceAlpha) {
+ if (isHardwareAccelerated()) {
+ /*
+ * Schedule a callback that reflects an alpha value onto the underlying surfaces.
+ * This gets called on a RenderThread worker thread, so members accessed here must
+ * be protected by a lock.
+ */
+ viewRoot.registerRtFrameCallback(frame -> {
+ try {
+ final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+ synchronized (mSurfaceControlLock) {
+ if (!parent.isValid()) {
+ if (DEBUG) {
+ Log.d(TAG, System.identityHashCode(this)
+ + " updateSurfaceAlpha RT:"
+ + " ViewRootImpl has no valid surface");
+ }
+ return;
+ }
+ if (mSurfaceControl == null) {
+ if (DEBUG) {
+ Log.d(TAG, System.identityHashCode(this)
+ + "updateSurfaceAlpha RT:"
+ + " mSurfaceControl has already released");
+ }
+ return;
+ }
+ if (DEBUG) {
+ Log.d(TAG, System.identityHashCode(this)
+ + " updateSurfaceAlpha RT: set alpha=" + alpha);
+ }
+ t.setAlpha(mSurfaceControl, alpha);
+ t.deferTransactionUntilSurface(mSurfaceControl, parent, frame);
+ }
+ // It's possible that mSurfaceControl is released in the UI thread before
+ // the transaction completes. If that happens, an exception is thrown, which
+ // must be caught immediately.
+ t.apply();
+ } catch (Exception e) {
+ Log.e(TAG, System.identityHashCode(this)
+ + "updateSurfaceAlpha RT: Exception during surface transaction", e);
+ }
+ });
+ damageInParent();
+ } else {
+ if (DEBUG) {
+ Log.d(TAG, System.identityHashCode(this)
+ + " updateSurfaceAlpha: set alpha=" + alpha);
+ }
+ SurfaceControl.openTransaction();
+ try {
+ mSurfaceControl.setAlpha(alpha);
+ } finally {
+ SurfaceControl.closeTransaction();
+ }
+ }
+ mSurfaceAlpha = alpha;
+ }
+ }
+
private void performDrawFinished() {
if (mPendingReportDraws > 0) {
mDrawFinished = true;
@@ -337,11 +489,7 @@
mRequestedVisible = false;
updateSurface();
- if (mSurfaceControl != null) {
- mSurfaceControl.remove();
- }
- mSurfaceControl = null;
-
+ releaseSurfaces();
mHaveFrame = false;
super.onDetachedFromWindow();
@@ -510,15 +658,6 @@
}
}
- private Rect getParentSurfaceInsets() {
- final ViewRootImpl root = getViewRootImpl();
- if (root == null) {
- return null;
- } else {
- return root.mWindowAttributes.surfaceInsets;
- }
- }
-
private void updateBackgroundVisibilityInTransaction(SurfaceControl viewRoot) {
if (mBackgroundControl == null) {
return;
@@ -532,23 +671,34 @@
}
private void releaseSurfaces() {
- if (mSurfaceControl != null) {
- mSurfaceControl.remove();
- mSurfaceControl = null;
+ synchronized (mSurfaceControlLock) {
+ if (mSurfaceControl != null) {
+ mTmpTransaction.remove(mSurfaceControl);
+ mSurfaceControl = null;
+ }
+ if (mBackgroundControl != null) {
+ mTmpTransaction.remove(mBackgroundControl);
+ mBackgroundControl = null;
+ }
+ mTmpTransaction.apply();
}
- if (mBackgroundControl != null) {
- mBackgroundControl.remove();
- mBackgroundControl = null;
- }
+ mSurfaceAlpha = 1f;
}
/** @hide */
protected void updateSurface() {
if (!mHaveFrame) {
+ if (DEBUG) {
+ Log.d(TAG, System.identityHashCode(this) + " updateSurface: has no frame");
+ }
return;
}
ViewRootImpl viewRoot = getViewRootImpl();
if (viewRoot == null || viewRoot.mSurface == null || !viewRoot.mSurface.isValid()) {
+ if (DEBUG) {
+ Log.d(TAG, System.identityHashCode(this)
+ + " updateSurface: no valid surface");
+ }
return;
}
@@ -562,20 +712,25 @@
int myHeight = mRequestedHeight;
if (myHeight <= 0) myHeight = getHeight();
+ final float alpha = getFixedAlpha();
final boolean formatChanged = mFormat != mRequestedFormat;
final boolean visibleChanged = mVisible != mRequestedVisible;
+ final boolean alphaChanged = mSurfaceAlpha != alpha;
final boolean creating = (mSurfaceControl == null || formatChanged || visibleChanged)
&& mRequestedVisible;
final boolean sizeChanged = mSurfaceWidth != myWidth || mSurfaceHeight != myHeight;
final boolean windowVisibleChanged = mWindowVisibility != mLastWindowVisibility;
boolean redrawNeeded = false;
- if (creating || formatChanged || sizeChanged || visibleChanged || windowVisibleChanged) {
+ if (creating || formatChanged || sizeChanged || visibleChanged || (mUseAlpha
+ && alphaChanged) || windowVisibleChanged) {
getLocationInWindow(mLocation);
if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "
+ "Changes: creating=" + creating
+ " format=" + formatChanged + " size=" + sizeChanged
+ + " visible=" + visibleChanged + " alpha=" + alphaChanged
+ + " mUseAlpha=" + mUseAlpha
+ " visible=" + visibleChanged
+ " left=" + (mWindowSpaceLeft != mLocation[0])
+ " top=" + (mWindowSpaceTop != mLocation[1]));
@@ -597,7 +752,7 @@
mTranslator.translateRectInAppWindowToScreen(mScreenRect);
}
- final Rect surfaceInsets = getParentSurfaceInsets();
+ final Rect surfaceInsets = viewRoot.mWindowAttributes.surfaceInsets;
mScreenRect.offset(surfaceInsets.left, surfaceInsets.top);
if (creating) {
@@ -646,6 +801,10 @@
mSurfaceControl.hide();
}
updateBackgroundVisibilityInTransaction(viewRoot.getSurfaceControl());
+ if (mUseAlpha) {
+ mSurfaceControl.setAlpha(alpha);
+ mSurfaceAlpha = alpha;
+ }
// While creating the surface, we will set it's initial
// geometry. Outside of that though, we should generally
@@ -788,7 +947,6 @@
mIsCreating = false;
if (mSurfaceControl != null && !mSurfaceCreated) {
mSurface.release();
-
releaseSurfaces();
}
}
@@ -828,10 +986,13 @@
if (!isHardwareAccelerated() || !mRtHandlingPositionUpdates) {
try {
- if (DEBUG) Log.d(TAG, String.format("%d updateSurfacePosition UI, " +
- "postion = [%d, %d, %d, %d]", System.identityHashCode(this),
- mScreenRect.left, mScreenRect.top,
- mScreenRect.right, mScreenRect.bottom));
+ if (DEBUG_POSITION) {
+ Log.d(TAG, String.format("%d updateSurfacePosition UI, "
+ + "position = [%d, %d, %d, %d]",
+ System.identityHashCode(this),
+ mScreenRect.left, mScreenRect.top,
+ mScreenRect.right, mScreenRect.bottom));
+ }
setParentSpaceRectangle(mScreenRect, -1);
} catch (Exception ex) {
Log.e(TAG, "Exception configuring surface", ex);
@@ -884,7 +1045,6 @@
if (mViewVisibility) {
mRtTransaction.show(surface);
}
-
}
private void setParentSpaceRectangle(Rect position, long frameNumber) {
@@ -925,7 +1085,7 @@
return;
}
try {
- if (DEBUG) {
+ if (DEBUG_POSITION) {
Log.d(TAG, String.format(
"%d updateSurfacePosition RenderWorker, frameNr = %d, "
+ "postion = [%d, %d, %d, %d]",
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 4e86e60..84665f7 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -14344,6 +14344,14 @@
}
/**
+ * @return true if this view and all ancestors are visible as of the last
+ * {@link #onVisibilityAggregated(boolean)} call.
+ */
+ boolean isAggregatedVisible() {
+ return (mPrivateFlags3 & PFLAG3_AGGREGATED_VISIBLE) != 0;
+ }
+
+ /**
* Internal dispatching method for {@link #onVisibilityAggregated}. Overridden by
* ViewGroup. Intended to only be called when {@link #isAttachedToWindow()},
* {@link #getWindowVisibility()} is {@link #VISIBLE} and this view's parent {@link #isShown()}.
@@ -14371,7 +14379,7 @@
@CallSuper
public void onVisibilityAggregated(boolean isVisible) {
// Update our internal visibility tracking so we can detect changes
- boolean oldVisible = (mPrivateFlags3 & PFLAG3_AGGREGATED_VISIBLE) != 0;
+ boolean oldVisible = isAggregatedVisible();
mPrivateFlags3 = isVisible ? (mPrivateFlags3 | PFLAG3_AGGREGATED_VISIBLE)
: (mPrivateFlags3 & ~PFLAG3_AGGREGATED_VISIBLE);
if (isVisible && mAttachInfo != null) {
@@ -14423,6 +14431,9 @@
}
notifyAppearedOrDisappearedForContentCaptureIfNeeded(isVisible);
+ if (isVisible != oldVisible) {
+ updateSystemGestureExclusionRects();
+ }
}
/**
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index d302c2b..032af1c 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -707,9 +707,10 @@
if (mBindSequence != bindSequence) {
return;
}
- if (matrixValues == null) {
- // That this app is unbound from the parent ActivityView. In this case,
- // calling updateCursorAnchorInfo() isn't safe. Only clear the matrix.
+ if (matrixValues == null || mActivityViewToScreenMatrix == null) {
+ // Either InputBoundResult#mActivityViewToScreenMatrixValues is null
+ // OR this app is unbound from the parent ActivityView. In this case,
+ // calling updateCursorAnchorInfo() isn't safe. Only clear the matrix.
mActivityViewToScreenMatrix = null;
return;
}
diff --git a/core/java/android/widget/SelectionActionModeHelper.java b/core/java/android/widget/SelectionActionModeHelper.java
index 51ca805..d0f8093 100644
--- a/core/java/android/widget/SelectionActionModeHelper.java
+++ b/core/java/android/widget/SelectionActionModeHelper.java
@@ -999,6 +999,7 @@
}
private void onTimeOut() {
+ Log.d(LOG_TAG, "Timeout in TextClassificationAsyncTask");
if (getStatus() == Status.RUNNING) {
onPostExecute(mTimeOutResultSupplier.get());
}
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 00206fc..de77aaa 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -164,6 +164,8 @@
public static final String LAUNCH_LOCATON_DIRECT_SHARE = "direct_share";
private static final int APP_PREDICTION_SHARE_TARGET_QUERY_PACKAGE_LIMIT = 20;
public static final String APP_PREDICTION_INTENT_FILTER_KEY = "intent_filter";
+
+ private boolean mIsAppPredictorComponentAvailable;
private AppPredictor mAppPredictor;
private AppPredictor.Callback mAppPredictorCallback;
private Map<ChooserTarget, AppTarget> mDirectShareAppTargetCache;
@@ -491,6 +493,9 @@
@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);
@@ -707,6 +712,32 @@
}
/**
+ * Returns true if app prediction service is defined and the component exists on device.
+ */
+ private boolean isAppPredictionServiceAvailable() {
+ final String appPredictionServiceName =
+ getString(R.string.config_defaultAppPredictionService);
+ if (appPredictionServiceName == null) {
+ return false;
+ }
+ final ComponentName appPredictionComponentName =
+ ComponentName.unflattenFromString(appPredictionServiceName);
+ if (appPredictionComponentName == null) {
+ return false;
+ }
+
+ // Check if the app prediction component actually exists on the device.
+ Intent intent = new Intent();
+ intent.setComponent(appPredictionComponentName);
+ if (getPackageManager().resolveService(intent, PackageManager.MATCH_ALL) == null) {
+ Log.e(TAG, "App prediction service is defined, but does not exist: "
+ + appPredictionServiceName);
+ return false;
+ }
+ return true;
+ }
+
+ /**
* Check if the profile currently used is a work profile.
* @return true if it is work profile, false if it is parent profile (or no work profile is
* set up)
@@ -1693,6 +1724,9 @@
@Nullable
private AppPredictor getAppPredictor() {
+ if (!mIsAppPredictorComponentAvailable) {
+ return null;
+ }
if (mAppPredictor == null
&& getPackageManager().getAppPredictionServicePackageName() != null) {
final IntentFilter filter = getTargetIntentFilter();
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index d60d543..15b1d75 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -106,7 +106,7 @@
void notePhoneOn();
void notePhoneOff();
void notePhoneSignalStrength(in SignalStrength signalStrength);
- void notePhoneDataConnectionState(int dataType, boolean hasData);
+ void notePhoneDataConnectionState(int dataType, boolean hasData, int serviceType);
void notePhoneState(int phoneState);
void noteWifiOn();
void noteWifiOff();
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 651991d..e1a640ee 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -906,8 +906,6 @@
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
protected StopwatchTimer mBluetoothScanTimer;
- boolean mIsCellularTxPowerHigh = false;
-
int mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
long mMobileRadioActiveStartTime;
StopwatchTimer mMobileRadioActiveTimer;
@@ -5261,16 +5259,26 @@
}
@UnsupportedAppUsage
- public void notePhoneDataConnectionStateLocked(int dataType, boolean hasData) {
+ public void notePhoneDataConnectionStateLocked(int dataType, boolean hasData, int serviceType) {
// BatteryStats uses 0 to represent no network type.
// Telephony does not have a concept of no network type, and uses 0 to represent unknown.
// Unknown is included in DATA_CONNECTION_OTHER.
- int bin = DATA_CONNECTION_NONE;
+ int bin = DATA_CONNECTION_OUT_OF_SERVICE;
if (hasData) {
if (dataType > 0 && dataType <= TelephonyManager.MAX_NETWORK_TYPE) {
bin = dataType;
} else {
- bin = DATA_CONNECTION_OTHER;
+ switch (serviceType) {
+ case ServiceState.STATE_OUT_OF_SERVICE:
+ bin = DATA_CONNECTION_OUT_OF_SERVICE;
+ break;
+ case ServiceState.STATE_EMERGENCY_ONLY:
+ bin = DATA_CONNECTION_EMERGENCY_SERVICE;
+ break;
+ default:
+ bin = DATA_CONNECTION_OTHER;
+ break;
+ }
}
}
if (DEBUG) Log.i(TAG, "Phone Data Connection -> " + dataType + " = " + hasData);
@@ -11190,19 +11198,9 @@
}
}
if (levelMaxTimeSpent == ModemActivityInfo.TX_POWER_LEVELS - 1) {
- if (!mIsCellularTxPowerHigh) {
- mHistoryCur.states2 |= HistoryItem.STATE2_CELLULAR_HIGH_TX_POWER_FLAG;
- addHistoryRecordLocked(elapsedRealtime, uptime);
- mIsCellularTxPowerHigh = true;
- }
- return;
- }
- if (mIsCellularTxPowerHigh) {
- mHistoryCur.states2 &= ~HistoryItem.STATE2_CELLULAR_HIGH_TX_POWER_FLAG;
+ mHistoryCur.states2 |= HistoryItem.STATE2_CELLULAR_HIGH_TX_POWER_FLAG;
addHistoryRecordLocked(elapsedRealtime, uptime);
- mIsCellularTxPowerHigh = false;
}
- return;
}
private final class BluetoothActivityInfoCache {
@@ -13660,7 +13658,6 @@
mCameraOnTimer.readSummaryFromParcelLocked(in);
mBluetoothScanNesting = 0;
mBluetoothScanTimer.readSummaryFromParcelLocked(in);
- mIsCellularTxPowerHigh = false;
int NRPMS = in.readInt();
if (NRPMS > 10000) {
@@ -14644,7 +14641,6 @@
mCameraOnTimer = new StopwatchTimer(mClocks, null, -13, null, mOnBatteryTimeBase, in);
mBluetoothScanNesting = 0;
mBluetoothScanTimer = new StopwatchTimer(mClocks, null, -14, null, mOnBatteryTimeBase, in);
- mIsCellularTxPowerHigh = false;
mDischargeUnplugLevel = in.readInt();
mDischargePlugLevel = in.readInt();
mDischargeCurrentLevel = in.readInt();
diff --git a/core/java/com/android/internal/util/ScreenshotHelper.java b/core/java/com/android/internal/util/ScreenshotHelper.java
index 7fd94c6..cac691c 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.UserHandle;
import android.util.Log;
+import java.util.function.Consumer;
+
public class ScreenshotHelper {
private static final String TAG = "ScreenshotHelper";
@@ -34,17 +37,58 @@
}
/**
- * Request a screenshot be taken.
+ * Request a screenshot be taken with a specific timeout.
*
- * @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 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, @NonNull Handler handler,
+ @Nullable Consumer<Boolean> completionConsumer) {
+ takeScreenshot(screenshotType, hasStatus, hasNav, SCREENSHOT_TIMEOUT_MS, handler,
+ completionConsumer);
+ }
+
+ /**
+ * Request a screenshot be taken.
+ *
+ * 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, long timeoutMs, @NonNull Handler handler,
+ @Nullable Consumer<Boolean> completionConsumer) {
synchronized (mScreenshotLock) {
if (mScreenshotConnection != null) {
return;
@@ -54,7 +98,8 @@
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 @@
notifyScreenshotError();
}
}
+ if (completionConsumer != null) {
+ completionConsumer.accept(false);
+ }
}
};
@@ -86,15 +134,22 @@
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 @@
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/java/com/android/internal/util/XmlUtils.java b/core/java/com/android/internal/util/XmlUtils.java
index 344d7ef..8799e3d 100644
--- a/core/java/com/android/internal/util/XmlUtils.java
+++ b/core/java/com/android/internal/util/XmlUtils.java
@@ -26,6 +26,8 @@
import android.util.Base64;
import android.util.Xml;
+import libcore.util.HexEncoding;
+
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
@@ -396,16 +398,7 @@
final int N = val.length;
out.attribute(null, "num", Integer.toString(N));
- StringBuilder sb = new StringBuilder(val.length*2);
- for (int i=0; i<N; i++) {
- int b = val[i];
- int h = (b >> 4) & 0x0f;
- sb.append((char)(h >= 10 ? ('a'+h-10) : ('0'+h)));
- h = b & 0x0f;
- sb.append((char)(h >= 10 ? ('a'+h-10) : ('0'+h)));
- }
-
- out.text(sb.toString());
+ out.text(HexEncoding.encodeToString(val).toLowerCase());
out.endTag(null, "byte-array");
}
@@ -1032,7 +1025,9 @@
"Not a number in num attribute in byte-array");
}
- byte[] array = new byte[num];
+ // 0 len byte array does not have a text in the XML tag. So, initialize to 0 len array.
+ // For all other array lens, HexEncoding.decode() below overrides the array.
+ byte[] array = new byte[0];
int eventType = parser.getEventType();
do {
@@ -1043,16 +1038,7 @@
throw new XmlPullParserException(
"Invalid value found in byte-array: " + values);
}
- // This is ugly, but keeping it to mirror the logic in #writeByteArrayXml.
- for (int i = 0; i < num; i ++) {
- char nibbleHighChar = values.charAt(2 * i);
- char nibbleLowChar = values.charAt(2 * i + 1);
- int nibbleHigh = nibbleHighChar > 'a' ? (nibbleHighChar - 'a' + 10)
- : (nibbleHighChar - '0');
- int nibbleLow = nibbleLowChar > 'a' ? (nibbleLowChar - 'a' + 10)
- : (nibbleLowChar - '0');
- array[i] = (byte) ((nibbleHigh & 0x0F) << 4 | (nibbleLow & 0x0F));
- }
+ array = HexEncoding.decode(values);
}
} else if (eventType == parser.END_TAG) {
if (parser.getName().equals(endTag)) {
diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java
index 9fc79cb..510b321 100644
--- a/core/java/com/android/server/SystemConfig.java
+++ b/core/java/com/android/server/SystemConfig.java
@@ -53,6 +53,8 @@
/**
* Loads global system configuration info.
+ * Note: Initializing this class hits the disk and is slow. This class should generally only be
+ * accessed by the system_server process.
*/
public class SystemConfig {
static final String TAG = "SystemConfig";
@@ -209,6 +211,11 @@
private final ArraySet<String> mBugreportWhitelistedPackages = new ArraySet<>();
public static SystemConfig getInstance() {
+ if (!isSystemProcess()) {
+ Slog.wtf(TAG, "SystemConfig is being accessed by a process other than "
+ + "system_server.");
+ }
+
synchronized (SystemConfig.class) {
if (sInstance == null) {
sInstance = new SystemConfig();
@@ -1154,4 +1161,8 @@
mSplitPermissions.add(new SplitPermissionInfo(splitPerm, newPermissions, targetSdk));
}
}
+
+ private static boolean isSystemProcess() {
+ return Process.myUid() == Process.SYSTEM_UID;
+ }
}
diff --git a/core/jni/android_hardware_input_InputWindowHandle.cpp b/core/jni/android_hardware_input_InputWindowHandle.cpp
index a1d1d4f..57d1649 100644
--- a/core/jni/android_hardware_input_InputWindowHandle.cpp
+++ b/core/jni/android_hardware_input_InputWindowHandle.cpp
@@ -28,6 +28,7 @@
#include "android_hardware_input_InputWindowHandle.h"
#include "android_hardware_input_InputApplicationHandle.h"
#include "android_util_Binder.h"
+#include <binder/IPCThreadState.h>
namespace android {
@@ -78,6 +79,12 @@
NativeInputWindowHandle::~NativeInputWindowHandle() {
JNIEnv* env = AndroidRuntime::getJNIEnv();
env->DeleteWeakGlobalRef(mObjWeak);
+
+ // Clear the weak reference to the layer handle and flush any binder ref count operations so we
+ // do not hold on to any binder references.
+ // TODO(b/139697085) remove this after it can be flushed automatically
+ mInfo.touchableRegionCropHandle.clear();
+ IPCThreadState::self()->flushCommands();
}
jobject NativeInputWindowHandle::getInputWindowHandleObjLocalRef(JNIEnv* env) {
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index a10300e..b60f6e9 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -1294,10 +1294,8 @@
<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>
- <!-- no translation found for wifi_suggestion_title (9099832833531486167) -->
- <skip />
- <!-- no translation found for wifi_suggestion_content (5883181205841582873) -->
- <skip />
+ <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>
diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml
index a531355..b6f6674 100644
--- a/core/res/res/values-en-rXC/strings.xml
+++ b/core/res/res/values-en-rXC/strings.xml
@@ -1294,10 +1294,8 @@
<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>
- <!-- no translation found for wifi_suggestion_title (9099832833531486167) -->
- <skip />
- <!-- no translation found for wifi_suggestion_content (5883181205841582873) -->
- <skip />
+ <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>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index efc943e..f8c8f5b 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -4284,4 +4284,9 @@
<!-- The list of packages to automatically opt out of refresh rates higher than 60hz because
of known compatibility issues. -->
<string-array name="config_highRefreshRateBlacklist"></string-array>
+
+ <!-- Whether or not to hide the navigation bar when the soft keyboard is visible in order to
+ create additional screen real estate outside beyond the keyboard. Note that the user needs
+ to have a confirmed way to dismiss the keyboard when desired. -->
+ <bool name="config_automotiveHideNavBarForKeyboard">false</bool>
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index b4edc4d..b35a9e9 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3390,13 +3390,13 @@
<string name="wifi_available_action_all_networks">All networks</string>
<!-- Notification title for a connection to a app suggested wireless network.-->
- <string name="wifi_suggestion_title">Connect to Wi\u2011Fi networks?</string>
+ <string name="wifi_suggestion_title">Allow suggested Wi\u2011Fi networks?</string>
<!-- Notification content for a connection to a app suggested wireless network.-->
- <string name="wifi_suggestion_content">Suggested by <xliff:g id="name" example="App123">%s</xliff:g></string>
+ <string name="wifi_suggestion_content"><xliff:g id="name" example="App123">%s</xliff:g> suggested networks. Device may connect automatically. </string>
<!-- Notification action for allowing app specified in the notification body.-->
- <string name="wifi_suggestion_action_allow_app">Yes</string>
+ <string name="wifi_suggestion_action_allow_app">Allow</string>
<!-- Notification action for disallowing app specified in the notification body.-->
- <string name="wifi_suggestion_action_disallow_app">No</string>
+ <string name="wifi_suggestion_action_disallow_app">No thanks</string>
<!--Notification title for Wi-Fi Wake onboarding. This is displayed the first time a user disables Wi-Fi with the feature enabled. -->
<string name="wifi_wakeup_onboarding_title">Wi\u2011Fi will turn on automatically</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index e5805fd..c419a9d 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3842,4 +3842,5 @@
<java-symbol type="drawable" name="android_logotype" />
<java-symbol type="layout" name="platlogo_layout" />
+ <java-symbol type="bool" name="config_automotiveHideNavBarForKeyboard" />
</resources>
diff --git a/core/tests/screenshothelpertests/Android.bp b/core/tests/screenshothelpertests/Android.bp
new file mode 100644
index 0000000..3d54b68
--- /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 0000000..2e12ef4
--- /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 0000000..8483645
--- /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/core/tests/utiltests/src/com/android/internal/util/XmlUtilsTest.java b/core/tests/utiltests/src/com/android/internal/util/XmlUtilsTest.java
index 2596ece..27f3596 100644
--- a/core/tests/utiltests/src/com/android/internal/util/XmlUtilsTest.java
+++ b/core/tests/utiltests/src/com/android/internal/util/XmlUtilsTest.java
@@ -16,13 +16,22 @@
package com.android.internal.util;
+import static org.junit.Assert.assertArrayEquals;
+
+import android.util.Xml;
+
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
+
import junit.framework.TestCase;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlSerializer;
+
public class XmlUtilsTest extends TestCase {
// https://code.google.com/p/android/issues/detail?id=63717
@@ -38,4 +47,23 @@
assertEquals("nullValue", deserialized.get(null));
assertEquals("fooValue", deserialized.get("foo"));
}
+
+ public void testreadWriteXmlByteArrayValue() throws Exception {
+ byte[] testByteArray = {0x1 , 0xa, 0xb, 0x9, 0x34, (byte) 0xaa, (byte) 0xba, (byte) 0x99};
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
+ XmlSerializer serializer = new FastXmlSerializer();
+ serializer.setOutput(baos, StandardCharsets.UTF_8.name());
+ serializer.startDocument(null, true);
+ XmlUtils.writeValueXml(testByteArray, "testByteArray", serializer);
+ serializer.endDocument();
+
+ InputStream bais = new ByteArrayInputStream(baos.toByteArray());
+ XmlPullParser pullParser = Xml.newPullParser();
+ pullParser.setInput(bais, StandardCharsets.UTF_8.name());
+ String[] name = new String[1];
+ byte[] testByteArrayDeserialized = (byte[]) XmlUtils.readValueXml(pullParser, name);
+ assertEquals("testByteArray", name[0]);
+ assertArrayEquals(testByteArray, testByteArrayDeserialized);
+ }
}
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index b9945cc..e6eaa696 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -207,7 +207,7 @@
}
public GradientDrawable() {
- this(new GradientState(Orientation.TOP_BOTTOM, null), null);
+ this(new GradientState(Orientation.LEFT_RIGHT, null), null);
}
/**
diff --git a/media/jni/android_media_ImageWriter.cpp b/media/jni/android_media_ImageWriter.cpp
index cfcba76..7a0eeee 100644
--- a/media/jni/android_media_ImageWriter.cpp
+++ b/media/jni/android_media_ImageWriter.cpp
@@ -26,6 +26,7 @@
#include <gui/IProducerListener.h>
#include <gui/Surface.h>
+#include <ui/PublicFormat.h>
#include <android_runtime/AndroidRuntime.h>
#include <android_runtime/android_view_Surface.h>
#include <android_runtime/android_hardware_HardwareBuffer.h>
@@ -126,7 +127,7 @@
Condition mCondition;
std::deque<wp<Surface>> mQueue;
- static const nsecs_t kWaitDuration = 20000000; // 20 ms
+ static const nsecs_t kWaitDuration = 500000000; // 500 ms
};
sp<DetachThread> mThread;
@@ -401,8 +402,28 @@
return 0;
}
} else {
+ // Set consumer buffer format to user specified format
+ PublicFormat publicFormat = static_cast<PublicFormat>(userFormat);
+ int nativeFormat = mapPublicFormatToHalFormat(publicFormat);
+ android_dataspace nativeDataspace = mapPublicFormatToHalDataspace(publicFormat);
+ res = native_window_set_buffers_format(anw.get(), nativeFormat);
+ if (res != OK) {
+ ALOGE("%s: Unable to configure consumer native buffer format to %#x",
+ __FUNCTION__, nativeFormat);
+ jniThrowRuntimeException(env, "Failed to set Surface format");
+ return 0;
+ }
+
+ res = native_window_set_buffers_data_space(anw.get(), nativeDataspace);
+ if (res != OK) {
+ ALOGE("%s: Unable to configure consumer dataspace %#x",
+ __FUNCTION__, nativeDataspace);
+ jniThrowRuntimeException(env, "Failed to set Surface dataspace");
+ return 0;
+ }
surfaceFormat = userFormat;
}
+
ctx->setBufferFormat(surfaceFormat);
env->SetIntField(thiz,
gImageWriterClassInfo.mWriterFormat, reinterpret_cast<jint>(surfaceFormat));
diff --git a/packages/CarSystemUI/Android.bp b/packages/CarSystemUI/Android.bp
index 589623b..bbae9ff 100644
--- a/packages/CarSystemUI/Android.bp
+++ b/packages/CarSystemUI/Android.bp
@@ -26,8 +26,8 @@
],
static_libs: [
- "CarNotificationLib",
"SystemUI-core",
+ "CarNotificationLib",
"SystemUIPluginLib",
"SystemUISharedLib",
"SettingsLib",
@@ -47,6 +47,8 @@
"androidx.lifecycle_lifecycle-extensions",
"SystemUI-tags",
"SystemUI-proto",
+ "dagger2-2.19",
+ "//external/kotlinc:kotlin-annotations",
],
libs: [
diff --git a/packages/CarSystemUI/AndroidManifest.xml b/packages/CarSystemUI/AndroidManifest.xml
index 195d4fe..261b9f5 100644
--- a/packages/CarSystemUI/AndroidManifest.xml
+++ b/packages/CarSystemUI/AndroidManifest.xml
@@ -21,4 +21,8 @@
coreApp="true">
<!-- This permission is required to monitor car power state. -->
<uses-permission android:name="android.car.permission.CAR_POWER" />
+ <!-- This permission is required to get the trusted device list of a user. -->
+ <uses-permission android:name="android.car.permission.CAR_ENROLL_TRUST"/>
+ <!-- This permission is required to get bluetooth broadcast. -->
+ <uses-permission android:name="android.permission.BLUETOOTH" />
</manifest>
diff --git a/packages/CarSystemUI/res/drawable/unlock_dialog_background.xml b/packages/CarSystemUI/res/drawable/unlock_dialog_background.xml
new file mode 100644
index 0000000..bec6ba7
--- /dev/null
+++ b/packages/CarSystemUI/res/drawable/unlock_dialog_background.xml
@@ -0,0 +1,26 @@
+<?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
+ -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+ <solid android:color="@color/unlock_dialog_background_color"/>
+ <padding
+ android:bottom="@*android:dimen/car_padding_2"
+ android:left="@*android:dimen/car_padding_2"
+ android:right="@*android:dimen/car_padding_2"
+ android:top="@*android:dimen/car_padding_2"/>
+ <corners
+ android:radius="@dimen/unlock_dialog_radius"/>
+</shape>
\ No newline at end of file
diff --git a/packages/CarSystemUI/res/layout/trust_agent_unlock_dialog.xml b/packages/CarSystemUI/res/layout/trust_agent_unlock_dialog.xml
new file mode 100644
index 0000000..9df78f1
--- /dev/null
+++ b/packages/CarSystemUI/res/layout/trust_agent_unlock_dialog.xml
@@ -0,0 +1,73 @@
+<?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/unlock_dialog_parent"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="center">
+
+ <LinearLayout
+ android:id="@+id/unlock_dialog"
+ android:layout_width="@dimen/unlock_dialog_width"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:layout_gravity="center"
+ android:orientation="vertical"
+ android:background="@drawable/unlock_dialog_background"
+ android:padding="@*android:dimen/car_padding_2">
+ <FrameLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+ <ProgressBar
+ android:layout_gravity="center"
+ android:layout_width="@dimen/unlock_dialog_progress_bar_size"
+ android:layout_height="@dimen/unlock_dialog_progress_bar_size" />
+ <ImageView
+ android:id="@+id/avatar"
+ android:layout_gravity="center"
+ android:layout_width="@dimen/unlock_dialog_avatar_size"
+ android:layout_height="@dimen/unlock_dialog_avatar_size"
+ android:scaleType="fitCenter"/>
+ </FrameLayout>
+
+ <TextView
+ android:id="@+id/user_name"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:text="@string/unlock_dialog_default_user_name"
+ android:textSize="@*android:dimen/car_body1_size"
+ android:textColor="@android:color/white"/>
+
+ <TextView
+ android:id="@+id/unlocking_text"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_marginTop="@*android:dimen/car_padding_1"
+ android:text="@string/unlock_dialog_message_default"
+ android:textSize="@*android:dimen/car_body4_size"
+ android:textColor="@color/unlock_dialog_message_text_default"/>
+
+ <Button
+ android:id="@+id/enter_pin_button"
+ android:layout_marginTop="@*android:dimen/car_padding_1"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:text="@string/unlock_dialog_button_text_pin"
+ style="@style/UnlockDialogButton"/>
+ </LinearLayout>
+</FrameLayout>
\ No newline at end of file
diff --git a/packages/CarSystemUI/res/values/colors_car.xml b/packages/CarSystemUI/res/values/colors_car.xml
index 69ab3f3..0a3f7aa 100644
--- a/packages/CarSystemUI/res/values/colors_car.xml
+++ b/packages/CarSystemUI/res/values/colors_car.xml
@@ -26,4 +26,9 @@
<color name="car_user_switcher_add_user_background_color">@*android:color/car_dark_blue_grey_600</color>
<color name="car_user_switcher_add_user_add_sign_color">@*android:color/car_body1_light</color>
+ <!-- colors for unlock dialog -->
+ <color name="unlock_dialog_background_color">#ff282a2d</color>
+ <color name="unlock_dialog_message_text_default">@*android:color/car_grey_400</color>
+ <color name="unlock_dialog_enter_pin_text_color">#ff66b5ff</color>
+
</resources>
diff --git a/packages/CarSystemUI/res/values/dimens_car.xml b/packages/CarSystemUI/res/values/dimens_car.xml
index 42a7649..9cb09c9 100644
--- a/packages/CarSystemUI/res/values/dimens_car.xml
+++ b/packages/CarSystemUI/res/values/dimens_car.xml
@@ -43,4 +43,10 @@
<!-- This must be the negative of car_user_switcher_container_height for the animation. -->
<dimen name="car_user_switcher_container_anim_height">-420dp</dimen>
+ <!-- dimensions for the unlock dialog -->
+ <dimen name="unlock_dialog_width">500dp</dimen>
+ <dimen name="unlock_dialog_radius">16dp</dimen>
+ <dimen name="unlock_dialog_avatar_size">100dp</dimen>
+ <dimen name="unlock_dialog_progress_bar_size">140dp</dimen>
+
</resources>
diff --git a/packages/CarSystemUI/res/values/integers_car.xml b/packages/CarSystemUI/res/values/integers_car.xml
index be2cb0d..fb67b30 100644
--- a/packages/CarSystemUI/res/values/integers_car.xml
+++ b/packages/CarSystemUI/res/values/integers_car.xml
@@ -31,5 +31,7 @@
<!--Percentage of the screen height, from the bottom, that a notification panel being peeked
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">0</integer>
</resources>
diff --git a/packages/CarSystemUI/res/values/strings_car.xml b/packages/CarSystemUI/res/values/strings_car.xml
index 83e91c5..717692e 100644
--- a/packages/CarSystemUI/res/values/strings_car.xml
+++ b/packages/CarSystemUI/res/values/strings_car.xml
@@ -29,4 +29,19 @@
<string name="user_add_user_message_setup">When you add a new user, that person needs to set up their space.</string>
<!-- Message to inform user that the newly created user will have permissions to update apps for all other users. [CHAR LIMIT=100] -->
<string name="user_add_user_message_update">Any user can update apps for all other users.</string>
+ <!-- Default messages displayed on the unlock dialog before unlock advertising started. [CHAR LIMIT=30]-->
+ <string name="unlock_dialog_message_default">Waiting\u2026</string>
+ <!-- Message to inform user that the IHU is looking for trusted device. [CHAR LIMIT=30] -->
+ <string name="unlock_dialog_message_start">Looking for trusted device\u2026</string>
+
+ <!-- Cancel Button text for user who has PIN as security lock. [CHAR LIMIT=30] -->
+ <string name="unlock_dialog_button_text_pin">Enter PIN instead</string>
+ <!-- Cancel Button text for user who has Pattern as security lock. [CHAR LIMIT=30] -->
+ <string name="unlock_dialog_button_text_pattern">Enter Pattern instead</string>
+ <!-- Cancel Button text for user who has Password as security lock. [CHAR LIMIT=30] -->
+ <string name="unlock_dialog_button_text_password">Enter Password instead</string>
+ <!-- Default user name shows on unlock dialog -->
+ <string name="unlock_dialog_default_user_name">Default Name</string>
+ <!-- Default title for unlock dialog -->
+ <string name="unlock_dialog_title">Unlock Dialogue</string>
</resources>
diff --git a/packages/CarSystemUI/res/values/styles.xml b/packages/CarSystemUI/res/values/styles.xml
index 371bebd..a9423bf 100644
--- a/packages/CarSystemUI/res/values/styles.xml
+++ b/packages/CarSystemUI/res/values/styles.xml
@@ -46,4 +46,12 @@
<item name="android:layout_width">96dp</item>
<item name="android:background">@drawable/nav_button_background</item>
</style>
+
+ <style name="UnlockDialogButton">
+ <item name="android:background">?android:attr/selectableItemBackground</item>
+ <item name="android:textAlignment">center</item>
+ <item name="android:textColor">@color/unlock_dialog_enter_pin_text_color</item>
+ <item name="android:paddingHorizontal">16dp</item>
+ <item name="android:textAllCaps">false</item>
+ </style>
</resources>
\ No newline at end of file
diff --git a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIFactory.java b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIFactory.java
index 3b278b4..c7654e8 100644
--- a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIFactory.java
+++ b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIFactory.java
@@ -20,12 +20,8 @@
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.ViewMediatorCallback;
-import com.android.systemui.car.CarNotificationEntryManager;
-import com.android.systemui.car.CarNotificationInterruptionStateProvider;
import com.android.systemui.statusbar.car.CarFacetButtonController;
import com.android.systemui.statusbar.car.CarStatusBarKeyguardViewManager;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
-import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.volume.CarVolumeDialogComponent;
import com.android.systemui.volume.VolumeDialogComponent;
@@ -33,8 +29,6 @@
import javax.inject.Singleton;
import dagger.Component;
-import dagger.Module;
-import dagger.Provides;
/**
* Class factory to provide car specific SystemUI components.
@@ -44,11 +38,14 @@
private CarDependencyComponent mCarDependencyComponent;
@Override
- protected void init(Context context) {
- super.init(context);
+ protected SystemUIRootComponent buildSystemUIRootComponent(Context context) {
mCarDependencyComponent = DaggerCarSystemUIFactory_CarDependencyComponent.builder()
.contextHolder(new ContextHolder(context))
.build();
+ return DaggerCarSystemUIRootComponent.builder()
+ .dependencyProvider(new com.android.systemui.DependencyProvider())
+ .contextHolder(new ContextHolder(context))
+ .build();
}
public CarDependencyComponent getCarDependencyComponent() {
@@ -64,42 +61,9 @@
return new CarVolumeDialogComponent(systemUi, context);
}
- @Override
- public NotificationInterruptionStateProvider provideNotificationInterruptionStateProvider(
- Context context) {
- return new CarNotificationInterruptionStateProvider(context);
- }
-
- @Override
- public boolean provideAllowNotificationLongPress() {
- return false;
- }
-
- @Module
- protected static class ContextHolder {
- private Context mContext;
-
- public ContextHolder(Context context) {
- mContext = context;
- }
-
- @Provides
- public Context provideContext() {
- return mContext;
- }
- }
-
@Singleton
@Component(modules = ContextHolder.class)
public interface CarDependencyComponent {
CarFacetButtonController getCarFacetButtonController();
}
-
- /**
- * Use {@link CarNotificationEntryManager}, which does nothing when adding a notification.
- */
- @Singleton
- public NotificationEntryManager provideNotificationEntryManager(Context context) {
- return new CarNotificationEntryManager(context);
- }
}
diff --git a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
new file mode 100644
index 0000000..9a063aa
--- /dev/null
+++ b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
@@ -0,0 +1,97 @@
+/*
+ * 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 static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME;
+import static com.android.systemui.Dependency.LEAK_REPORT_EMAIL_NAME;
+
+import android.content.Context;
+
+import com.android.systemui.car.CarNotificationEntryManager;
+import com.android.systemui.car.CarNotificationInterruptionStateProvider;
+import com.android.systemui.dock.DockManager;
+import com.android.systemui.dock.DockManagerImpl;
+import com.android.systemui.power.EnhancedEstimates;
+import com.android.systemui.power.EnhancedEstimatesImpl;
+import com.android.systemui.statusbar.NotificationLockscreenUserManager;
+import com.android.systemui.statusbar.NotificationLockscreenUserManagerImpl;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
+import com.android.systemui.statusbar.notification.collection.NotificationData;
+import com.android.systemui.statusbar.phone.KeyguardEnvironmentImpl;
+import com.android.systemui.statusbar.phone.ShadeController;
+import com.android.systemui.statusbar.phone.StatusBar;
+
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import dagger.Binds;
+import dagger.Module;
+import dagger.Provides;
+
+@Module
+abstract class CarSystemUIModule {
+
+ @Binds
+ abstract NotificationInterruptionStateProvider bindNotificationInterruptionStateProvider(
+ CarNotificationInterruptionStateProvider notificationInterruptionStateProvider);
+
+ @Singleton
+ @Provides
+ @Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME)
+ static boolean provideAllowNotificationLongPress() {
+ return false;
+ }
+
+ /**
+ * Use {@link CarNotificationEntryManager}, which does nothing when adding a notification.
+ */
+ @Binds
+ abstract NotificationEntryManager bindNotificationEntryManager(
+ CarNotificationEntryManager notificationEntryManager);
+
+ @Singleton
+ @Provides
+ @Named(LEAK_REPORT_EMAIL_NAME)
+ static String provideLeakReportEmail() {
+ return "buganizer-system+181579@google.com";
+ }
+
+ @Binds
+ abstract EnhancedEstimates bindEnhancedEstimates(EnhancedEstimatesImpl enhancedEstimates);
+
+ @Binds
+ abstract NotificationLockscreenUserManager bindNotificationLockscreenUserManager(
+ NotificationLockscreenUserManagerImpl notificationLockscreenUserManager);
+
+ @Binds
+ abstract DockManager bindDockManager(DockManagerImpl dockManager);
+
+ @Binds
+ abstract NotificationData.KeyguardEnvironment bindKeyguardEnvironment(
+ KeyguardEnvironmentImpl keyguardEnvironment);
+
+ @Singleton
+ @Provides
+ static ShadeController provideShadeController(Context context) {
+ return SysUiServiceProvider.getComponent(context, StatusBar.class);
+ }
+
+ @Binds
+ abstract SystemUIRootComponent bindSystemUIRootComponent(
+ CarSystemUIRootComponent systemUIRootComponent);
+}
diff --git a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIRootComponent.java b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIRootComponent.java
new file mode 100644
index 0000000..d6b766b
--- /dev/null
+++ b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIRootComponent.java
@@ -0,0 +1,35 @@
+/*
+ * 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 javax.inject.Singleton;
+
+import dagger.Component;
+
+@Singleton
+@Component(
+ modules = {
+ DependencyProvider.class,
+ DependencyBinder.class,
+ ServiceBinder.class,
+ SystemUIFactory.ContextHolder.class,
+ SystemUIModule.class,
+ CarSystemUIModule.class
+ })
+interface CarSystemUIRootComponent extends SystemUIRootComponent {
+
+}
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/CarNotificationEntryManager.java b/packages/CarSystemUI/src/com/android/systemui/car/CarNotificationEntryManager.java
index 6d9c7ba..a107dd7 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/CarNotificationEntryManager.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/CarNotificationEntryManager.java
@@ -21,13 +21,19 @@
import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
/**
* Car specific notification entry manager that does nothing when adding a notification.
*
* <p> This is because system UI notifications are disabled and we have a different implementation.
* Please see {@link com.android.car.notification}.
*/
+@Singleton
public class CarNotificationEntryManager extends NotificationEntryManager {
+
+ @Inject
public CarNotificationEntryManager(Context context) {
super(context);
}
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/CarNotificationInterruptionStateProvider.java b/packages/CarSystemUI/src/com/android/systemui/car/CarNotificationInterruptionStateProvider.java
index 6d960d7..ec40cc3 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/CarNotificationInterruptionStateProvider.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/CarNotificationInterruptionStateProvider.java
@@ -21,9 +21,15 @@
import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
/** Auto-specific implementation of {@link NotificationInterruptionStateProvider}. */
+@Singleton
public class CarNotificationInterruptionStateProvider extends
NotificationInterruptionStateProvider {
+
+ @Inject
public CarNotificationInterruptionStateProvider(Context context) {
super(context);
}
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index 2874ce6..2a55ff0 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -26,11 +26,15 @@
import android.car.drivingstate.CarDrivingStateEvent;
import android.car.drivingstate.CarUxRestrictionsManager;
import android.car.hardware.power.CarPowerManager.CarPowerStateListener;
+import android.car.trust.CarTrustAgentEnrollmentManager;
import android.content.Context;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
+import android.inputmethodservice.InputMethodService;
+import android.os.IBinder;
import android.util.Log;
+import android.view.Display;
import android.view.GestureDetector;
import android.view.Gravity;
import android.view.MotionEvent;
@@ -61,9 +65,9 @@
import com.android.systemui.R;
import com.android.systemui.SystemUIFactory;
import com.android.systemui.classifier.FalsingLog;
-import com.android.systemui.classifier.FalsingManagerFactory;
import com.android.systemui.fragments.FragmentHostManager;
import com.android.systemui.keyguard.ScreenLifecycle;
+import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.qs.car.CarQSFragment;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -85,8 +89,7 @@
/**
* A status bar (and navigation bar) tailored for the automotive use case.
*/
-public class CarStatusBar extends StatusBar implements
- CarBatteryController.BatteryViewHandler {
+public class CarStatusBar extends StatusBar implements CarBatteryController.BatteryViewHandler {
private static final String TAG = "CarStatusBar";
// used to calculate how fast to open or close the window
private static final float DEFAULT_FLING_VELOCITY = 0;
@@ -167,6 +170,9 @@
private boolean mIsSwipingVerticallyToClose;
// Whether heads-up notifications should be shown when shade is open.
private boolean mEnableHeadsUpNotificationWhenNotificationShadeOpen;
+ // If the nav bar should be hidden when the soft keyboard is visible.
+ private boolean mHideNavBarForKeyboard;
+ private boolean mBottomNavBarVisible;
private final CarPowerStateListener mCarPowerStateListener =
(int state) -> {
@@ -188,6 +194,12 @@
// builds the nav bar
mDeviceProvisionedController = Dependency.get(DeviceProvisionedController.class);
mDeviceIsProvisioned = mDeviceProvisionedController.isDeviceProvisioned();
+
+ // Keyboard related setup, before nav bars are created.
+ mHideNavBarForKeyboard = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_automotiveHideNavBarForKeyboard);
+ mBottomNavBarVisible = false;
+
super.start();
mTaskStackListener = new TaskStackListenerImpl();
mActivityManagerWrapper = ActivityManagerWrapper.getInstance();
@@ -718,6 +730,13 @@
buildNavBarContent();
attachNavBarWindows();
+ // Try setting up the initial state of the nav bar if applicable.
+ if (result != null) {
+ setImeWindowStatus(Display.DEFAULT_DISPLAY, result.mImeToken,
+ result.mImeWindowVis, result.mImeBackDisposition,
+ result.mShowImeSwitcher);
+ }
+
// There has been a car customized nav bar on the default display, so just create nav bars
// on external displays.
mNavigationBarController.createNavigationBars(false /* includeDefaultDisplay */, result);
@@ -756,22 +775,33 @@
}
- private void attachNavBarWindows() {
-
- if (mShowBottom) {
- WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
- LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
- WindowManager.LayoutParams.TYPE_NAVIGATION_BAR,
- WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
- | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
- | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
- | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
- PixelFormat.TRANSLUCENT);
- lp.setTitle("CarNavigationBar");
- lp.windowAnimations = 0;
- mWindowManager.addView(mNavigationBarWindow, lp);
+ /**
+ * We register for soft keyboard visibility events such that we can hide the navigation bar
+ * giving more screen space to the IME. Note: this is optional and controlled by
+ * {@code com.android.internal.R.bool.config_automotiveHideNavBarForKeyboard}.
+ */
+ @Override
+ public void setImeWindowStatus(int displayId, IBinder token, int vis, int backDisposition,
+ boolean showImeSwitcher) {
+ if (!mHideNavBarForKeyboard) {
+ return;
}
+ if (mContext.getDisplay().getDisplayId() != displayId) {
+ return;
+ }
+
+ boolean isKeyboardVisible = (vis & InputMethodService.IME_VISIBLE) != 0;
+ if (!isKeyboardVisible) {
+ attachBottomNavBarWindow();
+ } else {
+ detachBottomNavBarWindow();
+ }
+ }
+
+ private void attachNavBarWindows() {
+ attachBottomNavBarWindow();
+
if (mShowLeft) {
int width = mContext.getResources().getDimensionPixelSize(
R.dimen.car_left_navigation_bar_width);
@@ -806,7 +836,49 @@
rightlp.gravity = Gravity.RIGHT;
mWindowManager.addView(mRightNavigationBarWindow, rightlp);
}
+ }
+ /**
+ * Attaches the bottom nav bar window. Can be extended to modify the specific behavior of
+ * attaching the bottom nav bar.
+ */
+ protected void attachBottomNavBarWindow() {
+ if (!mShowBottom) {
+ return;
+ }
+
+ if (mBottomNavBarVisible) {
+ return;
+ }
+ mBottomNavBarVisible = true;
+
+ WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
+ LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
+ WindowManager.LayoutParams.TYPE_NAVIGATION_BAR,
+ WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+ | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+ | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
+ | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
+ PixelFormat.TRANSLUCENT);
+ lp.setTitle("CarNavigationBar");
+ lp.windowAnimations = 0;
+ mWindowManager.addView(mNavigationBarWindow, lp);
+ }
+
+ /**
+ * Detaches the bottom nav bar window. Can be extended to modify the specific behavior of
+ * detaching the bottom nav bar.
+ */
+ protected void detachBottomNavBarWindow() {
+ if (!mShowBottom) {
+ return;
+ }
+
+ if (!mBottomNavBarVisible) {
+ return;
+ }
+ mBottomNavBarVisible = false;
+ mWindowManager.removeView(mNavigationBarWindow);
}
private void buildBottomBar(int layout) {
@@ -877,7 +949,7 @@
KeyguardUpdateMonitor.getInstance(mContext).dump(fd, pw, args);
}
- FalsingManagerFactory.getInstance(mContext).dump(pw);
+ Dependency.get(FalsingManager.class).dump(pw);
FalsingLog.dump(pw);
pw.println("SharedPreferences:");
@@ -956,8 +1028,12 @@
UserSwitcherController userSwitcherController =
Dependency.get(UserSwitcherController.class);
if (userSwitcherController.useFullscreenUserSwitcher()) {
+ Car car = Car.createCar(mContext);
+ CarTrustAgentEnrollmentManager enrollmentManager = (CarTrustAgentEnrollmentManager) car
+ .getCarManager(Car.CAR_TRUST_AGENT_ENROLLMENT_SERVICE);
mFullscreenUserSwitcher = new FullscreenUserSwitcher(this,
- mStatusBarWindow.findViewById(R.id.fullscreen_user_switcher_stub), mContext);
+ mStatusBarWindow.findViewById(R.id.fullscreen_user_switcher_stub),
+ enrollmentManager, mContext);
} else {
super.createUserSwitcher();
}
@@ -1072,9 +1148,10 @@
// shade is visible to the user. When the notification shade is completely open then
// alpha value will be 1.
float alpha = (float) height / mNotificationView.getHeight();
- Drawable background = mNotificationView.getBackground();
+ Drawable background = mNotificationView.getBackground().mutate();
background.setAlpha((int) (alpha * 255));
+ mNotificationView.setBackground(background);
}
}
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarTrustAgentUnlockDialogHelper.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarTrustAgentUnlockDialogHelper.java
new file mode 100644
index 0000000..ec72ee7
--- /dev/null
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarTrustAgentUnlockDialogHelper.java
@@ -0,0 +1,256 @@
+/*
+ * 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.car;
+
+import android.app.admin.DevicePolicyManager;
+import android.bluetooth.BluetoothAdapter;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.graphics.PixelFormat;
+import android.os.Handler;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.android.internal.widget.LockPatternUtils;
+import com.android.systemui.R;
+
+/**
+ * A helper class displays an unlock dialog and receives broadcast about detecting trusted device
+ * & unlocking state to show the appropriate message on the dialog.
+ */
+class CarTrustAgentUnlockDialogHelper extends BroadcastReceiver{
+ private static final String TAG = CarTrustAgentUnlockDialogHelper.class.getSimpleName();
+
+ private final Context mContext;
+ private final WindowManager mWindowManager;
+ private final UserManager mUserManager;
+ private final WindowManager.LayoutParams mParams;
+ /**
+ * Not using Dialog because context passed from {@link FullscreenUserSwitcher} is not an
+ * activity.
+ */
+ private final View mUnlockDialogLayout;
+ private final TextView mUnlockingText;
+ private final Button mButton;
+ private final IntentFilter mFilter;
+ private int mUid;
+ private boolean mIsDialogShowing;
+ private OnHideListener mOnHideListener;
+
+ CarTrustAgentUnlockDialogHelper(Context context) {
+ mContext = context;
+ mUserManager = mContext.getSystemService(UserManager.class);
+ mWindowManager = mContext.getSystemService(WindowManager.class);
+ mParams = createLayoutParams();
+ mFilter = getIntentFilter();
+
+ mParams.packageName = mContext.getPackageName();
+ mParams.setTitle(mContext.getString(R.string.unlock_dialog_title));
+
+ mUnlockDialogLayout = LayoutInflater.from(mContext).inflate(
+ R.layout.trust_agent_unlock_dialog, null);
+ mUnlockDialogLayout.setLayoutParams(mParams);
+
+ View dialogParent = mUnlockDialogLayout.findViewById(R.id.unlock_dialog_parent);
+ dialogParent.setOnTouchListener((v, event)-> {
+ hideUnlockDialog(/* dismissUserSwitcher= */ false);
+ return true;
+ });
+ View unlockDialog = mUnlockDialogLayout.findViewById(R.id.unlock_dialog);
+ unlockDialog.setOnTouchListener((v, event) -> {
+ // If the person taps inside the unlock dialog, the touch event will be intercepted here
+ // and the dialog will not exit
+ return true;
+ });
+ mUnlockingText = mUnlockDialogLayout.findViewById(R.id.unlocking_text);
+ mButton = mUnlockDialogLayout.findViewById(R.id.enter_pin_button);
+ mButton.setOnClickListener(v -> {
+ hideUnlockDialog(/* dismissUserSwitcher= */true);
+ // TODO(b/138250105) Stop unlock advertising
+ });
+
+ BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
+ if (bluetoothAdapter != null
+ && bluetoothAdapter.getLeState() == BluetoothAdapter.STATE_BLE_ON) {
+ mUnlockingText.setText(R.string.unlock_dialog_message_start);
+ }
+ }
+
+ /**
+ * This filter is listening on:
+ * {@link BluetoothAdapter#ACTION_BLE_STATE_CHANGED} for starting unlock advertising;
+ * {@link Intent#ACTION_USER_UNLOCKED} for IHU unlocked
+ */
+ private IntentFilter getIntentFilter() {
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(BluetoothAdapter.ACTION_BLE_STATE_CHANGED);
+ filter.addAction(Intent.ACTION_USER_UNLOCKED);
+ return filter;
+ }
+
+ /**
+ * Show dialog for the given user
+ */
+ void showUnlockDialog(int uid, OnHideListener listener) {
+ showUnlockDialogAfterDelay(uid, 0, listener);
+ }
+
+ /**
+ * Show dialog for the given user after the certain time of delay has elapsed
+ *
+ * @param uid the user to unlock
+ * @param listener listener that listens to dialog hide
+ */
+ void showUnlockDialogAfterDelay(int uid, OnHideListener listener) {
+ long delayMillis = mContext.getResources().getInteger(R.integer.unlock_dialog_delay_ms);
+ showUnlockDialogAfterDelay(uid, delayMillis, listener);
+ }
+
+ /**
+ * Show dialog for the given user after the supplied delay has elapsed
+ */
+ private void showUnlockDialogAfterDelay(int uid, long delayMillis, OnHideListener listener) {
+ setUid(uid);
+ mOnHideListener = listener;
+ if (!mIsDialogShowing) {
+ logd("Receiver registered");
+ mContext.registerReceiverAsUser(this, UserHandle.ALL, mFilter,
+ /* broadcastPermission= */ null,
+ /* scheduler= */ null);
+ new Handler().postDelayed(() -> {
+ if (!mUserManager.isUserUnlocked(uid)) {
+ logd("Showed unlock dialog for user: " + uid + " after " + delayMillis
+ + " delay.");
+ mWindowManager.addView(mUnlockDialogLayout, mParams);
+ }
+ }, delayMillis);
+ }
+ mIsDialogShowing = true;
+ }
+
+ private void setUid(int uid) {
+ mUid = uid;
+ TextView userName = mUnlockDialogLayout.findViewById(R.id.user_name);
+ userName.setText(mUserManager.getUserInfo(mUid).name);
+ ImageView avatar = mUnlockDialogLayout.findViewById(R.id.avatar);
+ avatar.setImageBitmap(mUserManager.getUserIcon(mUid));
+ setButtonText();
+ }
+
+ private void hideUnlockDialog(boolean dismissUserSwitcher) {
+ if (!mIsDialogShowing) {
+ return;
+ }
+ mWindowManager.removeView(mUnlockDialogLayout);
+ logd("Receiver unregistered");
+ mContext.unregisterReceiver(this);
+ if (mOnHideListener != null) {
+ mOnHideListener.onHide(dismissUserSwitcher);
+ }
+ mIsDialogShowing = false;
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (action == null) {
+ return;
+ }
+ switch (action) {
+ case BluetoothAdapter.ACTION_BLE_STATE_CHANGED:
+ logd("Received ACTION_BLE_STATE_CHANGED");
+ int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1);
+ if (state == BluetoothAdapter.STATE_BLE_ON) {
+ logd("Received BLE_ON");
+ mUnlockingText.setText(R.string.unlock_dialog_message_start);
+ }
+ break;
+ case Intent.ACTION_USER_UNLOCKED:
+ int uid = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
+ if (uid == mUid) {
+ logd("IHU unlocked");
+ hideUnlockDialog(/* notifyOnHideListener= */false);
+ } else {
+ Log.e(TAG, "Received ACTION_USER_UNLOCKED for unexpected uid: " + uid);
+ }
+ break;
+ default:
+ Log.e(TAG, "Encountered unexpected action when attempting to set "
+ + "unlock state message: " + action);
+ }
+ }
+
+ // Set button text based on screen lock type
+ private void setButtonText() {
+ LockPatternUtils lockPatternUtils = new LockPatternUtils(mContext);
+ int passwordQuality = lockPatternUtils.getActivePasswordQuality(mUid);
+ switch (passwordQuality) {
+ // PIN
+ case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
+ case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
+ mButton.setText(R.string.unlock_dialog_button_text_pin);
+ break;
+ // Pattern
+ case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
+ mButton.setText(R.string.unlock_dialog_button_text_pattern);
+ break;
+ // Password
+ case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
+ case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
+ case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
+ mButton.setText(R.string.unlock_dialog_button_text_password);
+ break;
+ default:
+ Log.e(TAG, "Encountered unexpected screen lock type when attempting to set "
+ + "button text:" + passwordQuality);
+ }
+ }
+
+ private WindowManager.LayoutParams createLayoutParams() {
+ return new WindowManager.LayoutParams(
+ WindowManager.LayoutParams.MATCH_PARENT,
+ WindowManager.LayoutParams.MATCH_PARENT,
+ WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG,
+ WindowManager.LayoutParams.FLAG_FULLSCREEN
+ | WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
+ | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION,
+ PixelFormat.TRANSLUCENT
+ );
+ }
+
+ private void logd(String message) {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, message);
+ }
+ }
+
+ /**
+ * Listener used to notify when the dialog is hidden
+ */
+ interface OnHideListener {
+ void onHide(boolean dismissUserSwitcher);
+ }
+}
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
index 0a167d9..0f7c1ee 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
@@ -18,29 +18,61 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
+import android.car.trust.CarTrustAgentEnrollmentManager;
+import android.car.userlib.CarUserManagerHelper;
+import android.content.BroadcastReceiver;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.UserInfo;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.util.Log;
import android.view.View;
import android.view.ViewStub;
import androidx.recyclerview.widget.GridLayoutManager;
import com.android.systemui.R;
+import com.android.systemui.statusbar.car.CarTrustAgentUnlockDialogHelper.OnHideListener;
+import com.android.systemui.statusbar.car.UserGridRecyclerView.UserRecord;
/**
* Manages the fullscreen user switcher.
*/
public class FullscreenUserSwitcher {
+ private static final String TAG = FullscreenUserSwitcher.class.getSimpleName();
+ // Because user 0 is headless, user count for single user is 2
+ private static final int NUMBER_OF_BACKGROUND_USERS = 1;
private final UserGridRecyclerView mUserGridView;
private final View mParent;
private final int mShortAnimDuration;
private final CarStatusBar mStatusBar;
+ private final Context mContext;
+ private final UserManager mUserManager;
+ private final CarTrustAgentEnrollmentManager mEnrollmentManager;
+ private CarTrustAgentUnlockDialogHelper mUnlockDialogHelper;
+ private UserGridRecyclerView.UserRecord mSelectedUser;
+ private CarUserManagerHelper mCarUserManagerHelper;
+ private final BroadcastReceiver mUserUnlockReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "user 0 is unlocked, SharedPreference is accessible.");
+ }
+ showDialogForInitialUser();
+ mContext.unregisterReceiver(mUserUnlockReceiver);
+ }
+ };
- public FullscreenUserSwitcher(CarStatusBar statusBar, ViewStub containerStub, Context context) {
+
+ public FullscreenUserSwitcher(CarStatusBar statusBar, ViewStub containerStub,
+ CarTrustAgentEnrollmentManager enrollmentManager, Context context) {
mStatusBar = statusBar;
mParent = containerStub.inflate();
- // Hide the user grid by default. It will only be made visible by clicking on a cancel
- // button in a bouncer.
- hide();
+ mEnrollmentManager = enrollmentManager;
+ mContext = context;
+
View container = mParent.findViewById(R.id.container);
// Initialize user grid.
@@ -50,9 +82,51 @@
mUserGridView.setLayoutManager(layoutManager);
mUserGridView.buildAdapter();
mUserGridView.setUserSelectionListener(this::onUserSelected);
+ mCarUserManagerHelper = new CarUserManagerHelper(context);
+ mUnlockDialogHelper = new CarTrustAgentUnlockDialogHelper(mContext);
+ mUserManager = mContext.getSystemService(UserManager.class);
mShortAnimDuration = container.getResources()
.getInteger(android.R.integer.config_shortAnimTime);
+ IntentFilter filter = new IntentFilter(Intent.ACTION_USER_UNLOCKED);
+ if (mUserManager.isUserUnlocked(UserHandle.USER_SYSTEM)) {
+ // User0 is unlocked, switched to the initial user
+ showDialogForInitialUser();
+ } else {
+ // listen to USER_UNLOCKED
+ mContext.registerReceiverAsUser(mUserUnlockReceiver,
+ UserHandle.getUserHandleForUid(UserHandle.USER_SYSTEM),
+ filter,
+ /* broadcastPermission= */ null,
+ /* scheduler */ null);
+ }
+ }
+
+ private void showDialogForInitialUser() {
+ int initialUser = mCarUserManagerHelper.getInitialUser();
+ UserInfo initialUserInfo = mUserManager.getUserInfo(initialUser);
+ mSelectedUser = new UserRecord(initialUserInfo,
+ /* isStartGuestSession= */ false,
+ /* isAddUser= */ false,
+ /* isForeground= */ true);
+ // For single user without trusted device, hide the user switcher.
+ if (!hasMultipleUsers() && !hasTrustedDevice(initialUser)) {
+ dismissUserSwitcher();
+ return;
+ }
+ // Show unlock dialog for initial user
+ if (hasTrustedDevice(initialUser)) {
+ mUnlockDialogHelper.showUnlockDialogAfterDelay(initialUser,
+ mOnHideListener);
+ }
+ }
+
+ /**
+ * Check if there is only one possible user to login in.
+ * In a Multi-User system there is always one background user (user 0)
+ */
+ private boolean hasMultipleUsers() {
+ return mUserManager.getUserCount() > NUMBER_OF_BACKGROUND_USERS + 1;
}
/**
@@ -77,14 +151,33 @@
}
/**
- * Every time user clicks on an item in the switcher, we hide the switcher, either
- * gradually or immediately.
+ * Every time user clicks on an item in the switcher, if the clicked user has no trusted device,
+ * we hide the switcher, either gradually or immediately.
*
- * We dismiss the entire keyguard if user clicked on the foreground user (user we're already
- * logged in as).
+ * If the user has trusted device, we show an unlock dialog to notify user the unlock state.
+ * When the unlock dialog is dismissed by user, we hide the unlock dialog and the switcher.
+ *
+ * We dismiss the entire keyguard when we hide the switcher if user clicked on the foreground
+ * user (user we're already logged in as).
*/
private void onUserSelected(UserGridRecyclerView.UserRecord record) {
- if (record.mIsForeground) {
+ mSelectedUser = record;
+ if (hasTrustedDevice(record.mInfo.id)) {
+ mUnlockDialogHelper.showUnlockDialog(record.mInfo.id, mOnHideListener);
+ return;
+ }
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "no trusted device enrolled for uid: " + record.mInfo.id);
+ }
+ dismissUserSwitcher();
+ }
+
+ private void dismissUserSwitcher() {
+ if (mSelectedUser == null) {
+ Log.e(TAG, "Request to dismiss user switcher, but no user selected");
+ return;
+ }
+ if (mSelectedUser.mIsForeground) {
hide();
mStatusBar.dismissKeyguard();
return;
@@ -106,4 +199,22 @@
});
}
+
+ private boolean hasTrustedDevice(int uid) {
+ return !mEnrollmentManager.getEnrolledDeviceInfoForUser(uid).isEmpty();
+ }
+
+ private OnHideListener mOnHideListener = new OnHideListener() {
+ @Override
+ public void onHide(boolean dismissUserSwitcher) {
+ if (dismissUserSwitcher) {
+ dismissUserSwitcher();
+ } else {
+ // Re-draw the parent view, otherwise the unlock dialog will not be removed from
+ // the screen immediately.
+ mParent.invalidate();
+ }
+
+ }
+ };
}
diff --git a/packages/SettingsLib/HelpUtils/AndroidManifest.xml b/packages/SettingsLib/HelpUtils/AndroidManifest.xml
index 5240ce4..ccad6e4 100644
--- a/packages/SettingsLib/HelpUtils/AndroidManifest.xml
+++ b/packages/SettingsLib/HelpUtils/AndroidManifest.xml
@@ -16,6 +16,6 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.settingslib.helputils">
+ package="com.android.settingslib.widget">
</manifest>
diff --git a/packages/SettingsLib/HelpUtils/src/com/android/settingslib/HelpUtils.java b/packages/SettingsLib/HelpUtils/src/com/android/settingslib/HelpUtils.java
index e407d72..2d13b73 100644
--- a/packages/SettingsLib/HelpUtils/src/com/android/settingslib/HelpUtils.java
+++ b/packages/SettingsLib/HelpUtils/src/com/android/settingslib/HelpUtils.java
@@ -33,11 +33,11 @@
import android.view.MenuItem;
import android.view.MenuItem.OnMenuItemClickListener;
+import com.android.settingslib.widget.R;
+
import java.net.URISyntaxException;
import java.util.Locale;
-import com.android.settingslib.helputils.R;
-
/**
* Functions to easily prepare contextual help menu option items with an intent that opens up the
* browser to a particular URL, while taking into account the preferred language and app version.
diff --git a/packages/SettingsLib/RestrictedLockUtils/AndroidManifest.xml b/packages/SettingsLib/RestrictedLockUtils/AndroidManifest.xml
index d19a022..0975640 100644
--- a/packages/SettingsLib/RestrictedLockUtils/AndroidManifest.xml
+++ b/packages/SettingsLib/RestrictedLockUtils/AndroidManifest.xml
@@ -16,6 +16,6 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.settingslib.restrictedlockutils">
+ package="com.android.settingslib.widget">
</manifest>
\ No newline at end of file
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 3b67eead..bdc6a1d 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -143,7 +143,7 @@
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Aplicaciones eliminadas"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Aplicaciones y usuarios eliminados"</string>
<string name="data_usage_ota" msgid="5377889154805560860">"Actualizaciones del sistema"</string>
- <string name="tether_settings_title_usb" msgid="6688416425801386511">"Conexión mediante USB"</string>
+ <string name="tether_settings_title_usb" msgid="6688416425801386511">"Conexión USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Hotspot portátil"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Conexión mediante Bluetooth"</string>
<string name="tether_settings_title_usb_bluetooth" msgid="5355828977109785001">"Compartir conexión"</string>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index 76097fd..7bba7cf 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -90,7 +90,7 @@
<string name="bluetooth_profile_pbap_summary" msgid="6605229608108852198">"संपर्क साझाकरण के लिए उपयोग करें"</string>
<string name="bluetooth_profile_pan_nap" msgid="8429049285027482959">"इंटरनेट कनेक्शन साझाकरण"</string>
<string name="bluetooth_profile_map" msgid="1019763341565580450">"लेख संदेश"</string>
- <string name="bluetooth_profile_sap" msgid="5764222021851283125">"सिम ऐक्सेस"</string>
+ <string name="bluetooth_profile_sap" msgid="5764222021851283125">"सिम एक्सेस"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD ऑडियो: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD ऑडियो"</string>
<string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"सुनने में मदद करने वाले डिवाइस"</string>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 65e3c17..9240b45 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -204,7 +204,7 @@
<string name="tethering_settings_not_available" msgid="6765770438438291012">"Cài đặt chia sẻ kết nối không khả dụng cho người dùng này"</string>
<string name="apn_settings_not_available" msgid="7873729032165324000">"Cài đặt tên điểm truy cập không khả dụng cho người dùng này"</string>
<string name="enable_adb" msgid="7982306934419797485">"Gỡ lỗi USB"</string>
- <string name="enable_adb_summary" msgid="4881186971746056635">"Chế độ gỡ lỗi khi USB được kết nối"</string>
+ <string name="enable_adb_summary" msgid="4881186971746056635">"Bật chế độ gỡ lỗi khi kết nối USB"</string>
<string name="clear_adb_keys" msgid="4038889221503122743">"Thu hồi ủy quyền gỡ lỗi USB"</string>
<string name="bugreport_in_power" msgid="7923901846375587241">"Phím tắt báo cáo lỗi"</string>
<string name="bugreport_in_power_summary" msgid="1778455732762984579">"Hiển thị một nút trong menu nguồn để thêm báo cáo lỗi"</string>
@@ -261,8 +261,8 @@
<string name="allow_mock_location" msgid="2787962564578664888">"Cho phép vị trí mô phỏng"</string>
<string name="allow_mock_location_summary" msgid="317615105156345626">"Cho phép vị trí mô phỏng"</string>
<string name="debug_view_attributes" msgid="6485448367803310384">"Cho phép kiểm tra thuộc tính của chế độ xem"</string>
- <string name="mobile_data_always_on_summary" msgid="8149773901431697910">"Luôn giữ cho dữ liệu di động hoạt động, ngay cả khi Wi-Fi đang hoạt động (để chuyển đổi mạng nhanh)."</string>
- <string name="tethering_hardware_offload_summary" msgid="7726082075333346982">"Sử dụng tăng tốc phần cứng cho chia sẻ kết nối nếu được"</string>
+ <string name="mobile_data_always_on_summary" msgid="8149773901431697910">"Luôn bật dữ liệu di động ngay cả khi Wi-Fi đang hoạt động (để chuyển đổi mạng nhanh)."</string>
+ <string name="tethering_hardware_offload_summary" msgid="7726082075333346982">"Sử dụng tính năng tăng tốc phần cứng khi chia sẻ kết nối nếu có"</string>
<string name="adb_warning_title" msgid="6234463310896563253">"Cho phép gỡ lỗi USB?"</string>
<string name="adb_warning_message" msgid="7316799925425402244">"Gỡ lỗi USB chỉ dành cho mục đích phát triển. Hãy sử dụng tính năng này để sao chép dữ liệu giữa máy tính và thiết bị của bạn, cài đặt ứng dụng trên thiết bị của bạn mà không thông báo và đọc dữ liệu nhật ký."</string>
<string name="adb_keys_warning_message" msgid="5659849457135841625">"Thu hồi quyền truy cập gỡ lỗi USB từ tất cả máy tính mà bạn đã ủy quyền trước đó?"</string>
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index 4c52b132..636b90a 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -71,10 +71,6 @@
"telephony-common",
],
- aaptflags: [
- "--extra-packages",
- "com.android.keyguard",
- ],
kotlincflags: ["-Xjvm-default=enable"],
plugins: ["dagger2-compiler-2.19"],
@@ -132,7 +128,7 @@
kotlincflags: ["-Xjvm-default=enable"],
aaptflags: [
"--extra-packages",
- "com.android.keyguard:com.android.systemui",
+ "com.android.systemui",
],
plugins: ["dagger2-compiler-2.19"],
}
@@ -160,10 +156,6 @@
kotlincflags: ["-Xjvm-default=enable"],
dxflags: ["--multi-dex"],
- aaptflags: [
- "--extra-packages",
- "com.android.keyguard",
- ],
required: ["privapp_whitelist_com.android.systemui"],
}
@@ -180,10 +172,6 @@
privileged: true,
dxflags: ["--multi-dex"],
- aaptflags: [
- "--extra-packages",
- "com.android.keyguard",
- ],
optimize: {
proguard_flags_files: ["proguard.flags", "legacy/recents/proguard.flags"],
},
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 17274f4..4f74605b 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -20,6 +20,7 @@
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
package="com.android.systemui"
android:sharedUserId="android.uid.systemui"
+ xmlns:tools="http://schemas.android.com/tools"
coreApp="true">
<!-- Using OpenGL ES 2.0 -->
@@ -259,7 +260,8 @@
android:theme="@style/Theme.SystemUI"
android:defaultToDeviceProtectedStorage="true"
android:directBootAware="true"
- android:appComponentFactory="androidx.core.app.CoreComponentFactory">
+ tools:replace="android:appComponentFactory"
+ android:appComponentFactory=".SystemUIAppComponentFactory">
<!-- Keep theme in sync with SystemUIApplication.onCreate().
Setting the theme on the application does not affect views inflated by services.
The application theme is set again from onCreate to take effect for those views. -->
diff --git a/packages/SystemUI/docs/dagger.md b/packages/SystemUI/docs/dagger.md
index c2159df..c440fba 100644
--- a/packages/SystemUI/docs/dagger.md
+++ b/packages/SystemUI/docs/dagger.md
@@ -53,7 +53,7 @@
### Adding injection to a new SystemUI object
Anything that depends on any `@Singleton` provider from SystemUIRootComponent
-should be declared as an `@Subcomponent` of the root component, this requires
+should be declared as a `@Subcomponent` of the root component. This requires
declaring your own interface for generating your own modules or just the
object you need injected. The subcomponent also needs to be added to
SystemUIRootComponent in SystemUIFactory so it can be acquired.
@@ -204,6 +204,13 @@
}
```
+## Updating Dagger2
+
+Binaries can be downloaded from https://repo1.maven.org/maven2/com/google/dagger/ and then loaded
+into
+[/prebuilts/tools/common/m2/repository/com/google/dagger/](http://cs/android/prebuilts/tools/common/m2/repository/com/google/dagger/)
+
+
## TODO List
- Eliminate usages of Dependency#get
diff --git a/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/TaskStackView.java
index 14fd149..b89218c 100644
--- a/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/TaskStackView.java
@@ -41,8 +41,10 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.systemui.Dependency;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
+import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.recents.LegacyRecentsImpl;
import com.android.systemui.recents.RecentsActivity;
import com.android.systemui.recents.RecentsActivityLaunchState;
@@ -86,15 +88,15 @@
import com.android.systemui.recents.misc.DozeTrigger;
import com.android.systemui.recents.misc.ReferenceCountedTrigger;
import com.android.systemui.recents.misc.SystemServicesProxy;
+import com.android.systemui.recents.model.TaskStack;
import com.android.systemui.recents.utilities.AnimationProps;
import com.android.systemui.recents.utilities.Utilities;
-import com.android.systemui.shared.recents.model.Task;
-import com.android.systemui.recents.model.TaskStack;
import com.android.systemui.recents.views.grid.GridTaskView;
import com.android.systemui.recents.views.grid.TaskGridLayoutAlgorithm;
import com.android.systemui.recents.views.grid.TaskViewFocusFrame;
-
+import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.system.ActivityManagerWrapper;
+
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -256,7 +258,8 @@
mLayoutAlgorithm = new TaskStackLayoutAlgorithm(context, this);
mStableLayoutAlgorithm = new TaskStackLayoutAlgorithm(context, null);
mStackScroller = new TaskStackViewScroller(context, this, mLayoutAlgorithm);
- mTouchHandler = new TaskStackViewTouchHandler(context, this, mStackScroller);
+ mTouchHandler = new TaskStackViewTouchHandler(
+ context, this, mStackScroller, Dependency.get(FalsingManager.class));
mAnimationHelper = new TaskStackAnimationHelper(context, this);
mTaskCornerRadiusPx = LegacyRecentsImpl.getConfiguration().isGridEnabled ?
res.getDimensionPixelSize(R.dimen.recents_grid_task_view_rounded_corners_radius) :
diff --git a/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
index dd6926c..a7fb4fa 100644
--- a/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
+++ b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
@@ -37,6 +37,7 @@
import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.SwipeHelper;
+import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.recents.Constants;
import com.android.systemui.recents.LegacyRecentsImpl;
import com.android.systemui.recents.events.EventBus;
@@ -107,7 +108,7 @@
boolean mInterceptedBySwipeHelper;
public TaskStackViewTouchHandler(Context context, TaskStackView sv,
- TaskStackViewScroller scroller) {
+ TaskStackViewScroller scroller, FalsingManager falsingManager) {
Resources res = context.getResources();
ViewConfiguration configuration = ViewConfiguration.get(context);
mContext = context;
@@ -119,7 +120,7 @@
mWindowTouchSlop = configuration.getScaledWindowTouchSlop();
mFlingAnimUtils = new FlingAnimationUtils(context, 0.2f);
mOverscrollSize = res.getDimensionPixelSize(R.dimen.recents_fling_overscroll_distance);
- mSwipeHelper = new SwipeHelper(SwipeHelper.X, this, context) {
+ mSwipeHelper = new SwipeHelper(SwipeHelper.X, this, context, falsingManager) {
@Override
protected float getSize(View v) {
return getScaledDismissSize();
diff --git a/packages/SystemUI/res/layout/keyguard_bottom_area.xml b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
index 21c2c6b..1bfc4c0 100644
--- a/packages/SystemUI/res/layout/keyguard_bottom_area.xml
+++ b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
@@ -24,48 +24,7 @@
android:outlineProvider="none"
android:elevation="5dp" > <!-- Put it above the status bar header -->
- <LinearLayout
- android:id="@+id/keyguard_indication_area"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginBottom="@dimen/keyguard_indication_margin_bottom"
- android:layout_gravity="bottom|center_horizontal"
- android:orientation="horizontal">
-
- <include layout="@layout/left_docked_overlay" />
-
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:layout_gravity="center_vertical|center_horizontal"
- android:orientation="vertical">
-
- <com.android.systemui.statusbar.phone.KeyguardIndicationTextView
- android:id="@+id/keyguard_indication_enterprise_disclosure"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="center"
- android:paddingStart="@dimen/keyguard_indication_text_padding"
- android:paddingEnd="@dimen/keyguard_indication_text_padding"
- android:textAppearance="@style/TextAppearance.Keyguard.BottomArea"
- android:visibility="gone" />
-
- <com.android.systemui.statusbar.phone.KeyguardIndicationTextView
- android:id="@+id/keyguard_indication_text"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="center"
- android:paddingStart="@dimen/keyguard_indication_text_padding"
- android:paddingEnd="@dimen/keyguard_indication_text_padding"
- android:textAppearance="@style/TextAppearance.Keyguard.BottomArea"
- android:accessibilityLiveRegion="polite" />
-
- </LinearLayout>
-
- <include layout="@layout/right_docked_overlay" />
-
- </LinearLayout>
+ <include layout="@layout/keyguard_indication_area_overlay" />
<FrameLayout
android:id="@+id/preview_container"
diff --git a/packages/SystemUI/res/layout/keyguard_indication_area_overlay.xml b/packages/SystemUI/res/layout/keyguard_indication_area_overlay.xml
new file mode 100644
index 0000000..cc30a68
--- /dev/null
+++ b/packages/SystemUI/res/layout/keyguard_indication_area_overlay.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/keyguard_indication_area"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="@dimen/keyguard_indication_margin_bottom"
+ android:layout_gravity="bottom|center_horizontal"
+ android:orientation="vertical">
+
+ <include layout="@layout/keyguard_indication_text_view" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/keyguard_indication_text_view.xml b/packages/SystemUI/res/layout/keyguard_indication_text_view.xml
new file mode 100644
index 0000000..2b2100c
--- /dev/null
+++ b/packages/SystemUI/res/layout/keyguard_indication_text_view.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <com.android.systemui.statusbar.phone.KeyguardIndicationTextView
+ android:id="@+id/keyguard_indication_enterprise_disclosure"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:paddingStart="@dimen/keyguard_indication_text_padding"
+ android:paddingEnd="@dimen/keyguard_indication_text_padding"
+ android:textAppearance="@style/TextAppearance.Keyguard.BottomArea"
+ android:visibility="gone"/>
+
+ <com.android.systemui.statusbar.phone.KeyguardIndicationTextView
+ android:id="@+id/keyguard_indication_text"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:paddingStart="@dimen/keyguard_indication_text_padding"
+ android:paddingEnd="@dimen/keyguard_indication_text_padding"
+ android:textAppearance="@style/TextAppearance.Keyguard.BottomArea"
+ android:accessibilityLiveRegion="polite"/>
+</merge>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/left_docked_overlay.xml b/packages/SystemUI/res/layout/left_docked_overlay.xml
deleted file mode 100644
index 430143c..0000000
--- a/packages/SystemUI/res/layout/left_docked_overlay.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?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.
- -->
-
-<!-- empty stub -->
-<merge />
diff --git a/packages/SystemUI/res/layout/right_docked_overlay.xml b/packages/SystemUI/res/layout/right_docked_overlay.xml
deleted file mode 100644
index 430143c..0000000
--- a/packages/SystemUI/res/layout/right_docked_overlay.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?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.
- -->
-
-<!-- empty stub -->
-<merge />
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index 926b077..10f6317 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -385,8 +385,8 @@
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<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="8043466894212841998">"Swipe up to unlock"</string>
- <string name="do_disclosure_generic" msgid="5615898451805157556">"This device is managed by your organization"</string>
+ <string name="keyguard_unlock" msgid="6035822649218712063">"Swipe up to open"</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>
<string name="voice_hint" msgid="8939888732119726665">"Swipe from icon for voice assist"</string>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index e23236a..2383c79 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -385,7 +385,7 @@
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<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="8043466894212841998">"Swipe up to unlock"</string>
+ <string name="keyguard_unlock" msgid="6035822649218712063">"Swipe up to open"</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>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 340cb3a..78318cb 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -196,9 +196,6 @@
<!-- Doze: duration to avoid false pickup gestures triggered by notification vibrations -->
<integer name="doze_pickup_vibration_threshold">2000</integer>
- <!-- Doze: can we assume the pickup sensor includes a proximity check? -->
- <bool name="doze_pickup_performs_proximity_check">false</bool>
-
<!-- Type of a sensor that provides a low-power estimate of the desired display
brightness, suitable to listen to while the device is asleep (e.g. during
always-on display) -->
@@ -276,7 +273,6 @@
<!-- SystemUI Services: The classes of the stuff to start. -->
<string-array name="config_systemUIServiceComponents" translatable="false">
- <item>com.android.systemui.Dependency$DependencyCreator</item>
<item>com.android.systemui.util.NotificationChannels</item>
<item>com.android.systemui.statusbar.CommandQueue$CommandQueueStart</item>
<item>com.android.systemui.keyguard.KeyguardViewMediator</item>
@@ -307,7 +303,6 @@
<!-- SystemUI Services (per user): The classes of the stuff to start for each user. This is a subset of the config_systemUIServiceComponents -->
<string-array name="config_systemUIServiceComponentsPerUser" translatable="false">
- <item>com.android.systemui.Dependency$DependencyCreator</item>
<item>com.android.systemui.util.NotificationChannels</item>
</string-array>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index bef1fc2..be815e1 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -385,22 +385,16 @@
<!-- The width of the panel that holds the quick settings. -->
<dimen name="qs_panel_width">@dimen/notification_panel_width</dimen>
- <dimen name="volume_dialog_panel_transparent_padding_right">8dp</dimen>
+ <dimen name="volume_dialog_panel_transparent_padding_right">4dp</dimen>
<dimen name="volume_dialog_panel_transparent_padding">20dp</dimen>
<dimen name="volume_dialog_stream_padding">8dp</dimen>
- <!-- the amount the volume panel should be offset at the end from the view next to it (or
- the screen edge, in portrait-->
- <dimen name="volume_dialog_base_margin">8dp</dimen>
-
<dimen name="volume_dialog_panel_width">64dp</dimen>
<dimen name="volume_dialog_slider_height">116dp</dimen>
- <dimen name="volume_dialog_row_height">252dp</dimen>
-
<dimen name="volume_dialog_ringer_size">64dp</dimen>
<dimen name="volume_dialog_ringer_icon_padding">20dp</dimen>
@@ -417,8 +411,6 @@
<dimen name="volume_dialog_row_margin_bottom">8dp</dimen>
- <dimen name="volume_dialog_settings_icon_size">16dp</dimen>
-
<dimen name="volume_dialog_elevation">9dp</dimen>
<dimen name="volume_tool_tip_right_margin">76dp</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 7feacb4..19e682b 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -958,6 +958,9 @@
<!-- Message shown when lock screen is tapped or face authentication fails. [CHAR LIMIT=60] -->
<string name="keyguard_unlock">Swipe up to open</string>
+ <!-- Message shown when face authentication fails and the pin pad is visible. [CHAR LIMIT=60] -->
+ <string name="keyguard_retry">Swipe up to try again</string>
+
<!-- Text on keyguard screen and in Quick Settings footer indicating that the device is enterprise-managed by a Device Owner [CHAR LIMIT=60] -->
<string name="do_disclosure_generic">This device is managed by your organization</string>
@@ -1383,6 +1386,8 @@
buttons</string>
<string name="screen_pinning_toast_recents_invisible">To unpin this screen, touch & hold Back
and Home buttons</string>
+ <!-- Notify (in toast) user how to unpin screen in gesture navigation mode [CHAR LIMIT=NONE] -->
+ <string name="screen_pinning_toast_gesture_nav">To unpin this screen, swipe up & hold</string>
<!-- Screen pinning positive response. -->
<string name="screen_pinning_positive">Got it</string>
<!-- Screen pinning negative response. -->
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
index 328116d..13fc702 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
@@ -236,7 +236,8 @@
@Override
public void onAnimationCanceled(boolean deferredWithScreenshot) {
- animationHandler.onAnimationCanceled(deferredWithScreenshot);
+ animationHandler.onAnimationCanceled(
+ deferredWithScreenshot ? new ThumbnailData() : null);
}
};
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationListener.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationListener.java
index 5850fda..579858a 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationListener.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationListener.java
@@ -18,6 +18,8 @@
import android.graphics.Rect;
+import com.android.systemui.shared.recents.model.ThumbnailData;
+
public interface RecentsAnimationListener {
/**
@@ -29,5 +31,5 @@
/**
* Called when the animation into Recents was canceled. This call is made on the binder thread.
*/
- void onAnimationCanceled(boolean deferredWithScreenshot);
+ void onAnimationCanceled(ThumbnailData thumbnailData);
}
diff --git a/packages/SystemUI/src/com/android/keyguard/CarrierText.java b/packages/SystemUI/src/com/android/keyguard/CarrierText.java
index adcb7a1..b70d834 100644
--- a/packages/SystemUI/src/com/android/keyguard/CarrierText.java
+++ b/packages/SystemUI/src/com/android/keyguard/CarrierText.java
@@ -24,6 +24,8 @@
import android.view.View;
import android.widget.TextView;
+import com.android.systemui.R;
+
import java.util.Locale;
public class CarrierText extends TextView {
diff --git a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
index 10d132a..2b8e3ee 100644
--- a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
+++ b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
@@ -44,6 +44,7 @@
import com.android.internal.telephony.TelephonyProperties;
import com.android.settingslib.WirelessUtils;
import com.android.systemui.Dependency;
+import com.android.systemui.R;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import java.util.ArrayList;
diff --git a/packages/SystemUI/src/com/android/keyguard/EmergencyCarrierArea.java b/packages/SystemUI/src/com/android/keyguard/EmergencyCarrierArea.java
index e98ef06..225bebe 100644
--- a/packages/SystemUI/src/com/android/keyguard/EmergencyCarrierArea.java
+++ b/packages/SystemUI/src/com/android/keyguard/EmergencyCarrierArea.java
@@ -21,6 +21,8 @@
import android.view.MotionEvent;
import android.view.View;
+import com.android.systemui.R;
+
public class EmergencyCarrierArea extends AlphaOptimizedLinearLayout {
private CarrierText mCarrierText;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java
index a4b6958..d45603f 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java
@@ -33,6 +33,7 @@
import com.android.internal.util.LatencyTracker;
import com.android.internal.widget.LockPatternChecker;
import com.android.internal.widget.LockPatternUtils;
+import com.android.systemui.R;
import java.util.Arrays;
@@ -253,6 +254,7 @@
protected void onUserInput() {
if (mCallback != null) {
mCallback.userActivity();
+ mCallback.onUserInput();
}
mSecurityMessageDisplay.setMessage("");
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockAccessibilityDelegate.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockAccessibilityDelegate.java
index 6a83c71..a78c293 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockAccessibilityDelegate.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockAccessibilityDelegate.java
@@ -23,6 +23,8 @@
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.TextView;
+import com.android.systemui.R;
+
/**
* Replaces fancy colons with regular colons. Only works on TextViews.
*/
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
index 5097216..df0dc46 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
@@ -30,6 +30,7 @@
import com.android.internal.colorextraction.ColorExtractor.OnColorsChangedListener;
import com.android.keyguard.clock.ClockManager;
import com.android.systemui.Interpolators;
+import com.android.systemui.R;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.plugins.ClockPlugin;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java b/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java
index 0ec60e5..9380eb4 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java
@@ -35,6 +35,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.Dependency;
+import com.android.systemui.R;
import com.android.systemui.statusbar.NavigationBarController;
import com.android.systemui.statusbar.phone.NavigationBarView;
import com.android.systemui.util.InjectionInflationController;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardEsimArea.java b/packages/SystemUI/src/com/android/keyguard/KeyguardEsimArea.java
index c2bbfbf..fe64142 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardEsimArea.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardEsimArea.java
@@ -32,6 +32,8 @@
import android.view.WindowManager;
import android.widget.Button;
+import com.android.systemui.R;
+
/***
* This button is used by the device with embedded SIM card to disable current carrier to unlock
* the device with no cellular service.
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java
index 14ead04..8e1f6d3 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java
@@ -35,6 +35,7 @@
import com.android.keyguard.KeyguardSecurityContainer.SecurityCallback;
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
import com.android.settingslib.Utils;
+import com.android.systemui.R;
import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
import java.io.File;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardMessageArea.java b/packages/SystemUI/src/com/android/keyguard/KeyguardMessageArea.java
index 037a8d3..1ff98dd 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardMessageArea.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardMessageArea.java
@@ -31,6 +31,7 @@
import android.view.View;
import android.widget.TextView;
+import com.android.systemui.R;
import com.android.systemui.statusbar.policy.ConfigurationController;
import java.lang.ref.WeakReference;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java
index 6808c0f..15d2ea7 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java
@@ -24,6 +24,7 @@
import com.android.settingslib.animation.AppearAnimationUtils;
import com.android.settingslib.animation.DisappearAnimationUtils;
+import com.android.systemui.R;
/**
* Displays a PIN pad for unlocking.
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
index 96392156..eaaa3ed 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
@@ -37,6 +37,7 @@
import android.widget.TextView.OnEditorActionListener;
import com.android.internal.widget.TextViewInputDisabler;
+import com.android.systemui.R;
import java.util.List;
/**
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
index 55ddfc3..34c15e6 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
@@ -42,6 +42,7 @@
import com.android.settingslib.animation.AppearAnimationCreator;
import com.android.settingslib.animation.AppearAnimationUtils;
import com.android.settingslib.animation.DisappearAnimationUtils;
+import com.android.systemui.R;
import java.util.List;
@@ -274,6 +275,7 @@
@Override
public void onPatternCellAdded(List<LockPatternView.Cell> pattern) {
mCallback.userActivity();
+ mCallback.onUserInput();
}
@Override
@@ -336,6 +338,7 @@
});
if (pattern.size() > MIN_PATTERN_BEFORE_POKE_WAKELOCK) {
mCallback.userActivity();
+ mCallback.onUserInput();
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
index ecafc34..274f739 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
@@ -23,6 +23,8 @@
import android.view.MotionEvent;
import android.view.View;
+import com.android.systemui.R;
+
/**
* A Pin based Keyguard input view
*/
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityCallback.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityCallback.java
index cbfbffb..49dcfff 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityCallback.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityCallback.java
@@ -55,4 +55,9 @@
default void onCancelClicked() {
// No-op
}
+
+ /**
+ * Invoked whenever users are typing their password or drawing a pattern.
+ */
+ void onUserInput();
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index 8059dcf..ca7cd0d 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -45,6 +45,7 @@
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
import com.android.systemui.Dependency;
+import com.android.systemui.R;
import com.android.systemui.SystemUIFactory;
import com.android.systemui.statusbar.phone.UnlockMethodCache;
import com.android.systemui.util.InjectionInflationController;
@@ -596,6 +597,11 @@
}
}
+ @Override
+ public void onUserInput() {
+ mUpdateMonitor.cancelFaceAuth();
+ }
+
public void dismiss(boolean authenticated, int targetId) {
mSecurityCallback.dismiss(authenticated, targetId);
}
@@ -640,6 +646,8 @@
@Override
public void dismiss(boolean securityVerified, int targetUserId) { }
@Override
+ public void onUserInput() { }
+ @Override
public void reset() {}
};
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipper.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipper.java
index e6a0250..24da3ad 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipper.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipper.java
@@ -32,6 +32,7 @@
import android.widget.ViewFlipper;
import com.android.internal.widget.LockPatternUtils;
+import com.android.systemui.R;
/**
* Subclass of the current view flipper that allows us to overload dispatchTouchEvent() so
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
index 69da990..367a7bd 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
@@ -41,6 +41,7 @@
import com.android.internal.telephony.IccCardConstants;
import com.android.internal.telephony.IccCardConstants.State;
import com.android.internal.telephony.PhoneConstants;
+import com.android.systemui.R;
/**
* Displays a PIN pad for unlocking.
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
index 27f71d1..81f8c67 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
@@ -40,6 +40,7 @@
import com.android.internal.telephony.IccCardConstants;
import com.android.internal.telephony.IccCardConstants.State;
import com.android.internal.telephony.PhoneConstants;
+import com.android.systemui.R;
/**
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
index 37e89c0..1dfc5f2 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
@@ -40,6 +40,7 @@
import com.android.internal.widget.LockPatternUtils;
import com.android.systemui.Dependency;
+import com.android.systemui.R;
import com.android.systemui.statusbar.policy.ConfigurationController;
import java.io.FileDescriptor;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 109f270..8d858dc 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -94,6 +94,7 @@
import com.android.internal.util.Preconditions;
import com.android.internal.widget.LockPatternUtils;
import com.android.settingslib.WirelessUtils;
+import com.android.systemui.R;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
@@ -844,11 +845,6 @@
getCurrentUser());
}
- // The face timeout message is not very actionable, let's ask the user to
- // manually retry.
- if (msgId == FaceManager.FACE_ERROR_TIMEOUT) {
- errString = mContext.getString(R.string.keyguard_unlock);
- }
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
@@ -1408,6 +1404,7 @@
}
protected void handleStartedGoingToSleep(int arg1) {
+ mLockIconPressed = false;
clearBiometricRecognized();
final int count = mCallbacks.size();
for (int i = 0; i < count; i++) {
@@ -1443,7 +1440,6 @@
}
private void handleScreenTurnedOff() {
- mLockIconPressed = false;
mHardwareFingerprintUnavailableRetryCount = 0;
mHardwareFaceUnavailableRetryCount = 0;
final int count = mCallbacks.size();
@@ -1646,6 +1642,13 @@
updateFaceListeningState();
}
+ /**
+ * In case face auth is running, cancel it.
+ */
+ public void cancelFaceAuth() {
+ stopListeningForFace();
+ }
+
private void updateFaceListeningState() {
// If this message exists, we should not authenticate again until this message is
// consumed by the handler
@@ -1685,7 +1688,10 @@
return shouldListen;
}
- private boolean shouldListenForFace() {
+ /**
+ * If face auth is allows to scan on this exact moment.
+ */
+ public boolean shouldListenForFace() {
final boolean awakeKeyguard = mKeyguardIsVisible && mDeviceInteractive && !mGoingToSleep;
final int user = getCurrentUser();
final int strongAuth = mStrongAuthTracker.getStrongAuthForUser(user);
diff --git a/packages/SystemUI/src/com/android/keyguard/NumPadKey.java b/packages/SystemUI/src/com/android/keyguard/NumPadKey.java
index 08691ec..ebdd8c6 100644
--- a/packages/SystemUI/src/com/android/keyguard/NumPadKey.java
+++ b/packages/SystemUI/src/com/android/keyguard/NumPadKey.java
@@ -29,6 +29,7 @@
import android.widget.TextView;
import com.android.internal.widget.LockPatternUtils;
+import com.android.systemui.R;
public class NumPadKey extends ViewGroup {
// list of "ABC", etc per digit, starting with '0'
diff --git a/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java b/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java
index b21bcc9..409ae3f 100644
--- a/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java
+++ b/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java
@@ -42,6 +42,8 @@
import android.view.animation.Interpolator;
import android.widget.EditText;
+import com.android.systemui.R;
+
import java.util.ArrayList;
import java.util.Stack;
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/AnalogClockController.java b/packages/SystemUI/src/com/android/keyguard/clock/AnalogClockController.java
index 9c5242c..eba2400 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/AnalogClockController.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/AnalogClockController.java
@@ -26,7 +26,7 @@
import android.widget.TextClock;
import com.android.internal.colorextraction.ColorExtractor;
-import com.android.keyguard.R;
+import com.android.systemui.R;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.plugins.ClockPlugin;
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/BubbleClockController.java b/packages/SystemUI/src/com/android/keyguard/clock/BubbleClockController.java
index 8e81327..3a2fbe5 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/BubbleClockController.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/BubbleClockController.java
@@ -26,7 +26,7 @@
import android.widget.TextClock;
import com.android.internal.colorextraction.ColorExtractor;
-import com.android.keyguard.R;
+import com.android.systemui.R;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.plugins.ClockPlugin;
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/ClockLayout.java b/packages/SystemUI/src/com/android/keyguard/clock/ClockLayout.java
index 7485d33..d44d89e 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/ClockLayout.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/ClockLayout.java
@@ -24,7 +24,7 @@
import android.view.View;
import android.widget.FrameLayout;
-import com.android.keyguard.R;
+import com.android.systemui.R;
/**
* Positions clock faces (analog, digital, typographic) and handles pixel shifting
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/DefaultClockController.java b/packages/SystemUI/src/com/android/keyguard/clock/DefaultClockController.java
index 98679ade..c81935a 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/DefaultClockController.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/DefaultClockController.java
@@ -26,7 +26,7 @@
import android.widget.TextView;
import com.android.internal.colorextraction.ColorExtractor;
-import com.android.keyguard.R;
+import com.android.systemui.R;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.plugins.ClockPlugin;
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/ImageClock.java b/packages/SystemUI/src/com/android/keyguard/clock/ImageClock.java
index 95f1004..34c041b 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/ImageClock.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/ImageClock.java
@@ -21,7 +21,7 @@
import android.widget.FrameLayout;
import android.widget.ImageView;
-import com.android.keyguard.R;
+import com.android.systemui.R;
import java.text.SimpleDateFormat;
import java.util.Calendar;
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/SmallClockPosition.java b/packages/SystemUI/src/com/android/keyguard/clock/SmallClockPosition.java
index 60ca945..b304074 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/SmallClockPosition.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/SmallClockPosition.java
@@ -20,6 +20,7 @@
import android.util.MathUtils;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.R;
/**
* Computes preferred position of clock by considering height of status bar and lock icon.
@@ -40,10 +41,10 @@
private float mDarkAmount;
SmallClockPosition(Resources res) {
- this(res.getDimensionPixelSize(com.android.keyguard.R.dimen.status_bar_height),
- res.getDimensionPixelSize(com.android.keyguard.R.dimen.keyguard_lock_padding),
- res.getDimensionPixelSize(com.android.keyguard.R.dimen.keyguard_lock_height),
- res.getDimensionPixelSize(com.android.keyguard.R.dimen.burn_in_prevention_offset_y)
+ this(res.getDimensionPixelSize(R.dimen.status_bar_height),
+ res.getDimensionPixelSize(R.dimen.keyguard_lock_padding),
+ res.getDimensionPixelSize(R.dimen.keyguard_lock_height),
+ res.getDimensionPixelSize(R.dimen.burn_in_prevention_offset_y)
);
}
diff --git a/packages/SystemUI/src/com/android/systemui/ContextComponentHelper.java b/packages/SystemUI/src/com/android/systemui/ContextComponentHelper.java
new file mode 100644
index 0000000..8fabe7a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/ContextComponentHelper.java
@@ -0,0 +1,25 @@
+/*
+ * 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;
+
+/**
+ * Interface necessary to make Dagger happy. See {@link ContextComponentResolver}.
+ */
+public interface ContextComponentHelper {
+ /** Turns a classname into an instance of the class or returns null. */
+ <T> T resolve(String className);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/ContextComponentResolver.java b/packages/SystemUI/src/com/android/systemui/ContextComponentResolver.java
new file mode 100644
index 0000000..09bccd9
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/ContextComponentResolver.java
@@ -0,0 +1,48 @@
+/*
+ * 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 java.util.Map;
+
+import javax.inject.Inject;
+import javax.inject.Provider;
+
+/**
+ * Used during Service and Activity instantiation to make them injectable.
+ */
+public class ContextComponentResolver implements ContextComponentHelper {
+ private final Map<Class<?>, Provider<Object>> mCreators;
+
+ @Inject
+ ContextComponentResolver(Map<Class<?>, Provider<Object>> creators) {
+ mCreators = creators;
+ }
+
+ /**
+ * Looks up the class name to see if Dagger has an instance of it.
+ */
+ @Override
+ public <T> T resolve(String className) {
+ for (Map.Entry<Class<?>, Provider<Object>> p : mCreators.entrySet()) {
+ if (p.getKey().getName().equals(className)) {
+ return (T) p.getValue().get();
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/CornerHandleView.java b/packages/SystemUI/src/com/android/systemui/CornerHandleView.java
index a94952c..6209c2c 100644
--- a/packages/SystemUI/src/com/android/systemui/CornerHandleView.java
+++ b/packages/SystemUI/src/com/android/systemui/CornerHandleView.java
@@ -19,6 +19,7 @@
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.view.ContextThemeWrapper;
import android.view.View;
+import com.android.internal.graphics.ColorUtils;
import com.android.settingslib.Utils;
/**
@@ -107,6 +109,7 @@
mPaint.setColor((int) ArgbEvaluator.getInstance().evaluate(darkIntensity,
mLightColor,
mDarkColor));
+ updateShadow();
if (getVisibility() == VISIBLE) {
invalidate();
}
@@ -118,6 +121,21 @@
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/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index 6c36bc9..15bea24 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -16,7 +16,6 @@
import android.annotation.Nullable;
import android.app.INotificationManager;
-import android.content.Context;
import android.content.res.Configuration;
import android.hardware.SensorPrivacyManager;
import android.hardware.display.NightDisplayListener;
@@ -114,7 +113,6 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
-import java.util.HashMap;
import java.util.function.Consumer;
import javax.inject.Inject;
@@ -138,9 +136,7 @@
* they have no clients they should not have any registered resources like bound
* services, registered receivers, etc.
*/
-public class Dependency extends SystemUI {
- private static final String TAG = "Dependency";
-
+public class Dependency {
/**
* Key for getting a background Looper for background work.
*/
@@ -305,8 +301,20 @@
public Dependency() {
}
- @Override
- public void start() {
+
+ /**
+ * Initialize Depenency.
+ */
+ public static void initDependencies(SystemUIRootComponent rootComponent) {
+ if (sDependency != null) {
+ return;
+ }
+ sDependency = new Dependency();
+ rootComponent.createDependency().createSystemUI(sDependency);
+ sDependency.start();
+ }
+
+ protected void start() {
// TODO: Think about ways to push these creation rules out of Dependency to cut down
// on imports.
mProviders.put(TIME_TICK_HANDLER, mTimeTickHandler::get);
@@ -486,10 +494,14 @@
sDependency = this;
}
- @Override
- public synchronized void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- super.dump(fd, pw, args);
+ static void staticDump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ sDependency.dump(fd, pw, args);
+ }
+ /**
+ * {@see SystemUI.dump}
+ */
+ public synchronized void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
// Make sure that the DumpController gets added to mDependencies, as they are only added
// with Dependency#get.
getDependency(DumpController.class);
@@ -509,9 +521,11 @@
.forEach(o -> ((Dumpable) o).dump(fd, pw, args));
}
- @Override
+ protected static void staticOnConfigurationChanged(Configuration newConfig) {
+ sDependency.onConfigurationChanged(newConfig);
+ }
+
protected synchronized void onConfigurationChanged(Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
mDependencies.values().stream().filter(obj -> obj instanceof ConfigurationChangedReceiver)
.forEach(o -> ((ConfigurationChangedReceiver) o).onConfigurationChanged(newConfig));
}
@@ -565,20 +579,6 @@
}
/**
- * Used in separate processes (like tuner settings) to init the dependencies.
- */
- public static void initDependencies(Context context) {
- if (sDependency != null) return;
- Dependency d = new Dependency();
- SystemUIFactory.getInstance().getRootComponent()
- .createDependency()
- .createSystemUI(d);
- d.mContext = context;
- d.mComponents = new HashMap<>();
- d.start();
- }
-
- /**
* Used in separate process teardown to ensure the context isn't leaked.
*
* TODO: Remove once PreferenceFragment doesn't reference getActivity()
@@ -629,15 +629,4 @@
public interface DependencyInjector {
void createSystemUI(Dependency dependency);
}
-
- public static class DependencyCreator implements Injector {
- @Override
- public SystemUI apply(Context context) {
- Dependency dependency = new Dependency();
- SystemUIFactory.getInstance().getRootComponent()
- .createDependency()
- .createSystemUI(dependency);
- return dependency;
- }
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServicesDialog.java b/packages/SystemUI/src/com/android/systemui/ForegroundServicesDialog.java
index cb9523f..6fec92c 100644
--- a/packages/SystemUI/src/com/android/systemui/ForegroundServicesDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/ForegroundServicesDialog.java
@@ -75,7 +75,7 @@
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- Dependency.initDependencies(getApplicationContext());
+ Dependency.initDependencies(SystemUIFactory.getInstance().getRootComponent());
mMetricsLogger = Dependency.get(MetricsLogger.class);
diff --git a/packages/SystemUI/src/com/android/systemui/ServiceBinder.java b/packages/SystemUI/src/com/android/systemui/ServiceBinder.java
new file mode 100644
index 0000000..6282c6e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/ServiceBinder.java
@@ -0,0 +1,41 @@
+/*
+ * 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.doze.DozeService;
+
+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 ServiceBinder {
+
+ @Binds
+ public abstract ContextComponentHelper bindComponentHelper(
+ ContextComponentResolver componentHelper);
+
+ @Binds
+ @IntoMap
+ @ClassKey(DozeService.class)
+ public abstract Object bindDozeService(DozeService service);
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
index 84e0238..58c52a1 100644
--- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
@@ -34,7 +34,6 @@
import android.view.ViewConfiguration;
import android.view.accessibility.AccessibilityEvent;
-import com.android.systemui.classifier.FalsingManagerFactory;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.statusbar.FlingAnimationUtils;
@@ -98,7 +97,8 @@
private final ArrayMap<View, Animator> mDismissPendingMap = new ArrayMap<>();
- public SwipeHelper(int swipeDirection, Callback callback, Context context) {
+ public SwipeHelper(
+ int swipeDirection, Callback callback, Context context, FalsingManager falsingManager) {
mContext = context;
mCallback = callback;
mHandler = new Handler();
@@ -113,7 +113,7 @@
mDensityScale = res.getDisplayMetrics().density;
mFalsingThreshold = res.getDimensionPixelSize(R.dimen.swipe_helper_falsing_threshold);
mFadeDependingOnAmountSwiped = res.getBoolean(R.bool.config_fadeDependingOnAmountSwiped);
- mFalsingManager = FalsingManagerFactory.getInstance(context);
+ mFalsingManager = falsingManager;
mFlingAnimationUtils = new FlingAnimationUtils(context, getMaxEscapeAnimDuration() / 1000f);
}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactory.java
new file mode 100644
index 0000000..00ae992
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactory.java
@@ -0,0 +1,76 @@
+/*
+ * 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 android.app.Application;
+import android.app.Service;
+import android.content.Intent;
+
+import androidx.core.app.CoreComponentFactory;
+
+import javax.inject.Inject;
+
+/**
+ * Implementation of AppComponentFactory that injects into constructors.
+ */
+public class SystemUIAppComponentFactory extends CoreComponentFactory {
+
+ @Inject
+ public ContextComponentHelper mComponentHelper;
+
+ public SystemUIAppComponentFactory() {
+ super();
+ }
+
+ @Override
+ public Application instantiateApplication(ClassLoader cl, String className)
+ throws InstantiationException, IllegalAccessException, ClassNotFoundException {
+ Application app = super.instantiateApplication(cl, className);
+ if (app instanceof SystemUIApplication) {
+ ((SystemUIApplication) app).setContextAvailableCallback(
+ context -> {
+ SystemUIFactory.createFromConfig(context);
+ SystemUIFactory.getInstance().getRootComponent().inject(
+ SystemUIAppComponentFactory.this);
+ }
+ );
+ }
+
+ return app;
+ }
+
+ @Override
+ public Service instantiateService(ClassLoader cl, String className, Intent intent)
+ throws InstantiationException, IllegalAccessException, ClassNotFoundException {
+ Service service = mComponentHelper.resolve(className);
+ if (service != null) {
+ return checkCompatWrapper(service);
+ }
+ return super.instantiateService(cl, className, intent);
+ }
+
+ static <T> T checkCompatWrapper(T obj) {
+ if (obj instanceof CompatWrapped) {
+ T wrapper = (T) ((CompatWrapped) obj).getWrapper();
+ if (wrapper != null) {
+ return wrapper;
+ }
+ }
+
+ return obj;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index e89e6cb..48127a7 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -60,17 +60,30 @@
private boolean mServicesStarted;
private boolean mBootCompleted;
private final Map<Class<?>, Object> mComponents = new HashMap<>();
+ private ContextAvailableCallback mContextAvailableCallback;
+
+ public SystemUIApplication() {
+ super();
+ Log.v(TAG, "SystemUIApplication constructed.");
+ }
@Override
public void onCreate() {
super.onCreate();
+ Log.v(TAG, "SystemUIApplication created.");
+ // This line is used to setup Dagger's dependency injection and should be kept at the
+ // top of this method.
+ TimingsTraceLog log = new TimingsTraceLog("SystemUIBootTiming",
+ Trace.TRACE_TAG_APP);
+ log.traceBegin("DependencyInjection");
+ mContextAvailableCallback.onContextAvailable(this);
+ log.traceEnd();
+
// Set the application theme that is inherited by all services. Note that setting the
// application theme in the manifest does only work for activities. Keep this in sync with
// the theme set there.
setTheme(R.style.Theme_SystemUI);
- SystemUIFactory.createFromConfig(this);
-
if (Process.myUserHandle().equals(UserHandle.SYSTEM)) {
IntentFilter bootCompletedFilter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
bootCompletedFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
@@ -134,7 +147,7 @@
/**
* Ensures that all the Secondary user SystemUI services are running. If they are already
- * running, this is a no-op. This is needed to conditinally start all the services, as we only
+ * running, this is a no-op. This is needed to conditionally start all the services, as we only
* need to have it in the main process.
* <p>This method must only be called from the main thread.</p>
*/
@@ -155,7 +168,9 @@
// see ActivityManagerService.finishBooting()
if ("1".equals(SystemProperties.get("sys.boot_completed"))) {
mBootCompleted = true;
- if (DEBUG) Log.v(TAG, "BOOT_COMPLETED was already sent");
+ if (DEBUG) {
+ Log.v(TAG, "BOOT_COMPLETED was already sent");
+ }
}
}
@@ -269,6 +284,7 @@
@Override
public void onConfigurationChanged(Configuration newConfig) {
if (mServicesStarted) {
+ Dependency.staticOnConfigurationChanged(newConfig);
int len = mServices.length;
for (int i = 0; i < len; i++) {
if (mServices[i] != null) {
@@ -286,4 +302,12 @@
public SystemUI[] getServices() {
return mServices;
}
+
+ void setContextAvailableCallback(ContextAvailableCallback callback) {
+ mContextAvailableCallback = callback;
+ }
+
+ interface ContextAvailableCallback {
+ void onContextAvailable(Context context);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIDefaultModule.java b/packages/SystemUI/src/com/android/systemui/SystemUIDefaultModule.java
new file mode 100644
index 0000000..262b5ec
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIDefaultModule.java
@@ -0,0 +1,85 @@
+/*
+ * 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 static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME;
+import static com.android.systemui.Dependency.LEAK_REPORT_EMAIL_NAME;
+
+import android.content.Context;
+
+import androidx.annotation.Nullable;
+
+import com.android.systemui.dock.DockManager;
+import com.android.systemui.dock.DockManagerImpl;
+import com.android.systemui.power.EnhancedEstimates;
+import com.android.systemui.power.EnhancedEstimatesImpl;
+import com.android.systemui.statusbar.NotificationLockscreenUserManager;
+import com.android.systemui.statusbar.NotificationLockscreenUserManagerImpl;
+import com.android.systemui.statusbar.notification.collection.NotificationData;
+import com.android.systemui.statusbar.phone.KeyguardEnvironmentImpl;
+import com.android.systemui.statusbar.phone.ShadeController;
+import com.android.systemui.statusbar.phone.StatusBar;
+
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import dagger.Binds;
+import dagger.Module;
+import dagger.Provides;
+
+/**
+ * A dagger module for injecting default implementations of components of System UI that may be
+ * overridden by the System UI implementation.
+ */
+@Module
+abstract class SystemUIDefaultModule {
+
+ @Singleton
+ @Provides
+ @Named(LEAK_REPORT_EMAIL_NAME)
+ @Nullable
+ static String provideLeakReportEmail() {
+ return null;
+ }
+
+ @Binds
+ abstract EnhancedEstimates bindEnhancedEstimates(EnhancedEstimatesImpl enhancedEstimates);
+
+ @Binds
+ abstract NotificationLockscreenUserManager bindNotificationLockscreenUserManager(
+ NotificationLockscreenUserManagerImpl notificationLockscreenUserManager);
+
+ @Binds
+ abstract DockManager bindDockManager(DockManagerImpl dockManager);
+
+ @Binds
+ abstract NotificationData.KeyguardEnvironment bindKeyguardEnvironment(
+ KeyguardEnvironmentImpl keyguardEnvironment);
+
+ @Singleton
+ @Provides
+ static ShadeController provideShadeController(Context context) {
+ return SysUiServiceProvider.getComponent(context, StatusBar.class);
+ }
+
+ @Singleton
+ @Provides
+ @Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME)
+ static boolean provideAllowNotificationLongPress() {
+ return true;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index 0d85a3f..0899d95 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -16,13 +16,8 @@
package com.android.systemui;
-import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME;
-import static com.android.systemui.Dependency.LEAK_REPORT_EMAIL_NAME;
-
-import android.annotation.Nullable;
import android.app.AlarmManager;
import android.content.Context;
-import android.content.pm.PackageManager;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
@@ -33,63 +28,40 @@
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.ViewMediatorCallback;
-import com.android.systemui.assist.AssistManager;
-import com.android.systemui.classifier.FalsingManagerFactory;
-import com.android.systemui.dock.DockManager;
-import com.android.systemui.fragments.FragmentService;
import com.android.systemui.keyguard.DismissCallbackRegistry;
+import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.power.EnhancedEstimates;
-import com.android.systemui.power.EnhancedEstimatesImpl;
import com.android.systemui.statusbar.KeyguardIndicationController;
-import com.android.systemui.statusbar.NotificationListener;
-import com.android.systemui.statusbar.NotificationLockscreenUserManager;
-import com.android.systemui.statusbar.NotificationLockscreenUserManagerImpl;
import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.ScrimView;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
-import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
-import com.android.systemui.statusbar.notification.collection.NotificationData;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.KeyguardBouncer;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
-import com.android.systemui.statusbar.phone.KeyguardEnvironmentImpl;
-import com.android.systemui.statusbar.phone.KeyguardLiftController;
import com.android.systemui.statusbar.phone.LockIcon;
import com.android.systemui.statusbar.phone.LockscreenWallpaper;
import com.android.systemui.statusbar.phone.NotificationIconAreaController;
import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.statusbar.phone.ScrimState;
-import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.statusbar.phone.UnlockMethodCache;
-import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.KeyguardMonitor;
-import com.android.systemui.util.AsyncSensorManager;
-import com.android.systemui.util.InjectionInflationController;
-import com.android.systemui.util.leak.GarbageMonitor;
import com.android.systemui.volume.VolumeDialogComponent;
import java.util.function.Consumer;
-import javax.inject.Named;
-import javax.inject.Singleton;
-
-import dagger.Component;
import dagger.Module;
import dagger.Provides;
/**
* Class factory to provide customizable SystemUI components.
*/
-@Module
public class SystemUIFactory {
private static final String TAG = "SystemUIFactory";
static SystemUIFactory mFactory;
- private SystemUIRootComponent mRootComponent;
+ protected SystemUIRootComponent mRootComponent;
public static <T extends SystemUIFactory> T getInstance() {
return (T) mFactory;
@@ -114,9 +86,16 @@
public SystemUIFactory() {}
- protected void init(Context context) {
- mRootComponent = DaggerSystemUIFactory_SystemUIRootComponent.builder()
- .systemUIFactory(this)
+ private void init(Context context) {
+ mRootComponent = buildSystemUIRootComponent(context);
+
+ // Every other part of our codebase currently relies on Dependency, so we
+ // really need to ensure the Dependency gets initialized early on.
+ Dependency.initDependencies(mRootComponent);
+ }
+
+ protected SystemUIRootComponent buildSystemUIRootComponent(Context context) {
+ return DaggerSystemUIRootComponent.builder()
.dependencyProvider(new com.android.systemui.DependencyProvider())
.contextHolder(new ContextHolder(context))
.build();
@@ -132,12 +111,12 @@
}
public KeyguardBouncer createKeyguardBouncer(Context context, ViewMediatorCallback callback,
- LockPatternUtils lockPatternUtils, ViewGroup container,
+ LockPatternUtils lockPatternUtils, ViewGroup container,
DismissCallbackRegistry dismissCallbackRegistry,
KeyguardBouncer.BouncerExpansionCallback expansionCallback,
- KeyguardBypassController bypassController) {
+ FalsingManager falsingManager, KeyguardBypassController bypassController) {
return new KeyguardBouncer(context, callback, lockPatternUtils, container,
- dismissCallbackRegistry, FalsingManagerFactory.getInstance(context),
+ dismissCallbackRegistry, falsingManager,
expansionCallback, UnlockMethodCache.getInstance(context),
KeyguardUpdateMonitor.getInstance(context), bypassController,
new Handler(Looper.getMainLooper()));
@@ -171,93 +150,8 @@
return new VolumeDialogComponent(systemUi, context);
}
- @Singleton
- @Provides
- public NotificationData.KeyguardEnvironment provideKeyguardEnvironment(Context context) {
- return new KeyguardEnvironmentImpl();
- }
-
- @Singleton
- @Provides
- public NotificationLockscreenUserManager provideNotificationLockscreenUserManager(
- Context context) {
- return new NotificationLockscreenUserManagerImpl(context);
- }
-
- @Singleton
- @Provides
- public AssistManager provideAssistManager(DeviceProvisionedController controller,
- Context context) {
- return new AssistManager(controller, context);
- }
-
- @Singleton
- @Provides
- @Nullable
- public DockManager provideDockManager(Context context) {
- return null;
- }
-
- @Singleton
- @Provides
- public NotificationEntryManager provideNotificationEntryManager(Context context) {
- return new NotificationEntryManager(context);
- }
-
- @Singleton
- @Provides
- public EnhancedEstimates provideEnhancedEstimates(Context context) {
- return new EnhancedEstimatesImpl();
- }
-
- @Singleton
- @Provides
- @Named(LEAK_REPORT_EMAIL_NAME)
- @Nullable
- public String provideLeakReportEmail() {
- return null;
- }
-
- @Singleton
- @Provides
- @Nullable
- public KeyguardLiftController provideKeyguardLiftController(Context context,
- StatusBarStateController statusBarStateController,
- AsyncSensorManager asyncSensorManager) {
- if (!context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FACE)) {
- return null;
- }
- return new KeyguardLiftController(context, statusBarStateController, asyncSensorManager);
- }
-
- @Singleton
- @Provides
- public NotificationListener provideNotificationListener(Context context) {
- return new NotificationListener(context);
- }
-
- @Singleton
- @Provides
- public NotificationInterruptionStateProvider provideNotificationInterruptionStateProvider(
- Context context) {
- return new NotificationInterruptionStateProvider(context);
- }
-
- @Singleton
- @Provides
- @Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME)
- public boolean provideAllowNotificationLongPress() {
- return true;
- }
-
- @Singleton
- @Provides
- public ShadeController provideShadeController(Context context) {
- return SysUiServiceProvider.getComponent(context, StatusBar.class);
- }
-
@Module
- protected static class ContextHolder {
+ public static class ContextHolder {
private Context mContext;
public ContextHolder(Context context) {
@@ -269,29 +163,4 @@
return mContext;
}
}
-
- @Singleton
- @Component(modules = {SystemUIFactory.class, DependencyProvider.class, DependencyBinder.class,
- ContextHolder.class})
- public interface SystemUIRootComponent {
- @Singleton
- Dependency.DependencyInjector createDependency();
-
- @Singleton
- StatusBar.StatusBarInjector getStatusBarInjector();
-
- /**
- * FragmentCreator generates all Fragments that need injection.
- */
- @Singleton
- FragmentService.FragmentCreator createFragmentCreator();
-
- /**
- * ViewCreator generates all Views that need injection.
- */
- InjectionInflationController.ViewCreator createViewCreator();
-
- @Singleton
- GarbageMonitor createGarbageMonitor();
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/SystemUIModule.java
new file mode 100644
index 0000000..edd2463
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIModule.java
@@ -0,0 +1,50 @@
+/*
+ * 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 android.annotation.Nullable;
+import android.content.Context;
+import android.content.pm.PackageManager;
+
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.phone.KeyguardLiftController;
+import com.android.systemui.util.AsyncSensorManager;
+
+import javax.inject.Singleton;
+
+import dagger.Module;
+import dagger.Provides;
+
+/**
+ * A dagger module for injecting components of System UI that are not overridden by the System UI
+ * implementation.
+ */
+@Module
+public abstract class SystemUIModule {
+
+ @Singleton
+ @Provides
+ @Nullable
+ static KeyguardLiftController provideKeyguardLiftController(Context context,
+ StatusBarStateController statusBarStateController,
+ AsyncSensorManager asyncSensorManager) {
+ if (!context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FACE)) {
+ return null;
+ }
+ return new KeyguardLiftController(context, statusBarStateController, asyncSensorManager);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIRootComponent.java b/packages/SystemUI/src/com/android/systemui/SystemUIRootComponent.java
new file mode 100644
index 0000000..f18c8b2
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIRootComponent.java
@@ -0,0 +1,82 @@
+/*
+ * 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 static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME;
+
+import com.android.systemui.fragments.FragmentService;
+import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.util.InjectionInflationController;
+import com.android.systemui.util.leak.GarbageMonitor;
+
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import dagger.Component;
+
+/**
+ * Root component for Dagger injection.
+ */
+@Singleton
+@Component(modules = {
+ DependencyProvider.class,
+ DependencyBinder.class,
+ ServiceBinder.class,
+ SystemUIFactory.ContextHolder.class,
+ SystemUIModule.class,
+ SystemUIDefaultModule.class})
+public interface SystemUIRootComponent {
+ /**
+ * Main dependency providing module.
+ */
+ @Singleton
+ Dependency.DependencyInjector createDependency();
+
+ /**
+ * Injects the StatusBar.
+ */
+ @Singleton
+ StatusBar.StatusBarInjector getStatusBarInjector();
+
+ /**
+ * FragmentCreator generates all Fragments that need injection.
+ */
+ @Singleton
+ FragmentService.FragmentCreator createFragmentCreator();
+
+ /**
+ * ViewCreator generates all Views that need injection.
+ */
+ InjectionInflationController.ViewCreator createViewCreator();
+
+ /**
+ * Creatse a GarbageMonitor.
+ */
+ @Singleton
+ GarbageMonitor createGarbageMonitor();
+
+ /**
+ * Whether notification long press is allowed.
+ */
+ @Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME)
+ boolean allowNotificationLongPressName();
+
+ /**
+ * Injects into the supplied argument.
+ */
+ void inject(SystemUIAppComponentFactory factory);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUISecondaryUserService.java b/packages/SystemUI/src/com/android/systemui/SystemUISecondaryUserService.java
index c8a2e17..2d2d91d 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUISecondaryUserService.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUISecondaryUserService.java
@@ -38,25 +38,8 @@
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- SystemUI[] services = ((SystemUIApplication) getApplication()).getServices();
- if (args == null || args.length == 0) {
- for (SystemUI ui: services) {
- if (ui != null) {
- pw.println("dumping service: " + ui.getClass().getName());
- ui.dump(fd, pw, args);
- }
- }
- } else {
- String svc = args[0];
- for (SystemUI ui: services) {
- if (ui != null) {
- String name = ui.getClass().getName();
- if (name.endsWith(svc)) {
- ui.dump(fd, pw, args);
- }
- }
- }
- }
+ SystemUIService.dumpServices(
+ ((SystemUIApplication) getApplication()).getServices(), fd, pw, args);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIService.java b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
index dc1218d..1c5e800 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIService.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
@@ -66,8 +66,14 @@
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- SystemUI[] services = ((SystemUIApplication) getApplication()).getServices();
+ dumpServices(((SystemUIApplication) getApplication()).getServices(), fd, pw, args);
+ }
+
+ static void dumpServices(
+ SystemUI[] services, FileDescriptor fd, PrintWriter pw, String[] args) {
if (args == null || args.length == 0) {
+ pw.println("dumping service: " + Dependency.class.getName());
+ Dependency.staticDump(fd, pw, args);
for (SystemUI ui: services) {
pw.println("dumping service: " + ui.getClass().getName());
ui.dump(fd, pw, args);
@@ -78,6 +84,9 @@
}
} else {
String svc = args[0].toLowerCase();
+ if (Dependency.class.getName().endsWith(svc)) {
+ Dependency.staticDump(fd, pw, args);
+ }
for (SystemUI ui: services) {
String name = ui.getClass().getName().toLowerCase();
if (name.endsWith(svc)) {
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleBehaviorController.java b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleBehaviorController.java
index 6da3818..25d1645 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleBehaviorController.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleBehaviorController.java
@@ -177,6 +177,12 @@
mBehaviorMap.get(mCurrentBehavior).onAssistantGesturePerformed();
}
+ void onAssistHandlesRequested() {
+ if (mInGesturalMode) {
+ mBehaviorMap.get(mCurrentBehavior).onAssistHandlesRequested();
+ }
+ }
+
void setBehavior(AssistHandleBehavior behavior) {
if (mCurrentBehavior == behavior) {
return;
@@ -316,6 +322,7 @@
void onModeActivated(Context context, AssistHandleCallbacks callbacks);
default void onModeDeactivated() {}
default void onAssistantGesturePerformed() {}
+ default void onAssistHandlesRequested() {}
default void dump(PrintWriter pw, String prefix) {}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java
index f9ddeae..bdc666d 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java
@@ -211,6 +211,13 @@
mContext.getContentResolver(), LEARNING_EVENT_COUNT_KEY, ++mLearningCount);
}
+ @Override
+ public void onAssistHandlesRequested() {
+ if (mAssistHandleCallbacks != null && !mIsDozing && !mIsNavBarHidden && !mOnLockscreen) {
+ mAssistHandleCallbacks.showAndGo();
+ }
+ }
+
private static boolean isNavBarHidden(int sysuiStateFlags) {
return (sysuiStateFlags & QuickStepContract.SYSUI_STATE_NAV_BAR_HIDDEN) != 0;
}
@@ -365,11 +372,18 @@
long currentTimestamp = SystemClock.uptimeMillis();
mLearningTimeElapsed += currentTimestamp - mLastLearningTimestamp;
mLastLearningTimestamp = currentTimestamp;
- Settings.Secure.putLong(
- mContext.getContentResolver(), LEARNING_TIME_ELAPSED_KEY, mLearningTimeElapsed);
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 cf9c470..6f13e4f 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
@@ -19,6 +19,7 @@
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;
@@ -48,9 +49,13 @@
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
/**
* Class to manage everything related to assist in SystemUI.
*/
+@Singleton
public class AssistManager implements ConfigurationChangedReceiver {
/**
@@ -97,6 +102,8 @@
private static final String INVOCATION_TIME_MS_KEY = "invocation_time_ms";
private static final String INVOCATION_PHONE_STATE_KEY = "invocation_phone_state";
public static final String INVOCATION_TYPE_KEY = "invocation_type";
+ protected static final String ACTION_KEY = "action";
+ protected static final String SHOW_ASSIST_HANDLES_ACTION = "show_assist_handles";
public static final int INVOCATION_TYPE_GESTURE = 1;
public static final int INVOCATION_TYPE_ACTIVE_EDGE = 2;
@@ -147,6 +154,7 @@
}
};
+ @Inject
public AssistManager(DeviceProvisionedController controller, Context context) {
mContext = context;
mDeviceProvisionedController = controller;
@@ -154,8 +162,10 @@
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
@@ -204,6 +214,9 @@
if (VERBOSE) {
Log.v(TAG, "UI hints received");
}
+ if (SHOW_ASSIST_HANDLES_ACTION.equals(hints.getString(ACTION_KEY))) {
+ requestAssistHandles();
+ }
}
});
}
@@ -277,6 +290,10 @@
mUiController.onGestureCompletion(velocity);
}
+ protected void requestAssistHandles() {
+ mHandleController.onAssistHandlesRequested();
+ }
+
public void hideAssist() {
mAssistUtils.hideCurrentSession();
}
diff --git a/packages/SystemUI/src/com/android/systemui/assist/ui/InvocationLightsView.java b/packages/SystemUI/src/com/android/systemui/assist/ui/InvocationLightsView.java
index bc782a7..bb3bd78 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/ui/InvocationLightsView.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/ui/InvocationLightsView.java
@@ -100,7 +100,9 @@
int cornerRadiusBottom = DisplayUtils.getCornerRadiusBottom(context);
int cornerRadiusTop = DisplayUtils.getCornerRadiusTop(context);
- mViewHeight = Math.max(cornerRadiusBottom, cornerRadiusTop);
+ // ensure that height is non-zero even for square corners
+ mViewHeight = Math.max(Math.max(cornerRadiusBottom, cornerRadiusTop),
+ DisplayUtils.convertDpToPx(LIGHT_HEIGHT_DP, context));
final int dualToneDarkTheme = Utils.getThemeAttr(mContext, R.attr.darkIconTheme);
final int dualToneLightTheme = Utils.getThemeAttr(mContext, R.attr.lightIconTheme);
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
index 923ca20..de08a8c 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
@@ -182,7 +182,7 @@
mActivityView = new ActivityView(mContext, null /* attrs */, 0 /* defStyle */,
true /* singleTaskInstance */);
-
+ // Set ActivityView's alpha value as zero, since there is no view content to be shown.
setContentVisibility(false);
addView(mActivityView);
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFactory.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFactory.java
deleted file mode 100644
index 01921f0..0000000
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFactory.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2015 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.classifier;
-
-import android.content.Context;
-
-import com.android.systemui.Dependency;
-import com.android.systemui.plugins.FalsingManager;
-
-/**
- * When the phone is locked, listens to touch, sensor and phone events and sends them to
- * DataCollector and HumanInteractionClassifier.
- *
- * It does not collect touch events when the bouncer shows up.
- *
- * TODO: FalsingManager supports dependency injection. Use it.
- */
-public class FalsingManagerFactory {
- private static FalsingManager sInstance = null;
-
- private FalsingManagerFactory() {}
-
- public static FalsingManager getInstance(Context context) {
- if (sInstance == null) {
- sInstance = Dependency.get(FalsingManager.class);
- }
- return sInstance;
- }
-
-}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFake.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFake.java
new file mode 100644
index 0000000..ea175ed
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFake.java
@@ -0,0 +1,246 @@
+/*
+ * 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.classifier;
+
+import android.net.Uri;
+import android.view.MotionEvent;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.plugins.FalsingManager;
+
+import java.io.PrintWriter;
+
+/**
+ * Simple Fake for testing where {@link FalsingManager} is required.
+ */
+public class FalsingManagerFake implements FalsingManager {
+ private boolean mIsFalseTouch;
+ private boolean mIsUnlockingDisabled;
+ private boolean mIsClassiferEnabled;
+ private boolean mShouldEnforceBouncer;
+ private boolean mIsReportingEnabled;
+
+ @Override
+ public void onSucccessfulUnlock() {
+
+ }
+
+ @Override
+ public void onNotificationActive() {
+
+ }
+
+ @Override
+ public void setShowingAod(boolean showingAod) {
+
+ }
+
+ @Override
+ public void onNotificatonStartDraggingDown() {
+
+ }
+
+ @VisibleForTesting
+ public void setIsUnlockingDisabled(boolean isUnlockingDisabled) {
+ mIsUnlockingDisabled = isUnlockingDisabled;
+ }
+
+ @Override
+ public boolean isUnlockingDisabled() {
+ return mIsUnlockingDisabled;
+ }
+
+ @VisibleForTesting
+ public void setIsFalseTouch(boolean isFalseTouch) {
+ mIsFalseTouch = isFalseTouch;
+ }
+
+ @Override
+ public boolean isFalseTouch() {
+ return mIsFalseTouch;
+ }
+
+ @Override
+ public void onNotificatonStopDraggingDown() {
+
+ }
+
+ @Override
+ public void setNotificationExpanded() {
+
+ }
+
+ @VisibleForTesting
+ public void setIsClassiferEnabled(boolean isClassiferEnabled) {
+ mIsClassiferEnabled = isClassiferEnabled;
+ }
+
+ @Override
+ public boolean isClassiferEnabled() {
+ return mIsClassiferEnabled;
+ }
+
+ @Override
+ public void onQsDown() {
+
+ }
+
+ @Override
+ public void setQsExpanded(boolean expanded) {
+
+ }
+
+ @VisibleForTesting
+ public void setShouldEnforceBouncer(boolean shouldEnforceBouncer) {
+ mShouldEnforceBouncer = shouldEnforceBouncer;
+ }
+
+ @Override
+ public boolean shouldEnforceBouncer() {
+ return mShouldEnforceBouncer;
+ }
+
+ @Override
+ public void onTrackingStarted(boolean secure) {
+
+ }
+
+ @Override
+ public void onTrackingStopped() {
+
+ }
+
+ @Override
+ public void onLeftAffordanceOn() {
+
+ }
+
+ @Override
+ public void onCameraOn() {
+
+ }
+
+ @Override
+ public void onAffordanceSwipingStarted(boolean rightCorner) {
+
+ }
+
+ @Override
+ public void onAffordanceSwipingAborted() {
+
+ }
+
+ @Override
+ public void onStartExpandingFromPulse() {
+
+ }
+
+ @Override
+ public void onExpansionFromPulseStopped() {
+
+ }
+
+ @Override
+ public Uri reportRejectedTouch() {
+ return null;
+ }
+
+ @Override
+ public void onScreenOnFromTouch() {
+
+ }
+
+
+ @VisibleForTesting
+ public void setIsReportingEnabled(boolean isReportingEnabled) {
+ mIsReportingEnabled = isReportingEnabled;
+ }
+
+ @Override
+ public boolean isReportingEnabled() {
+ return mIsReportingEnabled;
+ }
+
+ @Override
+ public void onUnlockHintStarted() {
+
+ }
+
+ @Override
+ public void onCameraHintStarted() {
+
+ }
+
+ @Override
+ public void onLeftAffordanceHintStarted() {
+
+ }
+
+ @Override
+ public void onScreenTurningOn() {
+
+ }
+
+ @Override
+ public void onScreenOff() {
+
+ }
+
+ @Override
+ public void onNotificatonStopDismissing() {
+
+ }
+
+ @Override
+ public void onNotificationDismissed() {
+
+ }
+
+ @Override
+ public void onNotificatonStartDismissing() {
+
+ }
+
+ @Override
+ public void onNotificationDoubleTap(boolean accepted, float dx, float dy) {
+
+ }
+
+ @Override
+ public void onBouncerShown() {
+
+ }
+
+ @Override
+ public void onBouncerHidden() {
+
+ }
+
+ @Override
+ public void onTouchEvent(MotionEvent ev, int width, int height) {
+
+ }
+
+ @Override
+ public void dump(PrintWriter pw) {
+
+ }
+
+ @Override
+ public void cleanup() {
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/dock/DockManagerImpl.java b/packages/SystemUI/src/com/android/systemui/dock/DockManagerImpl.java
new file mode 100644
index 0000000..fa7f503
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/dock/DockManagerImpl.java
@@ -0,0 +1,41 @@
+/*
+ * 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.dock;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+@Singleton
+public class DockManagerImpl implements DockManager {
+
+ @Inject
+ public DockManagerImpl() {
+ }
+
+ @Override
+ public void addListener(DockEventListener callback) {
+ }
+
+ @Override
+ public void removeListener(DockEventListener callback) {
+ }
+
+ @Override
+ public boolean isDocked() {
+ return false;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeAuthRemover.java b/packages/SystemUI/src/com/android/systemui/doze/DozeAuthRemover.java
index e6a9e47..e5a54b8 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeAuthRemover.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeAuthRemover.java
@@ -25,7 +25,7 @@
*/
public class DozeAuthRemover implements DozeMachine.Part {
- KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+ private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
public DozeAuthRemover(Context context) {
mKeyguardUpdateMonitor = KeyguardUpdateMonitor.getInstance(context);
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
index d22d2c3..90cb05a 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
@@ -28,8 +28,9 @@
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.SystemUIApplication;
-import com.android.systemui.classifier.FalsingManagerFactory;
import com.android.systemui.dock.DockManager;
+import com.android.systemui.keyguard.WakefulnessLifecycle;
+import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.statusbar.phone.BiometricUnlockController;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.util.AsyncSensorManager;
@@ -42,11 +43,12 @@
}
/** Creates a DozeMachine with its parts for {@code dozeService}. */
- public DozeMachine assembleMachine(DozeService dozeService) {
+ public DozeMachine assembleMachine(DozeService dozeService, FalsingManager falsingManager) {
Context context = dozeService;
SensorManager sensorManager = Dependency.get(AsyncSensorManager.class);
AlarmManager alarmManager = context.getSystemService(AlarmManager.class);
DockManager dockManager = Dependency.get(DockManager.class);
+ WakefulnessLifecycle wakefulnessLifecycle = Dependency.get(WakefulnessLifecycle.class);
DozeHost host = getHost(dozeService);
AmbientDisplayConfiguration config = new AmbientDisplayConfiguration(context);
@@ -61,10 +63,11 @@
wrappedService = DozeSuspendScreenStatePreventingAdapter.wrapIfNeeded(wrappedService,
params);
- DozeMachine machine = new DozeMachine(wrappedService, config, wakeLock);
+ DozeMachine machine = new DozeMachine(wrappedService, config, wakeLock,
+ wakefulnessLifecycle);
machine.setParts(new DozeMachine.Part[]{
new DozePauser(handler, machine, alarmManager, params.getPolicy()),
- new DozeFalsingManagerAdapter(FalsingManagerFactory.getInstance(context)),
+ new DozeFalsingManagerAdapter(falsingManager),
createDozeTriggers(context, sensorManager, host, alarmManager, config, params,
handler, wakeLock, machine, dockManager),
createDozeUi(context, host, wakeLock, machine, handler, alarmManager, params),
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
index 8bf2256..93a51cc 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
@@ -24,6 +24,8 @@
import android.view.Display;
import com.android.internal.util.Preconditions;
+import com.android.systemui.keyguard.WakefulnessLifecycle;
+import com.android.systemui.keyguard.WakefulnessLifecycle.Wakefulness;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.util.Assert;
import com.android.systemui.util.wakelock.WakeLock;
@@ -118,6 +120,7 @@
private final Service mDozeService;
private final WakeLock mWakeLock;
private final AmbientDisplayConfiguration mConfig;
+ private final WakefulnessLifecycle mWakefulnessLifecycle;
private Part[] mParts;
private final ArrayList<State> mQueuedRequests = new ArrayList<>();
@@ -126,9 +129,10 @@
private boolean mWakeLockHeldForCurrentState = false;
public DozeMachine(Service service, AmbientDisplayConfiguration config,
- WakeLock wakeLock) {
+ WakeLock wakeLock, WakefulnessLifecycle wakefulnessLifecycle) {
mDozeService = service;
mConfig = config;
+ mWakefulnessLifecycle = wakefulnessLifecycle;
mWakeLock = wakeLock;
}
@@ -334,9 +338,18 @@
switch (state) {
case INITIALIZED:
case DOZE_PULSE_DONE:
- transitionTo(mConfig.alwaysOnEnabled(UserHandle.USER_CURRENT)
- ? DozeMachine.State.DOZE_AOD : DozeMachine.State.DOZE,
- DozeLog.PULSE_REASON_NONE);
+ final State nextState;
+ @Wakefulness int wakefulness = mWakefulnessLifecycle.getWakefulness();
+ if (wakefulness == WakefulnessLifecycle.WAKEFULNESS_AWAKE
+ || wakefulness == WakefulnessLifecycle.WAKEFULNESS_WAKING) {
+ nextState = State.FINISH;
+ } else if (mConfig.alwaysOnEnabled(UserHandle.USER_CURRENT)) {
+ nextState = State.DOZE_AOD;
+ } else {
+ nextState = State.DOZE;
+ }
+
+ transitionTo(nextState, DozeLog.PULSE_REASON_NONE);
break;
default:
break;
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
index 092eb46..026a625 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
@@ -107,8 +107,7 @@
config.dozePickupSensorAvailable(),
DozeLog.REASON_SENSOR_PICKUP, false /* touchCoords */,
false /* touchscreen */,
- false /* ignoresSetting */,
- mDozeParameters.getPickupPerformsProxCheck()),
+ false /* ignoresSetting */),
new TriggerSensor(
findSensorWithType(config.doubleTapSensorType()),
Settings.Secure.DOZE_DOUBLE_TAP_GESTURE,
@@ -205,11 +204,8 @@
public void updateListening() {
boolean anyListening = false;
for (TriggerSensor s : mSensors) {
- // We don't want to be listening while we're PAUSED (prox sensor is covered)
- // except when the sensor is already gated by prox.
- boolean listen = mListening && (!mPaused || s.performsProxCheck());
- s.setListening(listen);
- if (listen) {
+ s.setListening(mListening);
+ if (mListening) {
anyListening = true;
}
}
@@ -391,7 +387,6 @@
private final boolean mReportsTouchCoordinates;
private final boolean mSettingDefault;
private final boolean mRequiresTouchscreen;
- private final boolean mSensorPerformsProxCheck;
protected boolean mRequested;
protected boolean mRegistered;
@@ -408,14 +403,12 @@
boolean configured, int pulseReason, boolean reportsTouchCoordinates,
boolean requiresTouchscreen) {
this(sensor, setting, settingDef, configured, pulseReason, reportsTouchCoordinates,
- requiresTouchscreen, false /* ignoresSetting */,
- false /* sensorPerformsProxCheck */);
+ requiresTouchscreen, false /* ignoresSetting */);
}
private TriggerSensor(Sensor sensor, String setting, boolean settingDef,
boolean configured, int pulseReason, boolean reportsTouchCoordinates,
- boolean requiresTouchscreen, boolean ignoresSetting,
- boolean sensorPerformsProxCheck) {
+ boolean requiresTouchscreen, boolean ignoresSetting) {
mSensor = sensor;
mSetting = setting;
mSettingDefault = settingDef;
@@ -424,7 +417,6 @@
mReportsTouchCoordinates = reportsTouchCoordinates;
mRequiresTouchscreen = requiresTouchscreen;
mIgnoresSetting = ignoresSetting;
- mSensorPerformsProxCheck = sensorPerformsProxCheck;
}
public void setListening(boolean listen) {
@@ -498,23 +490,13 @@
screenX = event.values[0];
screenY = event.values[1];
}
- mCallback.onSensorPulse(mPulseReason, mSensorPerformsProxCheck, screenX, screenY,
- event.values);
+ mCallback.onSensorPulse(mPulseReason, screenX, screenY, event.values);
if (!mRegistered) {
updateListening(); // reregister, this sensor only fires once
}
}));
}
- /**
- * If the sensor itself performs proximity checks, to avoid pocket dialing.
- * Gated sensors don't need to be stopped when the {@link DozeMachine} is
- * {@link DozeMachine.State#DOZE_AOD_PAUSED}.
- */
- public boolean performsProxCheck() {
- return mSensorPerformsProxCheck;
- }
-
public void registerSettingsObserver(ContentObserver settingsObserver) {
if (mConfigured && !TextUtils.isEmpty(mSetting)) {
mResolver.registerContentObserver(
@@ -610,8 +592,7 @@
return;
}
if (DEBUG) Log.d(TAG, "onSensorEvent: " + triggerEventToString(event));
- mCallback.onSensorPulse(mPulseReason, true /* sensorPerformsProxCheck */, -1, -1,
- event.getValues());
+ mCallback.onSensorPulse(mPulseReason, -1, -1, event.getValues());
}));
}
}
@@ -621,13 +602,11 @@
/**
* Called when a sensor requests a pulse
* @param pulseReason Requesting sensor, e.g. {@link DozeLog#REASON_SENSOR_PICKUP}
- * @param sensorPerformedProxCheck true if the sensor already checked for FAR proximity.
* @param screenX the location on the screen where the sensor fired or -1
- * if the sensor doesn't support reporting screen locations.
+ * if the sensor doesn't support reporting screen locations.
* @param screenY the location on the screen where the sensor fired or -1
* @param rawValues raw values array from the event.
*/
- void onSensorPulse(int pulseReason, boolean sensorPerformedProxCheck,
- float screenX, float screenY, float[] rawValues);
+ void onSensorPulse(int pulseReason, float screenX, float screenY, float[] rawValues);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
index 2db7306..9e1514c 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
@@ -25,12 +25,15 @@
import com.android.systemui.Dependency;
import com.android.systemui.plugins.DozeServicePlugin;
import com.android.systemui.plugins.DozeServicePlugin.RequestDoze;
+import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.PluginListener;
import com.android.systemui.shared.plugins.PluginManager;
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import javax.inject.Inject;
+
public class DozeService extends DreamService
implements DozeMachine.Service, RequestDoze, PluginListener<DozeServicePlugin> {
private static final String TAG = "DozeService";
@@ -40,6 +43,7 @@
private DozeServicePlugin mDozePlugin;
private PluginManager mPluginManager;
+ @Inject
public DozeService() {
setDebug(DEBUG);
}
@@ -56,7 +60,8 @@
}
mPluginManager = Dependency.get(PluginManager.class);
mPluginManager.addPluginListener(this, DozeServicePlugin.class, false /* allowMultiple */);
- mDozeMachine = new DozeFactory().assembleMachine(this);
+ mDozeMachine = new DozeFactory().assembleMachine(
+ this, Dependency.get(FalsingManager.class));
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
index 310f04a..bab64db 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
@@ -41,6 +41,7 @@
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.util.Preconditions;
import com.android.systemui.Dependency;
+import com.android.systemui.R;
import com.android.systemui.dock.DockManager;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.util.Assert;
@@ -156,8 +157,7 @@
}
@VisibleForTesting
- void onSensor(int pulseReason, boolean sensorPerformedProxCheck,
- float screenX, float screenY, float[] rawValues) {
+ void onSensor(int pulseReason, float screenX, float screenY, float[] rawValues) {
boolean isDoubleTap = pulseReason == DozeLog.REASON_SENSOR_DOUBLE_TAP;
boolean isTap = pulseReason == DozeLog.REASON_SENSOR_TAP;
boolean isPickup = pulseReason == DozeLog.REASON_SENSOR_PICKUP;
@@ -169,10 +169,11 @@
if (isWakeDisplay) {
onWakeScreen(wakeEvent, mMachine.isExecutingTransition() ? null : mMachine.getState());
} else if (isLongPress) {
- requestPulse(pulseReason, sensorPerformedProxCheck, null /* onPulseSupressedListener */);
+ requestPulse(pulseReason, true /* alreadyPerformedProxCheck */,
+ null /* onPulseSupressedListener */);
} else if (isWakeLockScreen) {
if (wakeEvent) {
- requestPulse(pulseReason, sensorPerformedProxCheck,
+ requestPulse(pulseReason, true /* alreadyPerformedProxCheck */,
null /* onPulseSupressedListener */);
}
} else {
@@ -191,8 +192,7 @@
} else {
mDozeHost.extendPulse(pulseReason);
}
- }, sensorPerformedProxCheck
- || (mDockManager != null && mDockManager.isDocked()), pulseReason);
+ }, true /* alreadyPerformedProxCheck */, pulseReason);
}
if (isPickup) {
@@ -278,7 +278,7 @@
.setType(MetricsEvent.TYPE_OPEN)
.setSubtype(DozeLog.REASON_SENSOR_WAKE_UP));
}
- }, false /* alreadyPerformedProxCheck */, DozeLog.REASON_SENSOR_WAKE_UP);
+ }, true /* alreadyPerformedProxCheck */, DozeLog.REASON_SENSOR_WAKE_UP);
} else {
boolean paused = (state == DozeMachine.State.DOZE_AOD_PAUSED);
boolean pausing = (state == DozeMachine.State.DOZE_AOD_PAUSING);
@@ -417,6 +417,9 @@
mDozeSensors.dump(pw);
}
+ /**
+ * @see DozeSensors.ProxSensor
+ */
private abstract class ProximityCheck implements SensorEventListener, Runnable {
private static final int TIMEOUT_DELAY_MS = 500;
@@ -428,12 +431,18 @@
private boolean mRegistered;
private boolean mFinished;
private float mMaxRange;
+ private boolean mUsingBrightnessSensor;
protected abstract void onProximityResult(int result);
public void check() {
Preconditions.checkState(!mFinished && !mRegistered);
- final Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
+ Sensor sensor = DozeSensors.findSensorWithType(mSensorManager,
+ mContext.getString(R.string.doze_brightness_sensor_type));
+ mUsingBrightnessSensor = sensor != null;
+ if (sensor == null) {
+ sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
+ }
if (sensor == null) {
if (DozeMachine.DEBUG) Log.d(TAG, "ProxCheck: No sensor found");
finishWithResult(RESULT_UNKNOWN);
@@ -449,6 +458,9 @@
mRegistered = true;
}
+ /**
+ * @see DozeSensors.ProxSensor#onSensorChanged(SensorEvent)
+ */
@Override
public void onSensorChanged(SensorEvent event) {
if (event.values.length == 0) {
@@ -458,7 +470,14 @@
if (DozeMachine.DEBUG) {
Log.d(TAG, "ProxCheck: Event: value=" + event.values[0] + " max=" + mMaxRange);
}
- final boolean isNear = event.values[0] < mMaxRange;
+ final boolean isNear;
+ if (mUsingBrightnessSensor) {
+ // The custom brightness sensor is gated by the proximity sensor and will
+ // return 0 whenever prox is covered.
+ isNear = event.values[0] == 0;
+ } else {
+ isNear = event.values[0] < mMaxRange;
+ }
finishWithResult(isNear ? RESULT_NEAR : RESULT_FAR);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java b/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java
index 8dbaf0f..b4cc571 100644
--- a/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java
+++ b/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java
@@ -22,7 +22,7 @@
import com.android.systemui.ConfigurationChangedReceiver;
import com.android.systemui.Dumpable;
-import com.android.systemui.SystemUIFactory;
+import com.android.systemui.SystemUIRootComponent;
import com.android.systemui.qs.QSFragment;
import com.android.systemui.statusbar.phone.NavigationBarFragment;
@@ -51,7 +51,7 @@
private final FragmentCreator mFragmentCreator;
@Inject
- public FragmentService(SystemUIFactory.SystemUIRootComponent rootComponent) {
+ public FragmentService(SystemUIRootComponent rootComponent) {
mFragmentCreator = rootComponent.createFragmentCreator();
initInjectionMap();
}
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index 0e4c155..ff02e71 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 @@
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 7b22a49..2960634 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 @@
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 e9f99ac..f424a8e 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -81,10 +81,11 @@
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.Dependency;
+import com.android.systemui.R;
import com.android.systemui.SystemUI;
import com.android.systemui.SystemUIFactory;
import com.android.systemui.UiOffloadThread;
-import com.android.systemui.classifier.FalsingManagerFactory;
+import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.statusbar.phone.BiometricUnlockController;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.NotificationPanelView;
@@ -713,8 +714,7 @@
// Assume keyguard is showing (unless it's disabled) until we know for sure, unless Keyguard
// is disabled.
- if (mContext.getResources().getBoolean(
- com.android.keyguard.R.bool.config_enableKeyguardService)) {
+ if (mContext.getResources().getBoolean(R.bool.config_enableKeyguardService)) {
setShowingLocked(!shouldWaitForProvisioning()
&& !mLockPatternUtils.isLockScreenDisabled(
KeyguardUpdateMonitor.getCurrentUser()), true /* forceCallbacks */);
@@ -1599,7 +1599,7 @@
Trace.beginSection("KeyguardViewMediator#handleMessage START_KEYGUARD_EXIT_ANIM");
StartKeyguardExitAnimParams params = (StartKeyguardExitAnimParams) msg.obj;
handleStartKeyguardExitAnimation(params.startTime, params.fadeoutDuration);
- FalsingManagerFactory.getInstance(mContext).onSucccessfulUnlock();
+ Dependency.get(FalsingManager.class).onSucccessfulUnlock();
Trace.endSection();
break;
case KEYGUARD_DONE_PENDING_TIMEOUT:
@@ -2071,10 +2071,11 @@
public StatusBarKeyguardViewManager registerStatusBar(StatusBar statusBar,
ViewGroup container, NotificationPanelView panelView,
BiometricUnlockController biometricUnlockController, ViewGroup lockIconContainer,
- View notificationContainer, KeyguardBypassController bypassController) {
+ View notificationContainer, KeyguardBypassController bypassController,
+ FalsingManager falsingManager) {
mStatusBarKeyguardViewManager.registerStatusBar(statusBar, container, panelView,
biometricUnlockController, mDismissCallbackRegistry, lockIconContainer,
- notificationContainer, bypassController);
+ notificationContainer, bypassController, falsingManager);
return mStatusBarKeyguardViewManager;
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/WakefulnessLifecycle.java b/packages/SystemUI/src/com/android/systemui/keyguard/WakefulnessLifecycle.java
index 52a0214..d17f2f6 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/WakefulnessLifecycle.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/WakefulnessLifecycle.java
@@ -16,12 +16,15 @@
package com.android.systemui.keyguard;
+import android.annotation.IntDef;
import android.os.Trace;
import com.android.systemui.Dumpable;
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -33,6 +36,15 @@
public class WakefulnessLifecycle extends Lifecycle<WakefulnessLifecycle.Observer> implements
Dumpable {
+ @IntDef(prefix = { "WAKEFULNESS_" }, value = {
+ WAKEFULNESS_ASLEEP,
+ WAKEFULNESS_WAKING,
+ WAKEFULNESS_AWAKE,
+ WAKEFULNESS_GOING_TO_SLEEP,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Wakefulness {}
+
public static final int WAKEFULNESS_ASLEEP = 0;
public static final int WAKEFULNESS_WAKING = 1;
public static final int WAKEFULNESS_AWAKE = 2;
@@ -44,7 +56,7 @@
public WakefulnessLifecycle() {
}
- public int getWakefulness() {
+ public @Wakefulness int getWakefulness() {
return mWakefulness;
}
@@ -86,7 +98,7 @@
pw.println(" mWakefulness=" + mWakefulness);
}
- private void setWakefulness(int wakefulness) {
+ private void setWakefulness(@Wakefulness int wakefulness) {
mWakefulness = wakefulness;
Trace.traceCounter(Trace.TRACE_TAG_APP, "wakefulness", wakefulness);
}
diff --git a/packages/SystemUI/src/com/android/systemui/power/EnhancedEstimatesImpl.java b/packages/SystemUI/src/com/android/systemui/power/EnhancedEstimatesImpl.java
index 9b1f23a..78f5350 100644
--- a/packages/SystemUI/src/com/android/systemui/power/EnhancedEstimatesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/power/EnhancedEstimatesImpl.java
@@ -2,8 +2,16 @@
import com.android.settingslib.fuelgauge.Estimate;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+@Singleton
public class EnhancedEstimatesImpl implements EnhancedEstimates {
+ @Inject
+ public EnhancedEstimatesImpl() {
+ }
+
@Override
public boolean isHybridNotificationEnabled() {
return false;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
index 991d9fa..0403a05 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
@@ -248,7 +248,9 @@
int numPages = Math.max(nTiles / mPages.get(0).maxTiles(), 1);
// Add one more not full page if needed
- numPages += (nTiles % mPages.get(0).maxTiles() == 0 ? 0 : 1);
+ if (nTiles > numPages * mPages.get(0).maxTiles()) {
+ numPages++;
+ }
final int NP = mPages.size();
for (int i = 0; i < NP; i++) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
index f0413cd..be8a8fd 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
@@ -111,13 +111,25 @@
+ mQSPanel.getMeasuredHeight() + getPaddingBottom();
super.onMeasure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
-
// QSCustomizer will always be the height of the screen, but do this after
// other measuring to avoid changing the height of the QS.
mQSCustomizer.measure(widthMeasureSpec,
MeasureSpec.makeMeasureSpec(getDisplayHeight(), MeasureSpec.EXACTLY));
}
+
+ @Override
+ protected void measureChildWithMargins(View child, int parentWidthMeasureSpec, int widthUsed,
+ int parentHeightMeasureSpec, int heightUsed) {
+ // Do not measure QSPanel again when doing super.onMeasure.
+ // This prevents the pages in PagedTileLayout to be remeasured with a different (incorrect)
+ // size to the one used for determining the number of rows and then the number of pages.
+ if (child != mQSPanel) {
+ super.measureChildWithMargins(child, parentWidthMeasureSpec, widthUsed,
+ parentHeightMeasureSpec, heightUsed);
+ }
+ }
+
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
index 83b000d..38153ec 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
@@ -38,8 +38,8 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto;
-import com.android.systemui.Dependency;
import com.android.systemui.R;
+import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.qs.QSDetailClipper;
@@ -52,6 +52,8 @@
import java.util.ArrayList;
import java.util.List;
+import javax.inject.Inject;
+
/**
* Allows full-screen customization of QS, through show() and hide().
*
@@ -66,6 +68,8 @@
private final QSDetailClipper mClipper;
private final LightBarController mLightBarController;
+ private KeyguardMonitor mKeyguardMonitor;
+ private final ScreenLifecycle mScreenLifecycle;
private final TileQueryHelper mTileQueryHelper;
private final View mTransparentView;
@@ -82,7 +86,11 @@
private boolean mOpening;
private boolean mIsShowingNavBackdrop;
- public QSCustomizer(Context context, AttributeSet attrs) {
+ @Inject
+ public QSCustomizer(Context context, AttributeSet attrs,
+ LightBarController lightBarController,
+ KeyguardMonitor keyguardMonitor,
+ ScreenLifecycle screenLifecycle) {
super(new ContextThemeWrapper(context, R.style.edit_theme), attrs);
LayoutInflater.from(getContext()).inflate(R.layout.qs_customize_panel_content, this);
@@ -115,7 +123,9 @@
DefaultItemAnimator animator = new DefaultItemAnimator();
animator.setMoveDuration(TileAdapter.MOVE_DURATION);
mRecyclerView.setItemAnimator(animator);
- mLightBarController = Dependency.get(LightBarController.class);
+ mLightBarController = lightBarController;
+ mKeyguardMonitor = keyguardMonitor;
+ mScreenLifecycle = screenLifecycle;
updateNavBackDrop(getResources().getConfiguration());
}
@@ -177,7 +187,7 @@
queryTiles();
mNotifQsContainer.setCustomizerAnimating(true);
mNotifQsContainer.setCustomizerShowing(true);
- Dependency.get(KeyguardMonitor.class).addCallback(mKeyguardCallback);
+ mKeyguardMonitor.addCallback(mKeyguardCallback);
updateNavColors();
}
}
@@ -193,7 +203,7 @@
queryTiles();
mNotifQsContainer.setCustomizerAnimating(false);
mNotifQsContainer.setCustomizerShowing(true);
- Dependency.get(KeyguardMonitor.class).addCallback(mKeyguardCallback);
+ mKeyguardMonitor.addCallback(mKeyguardCallback);
updateNavColors();
}
}
@@ -203,16 +213,21 @@
}
public void hide() {
+ final boolean animate = mScreenLifecycle.getScreenState() != ScreenLifecycle.SCREEN_OFF;
if (isShown) {
MetricsLogger.hidden(getContext(), MetricsProto.MetricsEvent.QS_EDIT);
isShown = false;
mToolbar.dismissPopupMenus();
setCustomizing(false);
save();
- mClipper.animateCircularClip(mX, mY, false, mCollapseAnimationListener);
- mNotifQsContainer.setCustomizerAnimating(true);
+ if (animate) {
+ mClipper.animateCircularClip(mX, mY, false, mCollapseAnimationListener);
+ } else {
+ setVisibility(View.GONE);
+ }
+ mNotifQsContainer.setCustomizerAnimating(animate);
mNotifQsContainer.setCustomizerShowing(false);
- Dependency.get(KeyguardMonitor.class).removeCallback(mKeyguardCallback);
+ mKeyguardMonitor.removeCallback(mKeyguardCallback);
updateNavColors();
}
}
@@ -268,7 +283,7 @@
public void saveInstanceState(Bundle outState) {
if (isShown) {
- Dependency.get(KeyguardMonitor.class).removeCallback(mKeyguardCallback);
+ mKeyguardMonitor.removeCallback(mKeyguardCallback);
}
outState.putBoolean(EXTRA_QS_CUSTOMIZING, mCustomizing);
}
@@ -300,7 +315,7 @@
@Override
public void onKeyguardShowingChanged() {
if (!isAttachedToWindow()) return;
- if (Dependency.get(KeyguardMonitor.class).isShowing() && !mOpening) {
+ if (mKeyguardMonitor.isShowing() && !mOpening) {
hide();
}
}
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 b135f7b..effea6a 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 @@
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/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
index 20069ea..4de42cc 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -40,8 +40,10 @@
import com.android.systemui.R;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.qs.DetailAdapter;
+import com.android.systemui.plugins.qs.QSIconView;
import com.android.systemui.plugins.qs.QSTile.SignalState;
import com.android.systemui.qs.QSHost;
+import com.android.systemui.qs.SignalTileView;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.statusbar.phone.SystemUIDialog;
import com.android.systemui.statusbar.policy.NetworkController;
@@ -78,6 +80,11 @@
}
@Override
+ public QSIconView createTileView(Context context) {
+ return new SignalTileView(context);
+ }
+
+ @Override
public DetailAdapter getDetailAdapter() {
return mDetailAdapter;
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java
index 91d38bd..187a3bd 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java
@@ -76,8 +76,11 @@
UserSwitcherController.UserRecord item) {
UserDetailItemView v = UserDetailItemView.convertOrInflate(
mContext, convertView, parent);
- if (v != convertView) {
+ if (!item.isCurrent || item.isGuest) {
v.setOnClickListener(this);
+ } else {
+ v.setOnClickListener(null);
+ v.setClickable(false);
}
String name = getName(mContext, item);
if (item.picture == null) {
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java b/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java
index a9896f5..0383dee 100644
--- a/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java
@@ -22,34 +22,34 @@
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
+import android.content.ContentResolver;
+import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
+import android.graphics.Point;
import android.graphics.drawable.Icon;
import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;
import android.media.MediaRecorder;
-import android.media.ThumbnailUtils;
import android.media.projection.MediaProjection;
import android.media.projection.MediaProjectionManager;
import android.net.Uri;
-import android.os.Environment;
import android.os.IBinder;
import android.provider.MediaStore;
import android.provider.Settings;
import android.util.DisplayMetrics;
import android.util.Log;
+import android.util.Size;
import android.view.Surface;
import android.widget.Toast;
-import androidx.core.content.FileProvider;
-
import com.android.systemui.R;
import java.io.File;
import java.io.IOException;
+import java.io.OutputStream;
import java.nio.file.Files;
-import java.nio.file.Path;
import java.text.SimpleDateFormat;
import java.util.Date;
@@ -76,12 +76,10 @@
private static final String ACTION_DELETE = "com.android.systemui.screenrecord.DELETE";
private static final int TOTAL_NUM_TRACKS = 1;
- private static final String RECORD_DIR = "Captures"; // TODO: use a translatable string
private static final int VIDEO_BIT_RATE = 6000000;
private static final int VIDEO_FRAME_RATE = 30;
private static final int AUDIO_BIT_RATE = 16;
private static final int AUDIO_SAMPLE_RATE = 44100;
- private static final String FILE_PROVIDER = "com.android.systemui.fileprovider";
private MediaProjectionManager mMediaProjectionManager;
private MediaProjection mMediaProjection;
@@ -117,11 +115,11 @@
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
- Log.d(TAG, "RecordingService is starting");
if (intent == null) {
return Service.START_NOT_STICKY;
}
String action = intent.getAction();
+ Log.d(TAG, "onStartCommand " + action);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
@@ -157,26 +155,7 @@
case ACTION_STOP:
stopRecording();
-
- // Move temp file to user directory
- File recordDir = new File(
- Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES),
- RECORD_DIR);
- recordDir.mkdirs();
-
- String fileName = new SimpleDateFormat("'screen-'yyyyMMdd-HHmmss'.mp4'")
- .format(new Date());
- Path path = new File(recordDir, fileName).toPath();
-
- try {
- Files.move(mTempFile.toPath(), path);
- Notification notification = createSaveNotification(path);
- notificationManager.notify(NOTIFICATION_ID, notification);
- } catch (IOException e) {
- e.printStackTrace();
- Toast.makeText(this, R.string.screenrecord_delete_error, Toast.LENGTH_LONG)
- .show();
- }
+ saveRecording(notificationManager);
break;
case ACTION_PAUSE:
@@ -190,8 +169,7 @@
break;
case ACTION_SHARE:
- File shareFile = new File(intent.getStringExtra(EXTRA_PATH));
- Uri shareUri = FileProvider.getUriForFile(this, FILE_PROVIDER, shareFile);
+ Uri shareUri = Uri.parse(intent.getStringExtra(EXTRA_PATH));
Intent shareIntent = new Intent(Intent.ACTION_SEND)
.setType("video/mp4")
@@ -211,20 +189,18 @@
// Close quick shade
sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
- File file = new File(intent.getStringExtra(EXTRA_PATH));
- if (file.delete()) {
- Toast.makeText(
- this,
- R.string.screenrecord_delete_description,
- Toast.LENGTH_LONG).show();
+ ContentResolver resolver = getContentResolver();
+ Uri uri = Uri.parse(intent.getStringExtra(EXTRA_PATH));
+ resolver.delete(uri, null, null);
- // Remove notification
- notificationManager.cancel(NOTIFICATION_ID);
- } else {
- Log.e(TAG, "Error deleting screen recording!");
- Toast.makeText(this, R.string.screenrecord_delete_error, Toast.LENGTH_LONG)
- .show();
- }
+ Toast.makeText(
+ this,
+ R.string.screenrecord_delete_description,
+ Toast.LENGTH_LONG).show();
+
+ // Remove notification
+ notificationManager.cancel(NOTIFICATION_ID);
+ Log.d(TAG, "Deleted recording " + uri);
break;
}
return Service.START_STICKY;
@@ -295,6 +271,7 @@
mMediaRecorder.start();
} catch (IOException e) {
+ Log.e(TAG, "Error starting screen recording: " + e.getMessage());
e.printStackTrace();
throw new RuntimeException(e);
}
@@ -352,13 +329,10 @@
notificationManager.notify(NOTIFICATION_ID, mRecordingNotificationBuilder.build());
}
- private Notification createSaveNotification(Path path) {
- Uri saveUri = FileProvider.getUriForFile(this, FILE_PROVIDER, path.toFile());
- Log.d(TAG, "Screen recording saved to " + path.toString());
-
+ private Notification createSaveNotification(Uri uri) {
Intent viewIntent = new Intent(Intent.ACTION_VIEW)
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_GRANT_READ_URI_PERMISSION)
- .setDataAndType(saveUri, "video/mp4");
+ .setDataAndType(uri, "video/mp4");
Notification.Action shareAction = new Notification.Action.Builder(
Icon.createWithResource(this, R.drawable.ic_android),
@@ -366,7 +340,7 @@
PendingIntent.getService(
this,
REQUEST_CODE,
- getShareIntent(this, path.toString()),
+ getShareIntent(this, uri.toString()),
PendingIntent.FLAG_UPDATE_CURRENT))
.build();
@@ -376,7 +350,7 @@
PendingIntent.getService(
this,
REQUEST_CODE,
- getDeleteIntent(this, path.toString()),
+ getDeleteIntent(this, uri.toString()),
PendingIntent.FLAG_UPDATE_CURRENT))
.build();
@@ -394,8 +368,15 @@
.setAutoCancel(true);
// Add thumbnail if available
- Bitmap thumbnailBitmap = ThumbnailUtils.createVideoThumbnail(path.toString(),
- MediaStore.Video.Thumbnails.MINI_KIND);
+ Bitmap thumbnailBitmap = null;
+ try {
+ ContentResolver resolver = getContentResolver();
+ Size size = Point.convert(MediaStore.ThumbnailConstants.MINI_SIZE);
+ thumbnailBitmap = resolver.loadThumbnail(uri, size, null);
+ } catch (IOException e) {
+ Log.e(TAG, "Error creating thumbnail: " + e.getMessage());
+ e.printStackTrace();
+ }
if (thumbnailBitmap != null) {
Notification.BigPictureStyle pictureStyle = new Notification.BigPictureStyle()
.bigPicture(thumbnailBitmap)
@@ -417,6 +398,38 @@
stopSelf();
}
+ private void saveRecording(NotificationManager notificationManager) {
+ String fileName = new SimpleDateFormat("'screen-'yyyyMMdd-HHmmss'.mp4'")
+ .format(new Date());
+
+ ContentValues values = new ContentValues();
+ values.put(MediaStore.Video.Media.DISPLAY_NAME, fileName);
+ values.put(MediaStore.Video.Media.MIME_TYPE, "video/mp4");
+ values.put(MediaStore.Video.Media.DATE_ADDED, System.currentTimeMillis());
+ values.put(MediaStore.Video.Media.DATE_TAKEN, System.currentTimeMillis());
+
+ ContentResolver resolver = getContentResolver();
+ Uri collectionUri = MediaStore.Video.Media.getContentUri(
+ MediaStore.VOLUME_EXTERNAL_PRIMARY);
+ Uri itemUri = resolver.insert(collectionUri, values);
+
+ try {
+ // Add to the mediastore
+ OutputStream os = resolver.openOutputStream(itemUri, "w");
+ Files.copy(mTempFile.toPath(), os);
+ os.close();
+
+ Notification notification = createSaveNotification(itemUri);
+ notificationManager.notify(NOTIFICATION_ID, notification);
+
+ mTempFile.delete();
+ } catch (IOException e) {
+ Log.e(TAG, "Error saving screen recording: " + e.getMessage());
+ Toast.makeText(this, R.string.screenrecord_delete_error, Toast.LENGTH_LONG)
+ .show();
+ }
+ }
+
private void setTapsVisible(boolean turnOn) {
int value = turnOn ? 1 : 0;
Settings.System.putInt(getApplicationContext().getContentResolver(),
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
index 8385c8e..5adee40 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
@@ -29,7 +29,6 @@
import com.android.systemui.Gefingerpoken;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
-import com.android.systemui.classifier.FalsingManagerFactory;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.statusbar.notification.row.ExpandableView;
@@ -59,14 +58,15 @@
private FalsingManager mFalsingManager;
public DragDownHelper(Context context, View host, ExpandHelper.Callback callback,
- DragDownCallback dragDownCallback) {
+ DragDownCallback dragDownCallback,
+ FalsingManager falsingManager) {
mMinDragDistance = context.getResources().getDimensionPixelSize(
R.dimen.keyguard_drag_down_min_distance);
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
mCallback = callback;
mDragDownCallback = dragDownCallback;
mHost = host;
- mFalsingManager = FalsingManagerFactory.getInstance(context);
+ mFalsingManager = falsingManager;
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index 4be93df..6f87b29 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -562,11 +562,11 @@
return;
}
- String message = mContext.getString(R.string.keyguard_unlock);
if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
+ String message = mContext.getString(R.string.keyguard_retry);
mStatusBarKeyguardViewManager.showBouncerMessage(message, mInitialTextColorState);
} else if (mKeyguardUpdateMonitor.isScreenOn()) {
- showTransientIndication(message);
+ showTransientIndication(mContext.getString(R.string.keyguard_unlock));
hideTransientIndicationDelayed(BaseKeyguardCallback.HIDE_DELAY_MS);
}
}
@@ -650,7 +650,6 @@
if (!updateMonitor.isUnlockingWithBiometricAllowed()) {
return;
}
- animatePadlockError();
boolean showSwipeToUnlock =
msgId == KeyguardUpdateMonitor.BIOMETRIC_HELP_FACE_NOT_RECOGNIZED;
if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
@@ -676,7 +675,11 @@
return;
}
animatePadlockError();
- if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
+ if (msgId == FaceManager.FACE_ERROR_TIMEOUT) {
+ // The face timeout message is not very actionable, let's ask the user to
+ // manually retry.
+ showSwipeUpToUnlock();
+ } else if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
mStatusBarKeyguardViewManager.showBouncerMessage(errString, mInitialTextColorState);
} else if (updateMonitor.isScreenOn()) {
showTransientIndication(errString);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
index c375574..1400921 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
@@ -37,11 +37,15 @@
import java.util.ArrayList;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
/**
* This class handles listening to notification updates and passing them along to
* NotificationPresenter to be displayed to the user.
*/
@SuppressLint("OverrideAbstract")
+@Singleton
public class NotificationListener extends NotificationListenerWithPlugins {
private static final String TAG = "NotificationListener";
@@ -56,6 +60,7 @@
private final ArrayList<NotificationSettingsListener> mSettingsListeners = new ArrayList<>();
private final Context mContext;
+ @Inject
public NotificationListener(Context context) {
mContext = context;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
index e08a5ae..802a7d2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
@@ -58,10 +58,14 @@
import java.util.ArrayList;
import java.util.List;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
/**
* Handles keeping track of the current user, profiles, and various things related to hiding
* contents, redacting notifications, and the lockscreen.
*/
+@Singleton
public class NotificationLockscreenUserManagerImpl implements
Dumpable, NotificationLockscreenUserManager, StateListener {
private static final String TAG = "LockscreenUserManager";
@@ -171,6 +175,7 @@
return mEntryManager;
}
+ @Inject
public NotificationLockscreenUserManagerImpl(Context context) {
mContext = context;
mDevicePolicyManager = (DevicePolicyManager) mContext.getSystemService(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt b/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt
index 986486a..276afa7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt
@@ -27,11 +27,11 @@
import android.view.MotionEvent
import android.view.VelocityTracker
import android.view.ViewConfiguration
+import com.android.systemui.Dependency
import com.android.systemui.Gefingerpoken
import com.android.systemui.Interpolators
import com.android.systemui.R
-import com.android.systemui.classifier.FalsingManagerFactory
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
@@ -41,7 +41,6 @@
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone
import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.statusbar.phone.ShadeController
-import com.android.systemui.statusbar.policy.HeadsUpManager
import javax.inject.Inject
import javax.inject.Singleton
@@ -52,11 +51,13 @@
*/
@Singleton
class PulseExpansionHandler @Inject
-constructor(context: Context,
- private val wakeUpCoordinator: NotificationWakeUpCoordinator,
- private val bypassController: KeyguardBypassController,
- private val headsUpManager: HeadsUpManagerPhone,
- private val roundnessManager: NotificationRoundnessManager) : Gefingerpoken {
+constructor(
+ context: Context,
+ private val wakeUpCoordinator: NotificationWakeUpCoordinator,
+ private val bypassController: KeyguardBypassController,
+ private val headsUpManager: HeadsUpManagerPhone,
+ private val roundnessManager: NotificationRoundnessManager
+) : Gefingerpoken {
companion object {
private val RUBBERBAND_FACTOR_STATIC = 0.25f
private val SPRING_BACK_ANIMATION_LENGTH_MS = 375
@@ -115,7 +116,7 @@
mMinDragDistance = context.resources.getDimensionPixelSize(
R.dimen.keyguard_drag_down_min_distance)
mTouchSlop = ViewConfiguration.get(context).scaledTouchSlop.toFloat()
- mFalsingManager = FalsingManagerFactory.getInstance(context)
+ mFalsingManager = Dependency.get(FalsingManager::class.java)
mPowerManager = context.getSystemService(PowerManager::class.java)
}
@@ -124,8 +125,8 @@
}
private fun maybeStartExpansion(event: MotionEvent): Boolean {
- if (!wakeUpCoordinator.canShowPulsingHuns || qsExpanded
- || bouncerShowing) {
+ if (!wakeUpCoordinator.canShowPulsingHuns || qsExpanded ||
+ bouncerShowing) {
return false
}
if (velocityTracker == null) {
@@ -160,18 +161,18 @@
}
MotionEvent.ACTION_UP -> {
- recycleVelocityTracker();
+ recycleVelocityTracker()
}
MotionEvent.ACTION_CANCEL -> {
- recycleVelocityTracker();
+ recycleVelocityTracker()
}
}
return false
}
private fun recycleVelocityTracker() {
- velocityTracker?.recycle();
+ velocityTracker?.recycle()
velocityTracker = null
}
@@ -216,7 +217,7 @@
"com.android.systemui:PULSEDRAG")
}
shadeController.goToLockedShade(mStartingChild)
- leavingLockscreen = true;
+ leavingLockscreen = true
isExpanding = false
if (mStartingChild is ExpandableNotificationRow) {
val row = mStartingChild as ExpandableNotificationRow?
@@ -227,7 +228,7 @@
private fun updateExpansionHeight(height: Float) {
var expansionHeight = max(height, 0.0f)
if (!mReachedWakeUpHeight && height > mWakeUpHeight) {
- mReachedWakeUpHeight = true;
+ mReachedWakeUpHeight = true
}
if (mStartingChild != null) {
val child = mStartingChild!!
@@ -317,9 +318,11 @@
} else null
}
- fun setUp(stackScroller: NotificationStackScrollLayout,
- expansionCallback: ExpansionCallback,
- shadeController: ShadeController) {
+ fun setUp(
+ stackScroller: NotificationStackScrollLayout,
+ expansionCallback: ExpansionCallback,
+ shadeController: ShadeController
+ ) {
this.expansionCallback = expansionCallback
this.shadeController = shadeController
this.stackScroller = stackScroller
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/DynamicPrivacyController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/DynamicPrivacyController.java
index d9328fa..e4bd4fa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/DynamicPrivacyController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/DynamicPrivacyController.java
@@ -107,7 +107,7 @@
*/
public boolean isInLockedDownShade() {
if (!mStatusBarKeyguardViewManager.isShowing()
- || !mStatusBarKeyguardViewManager.isSecure()) {
+ || !mUnlockMethodCache.isMethodSecure()) {
return false;
}
int state = mStateController.getState();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
index 879a8df..f8fef7d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
@@ -54,11 +54,15 @@
import java.util.List;
import java.util.Map;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
/**
* NotificationEntryManager is responsible for the adding, removing, and updating of notifications.
* It also handles tasks such as their inflation and their interaction with other
* Notification.*Manager objects.
*/
+@Singleton
public class NotificationEntryManager implements
Dumpable,
NotificationContentInflater.InflationCallback,
@@ -118,6 +122,7 @@
}
}
+ @Inject
public NotificationEntryManager(Context context) {
mNotificationData = new NotificationData();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java
index 4fc6461..68d9546 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java
@@ -42,9 +42,13 @@
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
/**
* Provides heads-up and pulsing state for notification entries.
*/
+@Singleton
public class NotificationInterruptionStateProvider {
private static final String TAG = "InterruptionStateProvider";
@@ -72,6 +76,7 @@
protected boolean mUseHeadsUp = false;
private boolean mDisableNotificationAlerts;
+ @Inject
public NotificationInterruptionStateProvider(Context context) {
this(context,
(PowerManager) context.getSystemService(Context.POWER_SERVICE),
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
index dca152f..8d73251 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
@@ -33,9 +33,9 @@
import android.view.animation.Interpolator;
import android.view.animation.PathInterpolator;
+import com.android.systemui.Dependency;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
-import com.android.systemui.classifier.FalsingManagerFactory;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.notification.FakeShadowView;
@@ -130,7 +130,7 @@
private boolean mLastInSection;
private boolean mFirstInSection;
private boolean mIsBelowSpeedBump;
- private FalsingManager mFalsingManager;
+ private final FalsingManager mFalsingManager;
private float mNormalBackgroundVisibilityAmount;
private float mDimmedBackgroundFadeInAmount = -1;
@@ -164,10 +164,10 @@
super(context, attrs);
mSlowOutFastInInterpolator = new PathInterpolator(0.8f, 0.0f, 0.6f, 1.0f);
mSlowOutLinearInInterpolator = new PathInterpolator(0.8f, 0.0f, 1.0f, 1.0f);
+ mFalsingManager = Dependency.get(FalsingManager.class); // TODO: inject into a controller.
setClipChildren(false);
setClipToPadding(false);
updateColors();
- mFalsingManager = FalsingManagerFactory.getInstance(context);
mAccessibilityManager = AccessibilityManager.getInstance(mContext);
mDoubleTapHelper = new DoubleTapHelper(this, (active) -> {
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 ea31be4..65e744b 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
@@ -74,7 +74,6 @@
import com.android.systemui.Dependency;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
-import com.android.systemui.classifier.FalsingManagerFactory;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.PluginListener;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
@@ -1209,12 +1208,12 @@
mChildrenContainer.reInflateViews(mExpandClickListener, mEntry.notification);
}
if (mGuts != null) {
- View oldGuts = mGuts;
+ NotificationGuts oldGuts = mGuts;
int index = indexOfChild(oldGuts);
removeView(oldGuts);
mGuts = (NotificationGuts) LayoutInflater.from(mContext).inflate(
R.layout.notification_guts, this, false);
- mGuts.setVisibility(oldGuts.getVisibility());
+ mGuts.setVisibility(oldGuts.isExposed() ? VISIBLE : GONE);
addView(mGuts, index);
}
View oldMenu = mMenuRow == null ? null : mMenuRow.getMenuView();
@@ -1637,7 +1636,7 @@
public ExpandableNotificationRow(Context context, AttributeSet attrs) {
super(context, attrs);
- mFalsingManager = FalsingManagerFactory.getInstance(context);
+ mFalsingManager = Dependency.get(FalsingManager.class); // TODO: inject into a controller.
mNotificationInflater = new NotificationContentInflater(this);
mMenuRow = new NotificationMenuRow(mContext);
mImageResolver = new NotificationInlineImageResolver(context,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index f50790f..688e8eb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -86,7 +86,6 @@
import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.SwipeHelper;
-import com.android.systemui.classifier.FalsingManagerFactory;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.FalsingManager;
@@ -516,7 +515,8 @@
ActivityStarter activityStarter,
StatusBarStateController statusBarStateController,
HeadsUpManagerPhone headsUpManager,
- KeyguardBypassController keyguardBypassController) {
+ KeyguardBypassController keyguardBypassController,
+ FalsingManager falsingManager) {
super(context, attrs, 0, 0);
Resources res = getResources();
@@ -531,6 +531,7 @@
mHeadsUpManager.addListener(mRoundnessManager);
mHeadsUpManager.setAnimationStateHandler(this::setHeadsUpGoingAwayAnimationsAllowed);
mKeyguardBypassController = keyguardBypassController;
+ mFalsingManager = falsingManager;
mSectionsManager =
new NotificationSectionsManager(
@@ -555,10 +556,9 @@
mExpandHelper.setEventSource(this);
mExpandHelper.setScrollAdapter(this);
mSwipeHelper = new NotificationSwipeHelper(SwipeHelper.X, mNotificationCallback,
- getContext(), mMenuEventListener);
+ getContext(), mMenuEventListener, mFalsingManager);
mStackScrollAlgorithm = createStackScrollAlgorithm(context);
initView(context);
- mFalsingManager = FalsingManagerFactory.getInstance(context);
mShouldDrawNotificationBackground =
res.getBoolean(R.bool.config_drawNotificationBackground);
mFadeNotificationsOnDismiss =
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java
index 4dfc343..0968674 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java
@@ -28,6 +28,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.SwipeHelper;
+import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
@@ -50,9 +51,11 @@
private boolean mIsExpanded;
private boolean mPulsing;
- public NotificationSwipeHelper(int swipeDirection, NotificationCallback callback,
- Context context, NotificationMenuRowPlugin.OnMenuEventListener menuListener) {
- super(swipeDirection, callback, context);
+ NotificationSwipeHelper(
+ int swipeDirection, NotificationCallback callback, Context context,
+ NotificationMenuRowPlugin.OnMenuEventListener menuListener,
+ FalsingManager falsingManager) {
+ super(swipeDirection, callback, context, falsingManager);
mMenuListener = menuListener;
mCallback = callback;
mFalsingCheck = new Runnable() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
index 10b48e7..bb6a38e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
@@ -207,10 +207,6 @@
return SystemProperties.get(propName, mContext.getString(resId));
}
- public boolean getPickupPerformsProxCheck() {
- return mContext.getResources().getBoolean(R.bool.doze_pickup_performs_proximity_check);
- }
-
public int getPulseVisibleDurationExtended() {
return 2 * getPulseVisibleDuration();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
index 4691a31..66b1dd8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
@@ -27,7 +27,6 @@
import com.android.systemui.Interpolators;
import com.android.systemui.R;
-import com.android.systemui.classifier.FalsingManagerFactory;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.statusbar.FlingAnimationUtils;
import com.android.systemui.statusbar.KeyguardAffordanceView;
@@ -59,7 +58,7 @@
private KeyguardAffordanceView mLeftIcon;
private KeyguardAffordanceView mRightIcon;
private Animator mSwipeAnimator;
- private FalsingManager mFalsingManager;
+ private final FalsingManager mFalsingManager;
private int mMinBackgroundRadius;
private boolean mMotionCancelled;
private int mTouchTargetSize;
@@ -80,12 +79,13 @@
}
};
- KeyguardAffordanceHelper(Callback callback, Context context) {
+ KeyguardAffordanceHelper(Callback callback, Context context, FalsingManager falsingManager) {
mContext = context;
mCallback = callback;
initIcons();
updateIcon(mLeftIcon, 0.0f, mLeftIcon.getRestingAlpha(), false, false, true, false);
updateIcon(mRightIcon, 0.0f, mRightIcon.getRestingAlpha(), false, false, true, false);
+ mFalsingManager = falsingManager;
initDimens();
}
@@ -102,7 +102,6 @@
mHintGrowAmount =
mContext.getResources().getDimensionPixelSize(R.dimen.hint_grow_amount_sideways);
mFlingAnimationUtils = new FlingAnimationUtils(mContext, 0.4f);
- mFalsingManager = FalsingManagerFactory.getInstance(mContext);
}
private void initIcons() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index dc9b373..0854e84 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -40,9 +40,9 @@
import com.android.keyguard.KeyguardSecurityView;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
-import com.android.keyguard.R;
import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.DejankUtils;
+import com.android.systemui.R;
import com.android.systemui.keyguard.DismissCallbackRegistry;
import com.android.systemui.plugins.FalsingManager;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardEnvironmentImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardEnvironmentImpl.java
index 925a19d..2c931ae 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardEnvironmentImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardEnvironmentImpl.java
@@ -25,6 +25,10 @@
import com.android.systemui.statusbar.notification.collection.NotificationData.KeyguardEnvironment;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+@Singleton
public class KeyguardEnvironmentImpl implements KeyguardEnvironment {
private static final String TAG = "KeyguardEnvironmentImpl";
@@ -34,6 +38,7 @@
private final DeviceProvisionedController mDeviceProvisionedController =
Dependency.get(DeviceProvisionedController.class);
+ @Inject
public KeyguardEnvironmentImpl() {
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index f689a3e..a2740c8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.phone;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON;
+import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_HOME_DISABLED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED;
@@ -920,7 +921,8 @@
}
public void showPinningEscapeToast() {
- mScreenPinningNotify.showEscapeToast(isRecentsButtonVisible());
+ mScreenPinningNotify.showEscapeToast(
+ mNavBarMode == NAV_BAR_MODE_GESTURAL, isRecentsButtonVisible());
}
public boolean isVertical() {
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 a0847b6..83c5566 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -39,6 +39,7 @@
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.Region;
+import android.hardware.biometrics.BiometricSourceType;
import android.os.PowerManager;
import android.os.SystemClock;
import android.util.AttributeSet;
@@ -59,11 +60,11 @@
import com.android.keyguard.KeyguardClockSwitch;
import com.android.keyguard.KeyguardStatusView;
import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.systemui.DejankUtils;
import com.android.systemui.Dependency;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
-import com.android.systemui.classifier.FalsingManagerFactory;
import com.android.systemui.fragments.FragmentHostManager;
import com.android.systemui.fragments.FragmentHostManager.FragmentListener;
import com.android.systemui.plugins.FalsingManager;
@@ -165,6 +166,25 @@
R.id.keyguard_hun_animator_start_tag);
private static final AnimationProperties KEYGUARD_HUN_PROPERTIES =
new AnimationProperties().setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
+ @VisibleForTesting
+ final KeyguardUpdateMonitorCallback mKeyguardUpdateCallback =
+ new KeyguardUpdateMonitorCallback() {
+ @Override
+ public void onBiometricRunningStateChanged(boolean running,
+ BiometricSourceType biometricSourceType) {
+ boolean keyguardOrShadeLocked = mBarState == StatusBarState.KEYGUARD
+ || mBarState == StatusBarState.SHADE_LOCKED;
+ if (!running && mFirstBypassAttempt && keyguardOrShadeLocked && !mDozing) {
+ mFirstBypassAttempt = false;
+ animateKeyguardStatusBarIn(StackStateAnimator.ANIMATION_DURATION_STANDARD);
+ }
+ }
+
+ @Override
+ public void onFinishedGoingToSleep(int why) {
+ mFirstBypassAttempt = mKeyguardBypassController.getBypassEnabled();
+ }
+ };
private final InjectionInflationController mInjectionInflationController;
private final PowerManager mPowerManager;
@@ -172,8 +192,8 @@
private final NotificationWakeUpCoordinator mWakeUpCoordinator;
private final PulseExpansionHandler mPulseExpansionHandler;
private final KeyguardBypassController mKeyguardBypassController;
- private final KeyguardUpdateMonitor mUpdateMonitor;
-
+ @VisibleForTesting
+ protected KeyguardUpdateMonitor mUpdateMonitor;
@VisibleForTesting
protected KeyguardAffordanceHelper mAffordanceHelper;
private KeyguardUserSwitcher mKeyguardUserSwitcher;
@@ -384,6 +404,7 @@
private boolean mShowingKeyguardHeadsUp;
private boolean mAllowExpandForSmallExpansion;
private Runnable mExpandAfterLayoutRunnable;
+ private boolean mFirstBypassAttempt;
@Inject
public NotificationPanelView(@Named(VIEW_CONTEXT) Context context, AttributeSet attrs,
@@ -391,11 +412,12 @@
NotificationWakeUpCoordinator coordinator,
PulseExpansionHandler pulseExpansionHandler,
DynamicPrivacyController dynamicPrivacyController,
- KeyguardBypassController bypassController) {
+ KeyguardBypassController bypassController,
+ FalsingManager falsingManager) {
super(context, attrs);
setWillNotDraw(!DEBUG);
mInjectionInflationController = injectionInflationController;
- mFalsingManager = FalsingManagerFactory.getInstance(context);
+ mFalsingManager = falsingManager;
mPowerManager = context.getSystemService(PowerManager.class);
mWakeUpCoordinator = coordinator;
mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
@@ -413,6 +435,7 @@
mThemeResId = context.getThemeResId();
mKeyguardBypassController = bypassController;
mUpdateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
+ mFirstBypassAttempt = mKeyguardBypassController.getBypassEnabled();
dynamicPrivacyController.addListener(this);
mBottomAreaShadeAlphaAnimator = ValueAnimator.ofFloat(1f, 0);
@@ -485,6 +508,7 @@
Dependency.get(StatusBarStateController.class).addCallback(this);
Dependency.get(ZenModeController.class).addCallback(this);
Dependency.get(ConfigurationController.class).addCallback(this);
+ mUpdateMonitor.registerCallback(mKeyguardUpdateCallback);
// Theme might have changed between inflating this view and attaching it to the window, so
// force a call to onThemeChanged
onThemeChanged();
@@ -497,6 +521,7 @@
Dependency.get(StatusBarStateController.class).removeCallback(this);
Dependency.get(ZenModeController.class).removeCallback(this);
Dependency.get(ConfigurationController.class).removeCallback(this);
+ mUpdateMonitor.removeCallback(mKeyguardUpdateCallback);
}
@Override
@@ -625,7 +650,7 @@
}
private void initBottomArea() {
- mAffordanceHelper = new KeyguardAffordanceHelper(this, getContext());
+ mAffordanceHelper = new KeyguardAffordanceHelper(this, getContext(), mFalsingManager);
mKeyguardBottomArea.setAffordanceHelper(mAffordanceHelper);
mKeyguardBottomArea.setStatusBar(mStatusBar);
mKeyguardBottomArea.setUserSetupComplete(mUserSetupComplete);
@@ -1738,7 +1763,8 @@
private void setQsExpansion(float height) {
height = Math.min(Math.max(height, mQsMinExpansionHeight), mQsMaxExpansionHeight);
mQsFullyExpanded = height == mQsMaxExpansionHeight && mQsMaxExpansionHeight != 0;
- if (height > mQsMinExpansionHeight && !mQsExpanded && !mStackScrollerOverscrolling) {
+ if (height > mQsMinExpansionHeight && !mQsExpanded && !mStackScrollerOverscrolling
+ && !mDozing) {
setQsExpanded(true);
} else if (height <= mQsMinExpansionHeight && mQsExpanded) {
setQsExpanded(false);
@@ -2237,7 +2263,9 @@
* mKeyguardStatusBarAnimateAlpha;
newAlpha *= 1.0f - mKeyguardHeadsUpShowingAmount;
mKeyguardStatusBar.setAlpha(newAlpha);
- mKeyguardStatusBar.setVisibility(newAlpha != 0f && !mDozing ? VISIBLE : INVISIBLE);
+ boolean hideForBypass = mFirstBypassAttempt && mUpdateMonitor.shouldListenForFace();
+ mKeyguardStatusBar.setVisibility(newAlpha != 0f && !mDozing && !hideForBypass
+ ? VISIBLE : INVISIBLE);
}
private void updateKeyguardBottomAreaAlpha() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index f8e1093..31600e3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -42,7 +42,6 @@
import com.android.systemui.Dependency;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
-import com.android.systemui.classifier.FalsingManagerFactory;
import com.android.systemui.doze.DozeLog;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -111,7 +110,7 @@
private FlingAnimationUtils mFlingAnimationUtils;
private FlingAnimationUtils mFlingAnimationUtilsClosing;
private FlingAnimationUtils mFlingAnimationUtilsDismissing;
- private FalsingManager mFalsingManager;
+ private final FalsingManager mFalsingManager;
private final VibratorHelper mVibratorHelper;
/**
@@ -214,7 +213,7 @@
0.5f /* maxLengthSeconds */, 0.2f /* speedUpFactor */, 0.6f /* x2 */,
0.84f /* y2 */);
mBounceInterpolator = new BounceInterpolator();
- mFalsingManager = FalsingManagerFactory.getInstance(context);
+ mFalsingManager = Dependency.get(FalsingManager.class); // TODO: inject into a controller.
mNotificationsDragEnabled =
getResources().getBoolean(R.bool.config_enableNotificationShadeDrag);
mVibratorHelper = Dependency.get(VibratorHelper.class);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScreenPinningNotify.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScreenPinningNotify.java
index f8731b4..071e00d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScreenPinningNotify.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScreenPinningNotify.java
@@ -51,7 +51,7 @@
}
/** Show a toast that describes the gesture the user should use to escape pinned mode. */
- public void showEscapeToast(boolean isRecentsButtonVisible) {
+ public void showEscapeToast(boolean isGestureNavEnabled, boolean isRecentsButtonVisible) {
long showToastTime = SystemClock.elapsedRealtime();
if ((showToastTime - mLastShowToastTime) < SHOW_TOAST_MINIMUM_INTERVAL) {
Slog.i(TAG, "Ignore toast since it is requested in very short interval.");
@@ -60,9 +60,11 @@
if (mLastToast != null) {
mLastToast.cancel();
}
- mLastToast = makeAllUserToastAndShow(isRecentsButtonVisible
- ? R.string.screen_pinning_toast
- : R.string.screen_pinning_toast_recents_invisible);
+ mLastToast = makeAllUserToastAndShow(isGestureNavEnabled
+ ? R.string.screen_pinning_toast_gesture_nav
+ : isRecentsButtonVisible
+ ? R.string.screen_pinning_toast
+ : R.string.screen_pinning_toast_recents_invisible);
mLastShowToastTime = showToastTime;
}
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 d12bed9..5d5cbe9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -25,6 +25,7 @@
import static android.app.StatusBarManager.windowStateToString;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
+import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME;
import static com.android.systemui.Dependency.BG_HANDLER;
import static com.android.systemui.Dependency.MAIN_HANDLER;
import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_ASLEEP;
@@ -147,7 +148,6 @@
import com.android.systemui.bubbles.BubbleController;
import com.android.systemui.charging.WirelessChargingAnimation;
import com.android.systemui.classifier.FalsingLog;
-import com.android.systemui.classifier.FalsingManagerFactory;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.doze.DozeHost;
import com.android.systemui.doze.DozeLog;
@@ -239,6 +239,7 @@
import java.util.Map;
import javax.inject.Inject;
+import javax.inject.Named;
import dagger.Subcomponent;
@@ -383,6 +384,9 @@
@Nullable
@Inject
protected KeyguardLiftController mKeyguardLiftController;
+ @Inject
+ @Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME)
+ boolean mAllowNotificationLongPress;
// expanded notifications
protected NotificationPanelView mNotificationPanel; // the sliding/resizing panel within the notification window
@@ -701,6 +705,7 @@
mRecents = getComponent(Recents.class);
mKeyguardManager = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
+ mFalsingManager = Dependency.get(FalsingManager.class);
// Connect in to the status bar manager service
mCommandQueue = getComponent(CommandQueue.class);
@@ -776,7 +781,6 @@
putComponent(DozeHost.class, mDozeServiceHost);
mScreenPinningRequest = new ScreenPinningRequest(mContext);
- mFalsingManager = FalsingManagerFactory.getInstance(mContext);
Dependency.get(ActivityStarterDelegate.class).setActivityStarterImpl(this);
@@ -1065,7 +1069,7 @@
final NotificationRowBinderImpl rowBinder =
new NotificationRowBinderImpl(
mContext,
- SystemUIFactory.getInstance().provideAllowNotificationLongPress(),
+ mAllowNotificationLongPress,
mKeyguardBypassController,
mStatusBarStateController);
@@ -1243,7 +1247,7 @@
mStatusBarKeyguardViewManager = keyguardViewMediator.registerStatusBar(this,
getBouncerContainer(), mNotificationPanel, mBiometricUnlockController,
mStatusBarWindow.findViewById(R.id.lock_icon_container), mStackScroller,
- mKeyguardBypassController);
+ mKeyguardBypassController, mFalsingManager);
mKeyguardIndicationController
.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
mBiometricUnlockController.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
@@ -2415,7 +2419,7 @@
mKeyguardUpdateMonitor.dump(fd, pw, args);
}
- FalsingManagerFactory.getInstance(mContext).dump(pw);
+ Dependency.get(FalsingManager.class).dump(pw);
FalsingLog.dump(pw);
pw.println("SharedPreferences:");
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 7e86651..0c47d14 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -44,6 +44,7 @@
import com.android.systemui.SystemUIFactory;
import com.android.systemui.dock.DockManager;
import com.android.systemui.keyguard.DismissCallbackRegistry;
+import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.statusbar.CommandQueue;
@@ -210,7 +211,7 @@
BiometricUnlockController biometricUnlockController,
DismissCallbackRegistry dismissCallbackRegistry,
ViewGroup lockIconContainer, View notificationContainer,
- KeyguardBypassController bypassController) {
+ KeyguardBypassController bypassController, FalsingManager falsingManager) {
mStatusBar = statusBar;
mContainer = container;
mLockIconContainer = lockIconContainer;
@@ -220,7 +221,7 @@
mBiometricUnlockController = biometricUnlockController;
mBouncer = SystemUIFactory.getInstance().createKeyguardBouncer(mContext,
mViewMediatorCallback, mLockPatternUtils, container, dismissCallbackRegistry,
- mExpansionCallback, bypassController);
+ mExpansionCallback, falsingManager, bypassController);
mNotificationPanelView = notificationPanelView;
notificationPanelView.addExpansionListener(this);
mBypassController = bypassController;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
index 0ef981b..946fe0b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
@@ -39,9 +39,9 @@
import android.view.WindowManager.LayoutParams;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.keyguard.R;
import com.android.systemui.Dependency;
import com.android.systemui.Dumpable;
+import com.android.systemui.R;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index 1081bad..6789930 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -62,7 +62,6 @@
import com.android.systemui.Dependency;
import com.android.systemui.ExpandHelper;
import com.android.systemui.R;
-import com.android.systemui.classifier.FalsingManagerFactory;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.DragDownHelper;
@@ -157,7 +156,7 @@
setMotionEventSplittingEnabled(false);
mTransparentSrcPaint.setColor(0);
mTransparentSrcPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
- mFalsingManager = FalsingManagerFactory.getInstance(context);
+ mFalsingManager = Dependency.get(FalsingManager.class); // TODO: inject into a controller.
mGestureDetector = new GestureDetector(context, mGestureListener);
mStatusBarStateController = Dependency.get(StatusBarStateController.class);
Dependency.get(TunerService.class).addTunable(mTunable,
@@ -291,7 +290,7 @@
ExpandHelper.Callback expandHelperCallback = stackScrollLayout.getExpandHelperCallback();
DragDownHelper.DragDownCallback dragDownCallback = stackScrollLayout.getDragDownCallback();
setDragDownHelper(new DragDownHelper(getContext(), this, expandHelperCallback,
- dragDownCallback));
+ dragDownCallback, mFalsingManager));
}
@VisibleForTesting
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index e75365e..dbfb09f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -21,6 +21,7 @@
import android.net.NetworkCapabilities;
import android.os.Handler;
import android.os.Looper;
+import android.os.Message;
import android.provider.Settings.Global;
import android.telephony.NetworkRegistrationInfo;
import android.telephony.PhoneStateListener;
@@ -54,6 +55,10 @@
public class MobileSignalController extends SignalController<
MobileSignalController.MobileState, MobileSignalController.MobileIconGroup> {
+
+ // The message to display Nr5G icon gracfully by CarrierConfig timeout
+ private static final int MSG_DISPLAY_GRACE = 1;
+
private final TelephonyManager mPhone;
private final SubscriptionDefaults mDefaults;
private final String mNetworkNameDefault;
@@ -76,8 +81,11 @@
private SignalStrength mSignalStrength;
private MobileIconGroup mDefaultIcons;
private Config mConfig;
+ private final Handler mDisplayGraceHandler;
@VisibleForTesting
boolean mInflateSignalStrengths = false;
+ @VisibleForTesting
+ boolean mIsShowingIconGracefully = false;
// Some specific carriers have 5GE network which is special LTE CA network.
private static final int NETWORK_TYPE_LTE_CA_5GE = TelephonyManager.MAX_NETWORK_TYPE + 1;
@@ -116,6 +124,16 @@
updateTelephony();
}
};
+
+ mDisplayGraceHandler = new Handler(receiverLooper) {
+ @Override
+ public void handleMessage(Message msg) {
+ if (msg.what == MSG_DISPLAY_GRACE) {
+ mIsShowingIconGracefully = false;
+ updateTelephony();
+ }
+ }
+ };
}
public void setConfiguration(Config config) {
@@ -479,6 +497,10 @@
// When the device is camped on a 5G Non-Standalone network, the data network type is still
// LTE. In this case, we first check which 5G icon should be shown.
MobileIconGroup nr5GIconGroup = getNr5GIconGroup();
+ if (mConfig.nrIconDisplayGracePeriodMs > 0) {
+ nr5GIconGroup = adjustNr5GIconGroupByDisplayGraceTime(nr5GIconGroup);
+ }
+
if (nr5GIconGroup != null) {
mCurrentState.iconGroup = nr5GIconGroup;
} else if (mNetworkToIconLookup.indexOfKey(mDataNetType) >= 0) {
@@ -537,8 +559,14 @@
return mConfig.nr5GIconMap.get(Config.NR_CONNECTED);
}
} else if (nrState == NetworkRegistrationInfo.NR_STATE_NOT_RESTRICTED) {
- if (mConfig.nr5GIconMap.containsKey(Config.NR_NOT_RESTRICTED)) {
- return mConfig.nr5GIconMap.get(Config.NR_NOT_RESTRICTED);
+ if (mCurrentState.activityDormant) {
+ if (mConfig.nr5GIconMap.containsKey(Config.NR_NOT_RESTRICTED_RRC_IDLE)) {
+ return mConfig.nr5GIconMap.get(Config.NR_NOT_RESTRICTED_RRC_IDLE);
+ }
+ } else {
+ if (mConfig.nr5GIconMap.containsKey(Config.NR_NOT_RESTRICTED_RRC_CON)) {
+ return mConfig.nr5GIconMap.get(Config.NR_NOT_RESTRICTED_RRC_CON);
+ }
}
} else if (nrState == NetworkRegistrationInfo.NR_STATE_RESTRICTED) {
if (mConfig.nr5GIconMap.containsKey(Config.NR_RESTRICTED)) {
@@ -549,6 +577,46 @@
return null;
}
+ /**
+ * The function to adjust MobileIconGroup depend on CarrierConfig's time
+ * nextIconGroup == null imply next state could be 2G/3G/4G/4G+
+ * nextIconGroup != null imply next state will be 5G/5G+
+ * Flag : mIsShowingIconGracefully
+ * ---------------------------------------------------------------------------------
+ * | Last state | Current state | Flag | Action |
+ * ---------------------------------------------------------------------------------
+ * | 5G/5G+ | 2G/3G/4G/4G+ | true | return previous IconGroup |
+ * | 5G/5G+ | 5G/5G+ | true | Bypass |
+ * | 2G/3G/4G/4G+ | 5G/5G+ | true | Bypass |
+ * | 2G/3G/4G/4G+ | 2G/3G/4G/4G+ | true | Bypass |
+ * | SS.connected | SS.disconnect | T|F | Reset timer |
+ * |NETWORK_TYPE_LTE|!NETWORK_TYPE_LTE| T|F | Reset timer |
+ * | 5G/5G+ | 2G/3G/4G/4G+ | false| Bypass |
+ * | 5G/5G+ | 5G/5G+ | false| Bypass |
+ * | 2G/3G/4G/4G+ | 5G/5G+ | false| SendMessageDelay(time), flag->true |
+ * | 2G/3G/4G/4G+ | 2G/3G/4G/4G+ | false| Bypass |
+ * ---------------------------------------------------------------------------------
+ */
+ private MobileIconGroup adjustNr5GIconGroupByDisplayGraceTime(
+ MobileIconGroup candidateIconGroup) {
+ if (mIsShowingIconGracefully && candidateIconGroup == null) {
+ candidateIconGroup = (MobileIconGroup) mCurrentState.iconGroup;
+ } else if (!mIsShowingIconGracefully && candidateIconGroup != null
+ && mLastState.iconGroup != candidateIconGroup) {
+ mDisplayGraceHandler.sendMessageDelayed(
+ mDisplayGraceHandler.obtainMessage(MSG_DISPLAY_GRACE),
+ mConfig.nrIconDisplayGracePeriodMs);
+ mIsShowingIconGracefully = true;
+ } else if (!mCurrentState.connected || mDataState == TelephonyManager.DATA_DISCONNECTED
+ || candidateIconGroup == null) {
+ mDisplayGraceHandler.removeMessages(MSG_DISPLAY_GRACE);
+ mIsShowingIconGracefully = false;
+ candidateIconGroup = null;
+ }
+
+ return candidateIconGroup;
+ }
+
private boolean isDataDisabled() {
return !mPhone.isDataCapable();
}
@@ -559,6 +627,8 @@
|| activity == TelephonyManager.DATA_ACTIVITY_IN;
mCurrentState.activityOut = activity == TelephonyManager.DATA_ACTIVITY_INOUT
|| activity == TelephonyManager.DATA_ACTIVITY_OUT;
+ mCurrentState.activityDormant = activity == TelephonyManager.DATA_ACTIVITY_DORMANT;
+
notifyListenersIfNecessary();
}
@@ -572,6 +642,7 @@
pw.println(" mDataNetType=" + mDataNetType + ",");
pw.println(" mInflateSignalStrengths=" + mInflateSignalStrengths + ",");
pw.println(" isDataDisabled=" + isDataDisabled() + ",");
+ pw.println(" mIsShowingIconGracefully=" + mIsShowingIconGracefully + ",");
}
class MobilePhoneStateListener extends PhoneStateListener {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index 1c24bb9..bb37421 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -51,6 +51,7 @@
import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
+import android.text.format.DateUtils;
import android.util.Log;
import android.util.MathUtils;
import android.util.SparseArray;
@@ -829,6 +830,13 @@
pw.print(" mEmergencySource=");
pw.println(emergencyToString(mEmergencySource));
+ pw.println(" - config ------");
+ pw.print(" patternOfCarrierSpecificDataIcon=");
+ pw.println(mConfig.patternOfCarrierSpecificDataIcon);
+ pw.print(" nr5GIconMap=");
+ pw.println(mConfig.nr5GIconMap.toString());
+ pw.print(" nrIconDisplayGracePeriodMs=");
+ pw.println(mConfig.nrIconDisplayGracePeriodMs);
for (int i = 0; i < mMobileSignalControllers.size(); i++) {
MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
mobileSignalController.dump(pw);
@@ -992,6 +1000,8 @@
datatype.equals("3g") ? TelephonyIcons.THREE_G :
datatype.equals("4g") ? TelephonyIcons.FOUR_G :
datatype.equals("4g+") ? TelephonyIcons.FOUR_G_PLUS :
+ datatype.equals("5g") ? TelephonyIcons.NR_5G :
+ datatype.equals("5g+") ? TelephonyIcons.NR_5G_PLUS :
datatype.equals("e") ? TelephonyIcons.E :
datatype.equals("g") ? TelephonyIcons.G :
datatype.equals("h") ? TelephonyIcons.H :
@@ -1108,8 +1118,9 @@
static class Config {
static final int NR_CONNECTED_MMWAVE = 1;
static final int NR_CONNECTED = 2;
- static final int NR_NOT_RESTRICTED = 3;
- static final int NR_RESTRICTED = 4;
+ static final int NR_NOT_RESTRICTED_RRC_IDLE = 3;
+ static final int NR_NOT_RESTRICTED_RRC_CON = 4;
+ static final int NR_RESTRICTED = 5;
Map<Integer, MobileIconGroup> nr5GIconMap = new HashMap<>();
@@ -1122,6 +1133,7 @@
boolean inflateSignalStrengths = false;
boolean alwaysShowDataRatIcon = false;
public String patternOfCarrierSpecificDataIcon = "";
+ public long nrIconDisplayGracePeriodMs;
/**
* Mapping from NR 5G status string to an integer. The NR 5G status string should match
@@ -1129,10 +1141,11 @@
*/
private static final Map<String, Integer> NR_STATUS_STRING_TO_INDEX;
static {
- NR_STATUS_STRING_TO_INDEX = new HashMap<>(4);
+ NR_STATUS_STRING_TO_INDEX = new HashMap<>(5);
NR_STATUS_STRING_TO_INDEX.put("connected_mmwave", NR_CONNECTED_MMWAVE);
NR_STATUS_STRING_TO_INDEX.put("connected", NR_CONNECTED);
- NR_STATUS_STRING_TO_INDEX.put("not_restricted", NR_NOT_RESTRICTED);
+ NR_STATUS_STRING_TO_INDEX.put("not_restricted_rrc_idle", NR_NOT_RESTRICTED_RRC_IDLE);
+ NR_STATUS_STRING_TO_INDEX.put("not_restricted_rrc_con", NR_NOT_RESTRICTED_RRC_CON);
NR_STATUS_STRING_TO_INDEX.put("restricted", NR_RESTRICTED);
}
@@ -1173,6 +1186,9 @@
add5GIconMapping(pair, config);
}
}
+ setDisplayGraceTime(
+ b.getInt(CarrierConfigManager.KEY_5G_ICON_DISPLAY_GRACE_PERIOD_SEC_INT),
+ config);
}
return config;
@@ -1206,5 +1222,18 @@
TelephonyIcons.ICON_NAME_TO_ICON.get(value));
}
}
+
+ /**
+ * Set display gracefully period time(MS) depend on carrierConfig KEY
+ * KEY_5G_ICON_DISPLAY_GRACE_PERIOD_SEC_INT, and this function will convert to ms.
+ * {@link CarrierConfigManager}.
+ *
+ * @param time showing 5G icon gracefully in the period of the time(SECOND)
+ * @param config container that used to store the parsed configs.
+ */
+ @VisibleForTesting
+ static void setDisplayGraceTime(int time, Config config) {
+ config.nrIconDisplayGracePeriodMs = time * DateUtils.SECOND_IN_MILLIS;
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java
index 9ec30d4..abe3f2c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java
@@ -258,6 +258,7 @@
boolean enabled;
boolean activityIn;
boolean activityOut;
+ public boolean activityDormant;
int level;
IconGroup iconGroup;
int inetCondition;
@@ -274,6 +275,7 @@
inetCondition = state.inetCondition;
activityIn = state.activityIn;
activityOut = state.activityOut;
+ activityDormant = state.activityDormant;
rssi = state.rssi;
time = state.time;
}
@@ -297,6 +299,7 @@
.append("iconGroup=").append(iconGroup).append(',')
.append("activityIn=").append(activityIn).append(',')
.append("activityOut=").append(activityOut).append(',')
+ .append("activityDormant=").append(activityDormant).append(',')
.append("rssi=").append(rssi).append(',')
.append("lastModified=").append(DateFormat.format("MM-dd HH:mm:ss", time));
}
@@ -314,6 +317,7 @@
&& other.iconGroup == iconGroup
&& other.activityIn == activityIn
&& other.activityOut == activityOut
+ && other.activityDormant == activityDormant
&& other.rssi == rssi;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java
index 1d4f9b3..9750790 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java
@@ -31,6 +31,7 @@
import com.android.systemui.Dependency;
import com.android.systemui.R;
+import com.android.systemui.SystemUIFactory;
import com.android.systemui.fragments.FragmentService;
public class TunerActivity extends Activity implements
@@ -50,7 +51,7 @@
setActionBar(toolbar);
}
- Dependency.initDependencies(this);
+ Dependency.initDependencies(SystemUIFactory.getInstance().getRootComponent());
if (getFragmentManager().findFragmentByTag(TAG_TUNER) == null) {
final String action = getIntent().getAction();
diff --git a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
index de86f3d..ff5bd03 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
@@ -628,6 +628,14 @@
final int requestKey = vol.getId().hashCode();
return PendingIntent.getActivityAsUser(mContext, requestKey, intent,
PendingIntent.FLAG_CANCEL_CURRENT, null, UserHandle.CURRENT);
+ } else if (isAutomotive()) {
+ intent.setClassName("com.android.car.settings",
+ "com.android.car.settings.storage.StorageUnmountReceiver");
+ intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, vol.getId());
+
+ final int requestKey = vol.getId().hashCode();
+ return PendingIntent.getBroadcastAsUser(mContext, requestKey, intent,
+ PendingIntent.FLAG_CANCEL_CURRENT, UserHandle.CURRENT);
} else {
intent.setClassName("com.android.settings",
"com.android.settings.deviceinfo.StorageUnmountReceiver");
@@ -749,6 +757,11 @@
PendingIntent.FLAG_CANCEL_CURRENT, null, UserHandle.CURRENT);
}
+ private boolean isAutomotive() {
+ PackageManager packageManager = mContext.getPackageManager();
+ return packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
+ }
+
private boolean isTv() {
PackageManager packageManager = mContext.getPackageManager();
return packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK);
diff --git a/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java b/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
index ede3004..e44e58a 100644
--- a/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
+++ b/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
@@ -26,12 +26,13 @@
import com.android.keyguard.KeyguardClockSwitch;
import com.android.keyguard.KeyguardMessageArea;
import com.android.keyguard.KeyguardSliceView;
-import com.android.systemui.SystemUIFactory;
+import com.android.systemui.SystemUIRootComponent;
import com.android.systemui.qs.QSCarrierGroup;
import com.android.systemui.qs.QSFooterImpl;
import com.android.systemui.qs.QSPanel;
import com.android.systemui.qs.QuickQSPanel;
import com.android.systemui.qs.QuickStatusBarHeader;
+import com.android.systemui.qs.customize.QSCustomizer;
import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.phone.LockIcon;
@@ -62,7 +63,7 @@
private final LayoutInflater.Factory2 mFactory = new InjectionFactory();
@Inject
- public InjectionInflationController(SystemUIFactory.SystemUIRootComponent rootComponent) {
+ public InjectionInflationController(SystemUIRootComponent rootComponent) {
mViewCreator = rootComponent.createViewCreator();
initInjectionMap();
}
@@ -172,6 +173,11 @@
* Creates the QuickQSPanel.
*/
QuickQSPanel createQuickQSPanel();
+
+ /**
+ * Creates the QSCustomizer.
+ */
+ QSCustomizer createQSCustomizer();
}
/**
diff --git a/packages/SystemUI/tests/Android.mk b/packages/SystemUI/tests/Android.mk
index 5412cde..81e2c22 100644
--- a/packages/SystemUI/tests/Android.mk
+++ b/packages/SystemUI/tests/Android.mk
@@ -39,7 +39,7 @@
telephony-common \
android.test.base \
-LOCAL_AAPT_FLAGS := --extra-packages com.android.systemui:com.android.keyguard
+LOCAL_AAPT_FLAGS := --extra-packages com.android.systemui
# sign this with platform cert, so this test is allowed to inject key events into
# UI it doesn't own. This is necessary to allow screenshots to be taken
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java
index 0044ca7..1421b06 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java
@@ -46,6 +46,7 @@
import com.android.internal.telephony.IccCardConstants;
import com.android.systemui.Dependency;
+import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.keyguard.WakefulnessLifecycle;
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockAccessibilityDelegateTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockAccessibilityDelegateTest.java
index dcafa72..00f88bf 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockAccessibilityDelegateTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockAccessibilityDelegateTest.java
@@ -27,6 +27,7 @@
import androidx.test.filters.SmallTest;
+import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import org.junit.Before;
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java
index f01c0b4..de7664c 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java
@@ -39,6 +39,7 @@
import android.widget.TextClock;
import com.android.keyguard.clock.ClockManager;
+import com.android.systemui.R;
import com.android.systemui.SystemUIFactory;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.ClockPlugin;
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewTest.kt
index 5f03bdb..42a8950 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewTest.kt
@@ -21,6 +21,7 @@
import android.testing.TestableLooper
import android.view.LayoutInflater
+import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.statusbar.policy.ConfigurationController
import com.google.common.truth.Truth.assertThat
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinBasedInputViewTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinBasedInputViewTest.java
index eadb1b6..202fbd7 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinBasedInputViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinBasedInputViewTest.java
@@ -28,6 +28,7 @@
import androidx.test.filters.SmallTest;
+import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import org.junit.Before;
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
index 8db195a..d47fcee 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
@@ -23,6 +23,7 @@
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import org.junit.Test;
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSliceViewTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSliceViewTest.java
index b3accbc..116f8fc 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSliceViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSliceViewTest.java
@@ -27,6 +27,7 @@
import androidx.slice.SliceSpecs;
import androidx.slice.builders.ListBuilder;
+import com.android.systemui.R;
import com.android.systemui.SystemUIFactory;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.keyguard.KeyguardSliceProvider;
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewTest.java
index 31ea39c..87f2ef5 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewTest.java
@@ -24,6 +24,7 @@
import android.testing.TestableLooper.RunWithLooper;
import android.view.LayoutInflater;
+import com.android.systemui.R;
import com.android.systemui.SystemUIFactory;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.util.Assert;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/DependencyTest.java b/packages/SystemUI/tests/src/com/android/systemui/DependencyTest.java
index b1ca169..b9d09ce 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/DependencyTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/DependencyTest.java
@@ -74,6 +74,6 @@
@Test
public void testInitDependency() {
Dependency.clearDependencies();
- Dependency.initDependencies(mContext);
+ Dependency.initDependencies(SystemUIFactory.getInstance().getRootComponent());
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/IconPackOverlayTest.java b/packages/SystemUI/tests/src/com/android/systemui/IconPackOverlayTest.java
index ccc9afc..0fa7443 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/IconPackOverlayTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/IconPackOverlayTest.java
@@ -32,6 +32,7 @@
import androidx.test.runner.AndroidJUnit4;
import com.android.internal.util.XmlUtils;
+import com.android.systemui.tests.R;
import org.junit.After;
import org.junit.Before;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/TestableDependency.java b/packages/SystemUI/tests/src/com/android/systemui/TestableDependency.java
index 18bf75e..0c53b03 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/TestableDependency.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/TestableDependency.java
@@ -25,10 +25,6 @@
private final ArraySet<Object> mInstantiatedObjects = new ArraySet<>();
public TestableDependency(Context context) {
- if (context instanceof SysuiTestableContext) {
- mComponents = ((SysuiTestableContext) context).getComponents();
- }
- mContext = context;
SystemUIFactory.createFromConfig(context);
SystemUIFactory.getInstance().getRootComponent()
.createDependency()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubblesTestActivity.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubblesTestActivity.java
index 43d2ad1..8bc2e2b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubblesTestActivity.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubblesTestActivity.java
@@ -20,7 +20,7 @@
import android.content.Intent;
import android.os.Bundle;
-import com.android.systemui.R;
+import com.android.systemui.tests.R;
/**
* Referenced by NotificationTestHelper#makeBubbleMetadata
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java
index 2ed0970..0c124ff 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java
@@ -37,7 +37,6 @@
when(params.getPulseOnSigMotion()).thenReturn(false);
when(params.getPickupVibrationThreshold()).thenReturn(0);
when(params.getProxCheckBeforePulse()).thenReturn(true);
- when(params.getPickupPerformsProxCheck()).thenReturn(true);
when(params.getPolicy()).thenReturn(mock(AlwaysOnDisplayPolicy.class));
when(params.doubleTapReportsTouchCoordinates()).thenReturn(false);
when(params.getDisplayNeedsBlanking()).thenReturn(false);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
index 6dfb19e..1e18e51 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java
@@ -45,11 +45,14 @@
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.util.wakelock.WakeLockFake;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@@ -58,6 +61,8 @@
DozeMachine mMachine;
+ @Mock
+ private WakefulnessLifecycle mWakefulnessLifecycle;
private DozeServiceFake mServiceFake;
private WakeLockFake mWakeLockFake;
private AmbientDisplayConfiguration mConfigMock;
@@ -65,12 +70,13 @@
@Before
public void setUp() {
+ MockitoAnnotations.initMocks(this);
mServiceFake = new DozeServiceFake();
mWakeLockFake = new WakeLockFake();
mConfigMock = mock(AmbientDisplayConfiguration.class);
mPartMock = mock(DozeMachine.Part.class);
- mMachine = new DozeMachine(mServiceFake, mConfigMock, mWakeLockFake);
+ mMachine = new DozeMachine(mServiceFake, mConfigMock, mWakeLockFake, mWakefulnessLifecycle);
mMachine.setParts(new DozeMachine.Part[]{mPartMock});
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java
index 7df45a3..cd6d1e0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java
@@ -19,7 +19,6 @@
import static com.android.systemui.plugins.SensorManagerPlugin.Sensor.TYPE_WAKE_LOCK_SCREEN;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
@@ -79,8 +78,6 @@
private AlwaysOnDisplayPolicy mAlwaysOnDisplayPolicy;
@Mock
private TriggerSensor mTriggerSensor;
- @Mock
- private TriggerSensor mProxGatedTriggerSensor;
private SensorManagerPlugin.SensorEventListener mWakeLockScreenListener;
private TestableLooper mTestableLooper;
private DozeSensors mDozeSensors;
@@ -88,7 +85,6 @@
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- when(mProxGatedTriggerSensor.performsProxCheck()).thenReturn(true);
mTestableLooper = TestableLooper.get(this);
when(mAmbientDisplayConfiguration.getWakeLockScreenDebounce()).thenReturn(5000L);
when(mAmbientDisplayConfiguration.alwaysOnEnabled(anyInt())).thenReturn(true);
@@ -106,14 +102,14 @@
mWakeLockScreenListener.onSensorChanged(mock(SensorManagerPlugin.SensorEvent.class));
mTestableLooper.processAllMessages();
verify(mCallback).onSensorPulse(eq(DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN),
- anyBoolean(), anyFloat(), anyFloat(), eq(null));
+ anyFloat(), anyFloat(), eq(null));
mDozeSensors.requestTemporaryDisable();
reset(mCallback);
mWakeLockScreenListener.onSensorChanged(mock(SensorManagerPlugin.SensorEvent.class));
mTestableLooper.processAllMessages();
verify(mCallback, never()).onSensorPulse(eq(DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN),
- anyBoolean(), anyFloat(), anyFloat(), eq(null));
+ anyFloat(), anyFloat(), eq(null));
}
@Test
@@ -132,20 +128,17 @@
}
@Test
- public void testSetPaused_onlyPausesNonGatedSensors() {
+ public void testSetPaused_doesntPause_sensors() {
mDozeSensors.setListening(true);
verify(mTriggerSensor).setListening(eq(true));
- verify(mProxGatedTriggerSensor).setListening(eq(true));
- clearInvocations(mTriggerSensor, mProxGatedTriggerSensor);
+ clearInvocations(mTriggerSensor);
mDozeSensors.setPaused(true);
- verify(mTriggerSensor).setListening(eq(false));
- verify(mProxGatedTriggerSensor).setListening(eq(true));
-
- clearInvocations(mTriggerSensor, mProxGatedTriggerSensor);
- mDozeSensors.setPaused(false);
verify(mTriggerSensor).setListening(eq(true));
- verify(mProxGatedTriggerSensor).setListening(eq(true));
+
+ clearInvocations(mTriggerSensor);
+ mDozeSensors.setListening(false);
+ verify(mTriggerSensor).setListening(eq(false));
}
private class TestableDozeSensors extends DozeSensors {
@@ -161,7 +154,7 @@
mWakeLockScreenListener = (PluginSensor) sensor;
}
}
- mSensors = new TriggerSensor[] {mTriggerSensor, mProxGatedTriggerSensor};
+ mSensors = new TriggerSensor[] {mTriggerSensor};
}
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
index d464223..e190f99 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
@@ -20,7 +20,6 @@
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.clearInvocations;
-import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
@@ -134,28 +133,4 @@
mTriggers.transitionTo(DozeMachine.State.DOZE, DozeMachine.State.FINISH);
verify(mDockManagerFake).removeListener(any());
}
-
- @Test
- public void testOnSensor_whenUndockedWithNearAndDoubleTapScreen_shouldNotWakeUp() {
- mSensors.getMockProximitySensor().sendProximityResult(false /* far */);
-
- mTriggers.onSensor(DozeLog.REASON_SENSOR_DOUBLE_TAP,
- false /* sensorPerformedProxCheck */, 50 /* screenX */, 50 /* screenY */,
- null /* rawValues */);
- verify(mMachine, never()).wakeUp();
- }
-
- @Test
- public void testOnSensor_whenDockedWithNearAndDoubleTapScreen_shouldWakeUp() {
- doReturn(true).when(mDockManagerFake).isDocked();
- doReturn(true).when(mParameters).getDisplayNeedsBlanking();
- mSensors.getMockProximitySensor().sendProximityResult(false /* far */);
-
- mTriggers.onSensor(DozeLog.REASON_SENSOR_DOUBLE_TAP,
- false /* sensorPerformedProxCheck */, 50 /* screenX */, 50 /* screenY */,
- null /* rawValues */);
-
- verify(mHost).setAodDimmingScrim(eq(1f));
- verify(mMachine).wakeUp();
- }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UserDetailViewAdapterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UserDetailViewAdapterTest.kt
new file mode 100644
index 0000000..b51e716
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UserDetailViewAdapterTest.kt
@@ -0,0 +1,128 @@
+/*
+ * 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.content.Context
+import android.content.pm.UserInfo
+import android.graphics.Bitmap
+import android.testing.AndroidTestingRunner
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.statusbar.policy.UserSwitcherController
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.any
+import org.mockito.ArgumentMatchers.anyBoolean
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.Mock
+import org.mockito.Mockito.`when`
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@RunWith(AndroidTestingRunner::class)
+@SmallTest
+class UserDetailViewAdapterTest : SysuiTestCase() {
+
+ @Mock private lateinit var mUserSwitcherController: UserSwitcherController
+ @Mock private lateinit var mParent: ViewGroup
+ @Mock private lateinit var mUserDetailItemView: UserDetailItemView
+ @Mock private lateinit var mOtherView: View
+ @Mock private lateinit var mInflatedUserDetailItemView: UserDetailItemView
+ @Mock private lateinit var mUserInfo: UserInfo
+ @Mock private lateinit var mPicture: Bitmap
+ @Mock private lateinit var mLayoutInflater: LayoutInflater
+ private lateinit var adapter: UserDetailView.Adapter
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+
+ mContext.addMockSystemService(Context.LAYOUT_INFLATER_SERVICE, mLayoutInflater)
+ `when`(mLayoutInflater.inflate(anyInt(), any(ViewGroup::class.java), anyBoolean()))
+ .thenReturn(mInflatedUserDetailItemView)
+ adapter = UserDetailView.Adapter(mContext, mUserSwitcherController)
+ }
+
+ private fun clickableTest(
+ current: Boolean,
+ guest: Boolean,
+ convertView: View,
+ shouldBeClickable: Boolean
+ ) {
+ val user = createUserRecord(current, guest)
+ val v = adapter.createUserDetailItemView(convertView, mParent, user)
+ if (shouldBeClickable) {
+ verify(v).setOnClickListener(adapter)
+ } else {
+ verify(v).setOnClickListener(null)
+ }
+ }
+
+ @Test
+ fun testGuestIsClickable_differentViews_notCurrent() {
+ clickableTest(false, true, mOtherView, true)
+ }
+
+ @Test
+ fun testGuestIsClickable_differentViews_Current() {
+ clickableTest(true, true, mOtherView, true)
+ }
+
+ @Test
+ fun testGuestIsClickable_sameView_notCurrent() {
+ clickableTest(false, true, mUserDetailItemView, true)
+ }
+
+ @Test
+ fun testGuestIsClickable_sameView_Current() {
+ clickableTest(true, true, mUserDetailItemView, true)
+ }
+
+ @Test
+ fun testNotGuestCurrentUserIsNotClickable_otherView() {
+ clickableTest(true, false, mOtherView, false)
+ }
+
+ @Test
+ fun testNotGuestCurrentUserIsNotClickable_sameView() {
+ clickableTest(true, false, mUserDetailItemView, false)
+ }
+
+ @Test
+ fun testNotGuestNotCurrentUserIsClickable_otherView() {
+ clickableTest(false, false, mOtherView, true)
+ }
+
+ @Test
+ fun testNotGuestNotCurrentUserIsClickable_sameView() {
+ clickableTest(false, false, mUserDetailItemView, true)
+ }
+
+ private fun createUserRecord(current: Boolean, guest: Boolean) =
+ UserSwitcherController.UserRecord(
+ mUserInfo,
+ mPicture,
+ guest,
+ current,
+ false /* isAddUser */,
+ false /* isRestricted */,
+ true /* isSwitchToEnabled */)
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotStubActivity.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotStubActivity.java
index 784d035..0b871e4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotStubActivity.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotStubActivity.java
@@ -15,11 +15,11 @@
*/
package com.android.systemui.screenshot;
-import com.android.systemui.R;
-
import android.app.Activity;
import android.os.Bundle;
+import com.android.systemui.tests.R;
+
/**
* A stub activity used in {@link ScreenshotTest}.
*/
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 7063ddf..ab207f8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java
@@ -40,7 +40,6 @@
import androidx.test.InstrumentationRegistry;
-import com.android.systemui.R;
import com.android.systemui.bubbles.BubblesTestActivity;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -50,7 +49,7 @@
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
-import com.android.systemui.statusbar.policy.HeadsUpManager;
+import com.android.systemui.tests.R;
/**
* A helper class to create {@link ExpandableNotificationRow} (for both individual and group
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/MediaNotificationProcessorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/MediaNotificationProcessorTest.java
index 7eeae67..e6287e7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/MediaNotificationProcessorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/MediaNotificationProcessorTest.java
@@ -38,8 +38,8 @@
import androidx.palette.graphics.Palette;
import androidx.test.runner.AndroidJUnit4;
-import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.tests.R;
import org.junit.After;
import org.junit.Before;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentInflaterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentInflaterTest.java
index 2ec125e..ccadcc3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentInflaterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentInflaterTest.java
@@ -23,7 +23,6 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
@@ -44,12 +43,12 @@
import androidx.test.filters.SmallTest;
-import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.InflationTask;
import com.android.systemui.statusbar.NotificationTestHelper;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationCallback;
+import com.android.systemui.tests.R;
import org.junit.Assert;
import org.junit.Before;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapperTest.java
index 63e18ce..49a6410 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapperTest.java
@@ -24,10 +24,10 @@
import androidx.test.filters.SmallTest;
-import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.NotificationTestHelper;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.tests.R;
import org.junit.Assert;
import org.junit.Before;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
index c851c91..31054260 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
@@ -53,6 +53,7 @@
import com.android.systemui.InitController;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.EmptyShadeView;
@@ -80,7 +81,6 @@
import com.android.systemui.statusbar.policy.ConfigurationController;
import org.junit.After;
-import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -165,7 +165,8 @@
mock(ActivityStarterDelegate.class),
mock(SysuiStatusBarStateController.class),
mHeadsUpManager,
- mKeyguardBypassController);
+ mKeyguardBypassController,
+ new FalsingManagerFake());
mStackScroller = spy(mStackScrollerInternal);
mStackScroller.setShelf(notificationShelf);
mStackScroller.setStatusBar(mBar);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java
index b24c3dd..06a2eec 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java
@@ -40,6 +40,7 @@
import com.android.systemui.SwipeHelper;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
@@ -76,7 +77,8 @@
public void setUp() throws Exception {
mCallback = mock(NotificationSwipeHelper.NotificationCallback.class);
mListener = mock(NotificationMenuRowPlugin.OnMenuEventListener.class);
- mSwipeHelper = spy(new NotificationSwipeHelper(SwipeHelper.X, mCallback, mContext, mListener));
+ mSwipeHelper = spy(new NotificationSwipeHelper(
+ SwipeHelper.X, mCallback, mContext, mListener, new FalsingManagerFake()));
mView = mock(View.class);
mEvent = mock(MotionEvent.class);
mMenuRow = mock(NotificationMenuRowPlugin.class);
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 d14b460..0334d49 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
@@ -21,21 +21,26 @@
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.StatusBarManager;
+import android.hardware.biometrics.BiometricSourceType;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.view.MotionEvent;
+import android.view.View;
import android.view.ViewGroup;
import androidx.test.filters.SmallTest;
import com.android.keyguard.KeyguardStatusView;
+import com.android.keyguard.KeyguardUpdateMonitor;
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.statusbar.KeyguardAffordanceView;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
@@ -49,7 +54,6 @@
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.ZenModeController;
-import com.android.systemui.tuner.TunerService;
import com.android.systemui.util.InjectionInflationController;
import org.junit.Before;
@@ -98,6 +102,12 @@
private PanelBar mPanelBar;
@Mock
private KeyguardAffordanceHelper mAffordanceHelper;
+ @Mock
+ private KeyguardUpdateMonitor mUpdateMonitor;
+ @Mock
+ private FalsingManager mFalsingManager;
+ @Mock
+ private KeyguardBypassController mKeyguardBypassController;
private NotificationPanelView mNotificationPanelView;
@Before
@@ -112,18 +122,16 @@
mDependency.injectMockDependency(NotificationLockscreenUserManager.class);
mDependency.injectMockDependency(ConfigurationController.class);
mDependency.injectMockDependency(ZenModeController.class);
- KeyguardBypassController bypassController = new KeyguardBypassController(mContext,
- mock(TunerService.class), mStatusBarStateController,
- mock(NotificationLockscreenUserManager.class));
NotificationWakeUpCoordinator coordinator =
new NotificationWakeUpCoordinator(mContext,
mock(HeadsUpManagerPhone.class),
new StatusBarStateControllerImpl(),
- bypassController);
+ mKeyguardBypassController);
PulseExpansionHandler expansionHandler = new PulseExpansionHandler(mContext, coordinator,
- bypassController, mHeadsUpManager, mock(NotificationRoundnessManager.class));
+ mKeyguardBypassController, mHeadsUpManager,
+ mock(NotificationRoundnessManager.class));
mNotificationPanelView = new TestableNotificationPanelView(coordinator, expansionHandler,
- bypassController);
+ mKeyguardBypassController);
mNotificationPanelView.setHeadsUpManager(mHeadsUpManager);
mNotificationPanelView.setBar(mPanelBar);
@@ -183,6 +191,20 @@
assertThat(mNotificationPanelView.isTrackingBlocked()).isFalse();
}
+ @Test
+ public void testKeyguardStatusBarVisibility_hiddenForBypass() {
+ when(mUpdateMonitor.shouldListenForFace()).thenReturn(true);
+ mNotificationPanelView.mKeyguardUpdateCallback.onBiometricRunningStateChanged(true,
+ BiometricSourceType.FACE);
+ verify(mKeyguardStatusBar, never()).setVisibility(View.VISIBLE);
+
+ when(mKeyguardBypassController.getBypassEnabled()).thenReturn(true);
+ mNotificationPanelView.mKeyguardUpdateCallback.onFinishedGoingToSleep(0);
+ mNotificationPanelView.mKeyguardUpdateCallback.onBiometricRunningStateChanged(true,
+ BiometricSourceType.FACE);
+ verify(mKeyguardStatusBar, never()).setVisibility(View.VISIBLE);
+ }
+
private class TestableNotificationPanelView extends NotificationPanelView {
TestableNotificationPanelView(NotificationWakeUpCoordinator coordinator,
PulseExpansionHandler expansionHandler,
@@ -191,7 +213,8 @@
new InjectionInflationController(
SystemUIFactory.getInstance().getRootComponent()),
coordinator, expansionHandler, mock(DynamicPrivacyController.class),
- bypassController);
+ bypassController,
+ mFalsingManager);
mNotificationStackScroller = mNotificationStackScrollLayout;
mKeyguardStatusView = NotificationPanelViewTest.this.mKeyguardStatusView;
mKeyguardStatusBar = NotificationPanelViewTest.this.mKeyguardStatusBar;
@@ -199,6 +222,7 @@
mBigClockContainer = NotificationPanelViewTest.this.mBigClockContainer;
mQsFrame = NotificationPanelViewTest.this.mQsFrame;
mAffordanceHelper = NotificationPanelViewTest.this.mAffordanceHelper;
+ mUpdateMonitor = NotificationPanelViewTest.this.mUpdateMonitor;
initDependencies(NotificationPanelViewTest.this.mStatusBar,
NotificationPanelViewTest.this.mGroupManager,
NotificationPanelViewTest.this.mNotificationShelf,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
index da2e8dc..63f653b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
@@ -39,8 +39,10 @@
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.keyguard.DismissCallbackRegistry;
import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
+import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
@@ -93,7 +95,8 @@
mViewMediatorCallback, mLockPatternUtils);
mStatusBarKeyguardViewManager.registerStatusBar(mStatusBar, mContainer,
mNotificationPanelView, mBiometrucUnlockController, mDismissCallbackRegistry,
- mLockIconContainer, mNotificationContainer, mBypassController);
+ mLockIconContainer, mNotificationContainer, mBypassController,
+ new FalsingManagerFake());
mStatusBarKeyguardViewManager.show(null);
}
@@ -232,11 +235,11 @@
BiometricUnlockController fingerprintUnlockController,
DismissCallbackRegistry dismissCallbackRegistry,
ViewGroup lockIconContainer, View notificationContainer,
- KeyguardBypassController bypassController) {
+ KeyguardBypassController bypassController, FalsingManager falsingManager) {
super.registerStatusBar(statusBar, container, notificationPanelView,
fingerprintUnlockController, dismissCallbackRegistry, lockIconContainer,
- notificationContainer, bypassController);
+ notificationContainer, bypassController, falsingManager);
mBouncer = StatusBarKeyguardViewManagerTest.this.mBouncer;
}
}
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallbackTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallbackTest.java
index a97832f..4b6ca56 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallbackTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallbackTest.java
@@ -68,7 +68,7 @@
mDependency.injectTestDependency(ShadeController.class, mShadeController);
mDependency.injectTestDependency(NotificationLockscreenUserManager.class,
mNotificationLockscreenUserManager);
- mDependency.putComponent(CommandQueue.class, mock(CommandQueue.class));
+ mContext.putComponent(CommandQueue.class, mock(CommandQueue.class));
mRemoteInputCallback = spy(new StatusBarRemoteInputCallback(mContext,
mock(NotificationGroupManager.class)));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
index 9ae9ceb..c03f07e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
@@ -30,6 +30,7 @@
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
+import android.app.Instrumentation;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.Network;
@@ -48,6 +49,8 @@
import android.testing.TestableResources;
import android.util.Log;
+import androidx.test.InstrumentationRegistry;
+
import com.android.internal.telephony.cdma.EriInfo;
import com.android.settingslib.graph.SignalDrawable;
import com.android.settingslib.net.DataUsageController;
@@ -95,6 +98,7 @@
protected SubscriptionDefaults mMockSubDefaults;
protected DeviceProvisionedController mMockProvisionController;
protected DeviceProvisionedListener mUserCallback;
+ protected Instrumentation mInstrumentation;
protected int mSubId;
@@ -116,6 +120,7 @@
@Before
public void setUp() throws Exception {
+ mInstrumentation = InstrumentationRegistry.getInstrumentation();
Settings.Global.putInt(mContext.getContentResolver(), Global.AIRPLANE_MODE_ON, 0);
TestableResources res = mContext.getOrCreateTestableResources();
res.addOverride(R.string.cell_data_off_content_description, NO_DATA_STRING);
@@ -228,6 +233,28 @@
NetworkControllerImpl.Config.add5GIconMapping("connected:5g", mConfig);
}
+ public void setupNr5GIconConfigurationForNotRestrictedRrcCon() {
+ NetworkControllerImpl.Config.add5GIconMapping("connected_mmwave:5g_plus", mConfig);
+ NetworkControllerImpl.Config.add5GIconMapping("connected:5g_plus", mConfig);
+ NetworkControllerImpl.Config.add5GIconMapping("not_restricted_rrc_con:5g", mConfig);
+ }
+
+ public void setupNr5GIconConfigurationForNotRestrictedRrcIdle() {
+ NetworkControllerImpl.Config.add5GIconMapping("connected_mmwave:5g_plus", mConfig);
+ NetworkControllerImpl.Config.add5GIconMapping("connected:5g_plus", mConfig);
+ NetworkControllerImpl.Config.add5GIconMapping("not_restricted_rrc_idle:5g", mConfig);
+ }
+
+ public void setupDefaultNr5GIconDisplayGracePeriodTime_enableThirtySeconds() {
+ final int enableDisplayGraceTimeSec = 30;
+ NetworkControllerImpl.Config.setDisplayGraceTime(enableDisplayGraceTimeSec, mConfig);
+ }
+
+ public void setupDefaultNr5GIconDisplayGracePeriodTime_disabled() {
+ final int disableDisplayGraceTimeSec = 0;
+ NetworkControllerImpl.Config.setDisplayGraceTime(disableDisplayGraceTimeSec, mConfig);
+ }
+
public void setConnectivityViaBroadcast(
int networkType, boolean validated, boolean isConnected) {
setConnectivityCommon(networkType, validated, isConnected);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
index 5128675..3ddfbda 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
@@ -1,5 +1,7 @@
package com.android.systemui.statusbar.policy;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
@@ -175,6 +177,35 @@
}
@Test
+ public void testNr5GIcon_NrNotRestrictedRrcCon_show5GIcon() {
+ setupNr5GIconConfigurationForNotRestrictedRrcCon();
+ setupDefaultSignal();
+ updateDataConnectionState(TelephonyManager.DATA_CONNECTED,
+ TelephonyManager.NETWORK_TYPE_LTE);
+ updateDataActivity(TelephonyManager.DATA_ACTIVITY_INOUT);
+ ServiceState ss = Mockito.mock(ServiceState.class);
+ doReturn(NetworkRegistrationInfo.NR_STATE_NOT_RESTRICTED).when(ss).getNrState();
+ mPhoneStateListener.onServiceStateChanged(ss);
+
+ verifyLastMobileDataIndicators(true, DEFAULT_SIGNAL_STRENGTH, TelephonyIcons.ICON_5G,
+ true, DEFAULT_QS_SIGNAL_STRENGTH, TelephonyIcons.ICON_5G, true, true);
+ }
+
+ @Test
+ public void testNr5GIcon_NrNotRestrictedRrcIdle_show5GIcon() {
+ setupNr5GIconConfigurationForNotRestrictedRrcIdle();
+ setupDefaultSignal();
+ updateDataConnectionState(TelephonyManager.DATA_CONNECTED,
+ TelephonyManager.NETWORK_TYPE_LTE);
+ updateDataActivity(TelephonyManager.DATA_ACTIVITY_DORMANT);
+ ServiceState ss = Mockito.mock(ServiceState.class);
+ doReturn(NetworkRegistrationInfo.NR_STATE_NOT_RESTRICTED).when(ss).getNrState();
+ mPhoneStateListener.onServiceStateChanged(ss);
+
+ verifyDataIndicators(TelephonyIcons.ICON_5G);
+ }
+
+ @Test
public void testNr5GIcon_NrConnectedWithoutMMWave_show5GIcon() {
setupDefaultNr5GIconConfiguration();
setupDefaultSignal();
@@ -216,6 +247,186 @@
}
@Test
+ public void testNr5GIcon_displayGracePeriodTime_enabled() {
+ setupDefaultNr5GIconConfiguration();
+ setupDefaultNr5GIconDisplayGracePeriodTime_enableThirtySeconds();
+ setupDefaultSignal();
+ mNetworkController.handleConfigurationChanged();
+ mPhoneStateListener.onServiceStateChanged(mServiceState);
+
+ ServiceState ss = Mockito.mock(ServiceState.class);
+ // While nrIconDisplayGracePeriodMs > 0 & is Nr5G, mIsShowingIconGracefully should be true
+ doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(ss).getNrState();
+ doReturn(ServiceState.FREQUENCY_RANGE_HIGH).when(ss).getNrFrequencyRange();
+ mPhoneStateListener.onDataConnectionStateChanged(TelephonyManager.DATA_CONNECTED,
+ TelephonyManager.NETWORK_TYPE_LTE);
+ mPhoneStateListener.onServiceStateChanged(ss);
+
+ assertTrue(mConfig.nrIconDisplayGracePeriodMs > 0);
+ assertTrue(mMobileSignalController.mIsShowingIconGracefully);
+ }
+
+ @Test
+ public void testNr5GIcon_displayGracePeriodTime_disabled() {
+ setupDefaultNr5GIconConfiguration();
+ setupDefaultNr5GIconDisplayGracePeriodTime_disabled();
+ setupDefaultSignal();
+
+ assertTrue(mConfig.nrIconDisplayGracePeriodMs == 0);
+
+ // While nrIconDisplayGracePeriodMs <= 0, mIsShowingIconGracefully should be false
+ doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
+ doReturn(ServiceState.FREQUENCY_RANGE_HIGH).when(mServiceState).getNrFrequencyRange();
+ mPhoneStateListener.onDataConnectionStateChanged(TelephonyManager.DATA_CONNECTED,
+ TelephonyManager.NETWORK_TYPE_LTE);
+
+ assertFalse(mMobileSignalController.mIsShowingIconGracefully);
+ }
+
+ @Test
+ public void testNr5GIcon_enableDisplayGracePeriodTime_showIconGracefully() {
+ setupDefaultNr5GIconConfiguration();
+ setupDefaultNr5GIconDisplayGracePeriodTime_enableThirtySeconds();
+ setupDefaultSignal();
+ mNetworkController.handleConfigurationChanged();
+ mPhoneStateListener.onServiceStateChanged(mServiceState);
+
+ ServiceState ss = Mockito.mock(ServiceState.class);
+ doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(ss).getNrState();
+ doReturn(ServiceState.FREQUENCY_RANGE_HIGH).when(ss).getNrFrequencyRange();
+ mPhoneStateListener.onDataConnectionStateChanged(TelephonyManager.DATA_CONNECTED,
+ TelephonyManager.NETWORK_TYPE_LTE);
+ mPhoneStateListener.onServiceStateChanged(ss);
+
+ verifyDataIndicators(TelephonyIcons.ICON_5G);
+
+ // Enabled timer Nr5G switch to None Nr5G, showing 5G icon gracefully
+ ServiceState ssLte = Mockito.mock(ServiceState.class);
+ doReturn(NetworkRegistrationInfo.NR_STATE_NONE).when(ssLte).getNrState();
+ doReturn(ServiceState.FREQUENCY_RANGE_UNKNOWN).when(ssLte).getNrFrequencyRange();
+ mPhoneStateListener.onDataConnectionStateChanged(TelephonyManager.DATA_CONNECTED,
+ TelephonyManager.NETWORK_TYPE_LTE);
+ mPhoneStateListener.onServiceStateChanged(ssLte);
+
+ verifyDataIndicators(TelephonyIcons.ICON_5G);
+ }
+
+ @Test
+ public void testNr5GIcon_disableDisplayGracePeriodTime_showLatestIconImmediately() {
+ setupDefaultNr5GIconConfiguration();
+ setupDefaultNr5GIconDisplayGracePeriodTime_disabled();
+ setupDefaultSignal();
+ mNetworkController.handleConfigurationChanged();
+
+ doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
+ doReturn(ServiceState.FREQUENCY_RANGE_HIGH).when(mServiceState).getNrFrequencyRange();
+ mPhoneStateListener.onDataConnectionStateChanged(TelephonyManager.DATA_CONNECTED,
+ TelephonyManager.NETWORK_TYPE_LTE);
+
+ verifyDataIndicators(TelephonyIcons.ICON_5G);
+
+ doReturn(NetworkRegistrationInfo.NR_STATE_NONE).when(mServiceState).getNrState();
+ doReturn(ServiceState.FREQUENCY_RANGE_UNKNOWN).when(mServiceState).getNrFrequencyRange();
+ mPhoneStateListener.onDataConnectionStateChanged(TelephonyManager.DATA_CONNECTED,
+ TelephonyManager.NETWORK_TYPE_LTE);
+
+ verifyDataIndicators(TelephonyIcons.ICON_LTE);
+ }
+
+ @Test
+ public void testNr5GIcon_resetDisplayGracePeriodTime_whenDataDisconnected() {
+ setupDefaultNr5GIconConfiguration();
+ setupDefaultNr5GIconDisplayGracePeriodTime_enableThirtySeconds();
+ setupDefaultSignal();
+ mNetworkController.handleConfigurationChanged();
+ doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
+ doReturn(ServiceState.FREQUENCY_RANGE_HIGH).when(mServiceState).getNrFrequencyRange();
+ mPhoneStateListener.onDataConnectionStateChanged(TelephonyManager.DATA_CONNECTED,
+ TelephonyManager.NETWORK_TYPE_LTE);
+
+ verifyDataIndicators(TelephonyIcons.ICON_5G);
+
+ // Disabled timer, when out of service, reset timer to display latest state
+ updateDataConnectionState(TelephonyManager.DATA_CONNECTED,
+ TelephonyManager.NETWORK_TYPE_LTE);
+ doReturn(NetworkRegistrationInfo.NR_STATE_NONE).when(mServiceState).getNrState();
+ doReturn(ServiceState.FREQUENCY_RANGE_UNKNOWN).when(mServiceState).getNrFrequencyRange();
+ mPhoneStateListener.onDataConnectionStateChanged(TelephonyManager.DATA_DISCONNECTED,
+ TelephonyManager.NETWORK_TYPE_UMTS);
+
+ verifyDataIndicators(0);
+ }
+
+ @Test
+ public void testNr5GIcon_enableDisplayGracePeriodTime_show5G_switching_5GPlus() {
+ setupDefaultNr5GIconConfiguration();
+ setupDefaultNr5GIconDisplayGracePeriodTime_enableThirtySeconds();
+ setupDefaultSignal();
+ mNetworkController.handleConfigurationChanged();
+ mPhoneStateListener.onServiceStateChanged(mServiceState);
+
+ ServiceState ss5G = Mockito.mock(ServiceState.class);
+ doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(ss5G).getNrState();
+ doReturn(ServiceState.FREQUENCY_RANGE_HIGH).when(ss5G).getNrFrequencyRange();
+ mPhoneStateListener.onDataConnectionStateChanged(TelephonyManager.DATA_CONNECTED,
+ TelephonyManager.NETWORK_TYPE_LTE);
+ mPhoneStateListener.onServiceStateChanged(ss5G);
+
+ verifyDataIndicators(TelephonyIcons.ICON_5G);
+
+ // When timeout enabled, 5G/5G+ switching should be updated immediately
+ ServiceState ss5GPlus = Mockito.mock(ServiceState.class);
+ doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(ss5GPlus).getNrState();
+ doReturn(ServiceState.FREQUENCY_RANGE_MMWAVE).when(ss5GPlus).getNrFrequencyRange();
+ mPhoneStateListener.onDataConnectionStateChanged(TelephonyManager.DATA_CONNECTED,
+ TelephonyManager.NETWORK_TYPE_LTE);
+ mPhoneStateListener.onServiceStateChanged(ss5GPlus);
+
+ verifyDataIndicators(TelephonyIcons.ICON_5G_PLUS);
+ }
+
+ @Test
+ public void testNr5GIcon_carrierDisabledDisplayGracePeriodTime_shouldUpdateIconImmediately() {
+ setupDefaultNr5GIconConfiguration();
+ setupDefaultNr5GIconDisplayGracePeriodTime_enableThirtySeconds();
+ setupDefaultSignal();
+ mNetworkController.handleConfigurationChanged();
+ mPhoneStateListener.onServiceStateChanged(mServiceState);
+
+ ServiceState ss5G = Mockito.mock(ServiceState.class);
+ doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(ss5G).getNrState();
+ doReturn(ServiceState.FREQUENCY_RANGE_HIGH).when(ss5G).getNrFrequencyRange();
+ mPhoneStateListener.onDataConnectionStateChanged(TelephonyManager.DATA_CONNECTED,
+ TelephonyManager.NETWORK_TYPE_LTE);
+ mPhoneStateListener.onServiceStateChanged(ss5G);
+
+ verifyDataIndicators(TelephonyIcons.ICON_5G);
+
+ // State from NR_5G to NONE NR_5G with timeout, should show previous 5G icon
+ ServiceState ssLte = Mockito.mock(ServiceState.class);
+ doReturn(NetworkRegistrationInfo.NR_STATE_NONE).when(ssLte).getNrState();
+ doReturn(ServiceState.FREQUENCY_RANGE_UNKNOWN).when(ssLte).getNrFrequencyRange();
+ mPhoneStateListener.onDataConnectionStateChanged(TelephonyManager.DATA_CONNECTED,
+ TelephonyManager.NETWORK_TYPE_LTE);
+ mPhoneStateListener.onServiceStateChanged(ssLte);
+
+ verifyDataIndicators(TelephonyIcons.ICON_5G);
+
+ // Update nrIconDisplayGracePeriodMs to 0
+ setupDefaultNr5GIconDisplayGracePeriodTime_disabled();
+ mNetworkController.handleConfigurationChanged();
+
+ // State from NR_5G to NONE NR_STATE_RESTRICTED, showing corresponding icon
+ doReturn(NetworkRegistrationInfo.NR_STATE_RESTRICTED).when(mServiceState).getNrState();
+ doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mServiceState).getDataNetworkType();
+ mPhoneStateListener.onDataConnectionStateChanged(TelephonyManager.DATA_CONNECTED,
+ TelephonyManager.NETWORK_TYPE_LTE);
+
+ assertTrue(mConfig.nrIconDisplayGracePeriodMs == 0);
+ verifyDataIndicators(TelephonyIcons.ICON_LTE);
+ }
+
+ @Test
public void testDataDisabledIcon_UserNotSetup() {
setupNetworkController();
when(mMockTm.isDataCapable()).thenReturn(false);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java
index 6e3d906..3451183 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java
@@ -1,5 +1,12 @@
package com.android.systemui.statusbar.policy;
+import static junit.framework.Assert.assertEquals;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
import android.content.Intent;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
@@ -16,13 +23,6 @@
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
-import static junit.framework.Assert.assertEquals;
-
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyBoolean;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
@SmallTest
@RunWith(AndroidTestingRunner.class)
@RunWithLooper
diff --git a/packages/SystemUI/tools/lint/baseline.xml b/packages/SystemUI/tools/lint/baseline.xml
index 8c43222..096a639 100644
--- a/packages/SystemUI/tools/lint/baseline.xml
+++ b/packages/SystemUI/tools/lint/baseline.xml
@@ -2685,39 +2685,6 @@
<issue
id="UnusedResources"
- message="The resource `R.dimen.volume_dialog_base_margin` appears to be unused"
- errorLine1=" <dimen name="volume_dialog_base_margin">8dp</dimen>"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="res/values/dimens.xml"
- line="308"
- column="12"/>
- </issue>
-
- <issue
- id="UnusedResources"
- message="The resource `R.dimen.volume_dialog_row_height` appears to be unused"
- errorLine1=" <dimen name="volume_dialog_row_height">252dp</dimen>"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="res/values/dimens.xml"
- line="314"
- column="12"/>
- </issue>
-
- <issue
- id="UnusedResources"
- message="The resource `R.dimen.volume_dialog_settings_icon_size` appears to be unused"
- errorLine1=" <dimen name="volume_dialog_settings_icon_size">16dp</dimen>"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="res/values/dimens.xml"
- line="328"
- column="12"/>
- </issue>
-
- <issue
- id="UnusedResources"
message="The resource `R.dimen.carrier_label_height` appears to be unused"
errorLine1=" <dimen name="carrier_label_height">24dp</dimen>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
diff --git a/services/accessibility/java/com/android/server/accessibility/GlobalActionPerformer.java b/services/accessibility/java/com/android/server/accessibility/GlobalActionPerformer.java
index 672518c..b9b2654 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.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 @@
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/appprediction/java/com/android/server/appprediction/AppPredictionManagerService.java b/services/appprediction/java/com/android/server/appprediction/AppPredictionManagerService.java
index d7e68f8..5844f98 100644
--- a/services/appprediction/java/com/android/server/appprediction/AppPredictionManagerService.java
+++ b/services/appprediction/java/com/android/server/appprediction/AppPredictionManagerService.java
@@ -23,6 +23,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.UserIdInt;
import android.app.prediction.AppPredictionContext;
import android.app.prediction.AppPredictionSessionId;
import android.app.prediction.AppTargetEvent;
@@ -61,7 +62,8 @@
public AppPredictionManagerService(Context context) {
super(context, new FrameworkResourcesServiceNameResolver(context,
- com.android.internal.R.string.config_defaultAppPredictionService), null);
+ com.android.internal.R.string.config_defaultAppPredictionService), null,
+ PACKAGE_UPDATE_POLICY_NO_REFRESH | PACKAGE_RESTART_POLICY_NO_REFRESH);
mActivityTaskManagerInternal = LocalServices.getService(ActivityTaskManagerInternal.class);
}
@@ -80,6 +82,22 @@
getContext().enforceCallingPermission(MANAGE_APP_PREDICTIONS, TAG);
}
+ @Override // from AbstractMasterSystemService
+ protected void onServicePackageUpdatedLocked(@UserIdInt int userId) {
+ final AppPredictionPerUserService service = peekServiceForUserLocked(userId);
+ if (service != null) {
+ service.onPackageUpdatedLocked();
+ }
+ }
+
+ @Override // from AbstractMasterSystemService
+ protected void onServicePackageRestartedLocked(@UserIdInt int userId) {
+ final AppPredictionPerUserService service = peekServiceForUserLocked(userId);
+ if (service != null) {
+ service.onPackageRestartedLocked();
+ }
+ }
+
@Override
protected int getMaximumTemporaryServiceDurationMs() {
return MAX_TEMP_SERVICE_DURATION_MS;
diff --git a/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java b/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java
index 03c4542..4f49fb7 100644
--- a/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java
+++ b/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java
@@ -251,6 +251,40 @@
// Do nothing, eventually the system will bind to the remote service again...
}
+ void onPackageUpdatedLocked() {
+ if (isDebug()) {
+ Slog.v(TAG, "onPackageUpdatedLocked()");
+ }
+ destroyAndRebindRemoteService();
+ }
+
+ void onPackageRestartedLocked() {
+ if (isDebug()) {
+ Slog.v(TAG, "onPackageRestartedLocked()");
+ }
+ destroyAndRebindRemoteService();
+ }
+
+ private void destroyAndRebindRemoteService() {
+ if (mRemoteService == null) {
+ return;
+ }
+
+ if (isDebug()) {
+ Slog.d(TAG, "Destroying the old remote service.");
+ }
+ mRemoteService.destroy();
+ mRemoteService = null;
+
+ mRemoteService = getRemoteServiceLocked();
+ if (mRemoteService != null) {
+ if (isDebug()) {
+ Slog.d(TAG, "Rebinding to the new remote service.");
+ }
+ mRemoteService.reconnect();
+ }
+ }
+
/**
* Called after the remote service connected, it's used to restore state from a 'zombie'
* service (i.e., after it died).
diff --git a/services/appprediction/java/com/android/server/appprediction/RemoteAppPredictionService.java b/services/appprediction/java/com/android/server/appprediction/RemoteAppPredictionService.java
index c82e7a0..04e0e7f 100644
--- a/services/appprediction/java/com/android/server/appprediction/RemoteAppPredictionService.java
+++ b/services/appprediction/java/com/android/server/appprediction/RemoteAppPredictionService.java
@@ -135,6 +135,13 @@
}
/**
+ * Schedules a request to bind to the remote service.
+ */
+ public void reconnect() {
+ super.scheduleBind();
+ }
+
+ /**
* Failure callback
*/
public interface RemoteAppPredictionServiceCallbacks
diff --git a/services/core/java/com/android/server/BluetoothService.java b/services/core/java/com/android/server/BluetoothService.java
index 5c5b477..6a6ddc8 100644
--- a/services/core/java/com/android/server/BluetoothService.java
+++ b/services/core/java/com/android/server/BluetoothService.java
@@ -54,8 +54,11 @@
@Override
public void onSwitchUser(int userHandle) {
- initialize();
- mBluetoothManagerService.handleOnSwitchUser(userHandle);
+ if (!mInitialized) {
+ initialize();
+ } else {
+ mBluetoothManagerService.handleOnSwitchUser(userHandle);
+ }
}
@Override
diff --git a/services/core/java/com/android/server/EventLogTags.logtags b/services/core/java/com/android/server/EventLogTags.logtags
index 4d39f9a..bec08f4 100644
--- a/services/core/java/com/android/server/EventLogTags.logtags
+++ b/services/core/java/com/android/server/EventLogTags.logtags
@@ -39,6 +39,12 @@
27391 user_activity_timeout_override (override|2|3)
27392 battery_saver_setting (threshold|1)
+
+# ---------------------------
+# ThermalManagerService.java
+# ---------------------------
+2737 thermal_changed (name|3),(type|1|5),(temperature|5),(sensor_status|1|5),(previous_system_status|1|5)
+
#
# Leave IDs through 2740 for more power logs (2730 used by battery_discharge above)
#
diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java
index 30a3563..6b03897 100644
--- a/services/core/java/com/android/server/UiModeManagerService.java
+++ b/services/core/java/com/android/server/UiModeManagerService.java
@@ -48,7 +48,6 @@
import android.os.ShellCommand;
import android.os.SystemProperties;
import android.os.UserHandle;
-import android.os.UserManager;
import android.provider.Settings.Secure;
import android.service.dreams.Sandman;
import android.service.vr.IVrManager;
@@ -218,6 +217,15 @@
}
};
+ private final ContentObserver mDarkThemeObserver = new ContentObserver(mHandler) {
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ final int mode = Secure.getIntForUser(getContext().getContentResolver(),
+ Secure.UI_NIGHT_MODE, mNightMode, 0);
+ SystemProperties.set(SYSTEM_PROPERTY_DEVICE_THEME, Integer.toString(mode));
+ }
+ };
+
@Override
public void onSwitchUser(int userHandle) {
super.onSwitchUser(userHandle);
@@ -293,6 +301,9 @@
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_USER_SWITCHED);
context.registerReceiver(new UserSwitchedReceiver(), filter, null, mHandler);
+
+ context.getContentResolver().registerContentObserver(Secure.getUriFor(Secure.UI_NIGHT_MODE),
+ false, mDarkThemeObserver, 0);
}
// Records whether setup wizard has happened or not and adds an observer for this user if not.
@@ -417,11 +428,6 @@
if (!mCarModeEnabled) {
Secure.putIntForUser(getContext().getContentResolver(),
Secure.UI_NIGHT_MODE, mode, user);
-
- if (UserManager.get(getContext()).isPrimaryUser()) {
- SystemProperties.set(SYSTEM_PROPERTY_DEVICE_THEME,
- Integer.toString(mode));
- }
}
mNightMode = mode;
diff --git a/services/core/java/com/android/server/accounts/AccountManagerServiceShellCommand.java b/services/core/java/com/android/server/accounts/AccountManagerServiceShellCommand.java
index 9e5f722..9bf0bd3 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerServiceShellCommand.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerServiceShellCommand.java
@@ -17,6 +17,7 @@
package com.android.server.accounts;
import android.annotation.NonNull;
+import android.app.ActivityManager;
import android.os.ShellCommand;
import android.os.UserHandle;
@@ -83,7 +84,7 @@
return null;
}
}
- return UserHandle.USER_SYSTEM;
+ return ActivityManager.getCurrentUser();
}
@Override
@@ -92,9 +93,11 @@
pw.println("Account manager service commands:");
pw.println(" help");
pw.println(" Print this help text.");
- pw.println(" set-bind-instant-service-allowed [--user <USER_ID>] true|false ");
+ pw.println(" set-bind-instant-service-allowed "
+ + "[--user <USER_ID> (current user if not specified)] true|false ");
pw.println(" Set whether binding to services provided by instant apps is allowed.");
- pw.println(" get-bind-instant-service-allowed [--user <USER_ID>]");
+ pw.println(" get-bind-instant-service-allowed "
+ + "[--user <USER_ID> (current user if not specified)]");
pw.println(" Get whether binding to services provided by instant apps is allowed.");
}
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index cc5932e..ba4277d 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -9055,7 +9055,13 @@
throw e.rethrowAsRuntimeException();
}
}
- mAtmInternal.startHomeOnAllDisplays(currentUserId, "systemReady");
+ // 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.
+ final boolean bootingSystemUser = currentUserId == UserHandle.USER_SYSTEM;
+
+ if (bootingSystemUser) {
+ mAtmInternal.startHomeOnAllDisplays(currentUserId, "systemReady");
+ }
mAtmInternal.showSystemReadyErrorDialogsIfNeeded();
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index c2f4529..a47ea4f 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -722,10 +722,10 @@
}
}
- public void notePhoneDataConnectionState(int dataType, boolean hasData) {
+ public void notePhoneDataConnectionState(int dataType, boolean hasData, int serviceType) {
enforceCallingPermission();
synchronized (mStats) {
- mStats.notePhoneDataConnectionStateLocked(dataType, hasData);
+ mStats.notePhoneDataConnectionStateLocked(dataType, hasData, serviceType);
}
}
@@ -756,7 +756,7 @@
}
public void noteStartAudio(int uid) {
- enforceSelfOrCallingPermission(uid);
+ enforceCallingPermission();
synchronized (mStats) {
mStats.noteAudioOnLocked(uid);
StatsLog.write_non_chained(StatsLog.AUDIO_STATE_CHANGED, uid, null,
@@ -765,7 +765,7 @@
}
public void noteStopAudio(int uid) {
- enforceSelfOrCallingPermission(uid);
+ enforceCallingPermission();
synchronized (mStats) {
mStats.noteAudioOffLocked(uid);
StatsLog.write_non_chained(StatsLog.AUDIO_STATE_CHANGED, uid, null,
@@ -774,7 +774,7 @@
}
public void noteStartVideo(int uid) {
- enforceSelfOrCallingPermission(uid);
+ enforceCallingPermission();
synchronized (mStats) {
mStats.noteVideoOnLocked(uid);
StatsLog.write_non_chained(StatsLog.MEDIA_CODEC_STATE_CHANGED, uid, null,
@@ -783,7 +783,7 @@
}
public void noteStopVideo(int uid) {
- enforceSelfOrCallingPermission(uid);
+ enforceCallingPermission();
synchronized (mStats) {
mStats.noteVideoOffLocked(uid);
StatsLog.write_non_chained(StatsLog.MEDIA_CODEC_STATE_CHANGED, uid,
@@ -1184,13 +1184,6 @@
Binder.getCallingPid(), Binder.getCallingUid(), null);
}
- private void enforceSelfOrCallingPermission(int uid) {
- if (Binder.getCallingUid() == uid) {
- return;
- }
- enforceCallingPermission();
- }
-
final class WakeupReasonThread extends Thread {
private static final int MAX_REASON_SIZE = 512;
private CharsetDecoder mDecoder;
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 3d598dd..3c098d1 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -2097,10 +2097,10 @@
}
}
}
- if (lrui <= mLruProcessActivityStart) {
+ if (lrui < mLruProcessActivityStart) {
mLruProcessActivityStart--;
}
- if (lrui <= mLruProcessServiceStart) {
+ if (lrui < mLruProcessServiceStart) {
mLruProcessServiceStart--;
}
mLruProcesses.remove(lrui);
@@ -2632,7 +2632,7 @@
if (!moved) {
// Goes to the end of the group.
mLruProcesses.remove(i);
- mLruProcesses.add(endIndex - 1, subProc);
+ mLruProcesses.add(endIndex, subProc);
if (DEBUG_LRU) Slog.d(TAG_LRU,
"Moving " + subProc
+ " from position " + i + " to end of group @ "
@@ -2877,15 +2877,6 @@
pos--;
}
mLruProcesses.add(pos, app);
- if (pos == mLruProcessActivityStart) {
- mLruProcessActivityStart++;
- }
- if (pos == mLruProcessServiceStart) {
- // Unless {@code #hasService} is implemented, currently the starting position
- // for activity and service are the same, so the incoming position may equal to
- // the starting position of service.
- mLruProcessServiceStart++;
- }
// If this process is part of a group, need to pull up any other processes
// in that group to be with it.
int endIndex = pos - 1;
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 7569363..b449041 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -2979,17 +2979,40 @@
out.startTag(null, "app-ops");
out.attribute(null, "v", String.valueOf(CURRENT_VERSION));
- final int uidStateCount = mUidStates.size();
- for (int i = 0; i < uidStateCount; i++) {
- UidState uidState = mUidStates.valueAt(i);
- if (uidState.opModes != null && uidState.opModes.size() > 0) {
+ SparseArray<SparseIntArray> uidStatesClone;
+ synchronized (this) {
+ uidStatesClone = new SparseArray<>(mUidStates.size());
+
+ final int uidStateCount = mUidStates.size();
+ for (int uidStateNum = 0; uidStateNum < uidStateCount; uidStateNum++) {
+ UidState uidState = mUidStates.valueAt(uidStateNum);
+ int uid = mUidStates.keyAt(uidStateNum);
+
+ SparseIntArray opModes = uidState.opModes;
+ if (opModes != null && opModes.size() > 0) {
+ uidStatesClone.put(uid, new SparseIntArray(opModes.size()));
+
+ final int opCount = opModes.size();
+ for (int opCountNum = 0; opCountNum < opCount; opCountNum++) {
+ uidStatesClone.get(uid).put(
+ opModes.keyAt(opCountNum),
+ opModes.valueAt(opCountNum));
+ }
+ }
+ }
+ }
+
+ final int uidStateCount = uidStatesClone.size();
+ for (int uidStateNum = 0; uidStateNum < uidStateCount; uidStateNum++) {
+ SparseIntArray opModes = uidStatesClone.valueAt(uidStateNum);
+ if (opModes != null && opModes.size() > 0) {
out.startTag(null, "uid");
- out.attribute(null, "n", Integer.toString(uidState.uid));
- SparseIntArray uidOpModes = uidState.opModes;
- final int opCount = uidOpModes.size();
- for (int j = 0; j < opCount; j++) {
- final int op = uidOpModes.keyAt(j);
- final int mode = uidOpModes.valueAt(j);
+ out.attribute(null, "n",
+ Integer.toString(uidStatesClone.keyAt(uidStateNum)));
+ final int opCount = opModes.size();
+ for (int opCountNum = 0; opCountNum < opCount; opCountNum++) {
+ final int op = opModes.keyAt(opCountNum);
+ final int mode = opModes.valueAt(opCountNum);
out.startTag(null, "op");
out.attribute(null, "n", Integer.toString(op));
out.attribute(null, "m", Integer.toString(mode));
diff --git a/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java b/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java
index acb0207..85ca627 100644
--- a/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java
+++ b/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java
@@ -35,6 +35,8 @@
import android.hardware.broadcastradio.V2_0.VendorKeyValue;
import android.hardware.radio.RadioManager;
import android.os.DeadObjectException;
+import android.os.Handler;
+import android.os.Looper;
import android.os.RemoteException;
import android.util.MutableInt;
import android.util.Slog;
@@ -44,6 +46,7 @@
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
@@ -55,6 +58,7 @@
@NonNull public final RadioManager.ModuleProperties mProperties;
private final Object mLock = new Object();
+ @NonNull private final Handler mHandler;
@GuardedBy("mLock")
private ITunerSession mHalTunerSession;
@@ -70,38 +74,46 @@
private final ITunerCallback mHalTunerCallback = new ITunerCallback.Stub() {
@Override
public void onTuneFailed(int result, ProgramSelector programSelector) {
- fanoutAidlCallback(cb -> cb.onTuneFailed(result, Convert.programSelectorFromHal(
- programSelector)));
+ lockAndFireLater(() -> {
+ android.hardware.radio.ProgramSelector csel =
+ Convert.programSelectorFromHal(programSelector);
+ fanoutAidlCallbackLocked(cb -> cb.onTuneFailed(result, csel));
+ });
}
@Override
public void onCurrentProgramInfoChanged(ProgramInfo halProgramInfo) {
- RadioManager.ProgramInfo programInfo = Convert.programInfoFromHal(halProgramInfo);
- synchronized (mLock) {
- mProgramInfo = programInfo;
- fanoutAidlCallbackLocked(cb -> cb.onCurrentProgramInfoChanged(programInfo));
- }
+ lockAndFireLater(() -> {
+ mProgramInfo = Convert.programInfoFromHal(halProgramInfo);
+ fanoutAidlCallbackLocked(cb -> cb.onCurrentProgramInfoChanged(mProgramInfo));
+ });
}
@Override
public void onProgramListUpdated(ProgramListChunk programListChunk) {
// TODO: Cache per-AIDL client filters, send union of filters to HAL, use filters to fan
// back out to clients.
- fanoutAidlCallback(cb -> cb.onProgramListUpdated(Convert.programListChunkFromHal(
- programListChunk)));
+ lockAndFireLater(() -> {
+ android.hardware.radio.ProgramList.Chunk chunk =
+ Convert.programListChunkFromHal(programListChunk);
+ fanoutAidlCallbackLocked(cb -> cb.onProgramListUpdated(chunk));
+ });
}
@Override
public void onAntennaStateChange(boolean connected) {
- synchronized (mLock) {
+ lockAndFireLater(() -> {
mAntennaConnected = connected;
fanoutAidlCallbackLocked(cb -> cb.onAntennaState(connected));
- }
+ });
}
@Override
public void onParametersUpdated(ArrayList<VendorKeyValue> parameters) {
- fanoutAidlCallback(cb -> cb.onParametersUpdated(Convert.vendorInfoFromHal(parameters)));
+ lockAndFireLater(() -> {
+ Map<String, String> cparam = Convert.vendorInfoFromHal(parameters);
+ fanoutAidlCallbackLocked(cb -> cb.onParametersUpdated(cparam));
+ });
}
};
@@ -113,6 +125,7 @@
@NonNull RadioManager.ModuleProperties properties) throws RemoteException {
mProperties = Objects.requireNonNull(properties);
mService = Objects.requireNonNull(service);
+ mHandler = new Handler(Looper.getMainLooper());
}
public static @Nullable RadioModule tryLoadingModule(int idx, @NonNull String fqName) {
@@ -201,15 +214,22 @@
}
}
+ // add to mHandler queue, but ensure the runnable holds mLock when it gets executed
+ private void lockAndFireLater(Runnable r) {
+ mHandler.post(() -> {
+ synchronized (mLock) {
+ r.run();
+ }
+ });
+ }
+
interface AidlCallbackRunnable {
void run(android.hardware.radio.ITunerCallback callback) throws RemoteException;
}
// Invokes runnable with each TunerSession currently open.
void fanoutAidlCallback(AidlCallbackRunnable runnable) {
- synchronized (mLock) {
- fanoutAidlCallbackLocked(runnable);
- }
+ lockAndFireLater(() -> fanoutAidlCallbackLocked(runnable));
}
private void fanoutAidlCallbackLocked(AidlCallbackRunnable runnable) {
diff --git a/services/core/java/com/android/server/connectivity/DataConnectionStats.java b/services/core/java/com/android/server/connectivity/DataConnectionStats.java
index e6a4428..27f11ff 100644
--- a/services/core/java/com/android/server/connectivity/DataConnectionStats.java
+++ b/services/core/java/com/android/server/connectivity/DataConnectionStats.java
@@ -97,7 +97,8 @@
if (DEBUG) Log.d(TAG, String.format("Noting data connection for network type %s: %svisible",
networkType, visible ? "" : "not "));
try {
- mBatteryStats.notePhoneDataConnectionState(networkType, visible);
+ mBatteryStats.notePhoneDataConnectionState(networkType, visible,
+ mServiceState.getState());
} catch (RemoteException e) {
Log.w(TAG, "Error noting data connection state", e);
}
diff --git a/services/core/java/com/android/server/display/DisplayModeDirector.java b/services/core/java/com/android/server/display/DisplayModeDirector.java
index 500a242..1fc0db3 100644
--- a/services/core/java/com/android/server/display/DisplayModeDirector.java
+++ b/services/core/java/com/android/server/display/DisplayModeDirector.java
@@ -766,6 +766,7 @@
@Override
public void onDisplayChanged(int displayId) {
updateDisplayModes(displayId);
+ mBrightnessObserver.onDisplayChanged(displayId);
}
private void updateDisplayModes(int displayId) {
@@ -820,7 +821,6 @@
private AmbientFilter mAmbientFilter;
private final Context mContext;
- private final ScreenStateReceiver mScreenStateReceiver;
// Enable light sensor only when mShouldObserveAmbientChange is true, screen is on, peak
// refresh rate changeable and low power mode off. After initialization, these states will
@@ -834,7 +834,6 @@
BrightnessObserver(Context context, Handler handler) {
super(handler);
mContext = context;
- mScreenStateReceiver = new ScreenStateReceiver(mContext);
mDisplayBrightnessThresholds = context.getResources().getIntArray(
R.array.config_brightnessThresholdsOfPeakRefreshRate);
mAmbientBrightnessThresholds = context.getResources().getIntArray(
@@ -919,12 +918,16 @@
}
}
+ public void onDisplayChanged(int displayId) {
+ if (displayId == Display.DEFAULT_DISPLAY) {
+ onScreenOn(isDefaultDisplayOn());
+ }
+ }
+
@Override
public void onChange(boolean selfChange, Uri uri, int userId) {
synchronized (mLock) {
- if (mRefreshRateChangeable) {
- onBrightnessChangedLocked();
- }
+ onBrightnessChangedLocked();
}
}
@@ -970,16 +973,11 @@
mAmbientFilter = DisplayWhiteBalanceFactory.createBrightnessFilter(res);
mLightSensor = lightSensor;
- // Intent.ACTION_SCREEN_ON is not sticky. Check current screen status.
- if (mContext.getSystemService(PowerManager.class).isInteractive()) {
- onScreenOn(true);
- }
- mScreenStateReceiver.register();
+ onScreenOn(isDefaultDisplayOn());
}
} else {
mAmbientFilter = null;
mLightSensor = null;
- mScreenStateReceiver.unregister();
}
if (mRefreshRateChangeable) {
@@ -1049,8 +1047,6 @@
}
private void onScreenOn(boolean on) {
- // Not check mShouldObserveAmbientChange because Screen status receiver is registered
- // only when it is true.
if (mScreenOn != on) {
mScreenOn = on;
updateSensorStatus();
@@ -1072,6 +1068,13 @@
}
}
+ private boolean isDefaultDisplayOn() {
+ final Display display = mContext.getSystemService(DisplayManager.class)
+ .getDisplay(Display.DEFAULT_DISPLAY);
+ return display.getState() != Display.STATE_OFF
+ && mContext.getSystemService(PowerManager.class).isInteractive();
+ }
+
private final class LightSensorEventListener implements SensorEventListener {
final private static int INJECT_EVENTS_INTERVAL_MS = LIGHT_SENSOR_RATE_MS;
private float mLastSensorData;
@@ -1149,38 +1152,6 @@
}
}
};
- };
-
- private final class ScreenStateReceiver extends BroadcastReceiver {
- final Context mContext;
- boolean mRegistered;
-
- public ScreenStateReceiver(Context context) {
- mContext = context;
- }
-
- @Override
- public void onReceive(Context context, Intent intent) {
- onScreenOn(Intent.ACTION_SCREEN_ON.equals(intent.getAction()));
- }
-
- public void register() {
- if (!mRegistered) {
- IntentFilter filter = new IntentFilter();
- filter.addAction(Intent.ACTION_SCREEN_OFF);
- filter.addAction(Intent.ACTION_SCREEN_ON);
- filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
- mContext.registerReceiver(this, filter, null, mHandler);
- mRegistered = true;
- }
- }
-
- public void unregister() {
- if (mRegistered) {
- mContext.unregisterReceiver(this);
- mRegistered = false;
- }
- }
}
}
diff --git a/services/core/java/com/android/server/infra/AbstractMasterSystemService.java b/services/core/java/com/android/server/infra/AbstractMasterSystemService.java
index 9782f30..259527a 100644
--- a/services/core/java/com/android/server/infra/AbstractMasterSystemService.java
+++ b/services/core/java/com/android/server/infra/AbstractMasterSystemService.java
@@ -79,7 +79,7 @@
S extends AbstractPerUserSystemService<S, M>> extends SystemService {
/** On a package update, does not refresh the per-user service in the cache. */
- public static final int PACKAGE_UPDATE_POLICY_NO_REFRESH = 0;
+ public static final int PACKAGE_UPDATE_POLICY_NO_REFRESH = 0x00000001;
/**
* On a package update, removes any existing per-user services in the cache.
@@ -87,20 +87,40 @@
* <p>This does not immediately recreate these services. It is assumed they will be recreated
* for the next user request.
*/
- public static final int PACKAGE_UPDATE_POLICY_REFRESH_LAZY = 1;
+ public static final int PACKAGE_UPDATE_POLICY_REFRESH_LAZY = 0x00000002;
/**
* On a package update, removes and recreates any existing per-user services in the cache.
*/
- public static final int PACKAGE_UPDATE_POLICY_REFRESH_EAGER = 2;
+ public static final int PACKAGE_UPDATE_POLICY_REFRESH_EAGER = 0x00000004;
- @IntDef(flag = true, prefix = { "PACKAGE_UPDATE_POLICY_" }, value = {
+ /** On a package restart, does not refresh the per-user service in the cache. */
+ public static final int PACKAGE_RESTART_POLICY_NO_REFRESH = 0x00000010;
+
+ /**
+ * On a package restart, removes any existing per-user services in the cache.
+ *
+ * <p>This does not immediately recreate these services. It is assumed they will be recreated
+ * for the next user request.
+ */
+ public static final int PACKAGE_RESTART_POLICY_REFRESH_LAZY = 0x00000020;
+
+ /**
+ * On a package restart, removes and recreates any existing per-user services in the cache.
+ */
+ public static final int PACKAGE_RESTART_POLICY_REFRESH_EAGER = 0x00000040;
+
+ @IntDef(flag = true, prefix = { "PACKAGE_" }, value = {
PACKAGE_UPDATE_POLICY_NO_REFRESH,
PACKAGE_UPDATE_POLICY_REFRESH_LAZY,
- PACKAGE_UPDATE_POLICY_REFRESH_EAGER
+ PACKAGE_UPDATE_POLICY_REFRESH_EAGER,
+ PACKAGE_RESTART_POLICY_NO_REFRESH,
+ PACKAGE_RESTART_POLICY_REFRESH_LAZY,
+ PACKAGE_RESTART_POLICY_REFRESH_EAGER
})
+
@Retention(RetentionPolicy.SOURCE)
- public @interface PackageUpdatePolicy {}
+ public @interface ServicePackagePolicyFlags {}
/**
* Log tag
@@ -153,12 +173,10 @@
private final SparseArray<S> mServicesCache = new SparseArray<>();
/**
- * Whether the per-user service should be removed from the cache when its apk is updated.
- *
- * <p>One of {@link #PACKAGE_UPDATE_POLICY_NO_REFRESH},
- * {@link #PACKAGE_UPDATE_POLICY_REFRESH_LAZY} or {@link #PACKAGE_UPDATE_POLICY_REFRESH_EAGER}.
+ * Value that determines whether the per-user service should be removed from the cache when its
+ * apk is updated or restarted.
*/
- private final @PackageUpdatePolicy int mPackageUpdatePolicy;
+ private final @ServicePackagePolicyFlags int mServicePackagePolicyFlags;
/**
* Name of the service packages whose APK are being updated, keyed by user id.
@@ -184,11 +202,11 @@
@Nullable ServiceNameResolver serviceNameResolver,
@Nullable String disallowProperty) {
this(context, serviceNameResolver, disallowProperty,
- /*packageUpdatePolicy=*/ PACKAGE_UPDATE_POLICY_REFRESH_LAZY);
+ PACKAGE_UPDATE_POLICY_REFRESH_LAZY | PACKAGE_RESTART_POLICY_REFRESH_LAZY);
}
/**
- * Full constructor.
+ * Full Constructor.
*
* @param context system context.
* @param serviceNameResolver resolver for
@@ -197,19 +215,32 @@
* @param disallowProperty when not {@code null}, defines a {@link UserManager} restriction that
* disables the service. <b>NOTE: </b> you'll also need to add it to
* {@code UserRestrictionsUtils.USER_RESTRICTIONS}.
- * @param packageUpdatePolicy when {@link #PACKAGE_UPDATE_POLICY_REFRESH_LAZY}, the
- * {@link AbstractPerUserSystemService} is removed from the cache when the service
- * package is updated; when {@link #PACKAGE_UPDATE_POLICY_REFRESH_EAGER}, the
- * {@link AbstractPerUserSystemService} is removed from the cache and immediately
- * re-added when the service package is updated; when
- * {@link #PACKAGE_UPDATE_POLICY_NO_REFRESH}, the service is untouched during the update.
+ * @param servicePackagePolicyFlags a combination of
+ * {@link #PACKAGE_UPDATE_POLICY_NO_REFRESH},
+ * {@link #PACKAGE_UPDATE_POLICY_REFRESH_LAZY},
+ * {@link #PACKAGE_UPDATE_POLICY_REFRESH_EAGER},
+ * {@link #PACKAGE_RESTART_POLICY_NO_REFRESH},
+ * {@link #PACKAGE_RESTART_POLICY_REFRESH_LAZY} or
+ * {@link #PACKAGE_RESTART_POLICY_REFRESH_EAGER}
*/
protected AbstractMasterSystemService(@NonNull Context context,
- @Nullable ServiceNameResolver serviceNameResolver,
- @Nullable String disallowProperty, @PackageUpdatePolicy int packageUpdatePolicy) {
+ @Nullable ServiceNameResolver serviceNameResolver, @Nullable String disallowProperty,
+ @ServicePackagePolicyFlags int servicePackagePolicyFlags) {
super(context);
- mPackageUpdatePolicy = packageUpdatePolicy;
+ final int updatePolicyMask = PACKAGE_UPDATE_POLICY_NO_REFRESH
+ | PACKAGE_UPDATE_POLICY_REFRESH_LAZY | PACKAGE_UPDATE_POLICY_REFRESH_EAGER;
+ if ((servicePackagePolicyFlags & updatePolicyMask) == 0) {
+ // If the package update policy is not set, add the default flag
+ servicePackagePolicyFlags |= PACKAGE_UPDATE_POLICY_REFRESH_LAZY;
+ }
+ final int restartPolicyMask = PACKAGE_RESTART_POLICY_NO_REFRESH
+ | PACKAGE_RESTART_POLICY_REFRESH_LAZY | PACKAGE_RESTART_POLICY_REFRESH_EAGER;
+ if ((servicePackagePolicyFlags & restartPolicyMask) == 0) {
+ // If the package restart policy is not set, add the default flag
+ servicePackagePolicyFlags |= PACKAGE_RESTART_POLICY_REFRESH_LAZY;
+ }
+ mServicePackagePolicyFlags = servicePackagePolicyFlags;
mServiceNameResolver = serviceNameResolver;
if (mServiceNameResolver != null) {
@@ -606,6 +637,20 @@
}
/**
+ * Called after the package data that provides the service for the given user is cleared.
+ */
+ protected void onServicePackageDataClearedLocked(@UserIdInt int userId) {
+ if (verbose) Slog.v(mTag, "onServicePackageDataCleared(" + userId + ")");
+ }
+
+ /**
+ * Called after the package that provides the service for the given user is restarted.
+ */
+ protected void onServicePackageRestartedLocked(@UserIdInt int userId) {
+ if (verbose) Slog.v(mTag, "onServicePackageRestarted(" + userId + ")");
+ }
+
+ /**
* Called after the service is removed from the cache.
*/
@SuppressWarnings("unused")
@@ -677,7 +722,7 @@
final int size = mServicesCache.size();
pw.print(prefix); pw.print("Debug: "); pw.print(realDebug);
pw.print(" Verbose: "); pw.println(realVerbose);
- pw.print("Refresh on package update: "); pw.println(mPackageUpdatePolicy);
+ pw.print("Package policy flags: "); pw.println(mServicePackagePolicyFlags);
if (mUpdatingPackageNames != null) {
pw.print("Packages being updated: "); pw.println(mUpdatingPackageNames);
}
@@ -733,7 +778,12 @@
}
mUpdatingPackageNames.put(userId, packageName);
onServicePackageUpdatingLocked(userId);
- if (mPackageUpdatePolicy != PACKAGE_UPDATE_POLICY_NO_REFRESH) {
+ if ((mServicePackagePolicyFlags & PACKAGE_UPDATE_POLICY_NO_REFRESH) != 0) {
+ if (debug) {
+ Slog.d(mTag, "Holding service for user " + userId + " while package "
+ + activePackageName + " is being updated");
+ }
+ } else {
if (debug) {
Slog.d(mTag, "Removing service for user " + userId
+ " because package " + activePackageName
@@ -741,18 +791,14 @@
}
removeCachedServiceLocked(userId);
- if (mPackageUpdatePolicy == PACKAGE_UPDATE_POLICY_REFRESH_EAGER) {
+ if ((mServicePackagePolicyFlags & PACKAGE_UPDATE_POLICY_REFRESH_EAGER)
+ != 0) {
if (debug) {
Slog.d(mTag, "Eagerly recreating service for user "
+ userId);
}
getServiceForUserLocked(userId);
}
- } else {
- if (debug) {
- Slog.d(mTag, "Holding service for user " + userId + " while package "
- + activePackageName + " is being updated");
- }
}
}
}
@@ -804,7 +850,13 @@
if (!doit) {
return true;
}
- removeCachedServiceLocked(getChangingUserId());
+ final String action = intent.getAction();
+ final int userId = getChangingUserId();
+ if (Intent.ACTION_PACKAGE_RESTARTED.equals(action)) {
+ handleActiveServiceRestartedLocked(activePackageName, userId);
+ } else {
+ removeCachedServiceLocked(userId);
+ }
} else {
handlePackageUpdateLocked(pkg);
}
@@ -813,6 +865,23 @@
return false;
}
+ @Override
+ public void onPackageDataCleared(String packageName, int uid) {
+ if (verbose) Slog.v(mTag, "onPackageDataCleared(): " + packageName);
+ final int userId = getChangingUserId();
+ synchronized (mLock) {
+ final S service = peekServiceForUserLocked(userId);
+ if (service != null) {
+ final ComponentName componentName = service.getServiceComponentName();
+ if (componentName != null) {
+ if (packageName.equals(componentName.getPackageName())) {
+ onServicePackageDataClearedLocked(userId);
+ }
+ }
+ }
+ }
+ }
+
private void handleActiveServiceRemoved(@UserIdInt int userId) {
synchronized (mLock) {
removeCachedServiceLocked(userId);
@@ -824,6 +893,31 @@
}
}
+ private void handleActiveServiceRestartedLocked(String activePackageName,
+ @UserIdInt int userId) {
+ if ((mServicePackagePolicyFlags & PACKAGE_RESTART_POLICY_NO_REFRESH) != 0) {
+ if (debug) {
+ Slog.d(mTag, "Holding service for user " + userId + " while package "
+ + activePackageName + " is being restarted");
+ }
+ } else {
+ if (debug) {
+ Slog.d(mTag, "Removing service for user " + userId
+ + " because package " + activePackageName
+ + " is being restarted");
+ }
+ removeCachedServiceLocked(userId);
+
+ if ((mServicePackagePolicyFlags & PACKAGE_RESTART_POLICY_REFRESH_EAGER) != 0) {
+ if (debug) {
+ Slog.d(mTag, "Eagerly recreating service for user " + userId);
+ }
+ getServiceForUserLocked(userId);
+ }
+ }
+ onServicePackageRestartedLocked(userId);
+ }
+
private String getActiveServicePackageNameLocked() {
final int userId = getChangingUserId();
final S service = peekServiceForUserLocked(userId);
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
index 4a6eb27..4828bbf 100644
--- a/services/core/java/com/android/server/notification/ManagedServices.java
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -196,18 +196,20 @@
public void dump(PrintWriter pw, DumpFilter filter) {
pw.println(" Allowed " + getCaption() + "s:");
- final int N = mApproved.size();
- for (int i = 0 ; i < N; i++) {
- final int userId = mApproved.keyAt(i);
- final ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.valueAt(i);
- if (approvedByType != null) {
- final int M = approvedByType.size();
- for (int j = 0; j < M; j++) {
- final boolean isPrimary = approvedByType.keyAt(j);
- final ArraySet<String> approved = approvedByType.valueAt(j);
- if (approvedByType != null && approvedByType.size() > 0) {
- pw.println(" " + String.join(ENABLED_SERVICES_SEPARATOR, approved)
- + " (user: " + userId + " isPrimary: " + isPrimary + ")");
+ synchronized (mApproved) {
+ final int N = mApproved.size();
+ for (int i = 0; i < N; i++) {
+ final int userId = mApproved.keyAt(i);
+ final ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.valueAt(i);
+ if (approvedByType != null) {
+ final int M = approvedByType.size();
+ for (int j = 0; j < M; j++) {
+ final boolean isPrimary = approvedByType.keyAt(j);
+ final ArraySet<String> approved = approvedByType.valueAt(j);
+ if (approvedByType != null && approvedByType.size() > 0) {
+ pw.println(" " + String.join(ENABLED_SERVICES_SEPARATOR, approved)
+ + " (user: " + userId + " isPrimary: " + isPrimary + ")");
+ }
}
}
}
@@ -240,23 +242,25 @@
public void dump(ProtoOutputStream proto, DumpFilter filter) {
proto.write(ManagedServicesProto.CAPTION, getCaption());
- final int N = mApproved.size();
- for (int i = 0 ; i < N; i++) {
- final int userId = mApproved.keyAt(i);
- final ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.valueAt(i);
- if (approvedByType != null) {
- final int M = approvedByType.size();
- for (int j = 0; j < M; j++) {
- final boolean isPrimary = approvedByType.keyAt(j);
- final ArraySet<String> approved = approvedByType.valueAt(j);
- if (approvedByType != null && approvedByType.size() > 0) {
- final long sToken = proto.start(ManagedServicesProto.APPROVED);
- for (String s : approved) {
- proto.write(ServiceProto.NAME, s);
+ synchronized (mApproved) {
+ final int N = mApproved.size();
+ for (int i = 0; i < N; i++) {
+ final int userId = mApproved.keyAt(i);
+ final ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.valueAt(i);
+ if (approvedByType != null) {
+ final int M = approvedByType.size();
+ for (int j = 0; j < M; j++) {
+ final boolean isPrimary = approvedByType.keyAt(j);
+ final ArraySet<String> approved = approvedByType.valueAt(j);
+ if (approvedByType != null && approvedByType.size() > 0) {
+ final long sToken = proto.start(ManagedServicesProto.APPROVED);
+ for (String s : approved) {
+ proto.write(ServiceProto.NAME, s);
+ }
+ proto.write(ServiceProto.USER_ID, userId);
+ proto.write(ServiceProto.IS_PRIMARY, isPrimary);
+ proto.end(sToken);
}
- proto.write(ServiceProto.USER_ID, userId);
- proto.write(ServiceProto.IS_PRIMARY, isPrimary);
- proto.end(sToken);
}
}
}
@@ -315,33 +319,36 @@
trimApprovedListsAccordingToInstalledServices(userId);
}
- final int N = mApproved.size();
- for (int i = 0 ; i < N; i++) {
- final int approvedUserId = mApproved.keyAt(i);
- if (forBackup && approvedUserId != userId) {
- continue;
- }
- final ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.valueAt(i);
- if (approvedByType != null) {
- final int M = approvedByType.size();
- for (int j = 0; j < M; j++) {
- final boolean isPrimary = approvedByType.keyAt(j);
- final Set<String> approved = approvedByType.valueAt(j);
- if (approved != null) {
- String allowedItems = String.join(ENABLED_SERVICES_SEPARATOR, approved);
- out.startTag(null, TAG_MANAGED_SERVICES);
- out.attribute(null, ATT_APPROVED_LIST, allowedItems);
- out.attribute(null, ATT_USER_ID, Integer.toString(approvedUserId));
- out.attribute(null, ATT_IS_PRIMARY, Boolean.toString(isPrimary));
- writeExtraAttributes(out, approvedUserId);
- out.endTag(null, TAG_MANAGED_SERVICES);
+ synchronized (mApproved) {
+ final int N = mApproved.size();
+ for (int i = 0; i < N; i++) {
+ final int approvedUserId = mApproved.keyAt(i);
+ if (forBackup && approvedUserId != userId) {
+ continue;
+ }
+ final ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.valueAt(i);
+ if (approvedByType != null) {
+ final int M = approvedByType.size();
+ for (int j = 0; j < M; j++) {
+ final boolean isPrimary = approvedByType.keyAt(j);
+ final Set<String> approved = approvedByType.valueAt(j);
+ if (approved != null) {
+ String allowedItems = String.join(ENABLED_SERVICES_SEPARATOR, approved);
+ out.startTag(null, TAG_MANAGED_SERVICES);
+ out.attribute(null, ATT_APPROVED_LIST, allowedItems);
+ out.attribute(null, ATT_USER_ID, Integer.toString(approvedUserId));
+ out.attribute(null, ATT_IS_PRIMARY, Boolean.toString(isPrimary));
+ writeExtraAttributes(out, approvedUserId);
+ out.endTag(null, TAG_MANAGED_SERVICES);
- if (!forBackup && isPrimary) {
- // Also write values to settings, for observers who haven't migrated yet
- Settings.Secure.putStringForUser(mContext.getContentResolver(),
- getConfig().secureSettingName, allowedItems, approvedUserId);
+ if (!forBackup && isPrimary) {
+ // Also write values to settings, for observers who haven't migrated yet
+ Settings.Secure.putStringForUser(mContext.getContentResolver(),
+ getConfig().secureSettingName, allowedItems,
+ approvedUserId);
+ }
+
}
-
}
}
}
@@ -440,23 +447,25 @@
if (TextUtils.isEmpty(approved)) {
approved = "";
}
- ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.get(userId);
- if (approvedByType == null) {
- approvedByType = new ArrayMap<>();
- mApproved.put(userId, approvedByType);
- }
+ synchronized (mApproved) {
+ ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.get(userId);
+ if (approvedByType == null) {
+ approvedByType = new ArrayMap<>();
+ mApproved.put(userId, approvedByType);
+ }
- ArraySet<String> approvedList = approvedByType.get(isPrimary);
- if (approvedList == null) {
- approvedList = new ArraySet<>();
- approvedByType.put(isPrimary, approvedList);
- }
+ ArraySet<String> approvedList = approvedByType.get(isPrimary);
+ if (approvedList == null) {
+ approvedList = new ArraySet<>();
+ approvedByType.put(isPrimary, approvedList);
+ }
- String[] approvedArray = approved.split(ENABLED_SERVICES_SEPARATOR);
- for (String pkgOrComponent : approvedArray) {
- String approvedItem = getApprovedValue(pkgOrComponent);
- if (approvedItem != null) {
- approvedList.add(approvedItem);
+ String[] approvedArray = approved.split(ENABLED_SERVICES_SEPARATOR);
+ for (String pkgOrComponent : approvedArray) {
+ String approvedItem = getApprovedValue(pkgOrComponent);
+ if (approvedItem != null) {
+ approvedList.add(approvedItem);
+ }
}
}
}
@@ -469,23 +478,25 @@
boolean isPrimary, boolean enabled) {
Slog.i(TAG,
(enabled ? " Allowing " : "Disallowing ") + mConfig.caption + " " + pkgOrComponent);
- ArrayMap<Boolean, ArraySet<String>> allowedByType = mApproved.get(userId);
- if (allowedByType == null) {
- allowedByType = new ArrayMap<>();
- mApproved.put(userId, allowedByType);
- }
- ArraySet<String> approved = allowedByType.get(isPrimary);
- if (approved == null) {
- approved = new ArraySet<>();
- allowedByType.put(isPrimary, approved);
- }
- String approvedItem = getApprovedValue(pkgOrComponent);
+ synchronized (mApproved) {
+ ArrayMap<Boolean, ArraySet<String>> allowedByType = mApproved.get(userId);
+ if (allowedByType == null) {
+ allowedByType = new ArrayMap<>();
+ mApproved.put(userId, allowedByType);
+ }
+ ArraySet<String> approved = allowedByType.get(isPrimary);
+ if (approved == null) {
+ approved = new ArraySet<>();
+ allowedByType.put(isPrimary, approved);
+ }
+ String approvedItem = getApprovedValue(pkgOrComponent);
- if (approvedItem != null) {
- if (enabled) {
- approved.add(approvedItem);
- } else {
- approved.remove(approvedItem);
+ if (approvedItem != null) {
+ if (enabled) {
+ approved.add(approvedItem);
+ } else {
+ approved.remove(approvedItem);
+ }
}
}
@@ -504,22 +515,26 @@
}
protected String getApproved(int userId, boolean primary) {
- final ArrayMap<Boolean, ArraySet<String>> allowedByType =
- mApproved.getOrDefault(userId, new ArrayMap<>());
- ArraySet<String> approved = allowedByType.getOrDefault(primary, new ArraySet<>());
- return String.join(ENABLED_SERVICES_SEPARATOR, approved);
+ synchronized (mApproved) {
+ final ArrayMap<Boolean, ArraySet<String>> allowedByType =
+ mApproved.getOrDefault(userId, new ArrayMap<>());
+ ArraySet<String> approved = allowedByType.getOrDefault(primary, new ArraySet<>());
+ return String.join(ENABLED_SERVICES_SEPARATOR, approved);
+ }
}
protected List<ComponentName> getAllowedComponents(int userId) {
final List<ComponentName> allowedComponents = new ArrayList<>();
- final ArrayMap<Boolean, ArraySet<String>> allowedByType =
- mApproved.getOrDefault(userId, new ArrayMap<>());
- for (int i = 0; i < allowedByType.size(); i++) {
- final ArraySet<String> allowed = allowedByType.valueAt(i);
- for (int j = 0; j < allowed.size(); j++) {
- ComponentName cn = ComponentName.unflattenFromString(allowed.valueAt(j));
- if (cn != null) {
- allowedComponents.add(cn);
+ synchronized (mApproved) {
+ final ArrayMap<Boolean, ArraySet<String>> allowedByType =
+ mApproved.getOrDefault(userId, new ArrayMap<>());
+ for (int i = 0; i < allowedByType.size(); i++) {
+ final ArraySet<String> allowed = allowedByType.valueAt(i);
+ for (int j = 0; j < allowed.size(); j++) {
+ ComponentName cn = ComponentName.unflattenFromString(allowed.valueAt(j));
+ if (cn != null) {
+ allowedComponents.add(cn);
+ }
}
}
}
@@ -528,14 +543,16 @@
protected List<String> getAllowedPackages(int userId) {
final List<String> allowedPackages = new ArrayList<>();
- final ArrayMap<Boolean, ArraySet<String>> allowedByType =
- mApproved.getOrDefault(userId, new ArrayMap<>());
- for (int i = 0; i < allowedByType.size(); i++) {
- final ArraySet<String> allowed = allowedByType.valueAt(i);
- for (int j = 0; j < allowed.size(); j++) {
- String pkgName = getPackageName(allowed.valueAt(j));
- if (!TextUtils.isEmpty(pkgName)) {
- allowedPackages.add(pkgName);
+ synchronized (mApproved) {
+ final ArrayMap<Boolean, ArraySet<String>> allowedByType =
+ mApproved.getOrDefault(userId, new ArrayMap<>());
+ for (int i = 0; i < allowedByType.size(); i++) {
+ final ArraySet<String> allowed = allowedByType.valueAt(i);
+ for (int j = 0; j < allowed.size(); j++) {
+ String pkgName = getPackageName(allowed.valueAt(j));
+ if (!TextUtils.isEmpty(pkgName)) {
+ allowedPackages.add(pkgName);
+ }
}
}
}
@@ -543,12 +560,14 @@
}
protected boolean isPackageOrComponentAllowed(String pkgOrComponent, int userId) {
- ArrayMap<Boolean, ArraySet<String>> allowedByType =
- mApproved.getOrDefault(userId, new ArrayMap<>());
- for (int i = 0; i < allowedByType.size(); i++) {
- ArraySet<String> allowed = allowedByType.valueAt(i);
- if (allowed.contains(pkgOrComponent)) {
- return true;
+ synchronized (mApproved) {
+ ArrayMap<Boolean, ArraySet<String>> allowedByType =
+ mApproved.getOrDefault(userId, new ArrayMap<>());
+ for (int i = 0; i < allowedByType.size(); i++) {
+ ArraySet<String> allowed = allowedByType.valueAt(i);
+ if (allowed.contains(pkgOrComponent)) {
+ return true;
+ }
}
}
return false;
@@ -558,19 +577,21 @@
if (pkg == null) {
return false;
}
- ArrayMap<Boolean, ArraySet<String>> allowedByType =
- mApproved.getOrDefault(userId, new ArrayMap<>());
- for (int i = 0; i < allowedByType.size(); i++) {
- ArraySet<String> allowed = allowedByType.valueAt(i);
- for (String allowedEntry : allowed) {
- ComponentName component = ComponentName.unflattenFromString(allowedEntry);
- if (component != null) {
- if (pkg.equals(component.getPackageName())) {
- return true;
- }
- } else {
- if (pkg.equals(allowedEntry)) {
- return true;
+ synchronized (mApproved) {
+ ArrayMap<Boolean, ArraySet<String>> allowedByType =
+ mApproved.getOrDefault(userId, new ArrayMap<>());
+ for (int i = 0; i < allowedByType.size(); i++) {
+ ArraySet<String> allowed = allowedByType.valueAt(i);
+ for (String allowedEntry : allowed) {
+ ComponentName component = ComponentName.unflattenFromString(allowedEntry);
+ if (component != null) {
+ if (pkg.equals(component.getPackageName())) {
+ return true;
+ }
+ } else {
+ if (pkg.equals(allowedEntry)) {
+ return true;
+ }
}
}
}
@@ -616,7 +637,9 @@
public void onUserRemoved(int user) {
Slog.i(TAG, "Removing approved services for removed user " + user);
- mApproved.remove(user);
+ synchronized (mApproved) {
+ mApproved.remove(user);
+ }
rebindServices(true, user);
}
@@ -797,14 +820,16 @@
protected Set<String> getAllowedPackages() {
final Set<String> allowedPackages = new ArraySet<>();
- for (int k = 0; k < mApproved.size(); k++) {
- ArrayMap<Boolean, ArraySet<String>> allowedByType = mApproved.valueAt(k);
- for (int i = 0; i < allowedByType.size(); i++) {
- final ArraySet<String> allowed = allowedByType.valueAt(i);
- for (int j = 0; j < allowed.size(); j++) {
- String pkgName = getPackageName(allowed.valueAt(j));
- if (!TextUtils.isEmpty(pkgName)) {
- allowedPackages.add(pkgName);
+ synchronized (mApproved) {
+ for (int k = 0; k < mApproved.size(); k++) {
+ ArrayMap<Boolean, ArraySet<String>> allowedByType = mApproved.valueAt(k);
+ for (int i = 0; i < allowedByType.size(); i++) {
+ final ArraySet<String> allowed = allowedByType.valueAt(i);
+ for (int j = 0; j < allowed.size(); j++) {
+ String pkgName = getPackageName(allowed.valueAt(j));
+ if (!TextUtils.isEmpty(pkgName)) {
+ allowedPackages.add(pkgName);
+ }
}
}
}
@@ -813,22 +838,24 @@
}
private void trimApprovedListsAccordingToInstalledServices(int userId) {
- final ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.get(userId);
- if (approvedByType == null) {
- return;
- }
- for (int i = 0; i < approvedByType.size(); i++) {
- final ArraySet<String> approved = approvedByType.valueAt(i);
- for (int j = approved.size() - 1; j >= 0; j--) {
- final String approvedPackageOrComponent = approved.valueAt(j);
- if (!isValidEntry(approvedPackageOrComponent, userId)){
- approved.removeAt(j);
- Slog.v(TAG, "Removing " + approvedPackageOrComponent
- + " from approved list; no matching services found");
- } else {
- if (DEBUG) {
- Slog.v(TAG, "Keeping " + approvedPackageOrComponent
- + " on approved list; matching services found");
+ synchronized (mApproved) {
+ final ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.get(userId);
+ if (approvedByType == null) {
+ return;
+ }
+ for (int i = 0; i < approvedByType.size(); i++) {
+ final ArraySet<String> approved = approvedByType.valueAt(i);
+ for (int j = approved.size() - 1; j >= 0; j--) {
+ final String approvedPackageOrComponent = approved.valueAt(j);
+ if (!isValidEntry(approvedPackageOrComponent, userId)) {
+ approved.removeAt(j);
+ Slog.v(TAG, "Removing " + approvedPackageOrComponent
+ + " from approved list; no matching services found");
+ } else {
+ if (DEBUG) {
+ Slog.v(TAG, "Keeping " + approvedPackageOrComponent
+ + " on approved list; matching services found");
+ }
}
}
}
@@ -837,20 +864,23 @@
private boolean removeUninstalledItemsFromApprovedLists(int uninstalledUserId, String pkg) {
boolean removed = false;
- final ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.get(uninstalledUserId);
- if (approvedByType != null) {
- int M = approvedByType.size();
- for (int j = 0; j < M; j++) {
- final ArraySet<String> approved = approvedByType.valueAt(j);
- int O = approved.size();
- for (int k = O - 1; k >= 0; k--) {
- final String packageOrComponent = approved.valueAt(k);
- final String packageName = getPackageName(packageOrComponent);
- if (TextUtils.equals(pkg, packageName)) {
- approved.removeAt(k);
- if (DEBUG) {
- Slog.v(TAG, "Removing " + packageOrComponent
- + " from approved list; uninstalled");
+ synchronized (mApproved) {
+ final ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.get(
+ uninstalledUserId);
+ if (approvedByType != null) {
+ int M = approvedByType.size();
+ for (int j = 0; j < M; j++) {
+ final ArraySet<String> approved = approvedByType.valueAt(j);
+ int O = approved.size();
+ for (int k = O - 1; k >= 0; k--) {
+ final String packageOrComponent = approved.valueAt(k);
+ final String packageName = getPackageName(packageOrComponent);
+ if (TextUtils.equals(pkg, packageName)) {
+ approved.removeAt(k);
+ if (DEBUG) {
+ Slog.v(TAG, "Removing " + packageOrComponent
+ + " from approved list; uninstalled");
+ }
}
}
}
@@ -887,17 +917,19 @@
for (int i = 0; i < nUserIds; ++i) {
final int userId = userIds.get(i);
- final ArrayMap<Boolean, ArraySet<String>> approvedLists = mApproved.get(userId);
- if (approvedLists != null) {
- final int N = approvedLists.size();
- for (int j = 0; j < N; j++) {
- ArraySet<ComponentName> approvedByUser = componentsByUser.get(userId);
- if (approvedByUser == null) {
- approvedByUser = new ArraySet<>();
- componentsByUser.put(userId, approvedByUser);
+ synchronized (mApproved) {
+ final ArrayMap<Boolean, ArraySet<String>> approvedLists = mApproved.get(userId);
+ if (approvedLists != null) {
+ final int N = approvedLists.size();
+ for (int j = 0; j < N; j++) {
+ ArraySet<ComponentName> approvedByUser = componentsByUser.get(userId);
+ if (approvedByUser == null) {
+ approvedByUser = new ArraySet<>();
+ componentsByUser.put(userId, approvedByUser);
+ }
+ approvedByUser.addAll(
+ loadComponentNamesFromValues(approvedLists.valueAt(j), userId));
}
- approvedByUser.addAll(
- loadComponentNamesFromValues(approvedLists.valueAt(j), userId));
}
}
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index cc2df50..e0dd9d8 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -466,6 +466,8 @@
private MetricsLogger mMetricsLogger;
private TriPredicate<String, Integer, String> mAllowedManagedServicePackages;
+ private final SavePolicyFileRunnable mSavePolicyFile = new SavePolicyFileRunnable();
+
private static class Archive {
final int mBufferSize;
final ArrayDeque<StatusBarNotification> mBuffer;
@@ -659,7 +661,14 @@
@VisibleForTesting
protected void handleSavePolicyFile() {
- IoThread.getHandler().post(() -> {
+ if (!IoThread.getHandler().hasCallbacks(mSavePolicyFile)) {
+ IoThread.getHandler().post(mSavePolicyFile);
+ }
+ }
+
+ private final class SavePolicyFileRunnable implements Runnable {
+ @Override
+ public void run() {
if (DBG) Slog.d(TAG, "handleSavePolicyFile");
synchronized (mPolicyFile) {
final FileOutputStream stream;
@@ -679,7 +688,7 @@
}
}
BackupManager.dataChanged(getContext().getPackageName());
- });
+ }
}
private void writePolicyXml(OutputStream stream, boolean forBackup, int userId)
@@ -1838,6 +1847,7 @@
}
if (properties.getKeyset()
.contains(SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE)) {
+ mAssistants.allowAdjustmentType(Adjustment.KEY_IMPORTANCE);
mAssistants.resetDefaultAssistantsIfNecessary();
}
});
@@ -2270,7 +2280,7 @@
final int callingUid = Binder.getCallingUid();
final boolean isSystemToast = isCallerSystemOrPhone()
|| PackageManagerService.PLATFORM_PACKAGE_NAME.equals(pkg);
- final boolean isPackageSuspended = isPackageSuspendedForUser(pkg, callingUid);
+ final boolean isPackageSuspended = isPackagePaused(pkg);
final boolean notificationsDisabledForPackage = !areNotificationsEnabledForPackage(pkg,
callingUid);
@@ -2419,9 +2429,25 @@
}
@Override
+ public void silenceNotificationSound() {
+ checkCallerIsSystem();
+
+ mNotificationDelegate.clearEffects();
+ }
+
+ @Override
public void setNotificationsEnabledForPackage(String pkg, int uid, boolean enabled) {
enforceSystemOrSystemUI("setNotificationsEnabledForPackage");
+ synchronized (mNotificationLock) {
+ boolean wasEnabled = mPreferencesHelper.getImportance(pkg, uid)
+ != NotificationManager.IMPORTANCE_NONE;
+
+ if (wasEnabled == enabled) {
+ return;
+ }
+ }
+
mPreferencesHelper.setEnabled(pkg, uid, enabled);
mMetricsLogger.write(new LogMaker(MetricsEvent.ACTION_BAN_APP_NOTES)
.setType(MetricsEvent.TYPE_ACTION)
@@ -4108,17 +4134,7 @@
Preconditions.checkNotNull(pkg);
checkCallerIsSameApp(pkg);
- boolean isPaused;
-
- final PackageManagerInternal pmi = LocalServices.getService(
- PackageManagerInternal.class);
- int flags = pmi.getDistractingPackageRestrictions(
- pkg, Binder.getCallingUserHandle().getIdentifier());
- isPaused = ((flags & PackageManager.RESTRICTION_HIDE_NOTIFICATIONS) != 0);
-
- isPaused |= isPackageSuspendedForUser(pkg, Binder.getCallingUid());
-
- return isPaused;
+ return isPackagePausedOrSuspended(pkg, Binder.getCallingUid());
}
private void verifyPrivilegedListener(INotificationListener token, UserHandle user,
@@ -5340,11 +5356,18 @@
}
@GuardedBy("mNotificationLock")
- private boolean isPackageSuspendedLocked(NotificationRecord r) {
- final String pkg = r.sbn.getPackageName();
- final int callingUid = r.sbn.getUid();
+ boolean isPackagePausedOrSuspended(String pkg, int uid) {
+ boolean isPaused;
- return isPackageSuspendedForUser(pkg, callingUid);
+ final PackageManagerInternal pmi = LocalServices.getService(
+ PackageManagerInternal.class);
+ int flags = pmi.getDistractingPackageRestrictions(
+ pkg, Binder.getCallingUserHandle().getIdentifier());
+ isPaused = ((flags & PackageManager.RESTRICTION_HIDE_NOTIFICATIONS) != 0);
+
+ isPaused |= isPackageSuspendedForUser(pkg, uid);
+
+ return isPaused;
}
protected class PostNotificationRunnable implements Runnable {
@@ -5377,7 +5400,8 @@
return;
}
- final boolean isPackageSuspended = isPackageSuspendedLocked(r);
+ final boolean isPackageSuspended =
+ isPackagePausedOrSuspended(r.sbn.getPackageName(), r.getUid());
r.setHidden(isPackageSuspended);
if (isPackageSuspended) {
mUsageStats.registerSuspendedByAdmin(r);
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index 7b45a1b..e4c5f3d 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -73,6 +73,9 @@
private static final String NON_BLOCKABLE_CHANNEL_DELIM = ":";
@VisibleForTesting
+ static final int NOTIFICATION_CHANNEL_COUNT_LIMIT = 50000;
+
+ @VisibleForTesting
static final String TAG_RANKING = "ranking";
private static final String TAG_PACKAGE = "package";
private static final String TAG_CHANNEL = "channel";
@@ -179,6 +182,7 @@
// noop
}
}
+ boolean skipWarningLogged = false;
PackagePreferences r = getOrCreatePackagePreferencesLocked(name, uid,
XmlUtils.readIntAttribute(
@@ -225,6 +229,14 @@
}
// Channels
if (TAG_CHANNEL.equals(tagName)) {
+ if (r.channels.size() >= NOTIFICATION_CHANNEL_COUNT_LIMIT) {
+ if (!skipWarningLogged) {
+ Slog.w(TAG, "Skipping further channels for " + r.pkg
+ + "; app has too many");
+ skipWarningLogged = true;
+ }
+ continue;
+ }
String id = parser.getAttributeValue(null, ATT_ID);
String channelName = parser.getAttributeValue(null, ATT_NAME);
int channelImportance = XmlUtils.readIntAttribute(
@@ -690,6 +702,10 @@
return needsPolicyFileChange;
}
+ if (r.channels.size() >= NOTIFICATION_CHANNEL_COUNT_LIMIT) {
+ throw new IllegalStateException("Limit exceed; cannot create more channels");
+ }
+
needsPolicyFileChange = true;
if (channel.getImportance() < IMPORTANCE_NONE
diff --git a/services/core/java/com/android/server/notification/ZenLog.java b/services/core/java/com/android/server/notification/ZenLog.java
index c6af756..8f05636 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 @@
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 f81015d..ebc4191 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -942,12 +942,11 @@
}
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 86fb00d..c7cc8b1 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -198,6 +198,7 @@
import android.content.pm.dex.ArtManager;
import android.content.pm.dex.DexMetadataHelper;
import android.content.pm.dex.IArtManager;
+import android.content.pm.permission.SplitPermissionInfoParcelable;
import android.content.res.Resources;
import android.content.rollback.IRollbackManager;
import android.database.ContentObserver;
@@ -238,6 +239,7 @@
import android.os.storage.StorageManagerInternal;
import android.os.storage.VolumeInfo;
import android.os.storage.VolumeRecord;
+import android.permission.PermissionManager;
import android.provider.DeviceConfig;
import android.provider.MediaStore;
import android.provider.Settings.Global;
@@ -2121,6 +2123,12 @@
}
}
+ @Override
+ public List<SplitPermissionInfoParcelable> getSplitPermissions() {
+ return PermissionManager.splitPermissionInfoListToParcelableList(
+ SystemConfig.getInstance().getSplitPermissions());
+ }
+
private void notifyInstallObserver(String packageName) {
Pair<PackageInstalledInfo, IPackageInstallObserver2> pair =
mNoKillInstallObservers.remove(packageName);
@@ -18891,19 +18899,20 @@
// or packages running under the shared user of the removed
// package if revoking the permissions requested only by the removed
// package is successful and this causes a change in gids.
+ boolean shouldKill = false;
for (int userId : UserManagerService.getInstance().getUserIds()) {
final int userIdToKill = mSettings.updateSharedUserPermsLPw(deletedPs,
userId);
- if (userIdToKill == UserHandle.USER_ALL
- || userIdToKill >= UserHandle.USER_SYSTEM) {
- // If gids changed for this user, kill all affected packages.
- mHandler.post(() -> {
- // This has to happen with no lock held.
- killApplication(deletedPs.name, deletedPs.appId,
- KILL_APP_REASON_GIDS_CHANGED);
- });
- break;
- }
+ shouldKill |= userIdToKill == UserHandle.USER_ALL
+ || userIdToKill >= UserHandle.USER_SYSTEM;
+ }
+ // If gids changed, kill all affected packages.
+ if (shouldKill) {
+ mHandler.post(() -> {
+ // This has to happen with no lock held.
+ killApplication(deletedPs.name, deletedPs.appId,
+ KILL_APP_REASON_GIDS_CHANGED);
+ });
}
}
clearPackagePreferredActivitiesLPw(
diff --git a/services/core/java/com/android/server/pm/ProtectedPackages.java b/services/core/java/com/android/server/pm/ProtectedPackages.java
index a374e14..231168e 100644
--- a/services/core/java/com/android/server/pm/ProtectedPackages.java
+++ b/services/core/java/com/android/server/pm/ProtectedPackages.java
@@ -92,6 +92,9 @@
if (mDeviceOwnerUserId == userId) {
return mDeviceOwnerPackage;
}
+ if (mProfileOwnerPackages == null) {
+ return null;
+ }
return mProfileOwnerPackages.get(userId);
}
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 899f802..4c33bec 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -967,10 +967,12 @@
// or has updated its target SDK and AR is no longer implicit to it.
// This is a compatibility workaround for apps when AR permission was
// split in Q.
- int numSplitPerms = PermissionManager.SPLIT_PERMISSIONS.size();
+ final List<PermissionManager.SplitPermissionInfo> permissionList =
+ getSplitPermissions();
+ int numSplitPerms = permissionList.size();
for (int splitPermNum = 0; splitPermNum < numSplitPerms; splitPermNum++) {
PermissionManager.SplitPermissionInfo sp =
- PermissionManager.SPLIT_PERMISSIONS.get(splitPermNum);
+ permissionList.get(splitPermNum);
String splitPermName = sp.getSplitPermission();
if (sp.getNewPermissions().contains(permName)
&& origPermissions.hasInstallPermission(splitPermName)) {
@@ -1537,10 +1539,10 @@
String pkgName = pkg.packageName;
ArrayMap<String, ArraySet<String>> newToSplitPerms = new ArrayMap<>();
- int numSplitPerms = PermissionManager.SPLIT_PERMISSIONS.size();
+ final List<PermissionManager.SplitPermissionInfo> permissionList = getSplitPermissions();
+ int numSplitPerms = permissionList.size();
for (int splitPermNum = 0; splitPermNum < numSplitPerms; splitPermNum++) {
- PermissionManager.SplitPermissionInfo spi =
- PermissionManager.SPLIT_PERMISSIONS.get(splitPermNum);
+ PermissionManager.SplitPermissionInfo spi = permissionList.get(splitPermNum);
List<String> newPerms = spi.getNewPermissions();
int numNewPerms = newPerms.size();
@@ -1595,8 +1597,6 @@
Slog.i(TAG, newPerm + " does not inherit from " + sourcePerms
+ " for " + pkgName + " as split permission is also new");
}
-
- break;
} else {
// Inherit from new install or existing runtime permissions
inheritPermissionStateToNewImplicitPermissionLocked(sourcePerms,
@@ -1610,6 +1610,10 @@
return updatedUserIds;
}
+ private List<PermissionManager.SplitPermissionInfo> getSplitPermissions() {
+ return SystemConfig.getInstance().getSplitPermissions();
+ }
+
private boolean isNewPlatformPermissionForPackage(String perm, PackageParser.Package pkg) {
boolean allowed = false;
final int NP = PackageParser.NEW_PERMISSIONS.length;
@@ -2022,16 +2026,6 @@
return whitelistedPermissions;
}
- private void setWhitelistedRestrictedPermissions(@NonNull PackageParser.Package pkg,
- @NonNull int[] userIds, @Nullable List<String> permissions, int callingUid,
- @PackageManager.PermissionWhitelistFlags int whitelistFlags,
- @NonNull PermissionCallback callback) {
- for (int userId : userIds) {
- setWhitelistedRestrictedPermissionsForUser(pkg, userId, permissions,
- callingUid, whitelistFlags, callback);
- }
- }
-
private void grantRequestedRuntimePermissionsForUser(PackageParser.Package pkg, int userId,
String[] grantedPermissions, int callingUid, PermissionCallback callback) {
PackageSetting ps = (PackageSetting) pkg.mExtras;
@@ -2312,109 +2306,122 @@
}
}
- private void setWhitelistedRestrictedPermissionsForUser(@NonNull PackageParser.Package pkg,
- @UserIdInt int userId, @Nullable List<String> permissions, int callingUid,
- @PermissionWhitelistFlags int whitelistFlags, PermissionCallback callback) {
+ private void setWhitelistedRestrictedPermissions(@NonNull PackageParser.Package pkg,
+ @NonNull int[] userIds, @Nullable List<String> permissions, int callingUid,
+ @PackageManager.PermissionWhitelistFlags int whitelistFlags,
+ @NonNull PermissionCallback callback) {
+
final PackageSetting ps = (PackageSetting) pkg.mExtras;
if (ps == null) {
return;
}
final PermissionsState permissionsState = ps.getPermissionsState();
-
- ArraySet<String> oldGrantedRestrictedPermissions = null;
+ SparseArray<ArraySet<String>> oldGrantedRestrictedPermissionsByUser = new SparseArray<>();
boolean updatePermissions = false;
final int permissionCount = pkg.requestedPermissions.size();
- for (int i = 0; i < permissionCount; i++) {
- final String permissionName = pkg.requestedPermissions.get(i);
+ for (int userId : userIds) {
+ for (int i = 0; i < permissionCount; i++) {
+ final String permissionName = pkg.requestedPermissions.get(i);
- final BasePermission bp = mSettings.getPermissionLocked(permissionName);
- if (bp == null) {
- Slog.w(TAG, "Cannot whitelist unknown permission: " + permissionName);
- continue;
- }
-
- if (!bp.isHardOrSoftRestricted()) {
- continue;
- }
-
- if (permissionsState.hasPermission(permissionName, userId)) {
- if (oldGrantedRestrictedPermissions == null) {
- oldGrantedRestrictedPermissions = new ArraySet<>();
+ final BasePermission bp = mSettings.getPermissionLocked(permissionName);
+ if (bp == null) {
+ Slog.w(TAG, "Cannot whitelist unknown permission: " + permissionName);
+ continue;
}
- oldGrantedRestrictedPermissions.add(permissionName);
- }
- final int oldFlags = permissionsState.getPermissionFlags(permissionName, userId);
-
- int newFlags = oldFlags;
- int mask = 0;
- int whitelistFlagsCopy = whitelistFlags;
- while (whitelistFlagsCopy != 0) {
- final int flag = 1 << Integer.numberOfTrailingZeros(whitelistFlagsCopy);
- whitelistFlagsCopy &= ~flag;
- switch (flag) {
- case FLAG_PERMISSION_WHITELIST_SYSTEM: {
- mask |= PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT;
- if (permissions != null && permissions.contains(permissionName)) {
- newFlags |= PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT;
- } else {
- newFlags &= ~PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT;
- }
- } break;
- case FLAG_PERMISSION_WHITELIST_UPGRADE: {
- mask |= PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
- if (permissions != null && permissions.contains(permissionName)) {
- newFlags |= PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
- } else {
- newFlags &= ~PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
- }
- } break;
- case FLAG_PERMISSION_WHITELIST_INSTALLER: {
- mask |= PackageManager.FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
- if (permissions != null && permissions.contains(permissionName)) {
- newFlags |= PackageManager.FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
- } else {
- newFlags &= ~PackageManager.FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
- }
- } break;
+ if (!bp.isHardOrSoftRestricted()) {
+ continue;
}
- }
- if (oldFlags == newFlags) {
- continue;
- }
-
- updatePermissions = true;
-
- final boolean wasWhitelisted = (oldFlags
- & (PackageManager.FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT)) != 0;
- final boolean isWhitelisted = (newFlags
- & (PackageManager.FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT)) != 0;
-
- // If the permission is policy fixed as granted but it is no longer
- // on any of the whitelists we need to clear the policy fixed flag
- // as whitelisting trumps policy i.e. policy cannot grant a non
- // grantable permission.
- if ((oldFlags & PackageManager.FLAG_PERMISSION_POLICY_FIXED) != 0) {
- final boolean isGranted = permissionsState.hasPermission(permissionName, userId);
- if (!isWhitelisted && isGranted) {
- mask |= PackageManager.FLAG_PERMISSION_POLICY_FIXED;
- newFlags &= ~PackageManager.FLAG_PERMISSION_POLICY_FIXED;
+ if (permissionsState.hasPermission(permissionName, userId)) {
+ if (oldGrantedRestrictedPermissionsByUser.get(userId) == null) {
+ oldGrantedRestrictedPermissionsByUser.put(userId, new ArraySet<>());
+ }
+ oldGrantedRestrictedPermissionsByUser.get(userId).add(permissionName);
}
- }
- // If we are whitelisting an app that does not support runtime permissions
- // we need to make sure it goes through the permission review UI at launch.
- if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M
- && !wasWhitelisted && isWhitelisted) {
- mask |= PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
- newFlags |= PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
- }
+ final int oldFlags = permissionsState.getPermissionFlags(permissionName, userId);
- updatePermissionFlags(permissionName, pkg.packageName, mask, newFlags,
- callingUid, userId, false, null /*callback*/);
+ int newFlags = oldFlags;
+ int mask = 0;
+ int whitelistFlagsCopy = whitelistFlags;
+ while (whitelistFlagsCopy != 0) {
+ final int flag = 1 << Integer.numberOfTrailingZeros(whitelistFlagsCopy);
+ whitelistFlagsCopy &= ~flag;
+ switch (flag) {
+ case FLAG_PERMISSION_WHITELIST_SYSTEM: {
+ mask |= PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT;
+ if (permissions != null && permissions.contains(permissionName)) {
+ newFlags |=
+ PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT;
+ } else {
+ newFlags &=
+ ~PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT;
+ }
+ }
+ break;
+ case FLAG_PERMISSION_WHITELIST_UPGRADE: {
+ mask |= PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
+ if (permissions != null && permissions.contains(permissionName)) {
+ newFlags |=
+ PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
+ } else {
+ newFlags &=
+ ~PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
+ }
+ }
+ break;
+ case FLAG_PERMISSION_WHITELIST_INSTALLER: {
+ mask |= PackageManager.FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
+ if (permissions != null && permissions.contains(permissionName)) {
+ newFlags |=
+ PackageManager.FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
+ } else {
+ newFlags &= ~PackageManager
+ .FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
+ }
+ }
+ break;
+ }
+ }
+
+ if (oldFlags == newFlags) {
+ continue;
+ }
+
+ updatePermissions = true;
+
+ final boolean wasWhitelisted = (oldFlags
+ & (PackageManager.FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT)) != 0;
+ final boolean isWhitelisted = (newFlags
+ & (PackageManager.FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT)) != 0;
+
+ // If the permission is policy fixed as granted but it is no longer
+ // on any of the whitelists we need to clear the policy fixed flag
+ // as whitelisting trumps policy i.e. policy cannot grant a non
+ // grantable permission.
+ if ((oldFlags & PackageManager.FLAG_PERMISSION_POLICY_FIXED) != 0) {
+ final boolean isGranted = permissionsState.hasPermission(permissionName,
+ userId);
+ if (!isWhitelisted && isGranted) {
+ mask |= PackageManager.FLAG_PERMISSION_POLICY_FIXED;
+ newFlags &= ~PackageManager.FLAG_PERMISSION_POLICY_FIXED;
+ }
+ }
+
+ // If we are whitelisting an app that does not support runtime permissions
+ // we need to make sure it goes through the permission review UI at launch.
+ if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M
+ && !wasWhitelisted && isWhitelisted) {
+ mask |= PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
+ newFlags |= PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
+ }
+
+ updatePermissionFlags(permissionName, pkg.packageName, mask, newFlags,
+ callingUid, userId, false, null /*callback*/);
+ }
}
if (updatePermissions) {
@@ -2422,7 +2429,12 @@
restorePermissionState(pkg, false, pkg.packageName, callback);
// If this resulted in losing a permission we need to kill the app.
- if (oldGrantedRestrictedPermissions != null) {
+ int oldGrantedRestrictedPermissionsByUserCount =
+ oldGrantedRestrictedPermissionsByUser.size();
+ for (int j = 0; j < oldGrantedRestrictedPermissionsByUserCount; j++) {
+ final int userId = oldGrantedRestrictedPermissionsByUser.keyAt(j);
+ final ArraySet<String> oldGrantedRestrictedPermissions =
+ oldGrantedRestrictedPermissionsByUser.valueAt(j);
final int oldGrantedCount = oldGrantedRestrictedPermissions.size();
for (int i = 0; i < oldGrantedCount; i++) {
final String permission = oldGrantedRestrictedPermissions.valueAt(i);
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 21b13fe..48056b4 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -107,6 +107,7 @@
import android.app.ActivityTaskManager;
import android.app.AppOpsManager;
import android.app.IUiModeManager;
+import android.app.NotificationManager;
import android.app.ProgressDialog;
import android.app.SearchManager;
import android.app.UiModeManager;
@@ -2572,6 +2573,10 @@
return (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
}
+ NotificationManager getNotificationService() {
+ return mContext.getSystemService(NotificationManager.class);
+ }
+
static IAudioService getAudioService() {
IAudioService audioService = IAudioService.Stub.asInterface(
ServiceManager.checkService(Context.AUDIO_SERVICE));
@@ -3806,6 +3811,11 @@
if (down) {
sendSystemKeyToStatusBarAsync(event.getKeyCode());
+ NotificationManager nm = getNotificationService();
+ if (nm != null && !mHandleVolumeKeysInWM) {
+ nm.silenceNotificationSound();
+ }
+
TelecomManager telecomManager = getTelecommService();
if (telecomManager != null && !mHandleVolumeKeysInWM) {
// When {@link #mHandleVolumeKeysInWM} is set, volume key events
diff --git a/services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java b/services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java
index 77bf930..712012d 100644
--- a/services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java
+++ b/services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java
@@ -24,20 +24,17 @@
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
import android.content.pm.ResolveInfo;
-import android.os.Debug;
import android.provider.Settings;
-import android.telecom.TelecomManager;
import android.text.TextUtils;
-import android.util.Log;
import android.util.Slog;
+import com.android.internal.R;
import com.android.internal.telephony.SmsApplication;
import com.android.internal.util.CollectionUtils;
import com.android.server.LocalServices;
import com.android.server.role.RoleManagerService;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -67,14 +64,25 @@
public List<String> getRoleHolders(@NonNull String roleName, @UserIdInt int userId) {
switch (roleName) {
case RoleManager.ROLE_ASSISTANT: {
- String legacyAssistant = Settings.Secure.getStringForUser(
- mContext.getContentResolver(), Settings.Secure.ASSISTANT, userId);
- if (legacyAssistant == null || legacyAssistant.isEmpty()) {
- return Collections.emptyList();
+ String packageName;
+ String setting = Settings.Secure.getStringForUser(mContext.getContentResolver(),
+ Settings.Secure.ASSISTANT, userId);
+ // AssistUtils was using the default assistant app if Settings.Secure.ASSISTANT is
+ // null, while only an empty string means user selected "None".
+ if (setting != null) {
+ if (!setting.isEmpty()) {
+ ComponentName componentName = ComponentName.unflattenFromString(setting);
+ packageName = componentName != null ? componentName.getPackageName() : null;
+ } else {
+ packageName = null;
+ }
+ } else if (mContext.getPackageManager().isDeviceUpgrading()) {
+ String defaultAssistant = mContext.getString(R.string.config_defaultAssistant);
+ packageName = !TextUtils.isEmpty(defaultAssistant) ? defaultAssistant : null;
} else {
- return Collections.singletonList(
- ComponentName.unflattenFromString(legacyAssistant).getPackageName());
+ packageName = null;
}
+ return CollectionUtils.singletonOrEmpty(packageName);
}
case RoleManager.ROLE_BROWSER: {
PackageManagerInternal packageManagerInternal = LocalServices.getService(
@@ -84,44 +92,36 @@
return CollectionUtils.singletonOrEmpty(packageName);
}
case RoleManager.ROLE_DIALER: {
- String setting = Settings.Secure.getStringForUser(
- mContext.getContentResolver(),
+ String setting = Settings.Secure.getStringForUser(mContext.getContentResolver(),
Settings.Secure.DIALER_DEFAULT_APPLICATION, userId);
- return CollectionUtils.singletonOrEmpty(!TextUtils.isEmpty(setting)
- ? setting
- : mContext.getSystemService(TelecomManager.class).getSystemDialerPackage());
+ String packageName;
+ if (!TextUtils.isEmpty(setting)) {
+ packageName = setting;
+ } else if (mContext.getPackageManager().isDeviceUpgrading()) {
+ // DefaultDialerManager was using the default dialer app if
+ // Settings.Secure.DIALER_DEFAULT_APPLICATION is invalid.
+ // TelecomManager.getSystemDialerPackage() won't work because it might not
+ // be ready.
+ packageName = mContext.getString(R.string.config_defaultDialer);
+ } else {
+ packageName = null;
+ }
+ return CollectionUtils.singletonOrEmpty(packageName);
}
case RoleManager.ROLE_SMS: {
- // Moved over from SmsApplication#getApplication
- String result = Settings.Secure.getStringForUser(
- mContext.getContentResolver(),
+ String setting = Settings.Secure.getStringForUser(mContext.getContentResolver(),
Settings.Secure.SMS_DEFAULT_APPLICATION, userId);
- // TODO: STOPSHIP: Remove the following code once we read the value of
- // config_defaultSms in RoleControllerService.
- if (result == null) {
- Collection<SmsApplication.SmsApplicationData> applications =
- SmsApplication.getApplicationCollectionAsUser(mContext, userId);
- SmsApplication.SmsApplicationData applicationData;
- String defaultPackage = mContext.getResources()
- .getString(com.android.internal.R.string.default_sms_application);
- applicationData =
- SmsApplication.getApplicationForPackage(applications, defaultPackage);
-
- if (applicationData == null) {
- // Are there any applications?
- if (applications.size() != 0) {
- applicationData =
- (SmsApplication.SmsApplicationData) applications.toArray()[0];
- }
- }
- if (DEBUG) {
- Log.i(LOG_TAG, "Found default sms app: " + applicationData
- + " among: " + applications + " from " + Debug.getCallers(4));
- }
- SmsApplication.SmsApplicationData app = applicationData;
- result = app == null ? null : app.mPackageName;
+ String packageName;
+ if (!TextUtils.isEmpty(setting)) {
+ packageName = setting;
+ } else if (mContext.getPackageManager().isDeviceUpgrading()) {
+ // SmsApplication was using the default SMS app if
+ // Settings.Secure.DIALER_DEFAULT_APPLICATION is invalid.
+ packageName = mContext.getString(R.string.config_defaultSms);
+ } else {
+ packageName = null;
}
- return CollectionUtils.singletonOrEmpty(result);
+ return CollectionUtils.singletonOrEmpty(packageName);
}
case RoleManager.ROLE_HOME: {
PackageManager packageManager = mContext.getPackageManager();
diff --git a/services/core/java/com/android/server/power/ThermalManagerService.java b/services/core/java/com/android/server/power/ThermalManagerService.java
index 1552fd5..491c5ab 100644
--- a/services/core/java/com/android/server/power/ThermalManagerService.java
+++ b/services/core/java/com/android/server/power/ThermalManagerService.java
@@ -38,11 +38,13 @@
import android.os.ShellCommand;
import android.os.Temperature;
import android.util.ArrayMap;
+import android.util.EventLog;
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.DumpUtils;
+import com.android.server.EventLogTags;
import com.android.server.FgThread;
import com.android.server.SystemService;
@@ -250,6 +252,8 @@
} finally {
mThermalEventListeners.finishBroadcast();
}
+ EventLog.writeEvent(EventLogTags.THERMAL_CHANGED, temperature.getName(),
+ temperature.getType(), temperature.getValue(), temperature.getStatus(), mStatus);
}
private void shutdownIfNeeded(Temperature temperature) {
@@ -860,10 +864,10 @@
mThermalHal11.linkToDeath(new DeathRecipient(),
THERMAL_HAL_DEATH_COOKIE);
mThermalHal11.registerThermalCallback(mThermalCallback11);
+ Slog.i(TAG, "Thermal HAL 1.1 service connected, limited thermal functions "
+ + "due to legacy API.");
} catch (NoSuchElementException | RemoteException e) {
- Slog.e(TAG,
- "Thermal HAL 1.1 service not connected, no thermal call back will be "
- + "called.");
+ Slog.e(TAG, "Thermal HAL 1.1 service not connected.");
mThermalHal11 = null;
}
return (mThermalHal11 != null);
@@ -978,8 +982,9 @@
mThermalHal20.linkToDeath(new DeathRecipient(), THERMAL_HAL_DEATH_COOKIE);
mThermalHal20.registerThermalChangedCallback(mThermalCallback20, false,
0 /* not used */);
+ Slog.i(TAG, "Thermal HAL 2.0 service connected.");
} catch (NoSuchElementException | RemoteException e) {
- Slog.e(TAG, "Thermal HAL 2.0 service not connected, trying 1.1.");
+ Slog.e(TAG, "Thermal HAL 2.0 service not connected.");
mThermalHal20 = null;
}
return (mThermalHal20 != null);
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index c5c53d8..97682b7 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -5227,18 +5227,27 @@
* 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) {
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 747837b..59ae9ac 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 @@
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;
@@ -2522,15 +2524,16 @@
@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;
@@ -3587,6 +3590,11 @@
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 ed7dbd0..99a9db3 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -3622,7 +3622,8 @@
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/DisplayWindowSettings.java b/services/core/java/com/android/server/wm/DisplayWindowSettings.java
index a46fa13..207e8ef 100644
--- a/services/core/java/com/android/server/wm/DisplayWindowSettings.java
+++ b/services/core/java/com/android/server/wm/DisplayWindowSettings.java
@@ -30,6 +30,7 @@
import android.annotation.Nullable;
import android.app.WindowConfiguration;
import android.os.Environment;
+import android.os.FileUtils;
import android.provider.Settings;
import android.util.AtomicFile;
import android.util.Slog;
@@ -64,6 +65,11 @@
class DisplayWindowSettings {
private static final String TAG = TAG_WITH_CLASS_NAME ? "DisplayWindowSettings" : TAG_WM;
+ private static final String SYSTEM_DIRECTORY = "system";
+ private static final String DISPLAY_SETTINGS_FILE_NAME = "display_settings.xml";
+ private static final String VENDOR_DISPLAY_SETTINGS_PATH = "etc/" + DISPLAY_SETTINGS_FILE_NAME;
+ private static final String WM_DISPLAY_COMMIT_TAG = "wm-displays";
+
private static final int IDENTIFIER_UNIQUE_ID = 0;
private static final int IDENTIFIER_PORT = 1;
@IntDef(prefix = { "IDENTIFIER_" }, value = {
@@ -688,8 +694,26 @@
private final AtomicFile mAtomicFile;
AtomicFileStorage() {
- final File folder = new File(Environment.getDataDirectory(), "system");
- mAtomicFile = new AtomicFile(new File(folder, "display_settings.xml"), "wm-displays");
+ final File folder = new File(Environment.getDataDirectory(), SYSTEM_DIRECTORY);
+ final File settingsFile = new File(folder, DISPLAY_SETTINGS_FILE_NAME);
+ // If display_settings.xml doesn't exist, try to copy the vendor's one instead
+ // in order to provide the vendor specific initialization.
+ if (!settingsFile.exists()) {
+ copyVendorSettings(settingsFile);
+ }
+ mAtomicFile = new AtomicFile(settingsFile, WM_DISPLAY_COMMIT_TAG);
+ }
+
+ private static void copyVendorSettings(File target) {
+ final File vendorFile = new File(Environment.getVendorDirectory(),
+ VENDOR_DISPLAY_SETTINGS_PATH);
+ if (vendorFile.canRead()) {
+ try {
+ FileUtils.copy(vendorFile, target);
+ } catch (IOException e) {
+ Slog.e(TAG, "Failed to copy vendor display_settings.xml");
+ }
+ }
}
@Override
diff --git a/services/core/java/com/android/server/wm/RootActivityContainer.java b/services/core/java/com/android/server/wm/RootActivityContainer.java
index d58c613..2e3094a 100644
--- a/services/core/java/com/android/server/wm/RootActivityContainer.java
+++ b/services/core/java/com/android/server/wm/RootActivityContainer.java
@@ -2266,9 +2266,9 @@
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.mRunningTasks.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 3bf437d..22a9c32 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 @@
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 @@
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/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index e6ed2ed..0034b3c 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -23,6 +23,7 @@
import static android.view.Display.DEFAULT_DISPLAY;
import android.annotation.NonNull;
+import android.annotation.StringRes;
import android.app.ActivityThread;
import android.app.INotificationManager;
import android.app.usage.UsageStatsManagerInternal;
@@ -1262,14 +1263,22 @@
startSystemCaptionsManagerService(context);
// App prediction manager service
- traceBeginAndSlog("StartAppPredictionService");
- mSystemServiceManager.startService(APP_PREDICTION_MANAGER_SERVICE_CLASS);
- traceEnd();
+ if (deviceHasConfigString(context, R.string.config_defaultAppPredictionService)) {
+ traceBeginAndSlog("StartAppPredictionService");
+ mSystemServiceManager.startService(APP_PREDICTION_MANAGER_SERVICE_CLASS);
+ traceEnd();
+ } else {
+ Slog.d(TAG, "AppPredictionService not defined by OEM");
+ }
// Content suggestions manager service
- traceBeginAndSlog("StartContentSuggestionsService");
- mSystemServiceManager.startService(CONTENT_SUGGESTIONS_SERVICE_CLASS);
- traceEnd();
+ if (deviceHasConfigString(context, R.string.config_defaultContentSuggestionsService)) {
+ traceBeginAndSlog("StartContentSuggestionsService");
+ mSystemServiceManager.startService(CONTENT_SUGGESTIONS_SERVICE_CLASS);
+ traceEnd();
+ } else {
+ Slog.d(TAG, "ContentSuggestionsService not defined by OEM");
+ }
traceBeginAndSlog("InitConnectivityModuleConnector");
try {
@@ -2260,10 +2269,13 @@
}, BOOT_TIMINGS_TRACE_LOG);
}
+ private boolean deviceHasConfigString(@NonNull Context context, @StringRes int resId) {
+ String serviceName = context.getString(resId);
+ return !TextUtils.isEmpty(serviceName);
+ }
+
private void startSystemCaptionsManagerService(@NonNull Context context) {
- String serviceName = context.getString(
- com.android.internal.R.string.config_defaultSystemCaptionsManagerService);
- if (TextUtils.isEmpty(serviceName)) {
+ if (!deviceHasConfigString(context, R.string.config_defaultSystemCaptionsManagerService)) {
Slog.d(TAG, "SystemCaptionsManagerService disabled because resource is not overlaid");
return;
}
@@ -2290,9 +2302,7 @@
// Then check if OEM overlaid the resource that defines the service.
if (!explicitlyEnabled) {
- final String serviceName = context
- .getString(com.android.internal.R.string.config_defaultContentCaptureService);
- if (TextUtils.isEmpty(serviceName)) {
+ if (!deviceHasConfigString(context, R.string.config_defaultContentCaptureService)) {
Slog.d(TAG, "ContentCaptureService disabled because resource is not overlaid");
return;
}
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 e72e460..c73be6f 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.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.util.function.Consumer;
+
/**
* Tests for GlobalActionPerformer
*/
@@ -84,6 +86,6 @@
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/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 5ba1eb2..b5e4934 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -1508,14 +1508,22 @@
public void testUpdateAppNotifyCreatorBlock() throws Exception {
mService.setPreferencesHelper(mPreferencesHelper);
- mBinderService.setNotificationsEnabledForPackage(PKG, 0, false);
+ mBinderService.setNotificationsEnabledForPackage(PKG, 0, true);
ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
verify(mContext, times(1)).sendBroadcastAsUser(captor.capture(), any(), eq(null));
assertEquals(NotificationManager.ACTION_APP_BLOCK_STATE_CHANGED,
captor.getValue().getAction());
assertEquals(PKG, captor.getValue().getPackage());
- assertTrue(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, false));
+ assertFalse(captor.getValue().getBooleanExtra(EXTRA_BLOCKED_STATE, true));
+ }
+
+ @Test
+ public void testUpdateAppNotifyCreatorBlock_notIfMatchesExistingSetting() throws Exception {
+ mService.setPreferencesHelper(mPreferencesHelper);
+
+ mBinderService.setNotificationsEnabledForPackage(PKG, 0, false);
+ verify(mContext, never()).sendBroadcastAsUser(any(), any(), eq(null));
}
@Test
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
index 8f8b746..365cd80 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
@@ -22,6 +22,8 @@
import static android.app.NotificationManager.IMPORTANCE_NONE;
import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
+import static com.android.server.notification.PreferencesHelper.NOTIFICATION_CHANNEL_COUNT_LIMIT;
+
import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.fail;
@@ -2690,4 +2692,51 @@
assertFalse(mHelper.areBubblesAllowed(PKG_O, UID_O));
verify(mHandler, times(1)).requestSort();
}
+
+ @Test
+ public void testTooManyChannels() {
+ for (int i = 0; i < NOTIFICATION_CHANNEL_COUNT_LIMIT; i++) {
+ NotificationChannel channel = new NotificationChannel(String.valueOf(i),
+ String.valueOf(i), NotificationManager.IMPORTANCE_HIGH);
+ mHelper.createNotificationChannel(PKG_O, UID_O, channel, true, true);
+ }
+ try {
+ NotificationChannel channel = new NotificationChannel(
+ String.valueOf(NOTIFICATION_CHANNEL_COUNT_LIMIT),
+ String.valueOf(NOTIFICATION_CHANNEL_COUNT_LIMIT),
+ NotificationManager.IMPORTANCE_HIGH);
+ mHelper.createNotificationChannel(PKG_O, UID_O, channel, true, true);
+ fail("Allowed to create too many notification channels");
+ } catch (IllegalStateException e) {
+ // great
+ }
+ }
+
+ @Test
+ public void testTooManyChannels_xml() throws Exception {
+ String extraChannel = "EXTRA";
+ String extraChannel1 = "EXTRA1";
+
+ // create first... many... directly so we don't need a big xml blob in this test
+ for (int i = 0; i < NOTIFICATION_CHANNEL_COUNT_LIMIT; i++) {
+ NotificationChannel channel = new NotificationChannel(String.valueOf(i),
+ String.valueOf(i), NotificationManager.IMPORTANCE_HIGH);
+ mHelper.createNotificationChannel(PKG_O, UID_O, channel, true, true);
+ }
+
+ final String xml = "<ranking version=\"1\">\n"
+ + "<package name=\"" + PKG_O + "\" uid=\"" + UID_O + "\" >\n"
+ + "<channel id=\"" + extraChannel + "\" name=\"hi\" importance=\"3\"/>"
+ + "<channel id=\"" + extraChannel1 + "\" name=\"hi\" importance=\"3\"/>"
+ + "</package>"
+ + "</ranking>";
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(new BufferedInputStream(new ByteArrayInputStream(xml.getBytes())),
+ null);
+ parser.nextTag();
+ mHelper.readXml(parser, false, UserHandle.USER_ALL);
+
+ assertNull(mHelper.getNotificationChannel(PKG_O, UID_O, extraChannel, true));
+ assertNull(mHelper.getNotificationChannel(PKG_O, UID_O, extraChannel1, true));
+ }
}
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 a1999c90..bad6c7c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
@@ -1301,10 +1301,10 @@
@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 dc96480..cdd4c24 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 @@
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 @@
// 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/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index e1ffb0f..46d7509 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -1281,9 +1281,12 @@
RoleObserver(@NonNull @CallbackExecutor Executor executor) {
mRm.addOnRoleHoldersChangedListenerAsUser(executor, this, UserHandle.ALL);
- UserHandle currentUser = UserHandle.of(LocalServices.getService(
- ActivityManagerInternal.class).getCurrentUserId());
- onRoleHoldersChanged(RoleManager.ROLE_ASSISTANT, currentUser);
+ // Sync only if assistant role has been initialized.
+ if (mRm.isRoleAvailable(RoleManager.ROLE_ASSISTANT)) {
+ UserHandle currentUser = UserHandle.of(LocalServices.getService(
+ ActivityManagerInternal.class).getCurrentUserId());
+ onRoleHoldersChanged(RoleManager.ROLE_ASSISTANT, currentUser);
+ }
}
private @NonNull String getDefaultRecognizer(@NonNull UserHandle user) {
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
index f16dec6..0ff9273 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 @@
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/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 2ffc825..7121035 100755
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -1403,6 +1403,13 @@
"read_only_apn_fields_string_array";
/**
+ * Default value of APN types field if not specified by user when adding/modifying an APN.
+ * @hide
+ */
+ public static final String KEY_APN_SETTINGS_DEFAULT_APN_TYPES_STRING_ARRAY =
+ "apn_settings_default_apn_types_string_array";
+
+ /**
* Boolean indicating if intent for emergency call state changes should be broadcast
* @hide
*/
@@ -2668,25 +2675,34 @@
"call_waiting_service_class_int";
/**
- * This configuration allow the system UI to display different 5G icon for different 5G status.
+ * This configuration allow the system UI to display different 5G icon for different 5G
+ * scenario.
*
- * There are four 5G status:
+ * There are five 5G scenarios:
* 1. connected_mmwave: device currently connected to 5G cell as the secondary cell and using
* millimeter wave.
* 2. connected: device currently connected to 5G cell as the secondary cell but not using
* millimeter wave.
- * 3. not_restricted: device camped on a network that has 5G capability(not necessary to connect
- * a 5G cell as a secondary cell) and the use of 5G is not restricted.
- * 4. restricted: device camped on a network that has 5G capability(not necessary to connect a
+ * 3. not_restricted_rrc_idle: device camped on a network that has 5G capability(not necessary
+ * to connect a 5G cell as a secondary cell) and the use of 5G is not restricted and RRC
+ * currently in IDLE state.
+ * 4. not_restricted_rrc_con: device camped on a network that has 5G capability(not necessary
+ * to connect a 5G cell as a secondary cell) and the use of 5G is not restricted and RRC
+ * currently in CONNECTED state.
+ * 5. restricted: device camped on a network that has 5G capability(not necessary to connect a
* 5G cell as a secondary cell) but the use of 5G is restricted.
*
* The configured string contains multiple key-value pairs separated by comma. For each pair,
* the key and value is separated by a colon. The key is corresponded to a 5G status above and
* the value is the icon name. Use "None" as the icon name if no icon should be shown in a
- * specific 5G status.
+ * specific 5G scenario. If the scenario is "None", config can skip this key and value.
*
- * Here is an example of the configuration:
- * "connected_mmwave:5GPlus,connected:5G,not_restricted:None,restricted:None"
+ * Icon name options: "5G_Plus", "5G".
+ *
+ * Here is an example:
+ * UE want to display 5G_Plus icon for scenario#1, and 5G icon for scenario#2; otherwise no
+ * define.
+ * The configuration is: "connected_mmwave:5G_Plus,connected:5G"
*
* @hide
*/
@@ -2694,6 +2710,22 @@
"5g_icon_configuration_string";
/**
+ * Timeout in second for displaying 5G icon, default value is 0 which means the timer is
+ * disabled.
+ *
+ * System UI will show the 5G icon and start a timer with the timeout from this config when the
+ * device connects to a 5G cell. System UI stops displaying 5G icon when both the device
+ * disconnects from 5G cell and the timer is expired.
+ *
+ * If 5G is reacquired during this timer, the timer is canceled and restarted when 5G is next
+ * lost. Allows us to momentarily lose 5G without blinking the icon.
+ *
+ * @hide
+ */
+ public static final String KEY_5G_ICON_DISPLAY_GRACE_PERIOD_SEC_INT =
+ "5g_icon_display_grace_period_sec_int";
+
+ /**
* Support ASCII 7-BIT encoding for long SMS. This carrier config is used to enable
* this feature.
* @hide
@@ -2745,12 +2777,20 @@
/**
* Controls hysteresis time in milli seconds for which OpportunisticNetworkService
- * will wait before switching data to a network.
+ * will wait before switching data to an opportunistic network.
*/
public static final String KEY_OPPORTUNISTIC_NETWORK_DATA_SWITCH_HYSTERESIS_TIME_LONG =
"opportunistic_network_data_switch_hysteresis_time_long";
/**
+ * Controls hysteresis time in milli seconds for which OpportunisticNetworkService
+ * will wait before switching data from opportunistic network to primary network.
+ * @hide
+ */
+ public static final String KEY_OPPORTUNISTIC_NETWORK_DATA_SWITCH_EXIT_HYSTERESIS_TIME_LONG =
+ "opportunistic_network_data_switch_exit_hysteresis_time_long";
+
+ /**
* Indicates zero or more emergency number prefix(es), because some carrier requires
* if users dial an emergency number address with a specific prefix, the combination of the
* prefix and the address is also a valid emergency number to dial. For example, an emergency
@@ -3120,6 +3160,13 @@
public static final String KEY_SUPPORT_WPS_OVER_IMS_BOOL =
"support_wps_over_ims_bool";
+ /**
+ * Holds the list of carrier certificate hashes. Note that each carrier has its own certificates
+ * @hide
+ */
+ public static final String KEY_CARRIER_CERTIFICATE_STRING_ARRAY =
+ "carrier_certificate_string_array";
+
/** The default value for every variable. */
private final static PersistableBundle sDefaults;
@@ -3236,6 +3283,7 @@
sDefaults.putBoolean(KEY_ALLOW_ADDING_APNS_BOOL, true);
sDefaults.putStringArray(KEY_READ_ONLY_APN_TYPES_STRING_ARRAY, new String[] {"dun"});
sDefaults.putStringArray(KEY_READ_ONLY_APN_FIELDS_STRING_ARRAY, null);
+ sDefaults.putStringArray(KEY_APN_SETTINGS_DEFAULT_APN_TYPES_STRING_ARRAY, null);
sDefaults.putBoolean(KEY_BROADCAST_EMERGENCY_CALL_STATE_CHANGES_BOOL, false);
sDefaults.putBoolean(KEY_ALWAYS_SHOW_EMERGENCY_ALERT_ONOFF_BOOL, false);
sDefaults.putBoolean(KEY_DISABLE_SEVERE_WHEN_EXTREME_DISABLED_BOOL, true);
@@ -3499,7 +3547,8 @@
sDefaults.putBoolean(KEY_USE_CALLER_ID_USSD_BOOL, false);
sDefaults.putInt(KEY_CALL_WAITING_SERVICE_CLASS_INT, 1 /* SERVICE_CLASS_VOICE */);
sDefaults.putString(KEY_5G_ICON_CONFIGURATION_STRING,
- "connected_mmwave:None,connected:5G,not_restricted:None,restricted:None");
+ "connected_mmwave:5G,connected:5G");
+ sDefaults.putInt(KEY_5G_ICON_DISPLAY_GRACE_PERIOD_SEC_INT, 0);
sDefaults.putBoolean(KEY_ASCII_7_BIT_SUPPORT_FOR_LONG_MESSAGE_BOOL, false);
/* Default value is minimum RSRP level needed for SIGNAL_STRENGTH_GOOD */
sDefaults.putInt(KEY_OPPORTUNISTIC_NETWORK_ENTRY_THRESHOLD_RSRP_INT, -108);
@@ -3515,6 +3564,8 @@
sDefaults.putLong(KEY_OPPORTUNISTIC_NETWORK_ENTRY_OR_EXIT_HYSTERESIS_TIME_LONG, 10000);
/* Default value is 10 seconds. */
sDefaults.putLong(KEY_OPPORTUNISTIC_NETWORK_DATA_SWITCH_HYSTERESIS_TIME_LONG, 10000);
+ /* Default value is 3 seconds. */
+ sDefaults.putLong(KEY_OPPORTUNISTIC_NETWORK_DATA_SWITCH_EXIT_HYSTERESIS_TIME_LONG, 3000);
sDefaults.putAll(Gps.getDefaults());
sDefaults.putAll(Wifi.getDefaults());
sDefaults.putIntArray(KEY_CDMA_ENHANCED_ROAMING_INDICATOR_FOR_HOME_NETWORK_INT_ARRAY,
@@ -3524,7 +3575,7 @@
sDefaults.putStringArray(KEY_EMERGENCY_NUMBER_PREFIX_STRING_ARRAY, new String[0]);
sDefaults.putBoolean(KEY_USE_USIM_BOOL, false);
sDefaults.putBoolean(KEY_SHOW_WFC_LOCATION_PRIVACY_POLICY_BOOL, false);
- sDefaults.putBoolean(KEY_AUTO_CANCEL_CS_REJECT_NOTIFICATION, false);
+ sDefaults.putBoolean(KEY_AUTO_CANCEL_CS_REJECT_NOTIFICATION, true);
sDefaults.putString(KEY_SMART_FORWARDING_CONFIG_COMPONENT_NAME_STRING, "");
sDefaults.putBoolean(KEY_ALWAYS_SHOW_PRIMARY_SIGNAL_BAR_IN_OPPORTUNISTIC_NETWORK_BOOLEAN,
false);
@@ -3539,6 +3590,7 @@
});
sDefaults.putBoolean(KEY_SUPPORT_WPS_OVER_IMS_BOOL, true);
sDefaults.putAll(Ims.getDefaults());
+ sDefaults.putStringArray(KEY_CARRIER_CERTIFICATE_STRING_ARRAY, null);
}
/**
diff --git a/telephony/java/android/telephony/CellIdentity.java b/telephony/java/android/telephony/CellIdentity.java
index 258a873..432978d 100644
--- a/telephony/java/android/telephony/CellIdentity.java
+++ b/telephony/java/android/telephony/CellIdentity.java
@@ -17,6 +17,7 @@
package android.telephony;
import android.annotation.CallSuper;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;
@@ -61,7 +62,7 @@
mType = type;
// Only allow INT_MAX if unknown string mcc/mnc
- if (mcc == null || mcc.matches("^[0-9]{3}$")) {
+ if (mcc == null || isMcc(mcc)) {
mMccStr = mcc;
} else if (mcc.isEmpty() || mcc.equals(String.valueOf(Integer.MAX_VALUE))) {
// If the mccStr is empty or unknown, set it as null.
@@ -73,7 +74,7 @@
log("invalid MCC format: " + mcc);
}
- if (mnc == null || mnc.matches("^[0-9]{2,3}$")) {
+ if (mnc == null || isMnc(mnc)) {
mMncStr = mnc;
} else if (mnc.isEmpty() || mnc.equals(String.valueOf(Integer.MAX_VALUE))) {
// If the mncStr is empty or unknown, set it as null.
@@ -262,4 +263,30 @@
if ((value < rangeMin || value > rangeMax) && value != special) return CellInfo.UNAVAILABLE;
return value;
}
+
+ /** @hide */
+ private static boolean isMcc(@NonNull String mcc) {
+ // ensure no out of bounds indexing
+ if (mcc.length() != 3) return false;
+
+ // Character.isDigit allows all unicode digits, not just [0-9]
+ for (int i = 0; i < 3; i++) {
+ if (mcc.charAt(i) < '0' || mcc.charAt(i) > '9') return false;
+ }
+
+ return true;
+ }
+
+ /** @hide */
+ private static boolean isMnc(@NonNull String mnc) {
+ // ensure no out of bounds indexing
+ if (mnc.length() < 2 || mnc.length() > 3) return false;
+
+ // Character.isDigit allows all unicode digits, not just [0-9]
+ for (int i = 0; i < mnc.length(); i++) {
+ if (mnc.charAt(i) < '0' || mnc.charAt(i) > '9') return false;
+ }
+
+ return true;
+ }
}
diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java
index a8491d3..58f2858 100644
--- a/telephony/java/android/telephony/SubscriptionInfo.java
+++ b/telephony/java/android/telephony/SubscriptionInfo.java
@@ -38,6 +38,7 @@
import android.util.DisplayMetrics;
import android.util.Log;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@@ -147,7 +148,14 @@
* The access rules for this subscription, if it is embedded and defines any.
*/
@Nullable
- private UiccAccessRule[] mAccessRules;
+ private UiccAccessRule[] mNativeAccessRules;
+
+ /**
+ * The carrier certificates for this subscription that are saved in carrier configs.
+ * The other carrier certificates are embedded on Uicc and stored as part of mNativeAccessRules.
+ */
+ @Nullable
+ private UiccAccessRule[] mCarrierConfigAccessRules;
/**
* The string ID of the SIM card. It is the ICCID of the active profile for a UICC card and the
@@ -206,12 +214,12 @@
public SubscriptionInfo(int id, String iccId, int simSlotIndex, CharSequence displayName,
CharSequence carrierName, int nameSource, int iconTint, String number, int roaming,
Bitmap icon, String mcc, String mnc, String countryIso, boolean isEmbedded,
- @Nullable UiccAccessRule[] accessRules, String cardString) {
+ @Nullable UiccAccessRule[] nativeAccessRules, String cardString) {
this(id, iccId, simSlotIndex, displayName, carrierName, nameSource, iconTint, number,
- roaming, icon, mcc, mnc, countryIso, isEmbedded, accessRules, cardString, -1,
+ roaming, icon, mcc, mnc, countryIso, isEmbedded, nativeAccessRules, cardString, -1,
false, null, false, TelephonyManager.UNKNOWN_CARRIER_ID,
SubscriptionManager.PROFILE_CLASS_DEFAULT,
- SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM, null);
+ SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM, null, null);
}
/**
@@ -220,12 +228,12 @@
public SubscriptionInfo(int id, String iccId, int simSlotIndex, CharSequence displayName,
CharSequence carrierName, int nameSource, int iconTint, String number, int roaming,
Bitmap icon, String mcc, String mnc, String countryIso, boolean isEmbedded,
- @Nullable UiccAccessRule[] accessRules, String cardString, boolean isOpportunistic,
- @Nullable String groupUUID, int carrierId, int profileClass) {
+ @Nullable UiccAccessRule[] nativeAccessRules, String cardString,
+ boolean isOpportunistic, @Nullable String groupUUID, int carrierId, int profileClass) {
this(id, iccId, simSlotIndex, displayName, carrierName, nameSource, iconTint, number,
- roaming, icon, mcc, mnc, countryIso, isEmbedded, accessRules, cardString, -1,
+ roaming, icon, mcc, mnc, countryIso, isEmbedded, nativeAccessRules, cardString, -1,
isOpportunistic, groupUUID, false, carrierId, profileClass,
- SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM, null);
+ SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM, null, null);
}
/**
@@ -234,9 +242,10 @@
public SubscriptionInfo(int id, String iccId, int simSlotIndex, CharSequence displayName,
CharSequence carrierName, int nameSource, int iconTint, String number, int roaming,
Bitmap icon, String mcc, String mnc, String countryIso, boolean isEmbedded,
- @Nullable UiccAccessRule[] accessRules, String cardString, int cardId,
+ @Nullable UiccAccessRule[] nativeAccessRules, String cardString, int cardId,
boolean isOpportunistic, @Nullable String groupUUID, boolean isGroupDisabled,
- int carrierId, int profileClass, int subType, @Nullable String groupOwner) {
+ int carrierId, int profileClass, int subType, @Nullable String groupOwner,
+ @Nullable UiccAccessRule[] carrierConfigAccessRules) {
this.mId = id;
this.mIccId = iccId;
this.mSimSlotIndex = simSlotIndex;
@@ -251,7 +260,7 @@
this.mMnc = mnc;
this.mCountryIso = countryIso;
this.mIsEmbedded = isEmbedded;
- this.mAccessRules = accessRules;
+ this.mNativeAccessRules = nativeAccessRules;
this.mCardString = cardString;
this.mCardId = cardId;
this.mIsOpportunistic = isOpportunistic;
@@ -261,6 +270,7 @@
this.mProfileClass = profileClass;
this.mSubscriptionType = subType;
this.mGroupOwner = groupOwner;
+ this.mCarrierConfigAccessRules = carrierConfigAccessRules;
}
/**
@@ -541,7 +551,6 @@
*
* @param context Context of the application to check.
* @return whether the app is authorized to manage this subscription per its metadata.
- * @throws UnsupportedOperationException if this subscription is not embedded.
* @hide
* @deprecated - Do not use.
*/
@@ -557,16 +566,13 @@
* @param context Any context.
* @param packageName Package name of the app to check.
* @return whether the app is authorized to manage this subscription per its metadata.
- * @throws UnsupportedOperationException if this subscription is not embedded.
* @hide
* @deprecated - Do not use.
*/
@Deprecated
public boolean canManageSubscription(Context context, String packageName) {
- if (!isEmbedded()) {
- throw new UnsupportedOperationException("Not an embedded subscription");
- }
- if (mAccessRules == null) {
+ List<UiccAccessRule> allAccessRules = getAllAccessRules();
+ if (allAccessRules == null) {
return false;
}
PackageManager packageManager = context.getPackageManager();
@@ -574,9 +580,10 @@
try {
packageInfo = packageManager.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
} catch (PackageManager.NameNotFoundException e) {
- throw new IllegalArgumentException("Unknown package: " + packageName, e);
+ Log.d("SubscriptionInfo", "canManageSubscription: Unknown package: " + packageName, e);
+ return false;
}
- for (UiccAccessRule rule : mAccessRules) {
+ for (UiccAccessRule rule : allAccessRules) {
if (rule.getCarrierPrivilegeStatus(packageInfo)
== TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
return true;
@@ -586,17 +593,33 @@
}
/**
- * @return the {@link UiccAccessRule}s dictating who is authorized to manage this subscription.
+ * @return the {@link UiccAccessRule}s that are stored in Uicc, dictating who
+ * is authorized to manage this subscription.
+ * TODO and fix it properly in R / master: either deprecate this and have 3 APIs
+ * native + carrier + all, or have this return all by default.
* @throws UnsupportedOperationException if this subscription is not embedded.
* @hide
*/
@SystemApi
public @Nullable List<UiccAccessRule> getAccessRules() {
- if (!isEmbedded()) {
- throw new UnsupportedOperationException("Not an embedded subscription");
+ if (mNativeAccessRules == null) return null;
+ return Arrays.asList(mNativeAccessRules);
+ }
+
+ /**
+ * @return the {@link UiccAccessRule}s that are both stored on Uicc and in carrierConfigs
+ * dictating who is authorized to manage this subscription.
+ * @hide
+ */
+ public @Nullable List<UiccAccessRule> getAllAccessRules() {
+ List<UiccAccessRule> merged = new ArrayList<>();
+ if (mNativeAccessRules != null) {
+ merged.addAll(getAccessRules());
}
- if (mAccessRules == null) return null;
- return Arrays.asList(mAccessRules);
+ if (mCarrierConfigAccessRules != null) {
+ merged.addAll(Arrays.asList(mCarrierConfigAccessRules));
+ }
+ return merged.isEmpty() ? null : merged;
}
/**
@@ -651,7 +674,7 @@
String countryIso = source.readString();
Bitmap iconBitmap = source.readParcelable(Bitmap.class.getClassLoader());
boolean isEmbedded = source.readBoolean();
- UiccAccessRule[] accessRules = source.createTypedArray(UiccAccessRule.CREATOR);
+ UiccAccessRule[] nativeAccessRules = source.createTypedArray(UiccAccessRule.CREATOR);
String cardString = source.readString();
int cardId = source.readInt();
boolean isOpportunistic = source.readBoolean();
@@ -663,11 +686,14 @@
String[] ehplmns = source.readStringArray();
String[] hplmns = source.readStringArray();
String groupOwner = source.readString();
+ UiccAccessRule[] carrierConfigAccessRules = source.createTypedArray(
+ UiccAccessRule.CREATOR);
SubscriptionInfo info = new SubscriptionInfo(id, iccId, simSlotIndex, displayName,
carrierName, nameSource, iconTint, number, dataRoaming, iconBitmap, mcc, mnc,
- countryIso, isEmbedded, accessRules, cardString, cardId, isOpportunistic,
- groupUUID, isGroupDisabled, carrierid, profileClass, subType, groupOwner);
+ countryIso, isEmbedded, nativeAccessRules, cardString, cardId, isOpportunistic,
+ groupUUID, isGroupDisabled, carrierid, profileClass, subType, groupOwner,
+ carrierConfigAccessRules);
info.setAssociatedPlmns(ehplmns, hplmns);
return info;
}
@@ -694,7 +720,7 @@
dest.writeString(mCountryIso);
dest.writeParcelable(mIconBitmap, flags);
dest.writeBoolean(mIsEmbedded);
- dest.writeTypedArray(mAccessRules, flags);
+ dest.writeTypedArray(mNativeAccessRules, flags);
dest.writeString(mCardString);
dest.writeInt(mCardId);
dest.writeBoolean(mIsOpportunistic);
@@ -706,6 +732,7 @@
dest.writeStringArray(mEhplmns);
dest.writeStringArray(mHplmns);
dest.writeString(mGroupOwner);
+ dest.writeTypedArray(mCarrierConfigAccessRules, flags);
}
@Override
@@ -736,9 +763,9 @@
+ " carrierId=" + mCarrierId + " displayName=" + mDisplayName
+ " carrierName=" + mCarrierName + " nameSource=" + mNameSource
+ " iconTint=" + mIconTint + " mNumber=" + Rlog.pii(Build.IS_DEBUGGABLE, mNumber)
- + " dataRoaming=" + mDataRoaming + " iconBitmap=" + mIconBitmap + " mcc=" + mMcc
- + " mnc=" + mMnc + " mCountryIso=" + mCountryIso + " isEmbedded=" + mIsEmbedded
- + " accessRules=" + Arrays.toString(mAccessRules)
+ + " dataRoaming=" + mDataRoaming + " iconBitmap=" + mIconBitmap + " mcc " + mMcc
+ + " mnc " + mMnc + "mCountryIso=" + mCountryIso + " isEmbedded " + mIsEmbedded
+ + " nativeAccessRules " + Arrays.toString(mNativeAccessRules)
+ " cardString=" + cardStringToPrint + " cardId=" + mCardId
+ " isOpportunistic=" + mIsOpportunistic + " mGroupUUID=" + mGroupUUID
+ " mIsGroupDisabled=" + mIsGroupDisabled
@@ -746,14 +773,15 @@
+ " ehplmns=" + Arrays.toString(mEhplmns)
+ " hplmns=" + Arrays.toString(mHplmns)
+ " subscriptionType=" + mSubscriptionType
- + " mGroupOwner=" + mGroupOwner + "}";
+ + " mGroupOwner=" + mGroupOwner
+ + " carrierConfigAccessRules=" + mCarrierConfigAccessRules + "}";
}
@Override
public int hashCode() {
return Objects.hash(mId, mSimSlotIndex, mNameSource, mIconTint, mDataRoaming, mIsEmbedded,
mIsOpportunistic, mGroupUUID, mIccId, mNumber, mMcc, mMnc,
- mCountryIso, mCardString, mCardId, mDisplayName, mCarrierName, mAccessRules,
+ mCountryIso, mCardString, mCardId, mDisplayName, mCarrierName, mNativeAccessRules,
mIsGroupDisabled, mCarrierId, mProfileClass, mGroupOwner);
}
@@ -789,7 +817,7 @@
&& Objects.equals(mGroupOwner, toCompare.mGroupOwner)
&& TextUtils.equals(mDisplayName, toCompare.mDisplayName)
&& TextUtils.equals(mCarrierName, toCompare.mCarrierName)
- && Arrays.equals(mAccessRules, toCompare.mAccessRules)
+ && Arrays.equals(mNativeAccessRules, toCompare.mNativeAccessRules)
&& mProfileClass == toCompare.mProfileClass
&& Arrays.equals(mEhplmns, toCompare.mEhplmns)
&& Arrays.equals(mHplmns, toCompare.mHplmns);
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index bd0f225..7b1ba24 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -571,6 +571,16 @@
public static final String ACCESS_RULES = "access_rules";
/**
+ * TelephonyProvider column name for the encoded {@link UiccAccessRule}s from
+ * {@link UiccAccessRule#encodeRules} but for the rules that come from CarrierConfigs.
+ * Only present if there are access rules in CarrierConfigs
+ * <p>TYPE: BLOB
+ * @hide
+ */
+ public static final String ACCESS_RULES_FROM_CARRIER_CONFIGS =
+ "access_rules_from_carrier_configs";
+
+ /**
* TelephonyProvider column name identifying whether an embedded subscription is on a removable
* card. Such subscriptions are marked inaccessible as soon as the current card is removed.
* Otherwise, they will remain accessible unless explicitly deleted. Only present if
@@ -2583,7 +2593,6 @@
*
* @param info The subscription to check.
* @return whether the app is authorized to manage this subscription per its metadata.
- * @throws IllegalArgumentException if this subscription is not embedded.
*/
public boolean canManageSubscription(SubscriptionInfo info) {
return canManageSubscription(info, mContext.getPackageName());
@@ -2599,14 +2608,10 @@
* @param info The subscription to check.
* @param packageName Package name of the app to check.
* @return whether the app is authorized to manage this subscription per its access rules.
- * @throws IllegalArgumentException if this subscription is not embedded.
* @hide
*/
public boolean canManageSubscription(SubscriptionInfo info, String packageName) {
- if (!info.isEmbedded()) {
- throw new IllegalArgumentException("Not an embedded subscription");
- }
- if (info.getAccessRules() == null) {
+ if (info == null || info.getAllAccessRules() == null) {
return false;
}
PackageManager packageManager = mContext.getPackageManager();
@@ -2614,9 +2619,10 @@
try {
packageInfo = packageManager.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
} catch (PackageManager.NameNotFoundException e) {
- throw new IllegalArgumentException("Unknown package: " + packageName, e);
+ logd("Unknown package: " + packageName);
+ return false;
}
- for (UiccAccessRule rule : info.getAccessRules()) {
+ for (UiccAccessRule rule : info.getAllAccessRules()) {
if (rule.getCarrierPrivilegeStatus(packageInfo)
== TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
return true;
@@ -3007,7 +3013,7 @@
// to the caller.
boolean hasCarrierPrivilegePermission = TelephonyManager.from(mContext)
.hasCarrierPrivileges(info.getSubscriptionId())
- || (info.isEmbedded() && canManageSubscription(info));
+ || canManageSubscription(info);
return hasCarrierPrivilegePermission;
}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 00288d7..aff66db 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -11123,6 +11123,8 @@
* The {@link #EXTRA_NETWORK_COUNTRY} extra indicates the country code of the current
* network returned by {@link #getNetworkCountryIso()}.
*
+ * <p>There may be a delay of several minutes before reporting that no country is detected.
+ *
* @see #EXTRA_NETWORK_COUNTRY
* @see #getNetworkCountryIso()
*/
diff --git a/tests/testables/src/android/testing/DexmakerShareClassLoaderRule.java b/tests/testables/src/android/testing/DexmakerShareClassLoaderRule.java
index 1b8e58c..7057a90 100644
--- a/tests/testables/src/android/testing/DexmakerShareClassLoaderRule.java
+++ b/tests/testables/src/android/testing/DexmakerShareClassLoaderRule.java
@@ -20,6 +20,8 @@
import com.android.internal.annotations.VisibleForTesting;
+import libcore.util.SneakyThrow;
+
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
@@ -55,7 +57,11 @@
* WARNING: This is absolutely incompatible with running tests in parallel!
*/
public static void runWithDexmakerShareClassLoader(Runnable r) {
- apply(r::run).run();
+ try {
+ apply(r::run).run();
+ } catch (Throwable t) {
+ SneakyThrow.sneakyThrow(t);
+ }
}
/**