Merge "Add NAME_SOURCE_CARRIER for subscription display name." into qt-dev
diff --git a/core/java/android/app/VoiceInteractor.java b/core/java/android/app/VoiceInteractor.java
index 78285738..b37120f 100644
--- a/core/java/android/app/VoiceInteractor.java
+++ b/core/java/android/app/VoiceInteractor.java
@@ -79,10 +79,10 @@
/** @hide */
public static final String KEY_KILL_SIGNAL = "key_kill_signal";
- IVoiceInteractor mInteractor;
+ @Nullable IVoiceInteractor mInteractor;
- Context mContext;
- Activity mActivity;
+ @Nullable Context mContext;
+ @Nullable Activity mActivity;
boolean mRetaining;
final HandlerCaller mHandlerCaller;
@@ -999,7 +999,9 @@
// destroyed now
mInteractor = null;
- mActivity.setVoiceInteractor(null);
+ if (mActivity != null) {
+ mActivity.setVoiceInteractor(null);
+ }
}
public boolean submitRequest(Request request) {
diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java
index 59ae334..8e40449 100644
--- a/core/java/android/app/usage/NetworkStatsManager.java
+++ b/core/java/android/app/usage/NetworkStatsManager.java
@@ -278,6 +278,12 @@
return null;
}
+ return querySummary(template, startTime, endTime);
+ }
+
+ /** @hide */
+ public NetworkStats querySummary(NetworkTemplate template, long startTime,
+ long endTime) throws SecurityException, RemoteException {
NetworkStats result;
result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
result.startSummaryEnumeration();
@@ -296,6 +302,13 @@
NetworkStats.Bucket.TAG_NONE, NetworkStats.Bucket.STATE_ALL);
}
+ /** @hide */
+ public NetworkStats queryDetailsForUid(NetworkTemplate template,
+ long startTime, long endTime, int uid) throws SecurityException {
+ return queryDetailsForUidTagState(template, startTime, endTime, uid,
+ NetworkStats.Bucket.TAG_NONE, NetworkStats.Bucket.STATE_ALL);
+ }
+
/**
* Query network usage statistics details for a given uid and tag.
*
@@ -340,6 +353,13 @@
NetworkTemplate template;
template = createTemplate(networkType, subscriberId);
+ return queryDetailsForUidTagState(template, startTime, endTime, uid, tag, state);
+ }
+
+ /** @hide */
+ public NetworkStats queryDetailsForUidTagState(NetworkTemplate template,
+ long startTime, long endTime, int uid, int tag, int state) throws SecurityException {
+
NetworkStats result;
try {
result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index ee62af5..69c1295 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -248,6 +248,8 @@
public static final int FLAG_STORAGE_DE = IInstalld.FLAG_STORAGE_DE;
/** {@hide} */
public static final int FLAG_STORAGE_CE = IInstalld.FLAG_STORAGE_CE;
+ /** {@hide} */
+ public static final int FLAG_STORAGE_EXTERNAL = IInstalld.FLAG_STORAGE_EXTERNAL;
/** {@hide} */
public static final int FLAG_FOR_WRITE = 1 << 8;
diff --git a/core/java/android/os/storage/VolumeRecord.java b/core/java/android/os/storage/VolumeRecord.java
index b6ee261..1a794eb 100644
--- a/core/java/android/os/storage/VolumeRecord.java
+++ b/core/java/android/os/storage/VolumeRecord.java
@@ -25,6 +25,7 @@
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
+import java.util.Locale;
import java.util.Objects;
/**
@@ -45,6 +46,7 @@
public String nickname;
public int userFlags;
public long createdMillis;
+ public long lastSeenMillis;
public long lastTrimMillis;
public long lastBenchMillis;
@@ -61,6 +63,7 @@
nickname = parcel.readString();
userFlags = parcel.readInt();
createdMillis = parcel.readLong();
+ lastSeenMillis = parcel.readLong();
lastTrimMillis = parcel.readLong();
lastBenchMillis = parcel.readLong();
}
@@ -73,6 +76,10 @@
return fsUuid;
}
+ public String getNormalizedFsUuid() {
+ return fsUuid != null ? fsUuid.toLowerCase(Locale.US) : null;
+ }
+
public String getNickname() {
return nickname;
}
@@ -97,6 +104,7 @@
DebugUtils.flagsToString(VolumeRecord.class, "USER_FLAG_", userFlags));
pw.println();
pw.printPair("createdMillis", TimeUtils.formatForLogging(createdMillis));
+ pw.printPair("lastSeenMillis", TimeUtils.formatForLogging(lastSeenMillis));
pw.printPair("lastTrimMillis", TimeUtils.formatForLogging(lastTrimMillis));
pw.printPair("lastBenchMillis", TimeUtils.formatForLogging(lastBenchMillis));
pw.decreaseIndent();
@@ -155,6 +163,7 @@
parcel.writeString(nickname);
parcel.writeInt(userFlags);
parcel.writeLong(createdMillis);
+ parcel.writeLong(lastSeenMillis);
parcel.writeLong(lastTrimMillis);
parcel.writeLong(lastBenchMillis);
}
diff --git a/core/java/android/service/appprediction/AppPredictionService.java b/core/java/android/service/appprediction/AppPredictionService.java
index 1391d43..be20570 100644
--- a/core/java/android/service/appprediction/AppPredictionService.java
+++ b/core/java/android/service/appprediction/AppPredictionService.java
@@ -39,6 +39,7 @@
import android.os.RemoteException;
import android.service.appprediction.IPredictionService.Stub;
import android.util.ArrayMap;
+import android.util.Log;
import android.util.Slog;
import java.util.ArrayList;
@@ -46,7 +47,7 @@
import java.util.function.Consumer;
/**
- * TODO(b/111701043): Add java docs
+ * A service used to predict app and shortcut usage.
*
* @hide
*/
@@ -58,7 +59,9 @@
/**
* The {@link Intent} that must be declared as handled by the service.
- * TODO(b/111701043): Add any docs about permissions the service must hold
+ *
+ * <p>The service must also require the {@link android.permission#MANAGE_APP_PREDICTIONS}
+ * permission.
*
* @hide
*/
@@ -145,8 +148,11 @@
@Override
@NonNull
public final IBinder onBind(@NonNull Intent intent) {
- // TODO(b/111701043): Verify that the action is valid
- return mInterface.asBinder();
+ if (SERVICE_INTERFACE.equals(intent.getAction())) {
+ return mInterface.asBinder();
+ }
+ Log.w(TAG, "Tried to bind to wrong intent (should be " + SERVICE_INTERFACE + ": " + intent);
+ return null;
}
/**
@@ -180,7 +186,6 @@
/**
* Called by the client app to request sorting of targets based on prediction rank.
- * TODO(b/111701043): Implement CancellationSignal so caller can cancel a long running request
*/
@MainThread
public abstract void onSortAppTargets(@NonNull AppPredictionSessionId sessionId,
@@ -254,7 +259,6 @@
/**
* Called by the client app to request target predictions. This method is only called if there
* are one or more prediction callbacks registered.
- * TODO(b/111701043): Add java docs
*
* @see #updatePredictions(AppPredictionSessionId, List)
*/
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index d67c884..63e1485 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -2660,6 +2660,9 @@
*/
@NonNull
public Transaction merge(@NonNull Transaction other) {
+ if (this == other) {
+ return this;
+ }
mResizedSurfaces.putAll(other.mResizedSurfaces);
other.mResizedSurfaces.clear();
nativeMergeTransaction(mNativeObject, other.mNativeObject);
diff --git a/core/java/com/android/internal/infra/AbstractRemoteService.java b/core/java/com/android/internal/infra/AbstractRemoteService.java
index 64f8857..3900f16 100644
--- a/core/java/com/android/internal/infra/AbstractRemoteService.java
+++ b/core/java/com/android/internal/infra/AbstractRemoteService.java
@@ -231,6 +231,7 @@
@SuppressWarnings("unchecked") // TODO(b/117779333): fix this warning
final S castService = (S) this;
mVultureCallback.onServiceDied(castService);
+ handleBindFailure();
}
// Note: we are dumping without a lock held so this is a bit racy but
@@ -406,7 +407,8 @@
@NonNull BasePendingRequest<S, I> pendingRequest);
/**
- * Called if {@link Context#bindServiceAsUser} returns {@code false}.
+ * Called if {@link Context#bindServiceAsUser} returns {@code false}, or
+ * if {@link DeathRecipient#binderDied()} is called.
*/
abstract void handleBindFailure();
@@ -431,8 +433,6 @@
mBinding = false;
if (!mServiceDied) {
- // TODO(b/126266412): merge these 2 calls?
- handleBindFailure();
handleBinderDied();
}
}
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 0cf9500..7de6ca5 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1533,7 +1533,7 @@
<!-- Message shown during face acquisition when only the left part of the user's face was detected [CHAR LIMIT=50] -->
<string name="face_acquired_too_left">Move phone to the right.</string>
<!-- Message shown during face acquisition when the user is not front facing the sensor [CHAR LIMIT=50] -->
- <string name="face_acquired_poor_gaze">Look at the screen with your eyes open.</string>
+ <string name="face_acquired_poor_gaze">Please look more directly at your device.</string>
<!-- Message shown during face acquisition when the user is not detected [CHAR LIMIT=50] -->
<string name="face_acquired_not_detected">Can\u2019t see your face. Look at the phone.</string>
<!-- Message shown during face acquisition when the device is not steady [CHAR LIMIT=50] -->
diff --git a/data/etc/com.android.dialer.xml b/data/etc/com.android.dialer.xml
index ccdb21f..405279f 100644
--- a/data/etc/com.android.dialer.xml
+++ b/data/etc/com.android.dialer.xml
@@ -24,5 +24,7 @@
<permission name="android.permission.STOP_APP_SWITCHES"/>
<permission name="com.android.voicemail.permission.READ_VOICEMAIL"/>
<permission name="com.android.voicemail.permission.WRITE_VOICEMAIL"/>
+ <permission name="android.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS"/>
+ <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
</privapp-permissions>
</permissions>
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index 11d635e..297153d 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -637,8 +637,7 @@
* @see #setOrientation(Orientation)
*/
public Orientation getOrientation() {
- updateGradientStateOrientation();
- return mGradientState.mOrientation;
+ return mGradientState.getOrientation();
}
/**
@@ -654,10 +653,7 @@
* @see #getOrientation()
*/
public void setOrientation(Orientation orientation) {
- // Update the angle here so that subsequent attempts to obtain the orientation
- // from the angle overwrite previously configured values during inflation
- mGradientState.mAngle = getAngleFromOrientation(orientation);
- mGradientState.mOrientation = orientation;
+ mGradientState.setOrientation(orientation);
mGradientIsDirty = true;
invalidateSelf();
}
@@ -1246,76 +1242,6 @@
}
/**
- * Update the orientation of the gradient based on the given angle only if the type is
- * {@link #LINEAR_GRADIENT}
- */
- private void updateGradientStateOrientation() {
- if (mGradientState.mGradient == LINEAR_GRADIENT) {
- int angle = mGradientState.mAngle;
- if (angle % 45 != 0) {
- throw new IllegalArgumentException("Linear gradient requires 'angle' attribute to "
- + "be a multiple of 45");
- }
-
- Orientation orientation;
- switch (angle) {
- case 0:
- orientation = Orientation.LEFT_RIGHT;
- break;
- case 45:
- orientation = Orientation.BL_TR;
- break;
- case 90:
- orientation = Orientation.BOTTOM_TOP;
- break;
- case 135:
- orientation = Orientation.BR_TL;
- break;
- case 180:
- orientation = Orientation.RIGHT_LEFT;
- break;
- case 225:
- orientation = Orientation.TR_BL;
- break;
- case 270:
- orientation = Orientation.TOP_BOTTOM;
- break;
- case 315:
- orientation = Orientation.TL_BR;
- break;
- default:
- // Should not get here as exception is thrown above if angle is not multiple
- // of 45 degrees
- orientation = Orientation.LEFT_RIGHT;
- break;
- }
- mGradientState.mOrientation = orientation;
- }
- }
-
- private int getAngleFromOrientation(Orientation orientation) {
- switch (orientation) {
- default:
- case LEFT_RIGHT:
- return 0;
- case BL_TR:
- return 45;
- case BOTTOM_TOP:
- return 90;
- case BR_TL:
- return 135;
- case RIGHT_LEFT:
- return 180;
- case TR_BL:
- return 225;
- case TOP_BOTTOM:
- return 270;
- case TL_BR:
- return 315;
- }
- }
-
- /**
* This checks mGradientIsDirty, and if it is true, recomputes both our drawing
* rectangle (mRect) and the gradient itself, since it depends on our
* rectangle too.
@@ -1344,8 +1270,7 @@
if (st.mGradient == LINEAR_GRADIENT) {
final float level = st.mUseLevel ? getLevel() / 10000.0f : 1.0f;
- updateGradientStateOrientation();
- switch (st.mOrientation) {
+ switch (st.getOrientation()) {
case TOP_BOTTOM:
x0 = r.left; y0 = r.top;
x1 = x0; y1 = level * r.bottom;
@@ -2056,7 +1981,7 @@
int[] mAttrPadding;
public GradientState(Orientation orientation, int[] gradientColors) {
- mOrientation = orientation;
+ setOrientation(orientation);
setGradientColors(gradientColors);
}
@@ -2259,6 +2184,93 @@
mCenterY = y;
}
+ public void setOrientation(Orientation orientation) {
+ // Update the angle here so that subsequent attempts to obtain the orientation
+ // from the angle overwrite previously configured values during inflation
+ mAngle = getAngleFromOrientation(orientation);
+ mOrientation = orientation;
+ }
+
+ @NonNull
+ public Orientation getOrientation() {
+ updateGradientStateOrientation();
+ return mOrientation;
+ }
+
+ /**
+ * Update the orientation of the gradient based on the given angle only if the type is
+ * {@link #LINEAR_GRADIENT}
+ */
+ private void updateGradientStateOrientation() {
+ if (mGradient == LINEAR_GRADIENT) {
+ int angle = mAngle;
+ if (angle % 45 != 0) {
+ throw new IllegalArgumentException("Linear gradient requires 'angle' attribute "
+ + "to be a multiple of 45");
+ }
+
+ Orientation orientation;
+ switch (angle) {
+ case 0:
+ orientation = Orientation.LEFT_RIGHT;
+ break;
+ case 45:
+ orientation = Orientation.BL_TR;
+ break;
+ case 90:
+ orientation = Orientation.BOTTOM_TOP;
+ break;
+ case 135:
+ orientation = Orientation.BR_TL;
+ break;
+ case 180:
+ orientation = Orientation.RIGHT_LEFT;
+ break;
+ case 225:
+ orientation = Orientation.TR_BL;
+ break;
+ case 270:
+ orientation = Orientation.TOP_BOTTOM;
+ break;
+ case 315:
+ orientation = Orientation.TL_BR;
+ break;
+ default:
+ // Should not get here as exception is thrown above if angle is not multiple
+ // of 45 degrees
+ orientation = Orientation.LEFT_RIGHT;
+ break;
+ }
+ mOrientation = orientation;
+ }
+ }
+
+ private int getAngleFromOrientation(@Nullable Orientation orientation) {
+ if (orientation != null) {
+ switch (orientation) {
+ default:
+ case LEFT_RIGHT:
+ return 0;
+ case BL_TR:
+ return 45;
+ case BOTTOM_TOP:
+ return 90;
+ case BR_TL:
+ return 135;
+ case RIGHT_LEFT:
+ return 180;
+ case TR_BL:
+ return 225;
+ case TOP_BOTTOM:
+ return 270;
+ case TL_BR:
+ return 315;
+ }
+ } else {
+ return 0;
+ }
+ }
+
public void setGradientColors(@Nullable int[] colors) {
mGradientColors = colors;
mSolidColors = null;
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index 62fd489..5173f63 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -167,8 +167,6 @@
LOG_ALWAYS_FATAL_IF(physDeviceProperties.apiVersion < VK_MAKE_VERSION(1, 1, 0));
mDriverVersion = physDeviceProperties.driverVersion;
- mIsQualcomm = physDeviceProperties.vendorID == 20803;
-
// query to get the initial queue props size
uint32_t queueCount;
mGetPhysicalDeviceQueueFamilyProperties(mPhysicalDevice, &queueCount, nullptr);
diff --git a/libs/hwui/renderthread/VulkanManager.h b/libs/hwui/renderthread/VulkanManager.h
index 31de803..dd3c6d0 100644
--- a/libs/hwui/renderthread/VulkanManager.h
+++ b/libs/hwui/renderthread/VulkanManager.h
@@ -179,13 +179,6 @@
SwapBehavior mSwapBehavior = SwapBehavior::Discard;
GrVkExtensions mExtensions;
uint32_t mDriverVersion = 0;
-
- // TODO: Remove once fix has landed. Temporaryly needed for workaround for setting up AHB
- // surfaces on Qualcomm. Currently if you don't use VkSwapchain Qualcomm is not setting
- // reporting that we need to use one of their private vendor usage bits which greatly effects
- // performance if it is not used.
- bool mIsQualcomm = false;
- bool isQualcomm() const { return mIsQualcomm; }
};
} /* namespace renderthread */
diff --git a/libs/hwui/renderthread/VulkanSurface.cpp b/libs/hwui/renderthread/VulkanSurface.cpp
index df6b9ed..b2cc23e 100644
--- a/libs/hwui/renderthread/VulkanSurface.cpp
+++ b/libs/hwui/renderthread/VulkanSurface.cpp
@@ -297,11 +297,6 @@
native_window_get_consumer_usage(window, &consumerUsage);
windowInfo.windowUsageFlags = consumerUsage | hwbUsage.androidHardwareBufferUsage;
- if (vkManager.isQualcomm()) {
- windowInfo.windowUsageFlags =
- windowInfo.windowUsageFlags | AHARDWAREBUFFER_USAGE_VENDOR_0;
- }
-
/*
* Now we attempt to modify the window!
*/
diff --git a/media/java/android/media/ThumbnailUtils.java b/media/java/android/media/ThumbnailUtils.java
index 5de56c7..b3c2bb7 100644
--- a/media/java/android/media/ThumbnailUtils.java
+++ b/media/java/android/media/ThumbnailUtils.java
@@ -52,6 +52,7 @@
import java.io.IOException;
import java.util.Arrays;
import java.util.Comparator;
+import java.util.Objects;
import java.util.function.ToIntFunction;
/**
@@ -369,10 +370,12 @@
// If we're okay with something larger than native format, just
// return a frame without up-scaling it
if (size.getWidth() > width && size.getHeight() > height) {
- return mmr.getFrameAtTime(duration / 2, OPTION_CLOSEST_SYNC);
+ return Objects.requireNonNull(
+ mmr.getFrameAtTime(duration / 2, OPTION_CLOSEST_SYNC));
} else {
- return mmr.getScaledFrameAtTime(duration / 2, OPTION_CLOSEST_SYNC,
- size.getWidth(), size.getHeight());
+ return Objects.requireNonNull(
+ mmr.getScaledFrameAtTime(duration / 2, OPTION_CLOSEST_SYNC,
+ size.getWidth(), size.getHeight()));
}
} catch (RuntimeException e) {
throw new IOException("Failed to create thumbnail", e);
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java
index 2bfcc91..f30de13 100644
--- a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java
+++ b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java
@@ -175,9 +175,7 @@
private long getUsageLevel(NetworkTemplate template, long start, long end) {
try {
- final Bucket bucket = mNetworkStatsManager.querySummaryForDevice(
- getNetworkType(template), getActiveSubscriberId(),
- start, end);
+ final Bucket bucket = mNetworkStatsManager.querySummaryForDevice(template, start, end);
if (bucket != null) {
return bucket.getRxBytes() + bucket.getTxBytes();
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleChartDataLoader.java b/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleChartDataLoader.java
index ec5a0b5..787dc55 100644
--- a/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleChartDataLoader.java
+++ b/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleChartDataLoader.java
@@ -37,14 +37,14 @@
private NetworkCycleChartDataLoader(Builder builder) {
super(builder);
- mData = new ArrayList<NetworkCycleChartData>();
+ mData = new ArrayList<>();
}
@Override
void recordUsage(long start, long end) {
try {
final NetworkStats.Bucket bucket = mNetworkStatsManager.querySummaryForDevice(
- mNetworkType, mSubId, start, end);
+ mNetworkTemplate, start, end);
final long total = bucket == null ? 0L : bucket.getRxBytes() + bucket.getTxBytes();
if (total > 0L) {
final NetworkCycleChartData.Builder builder = new NetworkCycleChartData.Builder();
@@ -81,7 +81,7 @@
long usage = 0L;
try {
final NetworkStats.Bucket bucket = mNetworkStatsManager.querySummaryForDevice(
- mNetworkType, mSubId, bucketStart, bucketEnd);
+ mNetworkTemplate, bucketStart, bucketEnd);
if (bucket != null) {
usage = bucket.getRxBytes() + bucket.getTxBytes();
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleDataForUidLoader.java b/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleDataForUidLoader.java
index bd9a636..43c05b8 100644
--- a/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleDataForUidLoader.java
+++ b/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleDataForUidLoader.java
@@ -23,11 +23,11 @@
import android.content.Context;
import android.util.Log;
+import androidx.annotation.VisibleForTesting;
+
import java.util.ArrayList;
import java.util.List;
-import androidx.annotation.VisibleForTesting;
-
/**
* Loader for network data usage history. It returns a list of usage data per billing cycle for the
* specific Uid(s).
@@ -44,7 +44,7 @@
super(builder);
mUids = builder.mUids;
mRetrieveDetail = builder.mRetrieveDetail;
- mData = new ArrayList<NetworkCycleDataForUid>();
+ mData = new ArrayList<>();
}
@Override
@@ -54,7 +54,7 @@
long totalForeground = 0L;
for (int uid : mUids) {
final NetworkStats stats = mNetworkStatsManager.queryDetailsForUid(
- mNetworkType, mSubId, start, end, uid);
+ mNetworkTemplate, start, end, uid);
final long usage = getTotalUsage(stats);
if (usage > 0L) {
totalUsage += usage;
@@ -100,7 +100,7 @@
private long getForegroundUsage(long start, long end, int uid) {
final NetworkStats stats = mNetworkStatsManager.queryDetailsForUidTagState(
- mNetworkType, mSubId, start, end, uid, TAG_NONE, STATE_FOREGROUND);
+ mNetworkTemplate, start, end, uid, TAG_NONE, STATE_FOREGROUND);
return getTotalUsage(stats);
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleDataLoader.java b/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleDataLoader.java
index dd6d563..3e95b01 100644
--- a/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleDataLoader.java
+++ b/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleDataLoader.java
@@ -49,18 +49,14 @@
public abstract class NetworkCycleDataLoader<D> extends AsyncTaskLoader<D> {
private static final String TAG = "NetworkCycleDataLoader";
protected final NetworkStatsManager mNetworkStatsManager;
- protected final String mSubId;
- protected final int mNetworkType;
+ protected final NetworkTemplate mNetworkTemplate;
private final NetworkPolicy mPolicy;
- private final NetworkTemplate mNetworkTemplate;
private final ArrayList<Long> mCycles;
@VisibleForTesting
final INetworkStatsService mNetworkStatsService;
protected NetworkCycleDataLoader(Builder<?> builder) {
super(builder.mContext);
- mSubId = builder.mSubId;
- mNetworkType = builder.mNetworkType;
mNetworkTemplate = builder.mNetworkTemplate;
mCycles = builder.mCycles;
mNetworkStatsManager = (NetworkStatsManager)
@@ -180,8 +176,6 @@
public static abstract class Builder<T extends NetworkCycleDataLoader> {
private final Context mContext;
- private String mSubId;
- private int mNetworkType;
private NetworkTemplate mNetworkTemplate;
private ArrayList<Long> mCycles;
@@ -189,14 +183,8 @@
mContext = context;
}
- public Builder<T> setSubscriberId(String subId) {
- mSubId = subId;
- return this;
- }
-
public Builder<T> setNetworkTemplate(NetworkTemplate template) {
mNetworkTemplate = template;
- mNetworkType = DataUsageController.getNetworkType(template);
return this;
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/NetworkStatsSummaryLoader.java b/packages/SettingsLib/src/com/android/settingslib/net/NetworkStatsSummaryLoader.java
index 34e6097..ed093629 100644
--- a/packages/SettingsLib/src/com/android/settingslib/net/NetworkStatsSummaryLoader.java
+++ b/packages/SettingsLib/src/com/android/settingslib/net/NetworkStatsSummaryLoader.java
@@ -16,9 +16,10 @@
package com.android.settingslib.net;
-import android.app.usage.NetworkStatsManager;
import android.app.usage.NetworkStats;
+import android.app.usage.NetworkStatsManager;
import android.content.Context;
+import android.net.NetworkTemplate;
import android.os.RemoteException;
import android.util.Log;
@@ -33,15 +34,13 @@
private final NetworkStatsManager mNetworkStatsManager;
private final long mStart;
private final long mEnd;
- private final String mSubId;
- private final int mNetworkType;
+ private final NetworkTemplate mNetworkTemplate;
private NetworkStatsSummaryLoader(Builder builder) {
super(builder.mContext);
mStart = builder.mStart;
mEnd = builder.mEnd;
- mSubId = builder.mSubId;
- mNetworkType = builder.mNetworkType;
+ mNetworkTemplate = builder.mNetworkTemplate;
mNetworkStatsManager = (NetworkStatsManager)
builder.mContext.getSystemService(Context.NETWORK_STATS_SERVICE);
}
@@ -55,7 +54,7 @@
@Override
public NetworkStats loadInBackground() {
try {
- return mNetworkStatsManager.querySummary(mNetworkType, mSubId, mStart, mEnd);
+ return mNetworkStatsManager.querySummary(mNetworkTemplate, mStart, mEnd);
} catch (RemoteException e) {
Log.e(TAG, "Exception querying network detail.", e);
return null;
@@ -78,8 +77,7 @@
private final Context mContext;
private long mStart;
private long mEnd;
- private String mSubId;
- private int mNetworkType;
+ private NetworkTemplate mNetworkTemplate;
public Builder(Context context) {
mContext = context;
@@ -95,13 +93,11 @@
return this;
}
- public Builder setSubscriberId(String subId) {
- mSubId = subId;
- return this;
- }
-
- public Builder setNetworkType(int networkType) {
- mNetworkType = networkType;
+ /**
+ * Set {@link NetworkTemplate} for builder
+ */
+ public Builder setNetworkTemplate(NetworkTemplate template) {
+ mNetworkTemplate = template;
return this;
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageControllerTest.java
index a28bb6c..3da5e76 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageControllerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageControllerTest.java
@@ -31,7 +31,6 @@
import android.app.usage.NetworkStats;
import android.app.usage.NetworkStatsManager;
import android.content.Context;
-import android.net.ConnectivityManager;
import android.net.INetworkStatsSession;
import android.net.NetworkStatsHistory;
import android.net.NetworkTemplate;
@@ -52,6 +51,7 @@
public class DataUsageControllerTest {
private static final String SUB_ID = "Test Subscriber";
+ private static final String SUB_ID_2 = "Test Subscriber 2";
@Mock
private INetworkStatsSession mSession;
@@ -63,6 +63,9 @@
private NetworkStatsManager mNetworkStatsManager;
@Mock
private Context mContext;
+ private NetworkTemplate mNetworkTemplate;
+ private NetworkTemplate mNetworkTemplate2;
+ private NetworkTemplate mWifiNetworkTemplate;
private DataUsageController mController;
private NetworkStatsHistory mNetworkStatsHistory;
@@ -83,24 +86,27 @@
.when(mSession).getHistoryForNetwork(any(NetworkTemplate.class), anyInt());
ShadowSubscriptionManager.setDefaultDataSubscriptionId(mDefaultSubscriptionId);
doReturn(SUB_ID).when(mTelephonyManager).getSubscriberId();
+
+ mNetworkTemplate = NetworkTemplate.buildTemplateMobileAll(SUB_ID);
+ mNetworkTemplate2 = NetworkTemplate.buildTemplateMobileAll(SUB_ID_2);
+ mWifiNetworkTemplate = NetworkTemplate.buildTemplateWifiWildcard();
}
@Test
public void getHistoricalUsageLevel_shouldQuerySummaryForDevice() throws Exception {
+ mController.getHistoricalUsageLevel(mWifiNetworkTemplate);
- mController.getHistoricalUsageLevel(NetworkTemplate.buildTemplateWifiWildcard());
-
- verify(mNetworkStatsManager).querySummaryForDevice(eq(ConnectivityManager.TYPE_WIFI),
- eq(SUB_ID), eq(0L) /* startTime */, anyLong() /* endTime */);
+ verify(mNetworkStatsManager).querySummaryForDevice(eq(mWifiNetworkTemplate),
+ eq(0L) /* startTime */, anyLong() /* endTime */);
}
@Test
public void getHistoricalUsageLevel_noUsageData_shouldReturn0() throws Exception {
- when(mNetworkStatsManager.querySummaryForDevice(eq(ConnectivityManager.TYPE_WIFI),
- eq(SUB_ID), eq(0L) /* startTime */, anyLong() /* endTime */))
+ when(mNetworkStatsManager.querySummaryForDevice(eq(mWifiNetworkTemplate),
+ eq(0L) /* startTime */, anyLong() /* endTime */))
.thenReturn(mock(NetworkStats.Bucket.class));
- assertThat(mController.getHistoricalUsageLevel(NetworkTemplate.buildTemplateWifiWildcard()))
- .isEqualTo(0L);
+ assertThat(mController.getHistoricalUsageLevel(mWifiNetworkTemplate))
+ .isEqualTo(0L);
}
@Test
@@ -110,10 +116,10 @@
final NetworkStats.Bucket bucket = mock(NetworkStats.Bucket.class);
when(bucket.getRxBytes()).thenReturn(receivedBytes);
when(bucket.getTxBytes()).thenReturn(transmittedBytes);
- when(mNetworkStatsManager.querySummaryForDevice(eq(ConnectivityManager.TYPE_WIFI),
- eq(SUB_ID), eq(0L) /* startTime */, anyLong() /* endTime */)).thenReturn(bucket);
+ when(mNetworkStatsManager.querySummaryForDevice(eq(mWifiNetworkTemplate),
+ eq(0L) /* startTime */, anyLong() /* endTime */)).thenReturn(bucket);
- assertThat(mController.getHistoricalUsageLevel(NetworkTemplate.buildTemplateWifiWildcard()))
+ assertThat(mController.getHistoricalUsageLevel(mWifiNetworkTemplate))
.isEqualTo(receivedBytes + transmittedBytes);
}
@@ -126,9 +132,8 @@
final NetworkStats.Bucket defaultSubscriberBucket = mock(NetworkStats.Bucket.class);
when(defaultSubscriberBucket.getRxBytes()).thenReturn(defaultSubRx);
when(defaultSubscriberBucket.getTxBytes()).thenReturn(defaultSubTx);
- when(mNetworkStatsManager.querySummaryForDevice(eq(ConnectivityManager.TYPE_MOBILE),
- eq(SUB_ID), eq(0L)/* startTime */, anyLong() /* endTime */)).thenReturn(
- defaultSubscriberBucket);
+ when(mNetworkStatsManager.querySummaryForDevice(eq(mNetworkTemplate), eq(0L)/* startTime */,
+ anyLong() /* endTime */)).thenReturn(defaultSubscriberBucket);
// Now setup a stats bucket for a different, non-default subscription / subscriber ID.
final long nonDefaultSubRx = 7654321L;
@@ -137,25 +142,21 @@
when(nonDefaultSubscriberBucket.getRxBytes()).thenReturn(nonDefaultSubRx);
when(nonDefaultSubscriberBucket.getTxBytes()).thenReturn(nonDefaultSubTx);
final int explicitSubscriptionId = 55;
- final String subscriberId2 = "Test Subscriber 2";
- when(mNetworkStatsManager.querySummaryForDevice(eq(ConnectivityManager.TYPE_MOBILE),
- eq(subscriberId2), eq(0L)/* startTime */, anyLong() /* endTime */)).thenReturn(
+ when(mNetworkStatsManager.querySummaryForDevice(eq(mNetworkTemplate2),
+ eq(0L)/* startTime */, anyLong() /* endTime */)).thenReturn(
nonDefaultSubscriberBucket);
- doReturn(subscriberId2).when(mTelephonyManager).getSubscriberId();
+ doReturn(SUB_ID_2).when(mTelephonyManager).getSubscriberId();
// Now verify that when we're asking for stats on the non-default subscription, we get
// the data back for that subscription and *not* the default one.
mController.setSubscriptionId(explicitSubscriptionId);
- assertThat(mController.getHistoricalUsageLevel(
- NetworkTemplate.buildTemplateMobileAll(subscriberId2))).isEqualTo(
+ assertThat(mController.getHistoricalUsageLevel(mNetworkTemplate2)).isEqualTo(
nonDefaultSubRx + nonDefaultSubTx);
-
- verify(mTelephonyManager).createForSubscriptionId(explicitSubscriptionId);
}
@Test
- public void getTelephonyManager_shouldCreateWithExplicitSubId() throws Exception {
+ public void getTelephonyManager_shouldCreateWithExplicitSubId() {
int explicitSubId = 1;
TelephonyManager tmForSub1 = new TelephonyManager(mContext, explicitSubId);
when(mTelephonyManager.createForSubscriptionId(eq(explicitSubId))).thenReturn(tmForSub1);
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleChartDataLoaderTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleChartDataLoaderTest.java
index 011f234..c3e1613 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleChartDataLoaderTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleChartDataLoaderTest.java
@@ -21,9 +21,9 @@
import android.app.usage.NetworkStatsManager;
import android.content.Context;
-import android.net.ConnectivityManager;
import android.net.NetworkPolicy;
import android.net.NetworkPolicyManager;
+import android.net.NetworkTemplate;
import android.os.RemoteException;
import android.text.format.DateUtils;
@@ -43,6 +43,8 @@
private NetworkPolicyManager mNetworkPolicyManager;
@Mock
private Context mContext;
+ @Mock
+ private NetworkTemplate mNetworkTemplate;
private NetworkCycleChartDataLoader mLoader;
@@ -60,13 +62,12 @@
public void recordUsage_shouldQueryNetworkSummaryForDevice() throws RemoteException {
final long end = System.currentTimeMillis();
final long start = end - (DateUtils.WEEK_IN_MILLIS * 4);
- final int networkType = ConnectivityManager.TYPE_MOBILE;
- final String subId = "TestSubscriber";
mLoader = NetworkCycleChartDataLoader.builder(mContext)
- .setSubscriberId(subId).build();
+ .setNetworkTemplate(mNetworkTemplate)
+ .build();
mLoader.recordUsage(start, end);
- verify(mNetworkStatsManager).querySummaryForDevice(networkType, subId, start, end);
+ verify(mNetworkStatsManager).querySummaryForDevice(mNetworkTemplate, start, end);
}
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataForUidLoaderTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataForUidLoaderTest.java
index aafb46a..877eb61 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataForUidLoaderTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataForUidLoaderTest.java
@@ -28,9 +28,9 @@
import android.app.usage.NetworkStatsManager;
import android.content.Context;
-import android.net.ConnectivityManager;
import android.net.NetworkPolicy;
import android.net.NetworkPolicyManager;
+import android.net.NetworkTemplate;
import android.text.format.DateUtils;
import org.junit.Before;
@@ -42,6 +42,7 @@
@RunWith(RobolectricTestRunner.class)
public class NetworkCycleDataForUidLoaderTest {
+ private static final String SUB_ID = "Test Subscriber";
@Mock
private NetworkStatsManager mNetworkStatsManager;
@@ -49,6 +50,7 @@
private NetworkPolicyManager mNetworkPolicyManager;
@Mock
private Context mContext;
+ private NetworkTemplate mNetworkTemplate;
private NetworkCycleDataForUidLoader mLoader;
@@ -56,64 +58,62 @@
public void setUp() {
MockitoAnnotations.initMocks(this);
when(mContext.getSystemService(Context.NETWORK_STATS_SERVICE))
- .thenReturn(mNetworkStatsManager);
+ .thenReturn(mNetworkStatsManager);
when(mContext.getSystemService(Context.NETWORK_POLICY_SERVICE))
- .thenReturn(mNetworkPolicyManager);
+ .thenReturn(mNetworkPolicyManager);
when(mNetworkPolicyManager.getNetworkPolicies()).thenReturn(new NetworkPolicy[0]);
+ mNetworkTemplate = NetworkTemplate.buildTemplateMobileAll(SUB_ID);
}
@Test
public void recordUsage_shouldQueryNetworkDetailsForUidAndForegroundState() {
final long end = System.currentTimeMillis();
final long start = end - (DateUtils.WEEK_IN_MILLIS * 4);
- final int networkType = ConnectivityManager.TYPE_MOBILE;
- final String subId = "TestSubscriber";
final int uid = 1;
mLoader = spy(NetworkCycleDataForUidLoader.builder(mContext)
- .addUid(uid).setSubscriberId(subId).build());
+ .addUid(uid)
+ .setNetworkTemplate(mNetworkTemplate)
+ .build());
doReturn(1024L).when(mLoader).getTotalUsage(any());
mLoader.recordUsage(start, end);
- verify(mNetworkStatsManager).queryDetailsForUid(networkType, subId, start, end, uid);
+ verify(mNetworkStatsManager).queryDetailsForUid(mNetworkTemplate, start, end, uid);
verify(mNetworkStatsManager).queryDetailsForUidTagState(
- networkType, subId, start, end, uid, TAG_NONE, STATE_FOREGROUND);
+ mNetworkTemplate, start, end, uid, TAG_NONE, STATE_FOREGROUND);
}
@Test
public void recordUsage_retrieveDetailIsFalse_shouldNotQueryNetworkForegroundState() {
final long end = System.currentTimeMillis();
final long start = end - (DateUtils.WEEK_IN_MILLIS * 4);
- final int networkType = ConnectivityManager.TYPE_MOBILE;
- final String subId = "TestSubscriber";
final int uid = 1;
mLoader = spy(NetworkCycleDataForUidLoader.builder(mContext)
- .setRetrieveDetail(false).addUid(uid).setSubscriberId(subId).build());
+ .setRetrieveDetail(false).addUid(uid).build());
doReturn(1024L).when(mLoader).getTotalUsage(any());
mLoader.recordUsage(start, end);
verify(mNetworkStatsManager, never()).queryDetailsForUidTagState(
- networkType, subId, start, end, uid, TAG_NONE, STATE_FOREGROUND);
+ mNetworkTemplate, start, end, uid, TAG_NONE, STATE_FOREGROUND);
}
@Test
public void recordUsage_multipleUids_shouldQueryNetworkDetailsForEachUid() {
final long end = System.currentTimeMillis();
final long start = end - (DateUtils.WEEK_IN_MILLIS * 4);
- final int networkType = ConnectivityManager.TYPE_MOBILE;
- final String subId = "TestSubscriber";
mLoader = spy(NetworkCycleDataForUidLoader.builder(mContext)
- .addUid(1)
- .addUid(2)
- .addUid(3)
- .setSubscriberId(subId).build());
+ .addUid(1)
+ .addUid(2)
+ .addUid(3)
+ .setNetworkTemplate(mNetworkTemplate)
+ .build());
doReturn(1024L).when(mLoader).getTotalUsage(any());
mLoader.recordUsage(start, end);
- verify(mNetworkStatsManager).queryDetailsForUid(networkType, subId, start, end, 1);
- verify(mNetworkStatsManager).queryDetailsForUid(networkType, subId, start, end, 2);
- verify(mNetworkStatsManager).queryDetailsForUid(networkType, subId, start, end, 3);
+ verify(mNetworkStatsManager).queryDetailsForUid(mNetworkTemplate, start, end, 1);
+ verify(mNetworkStatsManager).queryDetailsForUid(mNetworkTemplate, start, end, 2);
+ verify(mNetworkStatsManager).queryDetailsForUid(mNetworkTemplate, start, end, 3);
}
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataLoaderTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataLoaderTest.java
index c5f54bb..74b9151 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataLoaderTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataLoaderTest.java
@@ -126,8 +126,6 @@
when(mIterator.next()).thenReturn(cycle);
mLoader = spy(new NetworkCycleDataTestLoader(mContext));
ReflectionHelpers.setField(mLoader, "mPolicy", mPolicy);
- ReflectionHelpers.setField(mLoader, "mNetworkType", networkType);
- ReflectionHelpers.setField(mLoader, "mSubId", subId);
mLoader.loadPolicyData();
diff --git a/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/LegacyRecentsImpl.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/LegacyRecentsImpl.java
index b7bb751..a150de9 100644
--- a/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/LegacyRecentsImpl.java
+++ b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/LegacyRecentsImpl.java
@@ -662,11 +662,17 @@
public final void onBusEvent(ExpandPipEvent event) {
PipUI pipUi = getComponent(PipUI.class);
+ if (pipUi == null) {
+ return;
+ }
pipUi.expandPip();
}
public final void onBusEvent(HidePipMenuEvent event) {
PipUI pipUi = getComponent(PipUI.class);
+ if (pipUi == null) {
+ return;
+ }
event.getAnimationTrigger().increment();
pipUi.hidePipMenu(() -> {
event.getAnimationTrigger().increment();
diff --git a/packages/SystemUI/res/layout/biometric_dialog.xml b/packages/SystemUI/res/layout/biometric_dialog.xml
index 1abb873..c560d7e 100644
--- a/packages/SystemUI/res/layout/biometric_dialog.xml
+++ b/packages/SystemUI/res/layout/biometric_dialog.xml
@@ -37,7 +37,8 @@
android:id="@+id/space"
android:layout_width="match_parent"
android:layout_height="0dp"
- android:layout_weight="1" />
+ android:layout_weight="1"
+ android:contentDescription="@string/biometric_dialog_empty_space_description"/>
<ScrollView
android:layout_width="match_parent"
diff --git a/packages/SystemUI/res/layout/keyguard_bottom_area.xml b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
index cdef09d..2792a01 100644
--- a/packages/SystemUI/res/layout/keyguard_bottom_area.xml
+++ b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
@@ -31,23 +31,36 @@
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/keyguard_indication_margin_bottom"
android:layout_gravity="bottom|center_horizontal"
- android:orientation="vertical">
+ android:orientation="horizontal">
- <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:textAppearance="@style/TextAppearance.Keyguard.BottomArea"
- android:visibility="gone" />
+ <include layout="@layout/left_docked_overlay" />
- <com.android.systemui.statusbar.phone.KeyguardIndicationTextView
- android:id="@+id/keyguard_indication_text"
- android:layout_width="match_parent"
+ <LinearLayout
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:gravity="center"
- android:textAppearance="@style/TextAppearance.Keyguard.BottomArea"
- android:accessibilityLiveRegion="polite" />
+ 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: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:textAppearance="@style/TextAppearance.Keyguard.BottomArea"
+ android:accessibilityLiveRegion="polite" />
+
+ </LinearLayout>
+
+ <include layout="@layout/right_docked_overlay" />
</LinearLayout>
diff --git a/packages/SystemUI/res/layout/left_docked_overlay.xml b/packages/SystemUI/res/layout/left_docked_overlay.xml
new file mode 100644
index 0000000..430143c
--- /dev/null
+++ b/packages/SystemUI/res/layout/left_docked_overlay.xml
@@ -0,0 +1,19 @@
+<?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
new file mode 100644
index 0000000..430143c
--- /dev/null
+++ b/packages/SystemUI/res/layout/right_docked_overlay.xml
@@ -0,0 +1,19 @@
+<?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/strings.xml b/packages/SystemUI/res/values/strings.xml
index 2643221..e01e6a8 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -288,8 +288,18 @@
<!-- Message shown when a biometric is authenticated, asking the user to confirm authentication [CHAR LIMIT=30] -->
<string name="biometric_dialog_confirm">Confirm</string>
- <!-- Button name on BiometricPrompt shown when a biometric is detected but not authenticated. Tapping the button resumes authentication [CHAR_LIMIT=30] -->
+ <!-- Button name on BiometricPrompt shown when a biometric is detected but not authenticated. Tapping the button resumes authentication [CHAR LIMIT=30] -->
<string name="biometric_dialog_try_again">Try again</string>
+ <!-- Content description for empty spaces that are not taken by the biometric dialog. Clicking on these areas will cancel authentication and dismiss the biometric dialog [CHAR LIMIT=NONE] -->
+ <string name="biometric_dialog_empty_space_description">Empty region, tap to cancel authentication</string>
+ <!-- Content description for the face icon when the device is not authenticating anymore [CHAR LIMIT=NONE] -->
+ <string name="biometric_dialog_face_icon_description_idle">Please try again</string>
+ <!-- Content description for the face icon when the device is authenticating [CHAR LIMIT=NONE] -->
+ <string name="biometric_dialog_face_icon_description_authenticating">Looking for your face</string>
+ <!-- Content description for the face icon when the user has been authenticated [CHAR LIMIT=NONE] -->
+ <string name="biometric_dialog_face_icon_description_authenticated">Face authenticated</string>
+ <!-- Content description for the face icon when the user has been authenticated and the confirm button has been pressed [CHAR LIMIT=NONE] -->
+ <string name="biometric_dialog_face_icon_description_confirmed">Confirmed</string>
<!-- Message shown when the system-provided fingerprint dialog is shown, asking for authentication -->
<string name="fingerprint_dialog_touch_sensor">Touch the fingerprint sensor</string>
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 6402884..ea8565e 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -238,6 +238,8 @@
private boolean mIsDreaming;
private final DevicePolicyManager mDevicePolicyManager;
private boolean mLogoutEnabled;
+ // If the user long pressed the lock icon, disabling face auth for the current session.
+ private boolean mLockIconPressed;
/**
* Short delay before restarting biometric authentication after a successful try
@@ -1384,6 +1386,7 @@
}
private void handleScreenTurnedOff() {
+ mLockIconPressed = false;
mHardwareFingerprintUnavailableRetryCount = 0;
mHardwareFaceUnavailableRetryCount = 0;
final int count = mCallbacks.size();
@@ -1608,35 +1611,36 @@
}
private boolean shouldListenForFingerprint() {
- final boolean switchingUsers;
- synchronized (this) {
- switchingUsers = mSwitchingUser;
- }
// Only listen if this KeyguardUpdateMonitor belongs to the primary user. There is an
// instance of KeyguardUpdateMonitor for each user but KeyguardUpdateMonitor is user-aware.
final boolean shouldListen = (mKeyguardIsVisible || !mDeviceInteractive ||
(mBouncer && !mKeyguardGoingAway) || mGoingToSleep ||
shouldListenForFingerprintAssistant() || (mKeyguardOccluded && mIsDreaming))
- && !switchingUsers && !isFingerprintDisabled(getCurrentUser())
+ && !mSwitchingUser && !isFingerprintDisabled(getCurrentUser())
&& (!mKeyguardGoingAway || !mDeviceInteractive) && mIsPrimaryUser;
return shouldListen;
}
private boolean shouldListenForFace() {
- final boolean switchingUsers;
- synchronized (this) {
- switchingUsers = mSwitchingUser;
- }
final boolean awakeKeyguard = mKeyguardIsVisible && mDeviceInteractive && !mGoingToSleep;
final int user = getCurrentUser();
// Only listen if this KeyguardUpdateMonitor belongs to the primary user. There is an
// instance of KeyguardUpdateMonitor for each user but KeyguardUpdateMonitor is user-aware.
return (mBouncer || mAuthInterruptActive || awakeKeyguard || shouldListenForFaceAssistant())
- && !switchingUsers && !getUserCanSkipBouncer(user) && !isFaceDisabled(user)
- && !mKeyguardGoingAway && mFaceSettingEnabledForUser
+ && !mSwitchingUser && !getUserCanSkipBouncer(user) && !isFaceDisabled(user)
+ && !mKeyguardGoingAway && mFaceSettingEnabledForUser && !mLockIconPressed
&& mUserManager.isUserUnlocked(user) && mIsPrimaryUser;
}
+ /**
+ * Whenever the lock icon is long pressed, disabling trust agents.
+ * This means that we cannot auth passively (face) until the user presses power.
+ */
+ public void onLockIconPressed() {
+ mLockIconPressed = true;
+ mUserFaceAuthenticated.put(getCurrentUser(), false);
+ updateFaceListeningState();
+ }
private void startListeningForFingerprint() {
if (mFingerprintRunningState == BIOMETRIC_STATE_CANCELLING) {
@@ -2188,11 +2192,13 @@
sendUpdates(callback);
}
+ public boolean isSwitchingUser() {
+ return mSwitchingUser;
+ }
+
@AnyThread
public void setSwitchingUser(boolean switching) {
- synchronized (this) {
- mSwitchingUser = switching;
- }
+ mSwitchingUser = switching;
// Since this comes in on a binder thread, we need to post if first
mHandler.post(mUpdateBiometricListeningState);
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogImpl.java b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogImpl.java
index 9dfcf7d..45c19ad 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogImpl.java
@@ -325,7 +325,6 @@
private void handleTryAgainPressed() {
try {
- mCurrentDialog.clearTemporaryMessage();
mReceiver.onTryAgainPressed();
} catch (RemoteException e) {
Log.e(TAG, "RemoteException when handling try again", e);
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogView.java b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogView.java
index f99587b..5717a54 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogView.java
@@ -33,7 +33,6 @@
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
-import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
@@ -224,13 +223,11 @@
});
mTryAgainButton.setOnClickListener((View v) -> {
+ handleResetMessage();
updateState(STATE_AUTHENTICATING);
showTryAgainButton(false /* show */);
mCallback.onTryAgainPressed();
});
-
- mLayout.setFocusableInTouchMode(true);
- mLayout.requestFocus();
}
public void onSaveState(Bundle bundle) {
@@ -269,6 +266,7 @@
if (mRestoredState == null) {
updateState(STATE_AUTHENTICATING);
mErrorText.setText(getHintStringResourceId());
+ mErrorText.setContentDescription(mContext.getString(getHintStringResourceId()));
mErrorText.setVisibility(View.VISIBLE);
} else {
updateState(mState);
@@ -278,7 +276,6 @@
mTitleText.setVisibility(View.VISIBLE);
mTitleText.setText(titleText);
- mTitleText.setSelected(true);
final CharSequence subtitleText = mBundle.getCharSequence(BiometricPrompt.KEY_SUBTITLE);
if (TextUtils.isEmpty(subtitleText)) {
@@ -323,11 +320,10 @@
private void setDismissesDialog(View v) {
v.setClickable(true);
- v.setOnTouchListener((View view, MotionEvent event) -> {
+ v.setOnClickListener(v1 -> {
if (mState != STATE_AUTHENTICATED && shouldGrayAreaDismissDialog()) {
mCallback.onUserCanceled();
}
- return true;
});
}
@@ -421,11 +417,6 @@
BiometricPrompt.HIDE_DIALOG_DELAY);
}
- public void clearTemporaryMessage() {
- mHandler.removeMessages(MSG_RESET_MESSAGE);
- mHandler.obtainMessage(MSG_RESET_MESSAGE).sendToTarget();
- }
-
/**
* Transient help message (acquire) is received, dialog stays showing. Sensor stays in
* "authenticating" state.
@@ -484,6 +475,7 @@
mPositiveButton.setVisibility(bundle.getInt(KEY_CONFIRM_VISIBILITY));
mState = bundle.getInt(KEY_STATE);
mErrorText.setText(bundle.getCharSequence(KEY_ERROR_TEXT_STRING));
+ mErrorText.setContentDescription(bundle.getCharSequence(KEY_ERROR_TEXT_STRING));
mErrorText.setVisibility(bundle.getInt(KEY_ERROR_TEXT_VISIBILITY));
mErrorText.setTextColor(bundle.getInt(KEY_ERROR_TEXT_COLOR));
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/FaceDialogView.java b/packages/SystemUI/src/com/android/systemui/biometrics/FaceDialogView.java
index dbbb71c..8f26f18 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/FaceDialogView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/FaceDialogView.java
@@ -288,6 +288,7 @@
@Override
protected void handleResetMessage() {
mErrorText.setText(getHintStringResourceId());
+ mErrorText.setContentDescription(mContext.getString(getHintStringResourceId()));
mErrorText.setTextColor(mTextColor);
if (getState() == STATE_AUTHENTICATING) {
mErrorText.setVisibility(View.VISIBLE);
@@ -406,13 +407,21 @@
} else {
mIconController.showIcon(R.drawable.face_dialog_pulse_dark_to_light);
}
+ mBiometricIcon.setContentDescription(mContext.getString(
+ R.string.biometric_dialog_face_icon_description_authenticating));
} else if (oldState == STATE_PENDING_CONFIRMATION && newState == STATE_AUTHENTICATED) {
mIconController.animateOnce(R.drawable.face_dialog_dark_to_checkmark);
+ mBiometricIcon.setContentDescription(mContext.getString(
+ R.string.biometric_dialog_face_icon_description_confirmed));
} else if (oldState == STATE_ERROR && newState == STATE_IDLE) {
mIconController.animateOnce(R.drawable.face_dialog_error_to_idle);
+ mBiometricIcon.setContentDescription(mContext.getString(
+ R.string.biometric_dialog_face_icon_description_idle));
} else if (oldState == STATE_ERROR && newState == STATE_AUTHENTICATED) {
mHandler.removeCallbacks(mErrorToIdleAnimationRunnable);
mIconController.animateOnce(R.drawable.face_dialog_dark_to_checkmark);
+ mBiometricIcon.setContentDescription(mContext.getString(
+ R.string.biometric_dialog_face_icon_description_authenticated));
} else if (newState == STATE_ERROR) {
// It's easier to only check newState and gate showing the animation on the
// mErrorToIdleAnimationRunnable as a proxy, than add a ton of extra state. For example,
@@ -426,11 +435,17 @@
}
} else if (oldState == STATE_AUTHENTICATING && newState == STATE_AUTHENTICATED) {
mIconController.animateOnce(R.drawable.face_dialog_dark_to_checkmark);
+ mBiometricIcon.setContentDescription(mContext.getString(
+ R.string.biometric_dialog_face_icon_description_authenticated));
} else if (newState == STATE_PENDING_CONFIRMATION) {
mHandler.removeCallbacks(mErrorToIdleAnimationRunnable);
mIconController.animateOnce(R.drawable.face_dialog_wink_from_dark);
+ mBiometricIcon.setContentDescription(mContext.getString(
+ R.string.biometric_dialog_face_icon_description_authenticated));
} else if (newState == STATE_IDLE) {
mIconController.showStatic(R.drawable.face_dialog_idle_static);
+ mBiometricIcon.setContentDescription(mContext.getString(
+ R.string.biometric_dialog_face_icon_description_idle));
} else {
Log.w(TAG, "Unknown animation from " + oldState + " -> " + newState);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index a76c9dc..fd76a79 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -189,6 +189,7 @@
mLockscreenGestureLogger.write(MetricsProto.MetricsEvent.ACTION_LS_LOCK,
0 /* lengthDp - N/A */, 0 /* velocityDp - N/A */);
showTransientIndication(R.string.keyguard_indication_trust_disabled);
+ mKeyguardUpdateMonitor.onLockIconPressed();
mLockPatternUtils.requireCredentialEntry(KeyguardUpdateMonitor.getCurrentUser());
return true;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
index b6f95b83c..6fe8964 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
@@ -41,6 +41,7 @@
import com.android.internal.statusbar.NotificationVisibility;
import com.android.internal.widget.MessagingGroup;
import com.android.internal.widget.MessagingMessage;
+import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.Dependency;
import com.android.systemui.ForegroundServiceNotificationListener;
import com.android.systemui.InitController;
@@ -121,6 +122,8 @@
private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
private final int mMaxAllowedKeyguardNotifications;
private final IStatusBarService mBarService;
+ private boolean mReinflateNotificationsOnUserSwitched;
+ private boolean mDispatchUiModeChangeOnUserSwitched;
private final UnlockMethodCache mUnlockMethodCache;
private TextView mNotificationPanelDebugText;
@@ -239,12 +242,20 @@
public void onDensityOrFontScaleChanged() {
MessagingMessage.dropCache();
MessagingGroup.dropCache();
- updateNotificationsOnDensityOrFontScaleChanged();
+ if (!KeyguardUpdateMonitor.getInstance(mContext).isSwitchingUser()) {
+ updateNotificationsOnDensityOrFontScaleChanged();
+ } else {
+ mReinflateNotificationsOnUserSwitched = true;
+ }
}
@Override
public void onUiModeChanged() {
- updateNotificationOnUiModeChanged();
+ if (!KeyguardUpdateMonitor.getInstance(mContext).isSwitchingUser()) {
+ updateNotificationOnUiModeChanged();
+ } else {
+ mDispatchUiModeChangeOnUserSwitched = true;
+ }
}
@Override
@@ -374,6 +385,14 @@
// End old BaseStatusBar.userSwitched
if (MULTIUSER_DEBUG) mNotificationPanelDebugText.setText("USER " + newUserId);
mCommandQueue.animateCollapsePanels();
+ if (mReinflateNotificationsOnUserSwitched) {
+ updateNotificationsOnDensityOrFontScaleChanged();
+ mReinflateNotificationsOnUserSwitched = false;
+ }
+ if (mDispatchUiModeChangeOnUserSwitched) {
+ updateNotificationOnUiModeChanged();
+ mDispatchUiModeChangeOnUserSwitched = false;
+ }
updateNotificationViews();
mMediaManager.clearCurrentMediaNotification();
mShadeController.setLockscreenUser(newUserId);
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 0b83b69..712e962 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -262,7 +262,9 @@
* Propagate {@link StatusBar} pulsing state.
*/
public void setPulsing(boolean pulsing) {
- mLockIcon.setPulsing(pulsing);
+ if (mLockIcon != null) {
+ mLockIcon.setPulsing(pulsing);
+ }
}
/**
@@ -270,14 +272,18 @@
* @param wakeAndUnlock If the type is {@link BiometricUnlockController#isWakeAndUnlock()}
*/
public void onBiometricAuthModeChanged(boolean wakeAndUnlock) {
- mLockIcon.onBiometricAuthModeChanged(wakeAndUnlock);
+ if (mLockIcon != null) {
+ mLockIcon.onBiometricAuthModeChanged(wakeAndUnlock);
+ }
}
/**
* Called after finished unlocking and the status bar window is already collapsed.
*/
public void onKeyguardFadedAway() {
- mLockIcon.onKeyguardFadedAway();
+ if (mLockIcon != null) {
+ mLockIcon.onKeyguardFadedAway();
+ }
}
public void setStatusBarView(PhoneStatusBarView statusBarView) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
index 6d9a77c..daee55b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
@@ -261,6 +261,7 @@
longClickCaptor.getValue().onLongClick(mLockIcon);
verify(mLockPatternUtils).requireCredentialEntry(anyInt());
+ verify(mKeyguardUpdateMonitor).onLockIconPressed();
}
@Test
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index facc299..f12bfc3 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -3497,7 +3497,8 @@
*/
@Override
public void startCaptivePortalAppInternal(Network network, Bundle appExtras) {
- mContext.checkCallingOrSelfPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
+ mContext.enforceCallingOrSelfPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
+ "ConnectivityService");
final Intent appIntent = new Intent(ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN);
appIntent.putExtras(appExtras);
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index c646149..fc355b7 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -286,6 +286,7 @@
private static final String ATTR_NICKNAME = "nickname";
private static final String ATTR_USER_FLAGS = "userFlags";
private static final String ATTR_CREATED_MILLIS = "createdMillis";
+ private static final String ATTR_LAST_SEEN_MILLIS = "lastSeenMillis";
private static final String ATTR_LAST_TRIM_MILLIS = "lastTrimMillis";
private static final String ATTR_LAST_BENCH_MILLIS = "lastBenchMillis";
@@ -1313,7 +1314,7 @@
private void onVolumeStateChangedLocked(VolumeInfo vol, int oldState, int newState) {
// Remember that we saw this volume so we're ready to accept user
// metadata, or so we can annoy them when a private volume is ejected
- if (vol.isMountedReadable() && !TextUtils.isEmpty(vol.fsUuid)) {
+ if (!TextUtils.isEmpty(vol.fsUuid)) {
VolumeRecord rec = mRecords.get(vol.fsUuid);
if (rec == null) {
rec = new VolumeRecord(vol.type, vol.fsUuid);
@@ -1323,14 +1324,15 @@
rec.nickname = vol.disk.getDescription();
}
mRecords.put(rec.fsUuid, rec);
- writeSettingsLocked();
} else {
// Handle upgrade case where we didn't store partition GUID
if (TextUtils.isEmpty(rec.partGuid)) {
rec.partGuid = vol.partGuid;
- writeSettingsLocked();
}
}
+
+ rec.lastSeenMillis = System.currentTimeMillis();
+ writeSettingsLocked();
}
mCallbacks.notifyVolumeStateChanged(vol, oldState, newState);
@@ -1731,9 +1733,10 @@
meta.partGuid = readStringAttribute(in, ATTR_PART_GUID);
meta.nickname = readStringAttribute(in, ATTR_NICKNAME);
meta.userFlags = readIntAttribute(in, ATTR_USER_FLAGS);
- meta.createdMillis = readLongAttribute(in, ATTR_CREATED_MILLIS);
- meta.lastTrimMillis = readLongAttribute(in, ATTR_LAST_TRIM_MILLIS);
- meta.lastBenchMillis = readLongAttribute(in, ATTR_LAST_BENCH_MILLIS);
+ meta.createdMillis = readLongAttribute(in, ATTR_CREATED_MILLIS, 0);
+ meta.lastSeenMillis = readLongAttribute(in, ATTR_LAST_SEEN_MILLIS, 0);
+ meta.lastTrimMillis = readLongAttribute(in, ATTR_LAST_TRIM_MILLIS, 0);
+ meta.lastBenchMillis = readLongAttribute(in, ATTR_LAST_BENCH_MILLIS, 0);
return meta;
}
@@ -1745,6 +1748,7 @@
writeStringAttribute(out, ATTR_NICKNAME, rec.nickname);
writeIntAttribute(out, ATTR_USER_FLAGS, rec.userFlags);
writeLongAttribute(out, ATTR_CREATED_MILLIS, rec.createdMillis);
+ writeLongAttribute(out, ATTR_LAST_SEEN_MILLIS, rec.lastSeenMillis);
writeLongAttribute(out, ATTR_LAST_TRIM_MILLIS, rec.lastTrimMillis);
writeLongAttribute(out, ATTR_LAST_BENCH_MILLIS, rec.lastBenchMillis);
out.endTag(null, TAG_VOLUME);
diff --git a/services/core/java/com/android/server/am/PreBootBroadcaster.java b/services/core/java/com/android/server/am/PreBootBroadcaster.java
index 376999d..beb0e47 100644
--- a/services/core/java/com/android/server/am/PreBootBroadcaster.java
+++ b/services/core/java/com/android/server/am/PreBootBroadcaster.java
@@ -107,9 +107,11 @@
EventLogTags.writeAmPreBoot(mUserId, componentName.getPackageName());
mIntent.setComponent(componentName);
- mService.broadcastIntentLocked(null, null, mIntent, null, this, 0, null, null, null,
- AppOpsManager.OP_NONE, null, true, false, ActivityManagerService.MY_PID,
- Process.SYSTEM_UID, Binder.getCallingUid(), Binder.getCallingPid(), mUserId);
+ synchronized (mService) {
+ mService.broadcastIntentLocked(null, null, mIntent, null, this, 0, null, null, null,
+ AppOpsManager.OP_NONE, null, true, false, ActivityManagerService.MY_PID,
+ Process.SYSTEM_UID, Binder.getCallingUid(), Binder.getCallingPid(), mUserId);
+ }
}
@Override
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 696697e..b394eea 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -1658,23 +1658,15 @@
app.killed = false;
final long startSeq = app.startSeq = ++mProcStartSeqCounter;
app.setStartParams(uid, hostingRecord, seInfo, startTime);
+ app.setUsingWrapper(invokeWith != null
+ || SystemProperties.get("wrap." + app.processName) != null);
+ mPendingStarts.put(startSeq, app);
+
if (mService.mConstants.FLAG_PROCESS_START_ASYNC) {
if (DEBUG_PROCESSES) Slog.i(TAG_PROCESSES,
"Posting procStart msg for " + app.toShortString());
mService.mProcStartHandler.post(() -> {
try {
- synchronized (mService) {
- final String reason = isProcStartValidLocked(app, startSeq);
- if (reason != null) {
- Slog.w(TAG_PROCESSES, app + " not valid anymore,"
- + " don't start process, " + reason);
- app.pendingStart = false;
- return;
- }
- app.setUsingWrapper(invokeWith != null
- || SystemProperties.get("wrap." + app.processName) != null);
- mPendingStarts.put(startSeq, app);
- }
final Process.ProcessStartResult startResult = startProcess(app.hostingRecord,
entryPoint, app, app.startUid, gids, runtimeFlags, mountExternal,
app.seInfo, requiredAbi, instructionSet, invokeWith, app.startTime);
diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java
index 88919df..b9a6a10 100644
--- a/services/core/java/com/android/server/biometrics/BiometricService.java
+++ b/services/core/java/com/android/server/biometrics/BiometricService.java
@@ -760,7 +760,6 @@
@Override // Binder call
public int canAuthenticate(String opPackageName) {
checkPermission();
- checkAppOp(opPackageName, Binder.getCallingUid());
final int userId = UserHandle.getCallingUserId();
final long ident = Binder.clearCallingIdentity();
@@ -833,9 +832,9 @@
}
private void checkPermission() {
- if (getContext().checkCallingPermission(USE_FINGERPRINT)
+ if (getContext().checkCallingOrSelfPermission(USE_FINGERPRINT)
!= PackageManager.PERMISSION_GRANTED) {
- getContext().enforceCallingPermission(USE_BIOMETRIC,
+ getContext().enforceCallingOrSelfPermission(USE_BIOMETRIC,
"Must have USE_BIOMETRIC permission");
}
}
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index eecbb16..35a82ae 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -1626,6 +1626,15 @@
}
/**
+ * Maximum time buffer in which JobScheduler will try to optimize periodic job scheduling. This
+ * does not cause a job's period to be larger than requested (eg: if the requested period is
+ * shorter than this buffer). This is used to put a limit on when JobScheduler will intervene
+ * and try to optimize scheduling if the current job finished less than this amount of time to
+ * the start of the next period
+ */
+ private static final long PERIODIC_JOB_WINDOW_BUFFER = 30 * MINUTE_IN_MILLIS;
+
+ /**
* Called after a periodic has executed so we can reschedule it. We take the last execution
* time of the job to be the time of completion (i.e. the time at which this function is
* called).
@@ -1645,16 +1654,18 @@
final long period = periodicToReschedule.getJob().getIntervalMillis();
final long latestRunTimeElapsed = periodicToReschedule.getOriginalLatestRunTimeElapsed();
final long flex = periodicToReschedule.getJob().getFlexMillis();
+ long rescheduleBuffer = 0;
+ final long diffMs = Math.abs(elapsedNow - latestRunTimeElapsed);
if (elapsedNow > latestRunTimeElapsed) {
// The job ran past its expected run window. Have it count towards the current window
// and schedule a new job for the next window.
if (DEBUG) {
Slog.i(TAG, "Periodic job ran after its intended window.");
}
- final long diffMs = (elapsedNow - latestRunTimeElapsed);
int numSkippedWindows = (int) (diffMs / period) + 1; // +1 to include original window
- if (period != flex && diffMs > Math.min(30 * MINUTE_IN_MILLIS, (period - flex) / 2)) {
+ if (period != flex && diffMs > Math.min(PERIODIC_JOB_WINDOW_BUFFER,
+ (period - flex) / 2)) {
if (DEBUG) {
Slog.d(TAG, "Custom flex job ran too close to next window.");
}
@@ -1665,9 +1676,15 @@
newLatestRuntimeElapsed = latestRunTimeElapsed + (period * numSkippedWindows);
} else {
newLatestRuntimeElapsed = latestRunTimeElapsed + period;
+ if (diffMs < PERIODIC_JOB_WINDOW_BUFFER && diffMs < period / 6) {
+ // Add a little buffer to the start of the next window so the job doesn't run
+ // too soon after this completed one.
+ rescheduleBuffer = Math.min(PERIODIC_JOB_WINDOW_BUFFER, period / 6 - diffMs);
+ }
}
- final long newEarliestRunTimeElapsed = newLatestRuntimeElapsed - flex;
+ final long newEarliestRunTimeElapsed = newLatestRuntimeElapsed
+ - Math.min(flex, period - rescheduleBuffer);
if (DEBUG) {
Slog.v(TAG, "Rescheduling executed periodic. New execution window [" +
diff --git a/services/core/java/com/android/server/location/GnssConfiguration.java b/services/core/java/com/android/server/location/GnssConfiguration.java
index bd6662d..aa51aec 100644
--- a/services/core/java/com/android/server/location/GnssConfiguration.java
+++ b/services/core/java/com/android/server/location/GnssConfiguration.java
@@ -317,8 +317,10 @@
if (configManager == null) {
return;
}
- PersistableBundle configs = configManager.getConfigForSubId(
- SubscriptionManager.getDefaultDataSubscriptionId());
+
+ int ddSubId = SubscriptionManager.getDefaultDataSubscriptionId();
+ PersistableBundle configs = SubscriptionManager.isValidSubscriptionId(ddSubId)
+ ? configManager.getConfigForSubId(ddSubId) : null;
if (configs == null) {
if (DEBUG) Log.d(TAG, "SIM not ready, use default carrier config.");
configs = CarrierConfigManager.getDefaultConfig();
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 5b7eca6..b2315c7 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -60,7 +60,6 @@
import android.provider.Settings;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
-import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
import android.telephony.TelephonyManager;
import android.telephony.gsm.GsmCellLocation;
import android.text.TextUtils;
@@ -75,6 +74,7 @@
import com.android.internal.location.ProviderProperties;
import com.android.internal.location.ProviderRequest;
import com.android.internal.location.gnssmetrics.GnssMetrics;
+import com.android.internal.telephony.TelephonyIntents;
import com.android.server.location.GnssSatelliteBlacklistHelper.GnssSatelliteBlacklistCallback;
import com.android.server.location.NtpTimeHelper.InjectNtpTimeCallback;
@@ -184,7 +184,6 @@
private static final int DOWNLOAD_PSDS_DATA = 6;
private static final int UPDATE_LOCATION = 7; // Handle external location from network listener
private static final int DOWNLOAD_PSDS_DATA_FINISHED = 11;
- private static final int SUBSCRIPTION_OR_CARRIER_CONFIG_CHANGED = 12;
private static final int INITIALIZE_HANDLER = 13;
private static final int REQUEST_LOCATION = 16;
private static final int REPORT_LOCATION = 17; // HAL reports location
@@ -484,22 +483,13 @@
updateLowPowerMode();
break;
case CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED:
+ case TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED:
subscriptionOrCarrierConfigChanged(context);
break;
}
}
};
- // TODO: replace OnSubscriptionsChangedListener with ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED
- // broadcast receiver.
- private final OnSubscriptionsChangedListener mOnSubscriptionsChangedListener =
- new OnSubscriptionsChangedListener() {
- @Override
- public void onSubscriptionsChanged() {
- sendMessage(SUBSCRIPTION_OR_CARRIER_CONFIG_CHANGED, 0, null);
- }
- };
-
/**
* Implements {@link GnssSatelliteBlacklistCallback#onUpdateSatelliteBlacklist}.
*/
@@ -515,12 +505,15 @@
mContext.getSystemService(Context.TELEPHONY_SERVICE);
CarrierConfigManager configManager = (CarrierConfigManager)
mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);
- String mccMnc = phone.getSimOperator();
+ int ddSubId = SubscriptionManager.getDefaultDataSubscriptionId();
+ String mccMnc = SubscriptionManager.isValidSubscriptionId(ddSubId)
+ ? phone.getSimOperator(ddSubId) : phone.getSimOperator();
boolean isKeepLppProfile = false;
if (!TextUtils.isEmpty(mccMnc)) {
if (DEBUG) Log.d(TAG, "SIM MCC/MNC is available: " + mccMnc);
if (configManager != null) {
- PersistableBundle b = configManager.getConfig();
+ PersistableBundle b = SubscriptionManager.isValidSubscriptionId(ddSubId)
+ ? configManager.getConfigForSubId(ddSubId) : null;
if (b != null) {
isKeepLppProfile =
b.getBoolean(CarrierConfigManager.Gps.KEY_PERSIST_LPP_MODE_BOOL);
@@ -539,7 +532,6 @@
SystemProperties.set(GnssConfiguration.LPP_PROFILE, "");
}
reloadGpsProperties();
- mNIHandler.setSuplEsEnabled(mSuplEsEnabled);
} else {
if (DEBUG) Log.d(TAG, "SIM MCC/MNC is still not available");
}
@@ -577,9 +569,9 @@
mC2KServerPort = mGnssConfiguration.getC2KPort(TCP_MIN_PORT);
mNIHandler.setEmergencyExtensionSeconds(mGnssConfiguration.getEsExtensionSec());
mSuplEsEnabled = mGnssConfiguration.getSuplEs(0) == 1;
+ mNIHandler.setSuplEsEnabled(mSuplEsEnabled);
if (mGnssVisibilityControl != null) {
- mGnssVisibilityControl.updateProxyApps(mGnssConfiguration.getProxyApps());
- mGnssVisibilityControl.setEsNotify(mGnssConfiguration.getEsNotify(0));
+ mGnssVisibilityControl.onConfigurationUpdated(mGnssConfiguration);
}
}
@@ -1892,28 +1884,34 @@
TelephonyManager phone = (TelephonyManager)
mContext.getSystemService(Context.TELEPHONY_SERVICE);
int type = AGPS_SETID_TYPE_NONE;
- String data = "";
+ String setId = null;
+ int ddSubId = SubscriptionManager.getDefaultDataSubscriptionId();
if ((flags & AGPS_RIL_REQUEST_SETID_IMSI) == AGPS_RIL_REQUEST_SETID_IMSI) {
- String data_temp = phone.getSubscriberId();
- if (data_temp == null) {
- // This means the framework does not have the SIM card ready.
- } else {
+ if (SubscriptionManager.isValidSubscriptionId(ddSubId)) {
+ setId = phone.getSubscriberId(ddSubId);
+ }
+ if (setId == null) {
+ setId = phone.getSubscriberId();
+ }
+ if (setId != null) {
// This means the framework has the SIM card.
- data = data_temp;
type = AGPS_SETID_TYPE_IMSI;
}
} else if ((flags & AGPS_RIL_REQUEST_SETID_MSISDN) == AGPS_RIL_REQUEST_SETID_MSISDN) {
- String data_temp = phone.getLine1Number();
- if (data_temp == null) {
- // This means the framework does not have the SIM card ready.
- } else {
+ if (SubscriptionManager.isValidSubscriptionId(ddSubId)) {
+ setId = phone.getLine1Number(ddSubId);
+ }
+ if (setId == null) {
+ setId = phone.getLine1Number();
+ }
+ if (setId != null) {
// This means the framework has the SIM card.
- data = data_temp;
type = AGPS_SETID_TYPE_MSISDN;
}
}
- native_agps_set_id(type, data);
+
+ native_agps_set_id(type, (setId == null) ? "" : setId);
}
@NativeEntryPoint
@@ -2025,9 +2023,6 @@
case UPDATE_LOCATION:
handleUpdateLocation((Location) msg.obj);
break;
- case SUBSCRIPTION_OR_CARRIER_CONFIG_CHANGED:
- subscriptionOrCarrierConfigChanged(mContext);
- break;
case INITIALIZE_HANDLER:
handleInitialize();
break;
@@ -2066,17 +2061,6 @@
// (this configuration might change in the future based on SIM changes)
reloadGpsProperties();
- // TODO: When this object "finishes" we should unregister by invoking
- // SubscriptionManager.getInstance(mContext).unregister
- // (mOnSubscriptionsChangedListener);
- // This is not strictly necessary because it will be unregistered if the
- // notification fails but it is good form.
-
- // Register for SubscriptionInfo list changes which is guaranteed
- // to invoke onSubscriptionsChanged the first time.
- SubscriptionManager.from(mContext)
- .addOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener);
-
// listen for events
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(ALARM_WAKEUP);
@@ -2086,6 +2070,7 @@
intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
intentFilter.addAction(Intent.ACTION_SCREEN_ON);
intentFilter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
+ intentFilter.addAction(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);
mContext.registerReceiver(mBroadcastReceiver, intentFilter, null, this);
mNetworkConnectivityHandler.registerNetworkCallbacks();
@@ -2164,8 +2149,6 @@
return "DOWNLOAD_PSDS_DATA_FINISHED";
case UPDATE_LOCATION:
return "UPDATE_LOCATION";
- case SUBSCRIPTION_OR_CARRIER_CONFIG_CHANGED:
- return "SUBSCRIPTION_OR_CARRIER_CONFIG_CHANGED";
case INITIALIZE_HANDLER:
return "INITIALIZE_HANDLER";
case REPORT_LOCATION:
diff --git a/services/core/java/com/android/server/location/GnssVisibilityControl.java b/services/core/java/com/android/server/location/GnssVisibilityControl.java
index a3670a4..c49d900 100644
--- a/services/core/java/com/android/server/location/GnssVisibilityControl.java
+++ b/services/core/java/com/android/server/location/GnssVisibilityControl.java
@@ -76,7 +76,7 @@
private final GpsNetInitiatedHandler mNiHandler;
private boolean mIsGpsEnabled;
- private volatile boolean mEsNotify;
+ private boolean mEsNotify;
// Number of non-framework location access proxy apps is expected to be small (< 5).
private static final int ARRAY_MAP_INITIAL_CAPACITY_PROXY_APP_TO_LOCATION_PERMISSIONS = 7;
@@ -124,10 +124,6 @@
}
}
- void updateProxyApps(List<String> nfwLocationAccessProxyApps) {
- runOnHandler(() -> handleUpdateProxyApps(nfwLocationAccessProxyApps));
- }
-
void reportNfwNotification(String proxyAppPackageName, byte protocolStack,
String otherProtocolStackName, byte requestor, String requestorId, byte responseType,
boolean inEmergencyMode, boolean isCachedLocation) {
@@ -136,15 +132,25 @@
requestor, requestorId, responseType, inEmergencyMode, isCachedLocation)));
}
- void setEsNotify(int esNotifyConfig) {
- if (esNotifyConfig != ES_NOTIFY_NONE && esNotifyConfig != ES_NOTIFY_ALL) {
+ void onConfigurationUpdated(GnssConfiguration configuration) {
+ // The configuration object must be accessed only in the caller thread and not in mHandler.
+ List<String> nfwLocationAccessProxyApps = configuration.getProxyApps();
+ int esNotify = configuration.getEsNotify(ES_NOTIFY_NONE);
+ runOnHandler(() -> {
+ setEsNotify(esNotify);
+ handleUpdateProxyApps(nfwLocationAccessProxyApps);
+ });
+ }
+
+ private void setEsNotify(int esNotify) {
+ if (esNotify != ES_NOTIFY_NONE && esNotify != ES_NOTIFY_ALL) {
Log.e(TAG, "Config parameter " + GnssConfiguration.CONFIG_ES_NOTIFY_INT
- + " is set to invalid value: " + esNotifyConfig
+ + " is set to invalid value: " + esNotify
+ ". Using default value: " + ES_NOTIFY_NONE);
- esNotifyConfig = ES_NOTIFY_NONE;
+ esNotify = ES_NOTIFY_NONE;
}
- mEsNotify = (esNotifyConfig == ES_NOTIFY_ALL);
+ mEsNotify = (esNotify == ES_NOTIFY_ALL);
}
private void handleInitialize() {
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index c2125b0..b246eb6 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -421,8 +421,9 @@
new PasswordSlotManager());
}
- public boolean hasBiometrics() {
- return BiometricManager.hasBiometrics(mContext);
+ public boolean hasEnrolledBiometrics() {
+ BiometricManager bm = mContext.getSystemService(BiometricManager.class);
+ return bm.canAuthenticate() == BiometricManager.BIOMETRIC_SUCCESS;
}
public int binderGetCallingUid() {
@@ -2502,7 +2503,8 @@
// TODO: When lockout is handled under the HAL for all biometrics (fingerprint),
// we need to generate challenge for each one, have it signed by GK and reset lockout
// for each modality.
- if (!hasChallenge && pm.hasSystemFeature(PackageManager.FEATURE_FACE)) {
+ if (!hasChallenge && pm.hasSystemFeature(PackageManager.FEATURE_FACE)
+ && mInjector.hasEnrolledBiometrics()) {
challenge = mContext.getSystemService(FaceManager.class).generateChallenge();
}
@@ -2544,8 +2546,8 @@
if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
notifyActivePasswordMetricsAvailable(credentialType, userCredential, userId);
unlockKeystore(authResult.authToken.deriveKeyStorePassword(), userId);
- // Reset lockout
- if (mInjector.hasBiometrics()) {
+ // Reset lockout only if user has enrolled templates
+ if (mInjector.hasEnrolledBiometrics()) {
BiometricManager bm = mContext.getSystemService(BiometricManager.class);
Slog.i(TAG, "Resetting lockout, length: "
+ authResult.gkResponse.getPayload().length);
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index bab612d..9d11596 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -73,6 +73,7 @@
public static final int FLAG_STORAGE_DE = IInstalld.FLAG_STORAGE_DE;
public static final int FLAG_STORAGE_CE = IInstalld.FLAG_STORAGE_CE;
+ public static final int FLAG_STORAGE_EXTERNAL = IInstalld.FLAG_STORAGE_EXTERNAL;
public static final int FLAG_CLEAR_CACHE_ONLY = IInstalld.FLAG_CLEAR_CACHE_ONLY;
public static final int FLAG_CLEAR_CODE_CACHE_ONLY = IInstalld.FLAG_CLEAR_CODE_CACHE_ONLY;
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 9d70209..23aa8f0 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -89,6 +89,7 @@
import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
import static android.os.storage.StorageManager.FLAG_STORAGE_CE;
import static android.os.storage.StorageManager.FLAG_STORAGE_DE;
+import static android.os.storage.StorageManager.FLAG_STORAGE_EXTERNAL;
import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_MANAGED_PROFILE;
import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_PARENT;
@@ -3249,7 +3250,7 @@
if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, ps.volumeUuid)) {
// No apps are running this early, so no need to freeze
clearAppDataLIF(ps.pkg, UserHandle.USER_ALL,
- StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE
+ FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL
| Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
}
}
@@ -3502,8 +3503,8 @@
}
return false;
}
- clearAppDataLIF(pkg, UserHandle.USER_ALL, FLAG_STORAGE_DE
- | FLAG_STORAGE_CE | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
+ clearAppDataLIF(pkg, UserHandle.USER_ALL, FLAG_STORAGE_DE | FLAG_STORAGE_CE
+ | FLAG_STORAGE_EXTERNAL | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
mDexManager.notifyPackageUpdated(pkg.packageName,
pkg.baseCodePath, pkg.splitCodePaths);
}
@@ -15975,6 +15976,9 @@
synchronized (mInstallLock) {
// Clean up both app data and code
// All package moves are frozen until finished
+
+ // We purposefully exclude FLAG_STORAGE_EXTERNAL here, since
+ // this task was only focused on moving data on internal storage.
for (int userId : userIds) {
try {
mInstaller.destroyAppData(volumeUuid, move.packageName, userId,
@@ -17075,8 +17079,8 @@
final String packageName = pkg.packageName;
prepareAppDataAfterInstallLIF(pkg);
if (reconciledPkg.prepareResult.clearCodeCache) {
- clearAppDataLIF(pkg, UserHandle.USER_ALL, StorageManager.FLAG_STORAGE_DE
- | StorageManager.FLAG_STORAGE_CE | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
+ clearAppDataLIF(pkg, UserHandle.USER_ALL, FLAG_STORAGE_DE | FLAG_STORAGE_CE
+ | FLAG_STORAGE_EXTERNAL | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
}
if (reconciledPkg.prepareResult.replace) {
mDexManager.notifyPackageUpdated(pkg.packageName,
@@ -18848,7 +18852,7 @@
resolvedPkg.setVolumeUuid(deletedPs.volumeUuid);
}
destroyAppDataLIF(resolvedPkg, UserHandle.USER_ALL,
- StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);
+ FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL);
destroyAppProfilesLIF(resolvedPkg);
if (outInfo != null) {
outInfo.dataRemoved = true;
@@ -19600,7 +19604,7 @@
}
destroyAppDataLIF(pkg, nextUserId,
- StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);
+ FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL);
clearDefaultBrowserIfNeededForUser(ps.name, nextUserId);
removeKeystoreDataIfNeeded(nextUserId, ps.appId);
final SparseBooleanArray changedUsers = new SparseBooleanArray();
@@ -19736,7 +19740,7 @@
}
clearAppDataLIF(pkg, userId,
- StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);
+ FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL);
final int appId = UserHandle.getAppId(pkg.applicationInfo.uid);
removeKeystoreDataIfNeeded(userId, appId);
@@ -19967,8 +19971,7 @@
}
if (doClearData) {
synchronized (mInstallLock) {
- final int flags = StorageManager.FLAG_STORAGE_DE
- | StorageManager.FLAG_STORAGE_CE;
+ final int flags = FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL;
// We're only clearing cache files, so we don't care if the
// app is unfrozen and still able to run
clearAppDataLIF(pkg, userId, flags | Installer.FLAG_CLEAR_CACHE_ONLY);
@@ -22516,9 +22519,8 @@
}
if (!Build.FINGERPRINT.equals(ver.fingerprint)) {
- clearAppDataLIF(ps.pkg, UserHandle.USER_ALL,
- StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE
- | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
+ clearAppDataLIF(ps.pkg, UserHandle.USER_ALL, FLAG_STORAGE_DE | FLAG_STORAGE_CE
+ | FLAG_STORAGE_EXTERNAL | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
}
}
}
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 37c1aaa..b2ba290 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -929,6 +929,7 @@
final BasePermission bp = mSettings.getPermissionLocked(permName);
final boolean appSupportsRuntimePermissions =
pkg.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.M;
+ String upgradedActivityRecognitionPermission = null;
if (DEBUG_INSTALL) {
Log.i(TAG, "Package " + pkg.packageName + " checking " + permName + ": " + bp);
@@ -947,11 +948,40 @@
// Cache newImplicitPermissions before modifing permissionsState as for the shared
// uids the original and new state are the same object
if (!origPermissions.hasRequestedPermission(permName)
- && pkg.implicitPermissions.contains(permName)) {
- newImplicitPermissions.add(permName);
+ && (pkg.implicitPermissions.contains(permName)
+ || (permName.equals(Manifest.permission.ACTIVITY_RECOGNITION)))) {
+ if (pkg.implicitPermissions.contains(permName)) {
+ // If permName is an implicit permission, try to auto-grant
+ newImplicitPermissions.add(permName);
- if (DEBUG_PERMISSIONS) {
- Slog.i(TAG, permName + " is newly added for " + pkg.packageName);
+ if (DEBUG_PERMISSIONS) {
+ Slog.i(TAG, permName + " is newly added for " + pkg.packageName);
+ }
+ } else {
+ // Special case for Activity Recognition permission. Even if AR permission
+ // is not an implicit permission we want to add it to the list (try to
+ // auto-grant it) if the app was installed on a device before AR permission
+ // was split, regardless of if the app now requests the new AR permission
+ // 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();
+ for (int splitPermNum = 0; splitPermNum < numSplitPerms; splitPermNum++) {
+ PermissionManager.SplitPermissionInfo sp =
+ PermissionManager.SPLIT_PERMISSIONS.get(splitPermNum);
+ String splitPermName = sp.getSplitPermission();
+ if (sp.getNewPermissions().contains(permName)
+ && origPermissions.hasInstallPermission(splitPermName)) {
+ upgradedActivityRecognitionPermission = splitPermName;
+ newImplicitPermissions.add(permName);
+
+ if (DEBUG_PERMISSIONS) {
+ Slog.i(TAG, permName + " is newly added for "
+ + pkg.packageName);
+ }
+ break;
+ }
+ }
}
}
@@ -985,7 +1015,8 @@
// For all apps normal permissions are install time ones.
grant = GRANT_INSTALL;
} else if (bp.isRuntime()) {
- if (origPermissions.hasInstallPermission(bp.getName())) {
+ if (origPermissions.hasInstallPermission(bp.getName())
+ || upgradedActivityRecognitionPermission != null) {
// Before Q we represented some runtime permissions as install permissions,
// in Q we cannot do this anymore. Hence upgrade them all.
grant = GRANT_UPGRADE;
@@ -1161,10 +1192,15 @@
.getInstallPermissionState(perm);
int flags = (permState != null) ? permState.getFlags() : 0;
+ BasePermission bpToRevoke =
+ upgradedActivityRecognitionPermission == null
+ ? bp : mSettings.getPermissionLocked(
+ upgradedActivityRecognitionPermission);
// Remove install permission
- if (origPermissions.revokeInstallPermission(bp)
+ if (origPermissions.revokeInstallPermission(bpToRevoke)
!= PERMISSION_OPERATION_FAILURE) {
- origPermissions.updatePermissionFlags(bp, UserHandle.USER_ALL,
+ origPermissions.updatePermissionFlags(bpToRevoke,
+ UserHandle.USER_ALL,
(MASK_PERMISSION_FLAGS_ALL
& ~FLAG_PERMISSION_APPLY_RESTRICTION), 0);
changedInstallPermission = true;
@@ -1489,9 +1525,11 @@
for (int userNum = 0; userNum < numUsers; userNum++) {
int userId = users[userNum];
- ps.updatePermissionFlags(bp, userId,
- FLAG_PERMISSION_REVOKE_WHEN_REQUESTED,
- FLAG_PERMISSION_REVOKE_WHEN_REQUESTED);
+ if (!newPerm.equals(Manifest.permission.ACTIVITY_RECOGNITION)) {
+ ps.updatePermissionFlags(bp, userId,
+ FLAG_PERMISSION_REVOKE_WHEN_REQUESTED,
+ FLAG_PERMISSION_REVOKE_WHEN_REQUESTED);
+ }
updatedUserIds = ArrayUtils.appendInt(updatedUserIds, userId);
boolean inheritsFromInstallPerm = false;
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index fd90f03..ecbecba 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -2005,7 +2005,7 @@
}
layoutLetterbox(winHint);
if (mLetterbox != null && mLetterbox.needsApplySurfaceChanges()) {
- mLetterbox.applySurfaceChanges(mPendingTransaction);
+ mLetterbox.applySurfaceChanges(getPendingTransaction());
}
}
@@ -3059,13 +3059,13 @@
if (mSurfaceControl != null) {
if (show && !mLastSurfaceShowing) {
- mPendingTransaction.show(mSurfaceControl);
+ getPendingTransaction().show(mSurfaceControl);
} else if (!show && mLastSurfaceShowing) {
- mPendingTransaction.hide(mSurfaceControl);
+ getPendingTransaction().hide(mSurfaceControl);
}
}
if (mThumbnail != null) {
- mThumbnail.setShowing(mPendingTransaction, show);
+ mThumbnail.setShowing(getPendingTransaction(), show);
}
mLastSurfaceShowing = show;
super.prepareSurfaces();
@@ -3225,8 +3225,8 @@
private void updateColorTransform() {
if (mSurfaceControl != null && mLastAppSaturationInfo != null) {
- mPendingTransaction.setColorTransform(mSurfaceControl, mLastAppSaturationInfo.mMatrix,
- mLastAppSaturationInfo.mTranslation);
+ getPendingTransaction().setColorTransform(mSurfaceControl,
+ mLastAppSaturationInfo.mMatrix, mLastAppSaturationInfo.mTranslation);
mWmService.scheduleAnimationLocked();
}
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 58a03b2..1e826ee 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -3340,7 +3340,7 @@
final SurfaceControl newParent =
shouldAttachToDisplay ? mWindowingLayer : computeImeParent();
if (newParent != null) {
- mPendingTransaction.reparent(mImeWindowsContainers.mSurfaceControl, newParent);
+ getPendingTransaction().reparent(mImeWindowsContainers.mSurfaceControl, newParent);
scheduleAnimation();
}
}
@@ -3747,7 +3747,8 @@
mPortalWindowHandle.touchableRegion.getBounds(mTmpRect);
if (!mTmpBounds.equals(mTmpRect)) {
mPortalWindowHandle.touchableRegion.set(mTmpBounds);
- mPendingTransaction.setInputWindowInfo(mParentSurfaceControl, mPortalWindowHandle);
+ getPendingTransaction().setInputWindowInfo(
+ mParentSurfaceControl, mPortalWindowHandle);
}
}
}
@@ -4846,18 +4847,23 @@
try {
final ScreenRotationAnimation screenRotationAnimation =
mWmService.mAnimator.getScreenRotationAnimationLocked(mDisplayId);
+ final Transaction transaction = getPendingTransaction();
if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {
screenRotationAnimation.getEnterTransformation().getMatrix().getValues(mTmpFloats);
- mPendingTransaction.setMatrix(mWindowingLayer,
+ transaction.setMatrix(mWindowingLayer,
mTmpFloats[Matrix.MSCALE_X], mTmpFloats[Matrix.MSKEW_Y],
mTmpFloats[Matrix.MSKEW_X], mTmpFloats[Matrix.MSCALE_Y]);
- mPendingTransaction.setPosition(mWindowingLayer,
+ transaction.setPosition(mWindowingLayer,
mTmpFloats[Matrix.MTRANS_X], mTmpFloats[Matrix.MTRANS_Y]);
- mPendingTransaction.setAlpha(mWindowingLayer,
+ transaction.setAlpha(mWindowingLayer,
screenRotationAnimation.getEnterTransformation().getAlpha());
}
super.prepareSurfaces();
+
+ // TODO: Once we totally eliminate global transaction we will pass transaction in here
+ // rather than merging to global.
+ SurfaceControl.mergeToGlobalTransaction(transaction);
} finally {
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
@@ -5013,7 +5019,7 @@
if (mPortalWindowHandle == null) {
mPortalWindowHandle = createPortalWindowHandle(sc.toString());
}
- mPendingTransaction.setInputWindowInfo(sc, mPortalWindowHandle)
+ getPendingTransaction().setInputWindowInfo(sc, mPortalWindowHandle)
.reparent(mWindowingLayer, sc).reparent(mOverlayLayer, sc);
}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index bb7867c..3820106 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -138,6 +138,7 @@
setOrientation(SCREEN_ORIENTATION_UNSET);
}
+ @Override
DisplayContent getDisplayContent() {
return mStack != null ? mStack.getDisplayContent() : null;
}
diff --git a/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java b/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java
index 17e4b89..ee4e462 100644
--- a/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java
+++ b/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java
@@ -77,7 +77,7 @@
@Override
public SurfaceControl.Transaction getPendingTransaction() {
- return mTask.mPendingTransaction;
+ return mTask.getPendingTransaction();
}
@Override
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 757f6a1..ab5e071 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -93,10 +93,6 @@
/** Unique identifier */
final int mStackId;
- /** The display this stack sits under. */
- // TODO: Track parent marks like this in WindowContainer.
- private DisplayContent mDisplayContent;
-
/** For comparison with DisplayContent bounds. */
private Rect mTmpRect = new Rect();
private Rect mTmpRect2 = new Rect();
@@ -177,10 +173,6 @@
EventLog.writeEvent(EventLogTags.WM_STACK_CREATED, stackId);
}
- DisplayContent getDisplayContent() {
- return mDisplayContent;
- }
-
Task findHomeTask() {
if (!isActivityTypeHome() || mChildren.isEmpty()) {
return null;
@@ -825,8 +817,7 @@
throw new IllegalStateException("onDisplayChanged: Already attached");
}
- final boolean movedToNewDisplay = mDisplayContent == null;
- mDisplayContent = dc;
+ super.onDisplayChanged(dc);
updateSurfaceBounds();
if (mAnimationBackgroundSurface == null) {
@@ -834,8 +825,6 @@
.setName("animation background stackId=" + mStackId)
.build();
}
-
- super.onDisplayChanged(dc);
}
/**
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index d5c3e4f..bbef261 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -109,14 +109,19 @@
// The owner/creator for this container. No controller if null.
WindowContainerController mController;
+ // The display this window container is on.
+ protected DisplayContent mDisplayContent;
+
protected SurfaceControl mSurfaceControl;
private int mLastLayer = 0;
private SurfaceControl mLastRelativeToLayer = null;
+ // TODO(b/132320879): Remove this from WindowContainers except DisplayContent.
+ private final Transaction mPendingTransaction;
+
/**
* Applied as part of the animation pass in "prepareSurfaces".
*/
- protected final Transaction mPendingTransaction;
protected final SurfaceAnimator mSurfaceAnimator;
protected final WindowManagerService mWmService;
@@ -320,12 +325,12 @@
}
if (mSurfaceControl != null) {
- mPendingTransaction.remove(mSurfaceControl);
+ getPendingTransaction().remove(mSurfaceControl);
// Merge to parent transaction to ensure the transactions on this WindowContainer are
// applied in native even if WindowContainer is removed.
if (mParent != null) {
- mParent.getPendingTransaction().merge(mPendingTransaction);
+ mParent.getPendingTransaction().merge(getPendingTransaction());
}
mSurfaceControl = null;
@@ -508,12 +513,20 @@
* @param dc The display this container is on after changes.
*/
void onDisplayChanged(DisplayContent dc) {
+ mDisplayContent = dc;
+ if (dc != null && dc != this) {
+ dc.getPendingTransaction().merge(mPendingTransaction);
+ }
for (int i = mChildren.size() - 1; i >= 0; --i) {
final WindowContainer child = mChildren.get(i);
child.onDisplayChanged(dc);
}
}
+ DisplayContent getDisplayContent() {
+ return mDisplayContent;
+ }
+
void setWaitingForDrawnIfResizingChanged() {
for (int i = mChildren.size() - 1; i >= 0; --i) {
final WindowContainer wc = mChildren.get(i);
@@ -1180,13 +1193,7 @@
}
}
- /**
- * TODO: Once we totally eliminate global transaction we will pass transaction in here
- * rather than merging to global.
- */
void prepareSurfaces() {
- SurfaceControl.mergeToGlobalTransaction(getPendingTransaction());
-
// If a leash has been set when the transaction was committed, then the leash reparent has
// been committed.
mCommittedReparentToAnimationLeash = mSurfaceAnimator.hasLeash();
@@ -1204,8 +1211,8 @@
}
/**
- * Trigger a call to prepareSurfaces from the animation thread, such that
- * mPendingTransaction will be applied.
+ * Trigger a call to prepareSurfaces from the animation thread, such that pending transactions
+ * will be applied.
*/
void scheduleAnimation() {
if (mParent != null) {
@@ -1224,6 +1231,14 @@
@Override
public Transaction getPendingTransaction() {
+ final DisplayContent displayContent = getDisplayContent();
+ if (displayContent != null && displayContent != this) {
+ return displayContent.getPendingTransaction();
+ }
+ // This WindowContainer has not attached to a display yet or this is a DisplayContent, so we
+ // let the caller to save the surface operations within the local mPendingTransaction.
+ // If this is not a DisplayContent, we will merge it to the pending transaction of its
+ // display once it attaches to it.
return mPendingTransaction;
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index dd3c600..5ef184a 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -1313,6 +1313,7 @@
mOrientationChangeTimedOut = true;
}
+ @Override
DisplayContent getDisplayContent() {
return mToken.getDisplayContent();
}
@@ -4602,7 +4603,7 @@
new WindowAnimationSpec(anim, mSurfacePosition, false /* canSkipFirstFrame */,
0 /* windowCornerRadius */),
mWmService.mSurfaceAnimationRunner);
- startAnimation(mPendingTransaction, adapter);
+ startAnimation(getPendingTransaction(), adapter);
commitPendingTransaction();
}
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index f0b9c62..8aee0f2 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -82,9 +82,6 @@
// windows will be put to the bottom of the list.
boolean sendingToBottom;
- // The display this token is on.
- protected DisplayContent mDisplayContent;
-
/** The owner has {@link android.Manifest.permission#MANAGE_APP_TOKENS} */
final boolean mOwnerCanManageAppTokens;
@@ -249,10 +246,6 @@
return null;
}
- DisplayContent getDisplayContent() {
- return mDisplayContent;
- }
-
@Override
void removeImmediately() {
if (mDisplayContent != null) {
@@ -266,7 +259,6 @@
@Override
void onDisplayChanged(DisplayContent dc) {
dc.reParentWindowToken(this);
- mDisplayContent = dc;
// TODO(b/36740756): One day this should perhaps be hooked
// up with goodToGo, so we don't move a window
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java
index f7edf65..18c524a 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java
@@ -183,15 +183,188 @@
assertEquals(nextWindowStartTime, rescheduledJob.getEarliestRunTime());
assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed());
- advanceElapsedClock(45 * MINUTE_IN_MILLIS); // now + 55 minutes
+ advanceElapsedClock(20 * MINUTE_IN_MILLIS); // now + 30 minutes
rescheduledJob = mService.getRescheduleJobForPeriodic(job);
assertEquals(nextWindowStartTime, rescheduledJob.getEarliestRunTime());
assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed());
+ advanceElapsedClock(25 * MINUTE_IN_MILLIS); // now + 55 minutes
+
+ rescheduledJob = mService.getRescheduleJobForPeriodic(job);
+ // Shifted because it's close to the end of the window.
+ assertEquals(nextWindowStartTime + 5 * MINUTE_IN_MILLIS,
+ rescheduledJob.getEarliestRunTime());
+ assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed());
+
advanceElapsedClock(4 * MINUTE_IN_MILLIS); // now + 59 minutes
rescheduledJob = mService.getRescheduleJobForPeriodic(job);
+ // Shifted because it's close to the end of the window.
+ assertEquals(nextWindowStartTime + 9 * MINUTE_IN_MILLIS,
+ rescheduledJob.getEarliestRunTime());
+ assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed());
+ }
+
+ /**
+ * Confirm that {@link JobSchedulerService#getRescheduleJobForPeriodic(JobStatus)} returns a job
+ * with an extra delay and correct deadline constraint if the periodic job is completed near the
+ * end of its expected running window.
+ */
+ @Test
+ public void testGetRescheduleJobForPeriodic_closeToEndOfWindow() {
+ JobStatus frequentJob = createJobStatus(
+ "testGetRescheduleJobForPeriodic_closeToEndOfWindow",
+ createJobInfo().setPeriodic(15 * MINUTE_IN_MILLIS));
+ long now = sElapsedRealtimeClock.millis();
+ long nextWindowStartTime = now + 15 * MINUTE_IN_MILLIS;
+ long nextWindowEndTime = now + 30 * MINUTE_IN_MILLIS;
+
+ // At the beginning of the window. Next window should be unaffected.
+ JobStatus rescheduledJob = mService.getRescheduleJobForPeriodic(frequentJob);
+ assertEquals(nextWindowStartTime, rescheduledJob.getEarliestRunTime());
+ assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed());
+
+ // Halfway through window. Next window should be unaffected.
+ advanceElapsedClock((long) (7.5 * MINUTE_IN_MILLIS));
+ rescheduledJob = mService.getRescheduleJobForPeriodic(frequentJob);
+ assertEquals(nextWindowStartTime, rescheduledJob.getEarliestRunTime());
+ assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed());
+
+ // In last 1/6 of window. Next window start time should be shifted slightly.
+ advanceElapsedClock(6 * MINUTE_IN_MILLIS);
+ rescheduledJob = mService.getRescheduleJobForPeriodic(frequentJob);
+ assertEquals(nextWindowStartTime + MINUTE_IN_MILLIS,
+ rescheduledJob.getEarliestRunTime());
+ assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed());
+
+ JobStatus mediumJob = createJobStatus("testGetRescheduleJobForPeriodic_closeToEndOfWindow",
+ createJobInfo().setPeriodic(HOUR_IN_MILLIS));
+ now = sElapsedRealtimeClock.millis();
+ nextWindowStartTime = now + HOUR_IN_MILLIS;
+ nextWindowEndTime = now + 2 * HOUR_IN_MILLIS;
+
+ // At the beginning of the window. Next window should be unaffected.
+ rescheduledJob = mService.getRescheduleJobForPeriodic(mediumJob);
+ assertEquals(nextWindowStartTime, rescheduledJob.getEarliestRunTime());
+ assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed());
+
+ // Halfway through window. Next window should be unaffected.
+ advanceElapsedClock(30 * MINUTE_IN_MILLIS);
+ rescheduledJob = mService.getRescheduleJobForPeriodic(mediumJob);
+ assertEquals(nextWindowStartTime, rescheduledJob.getEarliestRunTime());
+ assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed());
+
+ // At the edge 1/6 of window. Next window should be unaffected.
+ advanceElapsedClock(20 * MINUTE_IN_MILLIS);
+ rescheduledJob = mService.getRescheduleJobForPeriodic(mediumJob);
+ assertEquals(nextWindowStartTime, rescheduledJob.getEarliestRunTime());
+ assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed());
+
+ // In last 1/6 of window. Next window start time should be shifted slightly.
+ advanceElapsedClock(6 * MINUTE_IN_MILLIS);
+ rescheduledJob = mService.getRescheduleJobForPeriodic(mediumJob);
+ assertEquals(nextWindowStartTime + (6 * MINUTE_IN_MILLIS),
+ rescheduledJob.getEarliestRunTime());
+ assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed());
+
+ JobStatus longJob = createJobStatus("testGetRescheduleJobForPeriodic_closeToEndOfWindow",
+ createJobInfo().setPeriodic(6 * HOUR_IN_MILLIS));
+ now = sElapsedRealtimeClock.millis();
+ nextWindowStartTime = now + 6 * HOUR_IN_MILLIS;
+ nextWindowEndTime = now + 12 * HOUR_IN_MILLIS;
+
+ // At the beginning of the window. Next window should be unaffected.
+ rescheduledJob = mService.getRescheduleJobForPeriodic(longJob);
+ assertEquals(nextWindowStartTime, rescheduledJob.getEarliestRunTime());
+ assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed());
+
+ // Halfway through window. Next window should be unaffected.
+ advanceElapsedClock(3 * HOUR_IN_MILLIS);
+ rescheduledJob = mService.getRescheduleJobForPeriodic(longJob);
+ assertEquals(nextWindowStartTime, rescheduledJob.getEarliestRunTime());
+ assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed());
+
+ // At the edge 1/6 of window. Next window should be unaffected.
+ advanceElapsedClock(2 * HOUR_IN_MILLIS);
+ rescheduledJob = mService.getRescheduleJobForPeriodic(longJob);
+ assertEquals(nextWindowStartTime, rescheduledJob.getEarliestRunTime());
+ assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed());
+
+ // In last 1/6 of window. Next window should be unaffected since we're over the shift cap.
+ advanceElapsedClock(15 * MINUTE_IN_MILLIS);
+ rescheduledJob = mService.getRescheduleJobForPeriodic(longJob);
+ assertEquals(nextWindowStartTime, rescheduledJob.getEarliestRunTime());
+ assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed());
+
+ // In last 1/6 of window. Next window start time should be shifted slightly.
+ advanceElapsedClock(30 * MINUTE_IN_MILLIS);
+ rescheduledJob = mService.getRescheduleJobForPeriodic(longJob);
+ assertEquals(nextWindowStartTime + (30 * MINUTE_IN_MILLIS),
+ rescheduledJob.getEarliestRunTime());
+ assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed());
+
+ // Flex duration close to period duration.
+ JobStatus gameyFlex = createJobStatus("testGetRescheduleJobForPeriodic_closeToEndOfWindow",
+ createJobInfo().setPeriodic(HOUR_IN_MILLIS, 59 * MINUTE_IN_MILLIS));
+ now = sElapsedRealtimeClock.millis();
+ nextWindowStartTime = now + HOUR_IN_MILLIS + MINUTE_IN_MILLIS;
+ nextWindowEndTime = now + 2 * HOUR_IN_MILLIS;
+ advanceElapsedClock(MINUTE_IN_MILLIS);
+
+ // At the beginning of the window. Next window should be unaffected.
+ rescheduledJob = mService.getRescheduleJobForPeriodic(gameyFlex);
+ assertEquals(nextWindowStartTime, rescheduledJob.getEarliestRunTime());
+ assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed());
+
+ // Halfway through window. Next window should be unaffected.
+ advanceElapsedClock(29 * MINUTE_IN_MILLIS);
+ rescheduledJob = mService.getRescheduleJobForPeriodic(gameyFlex);
+ assertEquals(nextWindowStartTime, rescheduledJob.getEarliestRunTime());
+ assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed());
+
+ // At the edge 1/6 of window. Next window should be unaffected.
+ advanceElapsedClock(20 * MINUTE_IN_MILLIS);
+ rescheduledJob = mService.getRescheduleJobForPeriodic(gameyFlex);
+ assertEquals(nextWindowStartTime, rescheduledJob.getEarliestRunTime());
+ assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed());
+
+ // In last 1/6 of window. Next window start time should be shifted slightly.
+ advanceElapsedClock(6 * MINUTE_IN_MILLIS);
+ rescheduledJob = mService.getRescheduleJobForPeriodic(gameyFlex);
+ assertEquals(nextWindowStartTime + (5 * MINUTE_IN_MILLIS),
+ rescheduledJob.getEarliestRunTime());
+ assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed());
+
+ // Very short flex duration compared to period duration.
+ JobStatus superFlex = createJobStatus("testGetRescheduleJobForPeriodic_closeToEndOfWindow",
+ createJobInfo().setPeriodic(HOUR_IN_MILLIS, 10 * MINUTE_IN_MILLIS));
+ now = sElapsedRealtimeClock.millis();
+ nextWindowStartTime = now + HOUR_IN_MILLIS + 50 * MINUTE_IN_MILLIS;
+ nextWindowEndTime = now + 2 * HOUR_IN_MILLIS;
+ advanceElapsedClock(MINUTE_IN_MILLIS);
+
+ // At the beginning of the window. Next window should be unaffected.
+ rescheduledJob = mService.getRescheduleJobForPeriodic(superFlex);
+ assertEquals(nextWindowStartTime, rescheduledJob.getEarliestRunTime());
+ assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed());
+
+ // Halfway through window. Next window should be unaffected.
+ advanceElapsedClock(29 * MINUTE_IN_MILLIS);
+ rescheduledJob = mService.getRescheduleJobForPeriodic(superFlex);
+ assertEquals(nextWindowStartTime, rescheduledJob.getEarliestRunTime());
+ assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed());
+
+ // At the edge 1/6 of window. Next window should be unaffected.
+ advanceElapsedClock(20 * MINUTE_IN_MILLIS);
+ rescheduledJob = mService.getRescheduleJobForPeriodic(superFlex);
+ assertEquals(nextWindowStartTime, rescheduledJob.getEarliestRunTime());
+ assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed());
+
+ // In last 1/6 of window. Next window should be unaffected since the flex duration pushes
+ // the next window start time far enough away.
+ advanceElapsedClock(6 * MINUTE_IN_MILLIS);
+ rescheduledJob = mService.getRescheduleJobForPeriodic(superFlex);
assertEquals(nextWindowStartTime, rescheduledJob.getEarliestRunTime());
assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed());
}
@@ -265,7 +438,9 @@
advanceElapsedClock(10 * MINUTE_IN_MILLIS); // now + 55 minutes
rescheduledJob = mService.getRescheduleJobForPeriodic(failedJob);
- assertEquals(nextWindowStartTime, rescheduledJob.getEarliestRunTime());
+ // Shifted because it's close to the end of the window.
+ assertEquals(nextWindowStartTime + 5 * MINUTE_IN_MILLIS,
+ rescheduledJob.getEarliestRunTime());
assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed());
advanceElapsedClock(2 * MINUTE_IN_MILLIS); // now + 57 minutes
@@ -273,7 +448,9 @@
advanceElapsedClock(2 * MINUTE_IN_MILLIS); // now + 59 minutes
rescheduledJob = mService.getRescheduleJobForPeriodic(failedJob);
- assertEquals(nextWindowStartTime, rescheduledJob.getEarliestRunTime());
+ // Shifted because it's close to the end of the window.
+ assertEquals(nextWindowStartTime + 9 * MINUTE_IN_MILLIS,
+ rescheduledJob.getEarliestRunTime());
assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed());
}
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
index 10fb3ba..19ed5f3 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
@@ -110,7 +110,7 @@
}
@Override
- public boolean hasBiometrics() {
+ public boolean hasEnrolledBiometrics() {
return false;
}
diff --git a/services/usage/java/com/android/server/usage/StorageStatsService.java b/services/usage/java/com/android/server/usage/StorageStatsService.java
index faf6ee2..0f3050f 100644
--- a/services/usage/java/com/android/server/usage/StorageStatsService.java
+++ b/services/usage/java/com/android/server/usage/StorageStatsService.java
@@ -120,6 +120,7 @@
@Override
public void onVolumeStateChanged(VolumeInfo vol, int oldState, int newState) {
switch (vol.type) {
+ case VolumeInfo.TYPE_PUBLIC:
case VolumeInfo.TYPE_PRIVATE:
case VolumeInfo.TYPE_EMULATED:
if (newState == VolumeInfo.STATE_MOUNTED) {
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index e1ffb0f..d77ea6e 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -77,6 +77,7 @@
import com.android.internal.util.Preconditions;
import com.android.server.FgThread;
import com.android.server.LocalServices;
+import com.android.server.SystemServerInitThreadPool;
import com.android.server.SystemService;
import com.android.server.UiThread;
import com.android.server.soundtrigger.SoundTriggerInternal;
@@ -1283,7 +1284,9 @@
mRm.addOnRoleHoldersChangedListenerAsUser(executor, this, UserHandle.ALL);
UserHandle currentUser = UserHandle.of(LocalServices.getService(
ActivityManagerInternal.class).getCurrentUserId());
- onRoleHoldersChanged(RoleManager.ROLE_ASSISTANT, currentUser);
+ SystemServerInitThreadPool.get().submit(() -> onRoleHoldersChanged(
+ RoleManager.ROLE_ASSISTANT, currentUser),
+ "VoiceInteractionManagerService RoleObserver initialization");
}
private @NonNull String getDefaultRecognizer(@NonNull UserHandle user) {
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 93c1b21..eefaf47 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -1451,6 +1451,9 @@
* foreground call is ended.
* <p>
* Requires permission {@link android.Manifest.permission#ANSWER_PHONE_CALLS}.
+ * <p>
+ * Note: this method CANNOT be used to end ongoing emergency calls and will return {@code false}
+ * if an attempt is made to end an emergency call.
*
* @return {@code true} if there is a call which will be rejected or terminated, {@code false}
* otherwise.
@@ -1458,8 +1461,6 @@
* instead. Apps performing call screening should use the {@link CallScreeningService} API
* instead.
*/
-
-
@RequiresPermission(Manifest.permission.ANSWER_PHONE_CALLS)
@Deprecated
public boolean endCall() {
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index d00341b..6ba359b 100755
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -836,13 +836,6 @@
"carrier_metered_roaming_apn_types_strings";
/**
- * Default APN types that are metered on IWLAN by the carrier
- * @hide
- */
- public static final String KEY_CARRIER_METERED_IWLAN_APN_TYPES_STRINGS =
- "carrier_metered_iwlan_apn_types_strings";
-
- /**
* CDMA carrier ERI (Enhanced Roaming Indicator) file name
* @hide
*/
@@ -3116,15 +3109,6 @@
new String[]{"default", "mms", "dun", "supl"});
sDefaults.putStringArray(KEY_CARRIER_METERED_ROAMING_APN_TYPES_STRINGS,
new String[]{"default", "mms", "dun", "supl"});
- // By default all APNs should be unmetered if the device is on IWLAN. However, we add
- // default APN as metered here as a workaround for P because in some cases, a data
- // connection was brought up on cellular, but later on the device camped on IWLAN. That
- // data connection was incorrectly treated as unmetered due to the current RAT IWLAN.
- // Marking it as metered for now can workaround the issue.
- // Todo: This will be fixed in Q when IWLAN full refactoring is completed.
- sDefaults.putStringArray(KEY_CARRIER_METERED_IWLAN_APN_TYPES_STRINGS,
- new String[]{"default"});
-
sDefaults.putIntArray(KEY_ONLY_SINGLE_DC_ALLOWED_INT_ARRAY,
new int[]{
4, /* IS95A */
diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java
index c57f9e6..f31ac2e 100644
--- a/telephony/java/android/telephony/SubscriptionInfo.java
+++ b/telephony/java/android/telephony/SubscriptionInfo.java
@@ -173,6 +173,11 @@
private ParcelUuid mGroupUUID;
/**
+ * A package name that specifies who created the group. Null if mGroupUUID is null.
+ */
+ private String mGroupOwner;
+
+ /**
* Whether group of the subscription is disabled.
* This is only useful if it's a grouped opportunistic subscription. In this case, if all
* primary (non-opportunistic) subscriptions in the group are deactivated (unplugged pSIM
@@ -203,9 +208,10 @@
Bitmap icon, String mcc, String mnc, String countryIso, boolean isEmbedded,
@Nullable UiccAccessRule[] accessRules, String cardString) {
this(id, iccId, simSlotIndex, displayName, carrierName, nameSource, iconTint, number,
- roaming, icon, mcc, mnc, countryIso, isEmbedded, accessRules, cardString,
- false, null, TelephonyManager.UNKNOWN_CARRIER_ID,
- SubscriptionManager.PROFILE_CLASS_DEFAULT);
+ roaming, icon, mcc, mnc, countryIso, isEmbedded, accessRules, cardString, -1,
+ false, null, false, TelephonyManager.UNKNOWN_CARRIER_ID,
+ SubscriptionManager.PROFILE_CLASS_DEFAULT,
+ SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM, null);
}
/**
@@ -219,7 +225,7 @@
this(id, iccId, simSlotIndex, displayName, carrierName, nameSource, iconTint, number,
roaming, icon, mcc, mnc, countryIso, isEmbedded, accessRules, cardString, -1,
isOpportunistic, groupUUID, false, carrierId, profileClass,
- SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM);
+ SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM, null);
}
/**
@@ -229,8 +235,8 @@
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,
- boolean isOpportunistic, @Nullable String groupUUID,
- boolean isGroupDisabled, int carrierId, int profileClass, int subType) {
+ boolean isOpportunistic, @Nullable String groupUUID, boolean isGroupDisabled,
+ int carrierId, int profileClass, int subType, @Nullable String groupOwner) {
this.mId = id;
this.mIccId = iccId;
this.mSimSlotIndex = simSlotIndex;
@@ -254,6 +260,7 @@
this.mCarrierId = carrierId;
this.mProfileClass = profileClass;
this.mSubscriptionType = subType;
+ this.mGroupOwner = groupOwner;
}
/**
@@ -500,6 +507,15 @@
}
/**
+ * Return owner package of group the subscription belongs to.
+ *
+ * @hide
+ */
+ public @Nullable String getGroupOwner() {
+ return mGroupOwner;
+ }
+
+ /**
* @return the profile class of this subscription.
* @hide
*/
@@ -646,11 +662,12 @@
int subType = source.readInt();
String[] ehplmns = source.readStringArray();
String[] hplmns = source.readStringArray();
+ String groupOwner = source.readString();
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);
+ groupUUID, isGroupDisabled, carrierid, profileClass, subType, groupOwner);
info.setAssociatedPlmns(ehplmns, hplmns);
return info;
}
@@ -688,6 +705,7 @@
dest.writeInt(mSubscriptionType);
dest.writeStringArray(mEhplmns);
dest.writeStringArray(mHplmns);
+ dest.writeString(mGroupOwner);
}
@Override
@@ -727,7 +745,8 @@
+ " profileClass=" + mProfileClass
+ " ehplmns = " + Arrays.toString(mEhplmns)
+ " hplmns = " + Arrays.toString(mHplmns)
- + " subscriptionType=" + mSubscriptionType + "}";
+ + " subscriptionType=" + mSubscriptionType
+ + " mGroupOwner=" + mGroupOwner + "}";
}
@Override
@@ -735,7 +754,7 @@
return Objects.hash(mId, mSimSlotIndex, mNameSource, mIconTint, mDataRoaming, mIsEmbedded,
mIsOpportunistic, mGroupUUID, mIccId, mNumber, mMcc, mMnc,
mCountryIso, mCardString, mCardId, mDisplayName, mCarrierName, mAccessRules,
- mIsGroupDisabled, mCarrierId, mProfileClass);
+ mIsGroupDisabled, mCarrierId, mProfileClass, mGroupOwner);
}
@Override
@@ -767,6 +786,7 @@
&& Objects.equals(mCountryIso, toCompare.mCountryIso)
&& Objects.equals(mCardString, toCompare.mCardString)
&& Objects.equals(mCardId, toCompare.mCardId)
+ && Objects.equals(mGroupOwner, toCompare.mGroupOwner)
&& TextUtils.equals(mDisplayName, toCompare.mDisplayName)
&& TextUtils.equals(mCarrierName, toCompare.mCarrierName)
&& Arrays.equals(mAccessRules, toCompare.mAccessRules)
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 79dd31b..addd9e0 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -692,6 +692,15 @@
* @hide
*/
public static final String GROUP_UUID = "group_uuid";
+
+ /**
+ * TelephonyProvider column name for group owner. It's the package name who created
+ * the subscription group.
+ *
+ * @hide
+ */
+ public static final String GROUP_OWNER = "group_owner";
+
/**
* TelephonyProvider column name for whether a subscription is metered or not, that is, whether
* the network it connects to charges for subscription or not. For example, paid CBRS or unpaid.
diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java
index a86fda4..a78bae4 100644
--- a/telephony/java/android/telephony/data/ApnSetting.java
+++ b/telephony/java/android/telephony/data/ApnSetting.java
@@ -1273,6 +1273,23 @@
}
/**
+ * Get supported APN types
+ *
+ * @return list of APN types
+ * @hide
+ */
+ @ApnType
+ public List<Integer> getApnTypes() {
+ List<Integer> types = new ArrayList<>();
+ for (Integer type : APN_TYPE_INT_MAP.keySet()) {
+ if ((mApnTypeBitmask & type) == type) {
+ types.add(type);
+ }
+ }
+ return types;
+ }
+
+ /**
* @param apnTypeBitmask bitmask of APN types.
* @return comma delimited list of APN types.
* @hide