Merge "Use pointer width from res before getWidth is ready" into qt-dev
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index 8191d37..bbd3dca 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -1264,7 +1264,7 @@
// This method only sends data, it does not receive it.
pid_t pid = IPCThreadState::self()->getCallingPid();
uid_t uid = IPCThreadState::self()->getCallingUid();
- // Root, system, and shell always have access
+ // Root, system, and shell always have access
if (uid != AID_ROOT && uid != AID_SYSTEM && uid != AID_SHELL) {
// Caller must be granted these permissions
if (!checkCallingPermission(String16(kPermissionDump))) {
@@ -1349,6 +1349,64 @@
return Status::ok();
}
+Status StatsService::sendWatchdogRollbackOccurredAtom(const int32_t rollbackTypeIn,
+ const android::String16& packageNameIn,
+ const int64_t packageVersionCodeIn) {
+ // Note: We skip the usage stats op check here since we do not have a package name.
+ // This is ok since we are overloading the usage_stats permission.
+ // This method only sends data, it does not receive it.
+ pid_t pid = IPCThreadState::self()->getCallingPid();
+ uid_t uid = IPCThreadState::self()->getCallingUid();
+ // Root, system, and shell always have access
+ if (uid != AID_ROOT && uid != AID_SYSTEM && uid != AID_SHELL) {
+ // Caller must be granted these permissions
+ if (!checkCallingPermission(String16(kPermissionDump))) {
+ return exception(binder::Status::EX_SECURITY,
+ StringPrintf("UID %d / PID %d lacks permission %s", uid, pid,
+ kPermissionDump));
+ }
+ if (!checkCallingPermission(String16(kPermissionUsage))) {
+ return exception(binder::Status::EX_SECURITY,
+ StringPrintf("UID %d / PID %d lacks permission %s", uid, pid,
+ kPermissionUsage));
+ }
+ }
+
+ android::util::stats_write(android::util::WATCHDOG_ROLLBACK_OCCURRED,
+ rollbackTypeIn, String8(packageNameIn).string(), packageVersionCodeIn);
+
+ // Fast return to save disk read.
+ if (rollbackTypeIn != android::util::WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_SUCCESS
+ && rollbackTypeIn !=
+ android::util::WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_INITIATE) {
+ return Status::ok();
+ }
+
+ bool readTrainInfoSuccess = false;
+ InstallTrainInfo trainInfoOnDisk;
+ readTrainInfoSuccess = StorageManager::readTrainInfo(trainInfoOnDisk);
+
+ if (!readTrainInfoSuccess) {
+ return Status::ok();
+ }
+ std::vector<int64_t> experimentIds = trainInfoOnDisk.experimentIds;
+ if (experimentIds.empty()) {
+ return Status::ok();
+ }
+ switch (rollbackTypeIn) {
+ case android::util::WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_INITIATE:
+ experimentIds.push_back(experimentIds[0] + 4);
+ break;
+ case android::util::WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_SUCCESS:
+ experimentIds.push_back(experimentIds[0] + 5);
+ break;
+ }
+ StorageManager::writeTrainInfo(trainInfoOnDisk.trainVersionCode, trainInfoOnDisk.trainName,
+ trainInfoOnDisk.status, experimentIds);
+ return Status::ok();
+}
+
+
Status StatsService::getRegisteredExperimentIds(std::vector<int64_t>* experimentIdsOut) {
uid_t uid = IPCThreadState::self()->getCallingUid();
diff --git a/cmds/statsd/src/StatsService.h b/cmds/statsd/src/StatsService.h
index a4e6d7f..8d8514f 100644
--- a/cmds/statsd/src/StatsService.h
+++ b/cmds/statsd/src/StatsService.h
@@ -196,6 +196,14 @@
const std::vector<int64_t>& experimentIdsIn) override;
/**
+ * Binder call to log WatchdogRollbackOccurred atom.
+ */
+ virtual Status sendWatchdogRollbackOccurredAtom(
+ const int32_t rollbackTypeIn,
+ const android::String16& packageNameIn,
+ const int64_t packageVersionCodeIn) override;
+
+ /**
* Binder call to get registered experiment IDs.
*/
virtual Status getRegisteredExperimentIds(std::vector<int64_t>* expIdsOut);
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 24df883..7646c3c 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -994,6 +994,19 @@
// Name of source package (for historical reasons, since BatteryStats tracked it).
optional string package_name = 3;
+
+ // These enum values match the STANDBY_BUCKET_XXX constants defined in UsageStatsManager.java.
+ enum Bucket {
+ UNKNOWN = 0;
+ EXEMPTED = 5;
+ ACTIVE = 10;
+ WORKING_SET = 20;
+ FREQUENT = 30;
+ RARE = 40;
+ NEVER = 50;
+ }
+ // The App Standby bucket of the app that scheduled the alarm at the time the alarm fired.
+ optional Bucket app_standby_bucket = 4;
}
/**
diff --git a/config/hiddenapi-greylist.txt b/config/hiddenapi-greylist.txt
index c267e77..82d0fbe 100644
--- a/config/hiddenapi-greylist.txt
+++ b/config/hiddenapi-greylist.txt
@@ -1431,8 +1431,6 @@
Lcom/android/internal/telephony/Sms7BitEncodingTranslator;->mTranslationTableCDMA:Landroid/util/SparseIntArray;
Lcom/android/internal/telephony/Sms7BitEncodingTranslator;->mTranslationTableCommon:Landroid/util/SparseIntArray;
Lcom/android/internal/telephony/Sms7BitEncodingTranslator;->mTranslationTableGSM:Landroid/util/SparseIntArray;
-Lcom/android/internal/telephony/Sms7BitEncodingTranslator;->translate(Ljava/lang/CharSequence;)Ljava/lang/String;
-Lcom/android/internal/telephony/Sms7BitEncodingTranslator;->useCdmaFormatForMoSms()Z
Lcom/android/internal/telephony/SmsApplication$SmsApplicationData;->mApplicationName:Ljava/lang/String;
Lcom/android/internal/telephony/SmsApplication;->configurePreferredActivity(Landroid/content/pm/PackageManager;Landroid/content/ComponentName;I)V
Lcom/android/internal/telephony/SmsApplication;->getApplicationCollection(Landroid/content/Context;)Ljava/util/Collection;
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index 5a69e6b..376a211 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -844,6 +844,13 @@
*/
public abstract void forEachPackage(Consumer<PackageParser.Package> actionLocked);
+ /**
+ * Perform the given action for each installed package for a user.
+ * Note that packages lock will be held while performin the actions.
+ */
+ public abstract void forEachInstalledPackage(
+ @NonNull Consumer<PackageParser.Package> actionLocked, @UserIdInt int userId);
+
/** Returns the list of enabled components */
public abstract ArraySet<String> getEnabledComponents(String packageName, int userId);
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 3bc40a7..fbfbfc0 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -3449,6 +3449,11 @@
final NetworkCallback callback;
synchronized (sCallbacks) {
callback = sCallbacks.get(request);
+ if (callback == null) {
+ Log.w(TAG,
+ "callback not found for " + getCallbackName(message.what) + " message");
+ return;
+ }
if (message.what == CALLBACK_UNAVAIL) {
sCallbacks.remove(request);
callback.networkRequest = ALREADY_UNREGISTERED;
@@ -3457,10 +3462,6 @@
if (DBG) {
Log.d(TAG, getCallbackName(message.what) + " for network " + network);
}
- if (callback == null) {
- Log.w(TAG, "callback not found for " + getCallbackName(message.what) + " message");
- return;
- }
switch (message.what) {
case CALLBACK_PRECHECK: {
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 1c97407..deb9eba 100755
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -132,10 +132,24 @@
* <a href="/training/articles/security-key-attestation.html">key attestation</a> to obtain
* proof of the device's original identifiers.
*
- * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, or for the calling package to be the
- * device or profile owner and have the READ_PHONE_STATE permission. Profile owner access is
- * deprecated and will be removed in a future release.
+ * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, for the calling app to be the device or
+ * profile owner and have the READ_PHONE_STATE permission, or that the calling app has carrier
+ * privileges (see {@link android.telephony.TelephonyManager#hasCarrierPrivileges}). The profile
+ * owner is an app that owns a managed profile on the device; for more details see <a
+ * href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner
+ * access is deprecated and will be removed in a future release.
*
+ * <p>If the calling app does not meet one of these requirements then this method will behave
+ * as follows:
+ *
+ * <ul>
+ * <li>If the calling app's target SDK is API level 28 or lower and the app has the
+ * READ_PHONE_STATE permission then {@link Build#UNKNOWN} is returned.</li>
+ * <li>If the calling app's target SDK is API level 28 or lower and the app does not have
+ * the READ_PHONE_STATE permission, or if the calling app is targeting API level 29 or
+ * higher, then a SecurityException is thrown.</li>
+ * </ul>
+ * *
* @return The serial number if specified.
*/
@SuppressAutoDoc // No support for device / profile owner.
diff --git a/core/java/android/os/IStatsManager.aidl b/core/java/android/os/IStatsManager.aidl
index 311c86d..a596fdc 100644
--- a/core/java/android/os/IStatsManager.aidl
+++ b/core/java/android/os/IStatsManager.aidl
@@ -219,6 +219,12 @@
in int options, in int state, in long[] experimentId);
/**
+ * Logs an event for watchdog rollbacks.
+ */
+ oneway void sendWatchdogRollbackOccurredAtom(in int rollbackType, in String packageName,
+ in long packageVersionCode);
+
+ /**
* Returns the most recently registered experiment IDs.
*/
long[] getRegisteredExperimentIds();
diff --git a/core/java/android/util/StatsLog.java b/core/java/android/util/StatsLog.java
index cfc092c..f7077bb 100644
--- a/core/java/android/util/StatsLog.java
+++ b/core/java/android/util/StatsLog.java
@@ -23,7 +23,6 @@
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
-import android.app.IActivityManager;
import android.content.Context;
import android.os.IStatsManager;
import android.os.RemoteException;
@@ -159,10 +158,6 @@
}
return false;
}
- int userId = IActivityManager.Stub.asInterface(
- ServiceManager.getService("activity"))
- .getCurrentUser()
- .id;
service.sendBinaryPushStateChangedAtom(
trainName, trainVersionCode, options, state, experimentIds);
return true;
@@ -178,6 +173,46 @@
}
}
+ /**
+ * Logs an event for watchdog rollbacks.
+ *
+ * @param rollbackType state of the rollback.
+ * @param packageName package name being rolled back.
+ * @param packageVersionCode version of the package being rolled back.
+ *
+ * @return True if the log request was sent to statsd.
+ *
+ * @hide
+ */
+ @RequiresPermission(allOf = {DUMP, PACKAGE_USAGE_STATS})
+ public static boolean logWatchdogRollbackOccurred(int rollbackType, String packageName,
+ long packageVersionCode) {
+ synchronized (sLogLock) {
+ try {
+ IStatsManager service = getIStatsManagerLocked();
+ if (service == null) {
+ if (DEBUG) {
+ Slog.d(TAG, "Failed to find statsd when logging event");
+ }
+ return false;
+ }
+
+ service.sendWatchdogRollbackOccurredAtom(rollbackType, packageName,
+ packageVersionCode);
+ return true;
+ } catch (RemoteException e) {
+ sService = null;
+ if (DEBUG) {
+ Slog.d(TAG,
+ "Failed to connect to StatsCompanionService when logging "
+ + "WatchdogRollbackOccurred");
+ }
+ return false;
+ }
+ }
+ }
+
+
private static IStatsManager getIStatsManagerLocked() throws RemoteException {
if (sService != null) {
return sService;
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index a6d0dee..bf6191e 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -21509,23 +21509,27 @@
}
saveCount = canvas.getSaveCount();
+ int topSaveCount = -1;
+ int bottomSaveCount = -1;
+ int leftSaveCount = -1;
+ int rightSaveCount = -1;
int solidColor = getSolidColor();
if (solidColor == 0) {
if (drawTop) {
- canvas.saveUnclippedLayer(left, top, right, top + length);
+ topSaveCount = canvas.saveUnclippedLayer(left, top, right, top + length);
}
if (drawBottom) {
- canvas.saveUnclippedLayer(left, bottom - length, right, bottom);
+ bottomSaveCount = canvas.saveUnclippedLayer(left, bottom - length, right, bottom);
}
if (drawLeft) {
- canvas.saveUnclippedLayer(left, top, left + length, bottom);
+ leftSaveCount = canvas.saveUnclippedLayer(left, top, left + length, bottom);
}
if (drawRight) {
- canvas.saveUnclippedLayer(right - length, top, right, bottom);
+ rightSaveCount = canvas.saveUnclippedLayer(right - length, top, right, bottom);
}
} else {
scrollabilityCache.setFadeColor(solidColor);
@@ -21542,21 +21546,19 @@
final Matrix matrix = scrollabilityCache.matrix;
final Shader fade = scrollabilityCache.shader;
- if (drawTop) {
- matrix.setScale(1, fadeHeight * topFadeStrength);
- matrix.postTranslate(left, top);
+ // must be restored in the reverse order that they were saved
+ if (drawRight) {
+ matrix.setScale(1, fadeHeight * rightFadeStrength);
+ matrix.postRotate(90);
+ matrix.postTranslate(right, top);
fade.setLocalMatrix(matrix);
p.setShader(fade);
- canvas.drawRect(left, top, right, top + length, p);
- }
+ if (solidColor == 0) {
+ canvas.restoreUnclippedLayer(rightSaveCount, p);
- if (drawBottom) {
- matrix.setScale(1, fadeHeight * bottomFadeStrength);
- matrix.postRotate(180);
- matrix.postTranslate(left, bottom);
- fade.setLocalMatrix(matrix);
- p.setShader(fade);
- canvas.drawRect(left, bottom - length, right, bottom, p);
+ } else {
+ canvas.drawRect(right - length, top, right, bottom, p);
+ }
}
if (drawLeft) {
@@ -21565,16 +21567,36 @@
matrix.postTranslate(left, top);
fade.setLocalMatrix(matrix);
p.setShader(fade);
- canvas.drawRect(left, top, left + length, bottom, p);
+ if (solidColor == 0) {
+ canvas.restoreUnclippedLayer(leftSaveCount, p);
+ } else {
+ canvas.drawRect(left, top, left + length, bottom, p);
+ }
}
- if (drawRight) {
- matrix.setScale(1, fadeHeight * rightFadeStrength);
- matrix.postRotate(90);
- matrix.postTranslate(right, top);
+ if (drawBottom) {
+ matrix.setScale(1, fadeHeight * bottomFadeStrength);
+ matrix.postRotate(180);
+ matrix.postTranslate(left, bottom);
fade.setLocalMatrix(matrix);
p.setShader(fade);
- canvas.drawRect(right - length, top, right, bottom, p);
+ if (solidColor == 0) {
+ canvas.restoreUnclippedLayer(bottomSaveCount, p);
+ } else {
+ canvas.drawRect(left, bottom - length, right, bottom, p);
+ }
+ }
+
+ if (drawTop) {
+ matrix.setScale(1, fadeHeight * topFadeStrength);
+ matrix.postTranslate(left, top);
+ fade.setLocalMatrix(matrix);
+ p.setShader(fade);
+ if (solidColor == 0) {
+ canvas.restoreUnclippedLayer(topSaveCount, p);
+ } else {
+ canvas.drawRect(left, top, right, top + length, p);
+ }
}
canvas.restoreToCount(saveCount);
diff --git a/core/java/android/view/textclassifier/SelectionEvent.java b/core/java/android/view/textclassifier/SelectionEvent.java
index 105cbcc..9ae0c65 100644
--- a/core/java/android/view/textclassifier/SelectionEvent.java
+++ b/core/java/android/view/textclassifier/SelectionEvent.java
@@ -24,6 +24,7 @@
import android.view.textclassifier.TextClassifier.EntityType;
import android.view.textclassifier.TextClassifier.WidgetType;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.Preconditions;
import java.lang.annotation.Retention;
@@ -115,7 +116,7 @@
/** Unknown invocation method */
public static final int INVOCATION_UNKNOWN = 0;
- private static final String NO_SIGNATURE = "";
+ static final String NO_SIGNATURE = "";
private final int mAbsoluteStart;
private final int mAbsoluteEnd;
@@ -374,8 +375,10 @@
/**
* Sets the event type.
+ * @hide
*/
- void setEventType(@EventType int eventType) {
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+ public void setEventType(@EventType int eventType) {
mEventType = eventType;
}
@@ -416,8 +419,10 @@
/**
* Sets the {@link TextClassificationContext} for this event.
+ * @hide
*/
- void setTextClassificationSessionContext(TextClassificationContext context) {
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+ public void setTextClassificationSessionContext(TextClassificationContext context) {
mPackageName = context.getPackageName();
mWidgetType = context.getWidgetType();
mWidgetVersion = context.getWidgetVersion();
@@ -432,8 +437,10 @@
/**
* Sets the invocationMethod for this event.
+ * @hide
*/
- void setInvocationMethod(@InvocationMethod int invocationMethod) {
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+ public void setInvocationMethod(@InvocationMethod int invocationMethod) {
mInvocationMethod = invocationMethod;
}
@@ -495,7 +502,9 @@
return mEventIndex;
}
- SelectionEvent setEventIndex(int index) {
+ /** @hide */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+ public SelectionEvent setEventIndex(int index) {
mEventIndex = index;
return this;
}
@@ -508,7 +517,9 @@
return mSessionId;
}
- SelectionEvent setSessionId(TextClassificationSessionId id) {
+ /** @hide */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+ public SelectionEvent setSessionId(@Nullable TextClassificationSessionId id) {
mSessionId = id;
return this;
}
@@ -521,7 +532,9 @@
return mStart;
}
- SelectionEvent setStart(int start) {
+ /** @hide */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+ public SelectionEvent setStart(int start) {
mStart = start;
return this;
}
@@ -534,7 +547,9 @@
return mEnd;
}
- SelectionEvent setEnd(int end) {
+ /** @hide */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+ public SelectionEvent setEnd(int end) {
mEnd = end;
return this;
}
@@ -547,7 +562,9 @@
return mSmartStart;
}
- SelectionEvent setSmartStart(int start) {
+ /** @hide */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+ public SelectionEvent setSmartStart(int start) {
this.mSmartStart = start;
return this;
}
@@ -560,7 +577,9 @@
return mSmartEnd;
}
- SelectionEvent setSmartEnd(int end) {
+ /** @hide */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+ public SelectionEvent setSmartEnd(int end) {
mSmartEnd = end;
return this;
}
diff --git a/core/java/android/view/textclassifier/TextClassificationSession.java b/core/java/android/view/textclassifier/TextClassificationSession.java
index 15f54ef..db0202a 100644
--- a/core/java/android/view/textclassifier/TextClassificationSession.java
+++ b/core/java/android/view/textclassifier/TextClassificationSession.java
@@ -84,6 +84,7 @@
@Override
public void onTextClassifierEvent(TextClassifierEvent event) {
try {
+ event.mHiddenTempSessionId = mSessionId;
mDelegate.onTextClassifierEvent(event);
} catch (Exception e) {
// Avoid crashing for event reporting.
diff --git a/core/java/android/view/textclassifier/TextClassifierEvent.java b/core/java/android/view/textclassifier/TextClassifierEvent.java
index 7b623e9..57da829 100644
--- a/core/java/android/view/textclassifier/TextClassifierEvent.java
+++ b/core/java/android/view/textclassifier/TextClassifierEvent.java
@@ -24,6 +24,7 @@
import android.os.Parcel;
import android.os.Parcelable;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.Preconditions;
import java.lang.annotation.Retention;
@@ -150,6 +151,14 @@
private final ULocale mLocale;
private final Bundle mExtras;
+ /**
+ * Session id holder to help with converting this event to the legacy SelectionEvent.
+ * @hide
+ */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+ @Nullable
+ public TextClassificationSessionId mHiddenTempSessionId;
+
private TextClassifierEvent(Builder builder) {
mEventCategory = builder.mEventCategory;
mEventType = builder.mEventType;
@@ -360,6 +369,120 @@
}
/**
+ * Returns a {@link SelectionEvent} equivalent of this event; or {@code null} if it can not be
+ * converted to a {@link SelectionEvent}.
+ * @hide
+ */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+ @Nullable
+ public final SelectionEvent toSelectionEvent() {
+ final int invocationMethod;
+ switch (getEventCategory()) {
+ case TextClassifierEvent.CATEGORY_SELECTION:
+ invocationMethod = SelectionEvent.INVOCATION_MANUAL;
+ break;
+ case TextClassifierEvent.CATEGORY_LINKIFY:
+ invocationMethod = SelectionEvent.INVOCATION_LINK;
+ break;
+ default:
+ // Cannot be converted to a SelectionEvent.
+ return null;
+ }
+
+ final String entityType = getEntityTypes().length > 0
+ ? getEntityTypes()[0] : TextClassifier.TYPE_UNKNOWN;
+ final SelectionEvent out = new SelectionEvent(
+ /* absoluteStart= */ 0,
+ /* absoluteEnd= */ 0,
+ /* eventType= */0,
+ entityType,
+ SelectionEvent.INVOCATION_UNKNOWN,
+ SelectionEvent.NO_SIGNATURE);
+ out.setInvocationMethod(invocationMethod);
+
+ final TextClassificationContext eventContext = getEventContext();
+ if (eventContext != null) {
+ out.setTextClassificationSessionContext(getEventContext());
+ }
+ out.setSessionId(mHiddenTempSessionId);
+ final String resultId = getResultId();
+ out.setResultId(resultId == null ? SelectionEvent.NO_SIGNATURE : resultId);
+ out.setEventIndex(getEventIndex());
+
+
+ final int eventType;
+ switch (getEventType()) {
+ case TextClassifierEvent.TYPE_SELECTION_STARTED:
+ eventType = SelectionEvent.EVENT_SELECTION_STARTED;
+ break;
+ case TextClassifierEvent.TYPE_SELECTION_MODIFIED:
+ eventType = SelectionEvent.EVENT_SELECTION_MODIFIED;
+ break;
+ case TextClassifierEvent.TYPE_SMART_SELECTION_SINGLE:
+ eventType = SelectionEvent.EVENT_SMART_SELECTION_SINGLE;
+ break;
+ case TextClassifierEvent.TYPE_SMART_SELECTION_MULTI:
+ eventType = SelectionEvent.EVENT_SMART_SELECTION_MULTI;
+ break;
+ case TextClassifierEvent.TYPE_AUTO_SELECTION:
+ eventType = SelectionEvent.EVENT_AUTO_SELECTION;
+ break;
+ case TextClassifierEvent.TYPE_OVERTYPE:
+ eventType = SelectionEvent.ACTION_OVERTYPE;
+ break;
+ case TextClassifierEvent.TYPE_COPY_ACTION:
+ eventType = SelectionEvent.ACTION_COPY;
+ break;
+ case TextClassifierEvent.TYPE_PASTE_ACTION:
+ eventType = SelectionEvent.ACTION_PASTE;
+ break;
+ case TextClassifierEvent.TYPE_CUT_ACTION:
+ eventType = SelectionEvent.ACTION_CUT;
+ break;
+ case TextClassifierEvent.TYPE_SHARE_ACTION:
+ eventType = SelectionEvent.ACTION_SHARE;
+ break;
+ case TextClassifierEvent.TYPE_SMART_ACTION:
+ eventType = SelectionEvent.ACTION_SMART_SHARE;
+ break;
+ case TextClassifierEvent.TYPE_SELECTION_DRAG:
+ eventType = SelectionEvent.ACTION_DRAG;
+ break;
+ case TextClassifierEvent.TYPE_SELECTION_DESTROYED:
+ eventType = SelectionEvent.ACTION_ABANDON;
+ break;
+ case TextClassifierEvent.TYPE_OTHER_ACTION:
+ eventType = SelectionEvent.ACTION_OTHER;
+ break;
+ case TextClassifierEvent.TYPE_SELECT_ALL:
+ eventType = SelectionEvent.ACTION_SELECT_ALL;
+ break;
+ case TextClassifierEvent.TYPE_SELECTION_RESET:
+ eventType = SelectionEvent.ACTION_RESET;
+ break;
+ default:
+ eventType = 0;
+ break;
+ }
+ out.setEventType(eventType);
+
+ if (this instanceof TextClassifierEvent.TextSelectionEvent) {
+ final TextClassifierEvent.TextSelectionEvent selEvent =
+ (TextClassifierEvent.TextSelectionEvent) this;
+ // TODO: Ideally, we should have these fields in events of type
+ // TextClassifierEvent.TextLinkifyEvent events too but we're now past the API deadline
+ // and will have to do with these fields being set only in TextSelectionEvent events.
+ // Fix this at the next API bump.
+ out.setStart(selEvent.getRelativeWordStartIndex());
+ out.setEnd(selEvent.getRelativeWordEndIndex());
+ out.setSmartStart(selEvent.getRelativeSuggestedWordStartIndex());
+ out.setSmartEnd(selEvent.getRelativeSuggestedWordEndIndex());
+ }
+
+ return out;
+ }
+
+ /**
* Builder to build a text classifier event.
*
* @param <T> The subclass to be built.
diff --git a/core/java/android/view/textclassifier/TextClassifierImpl.java b/core/java/android/view/textclassifier/TextClassifierImpl.java
index 3e95f1b..024c379 100644
--- a/core/java/android/view/textclassifier/TextClassifierImpl.java
+++ b/core/java/android/view/textclassifier/TextClassifierImpl.java
@@ -376,7 +376,6 @@
/** @inheritDoc */
@Override
public void onSelectionEvent(SelectionEvent event) {
- Preconditions.checkNotNull(event);
mSessionLogger.writeEvent(event);
}
@@ -386,7 +385,12 @@
Log.d(DEFAULT_LOG_TAG, "onTextClassifierEvent() called with: event = [" + event + "]");
}
try {
- mTextClassifierEventTronLogger.writeEvent(event);
+ final SelectionEvent selEvent = event.toSelectionEvent();
+ if (selEvent != null) {
+ mSessionLogger.writeEvent(selEvent);
+ } else {
+ mTextClassifierEventTronLogger.writeEvent(event);
+ }
} catch (Exception e) {
Log.e(LOG_TAG, "Error writing event", e);
}
diff --git a/core/jni/android_graphics_Canvas.cpp b/core/jni/android_graphics_Canvas.cpp
index 7a8c5c8..ebc6cd7 100644
--- a/core/jni/android_graphics_Canvas.cpp
+++ b/core/jni/android_graphics_Canvas.cpp
@@ -106,6 +106,11 @@
return reinterpret_cast<jint>(get_canvas(canvasHandle)->saveUnclippedLayer(l, t, r, b));
}
+static void restoreUnclippedLayer(jlong canvasHandle, jint saveCount, jlong paintHandle) {
+ Paint* paint = reinterpret_cast<Paint*>(paintHandle);
+ get_canvas(canvasHandle)->restoreUnclippedLayer(saveCount, *paint);
+}
+
static bool restore(jlong canvasHandle) {
Canvas* canvas = get_canvas(canvasHandle);
if (canvas->getSaveCount() <= 1) {
@@ -668,6 +673,7 @@
{"nSaveLayer","(JFFFFJI)I", (void*) CanvasJNI::saveLayer},
{"nSaveLayerAlpha","(JFFFFII)I", (void*) CanvasJNI::saveLayerAlpha},
{"nSaveUnclippedLayer","(JIIII)I", (void*) CanvasJNI::saveUnclippedLayer},
+ {"nRestoreUnclippedLayer","(JIJ)V", (void*) CanvasJNI::restoreUnclippedLayer},
{"nGetSaveCount","(J)I", (void*) CanvasJNI::getSaveCount},
{"nRestore","(J)Z", (void*) CanvasJNI::restore},
{"nRestoreToCount","(JI)V", (void*) CanvasJNI::restoreToCount},
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 0daebd7..2de5397 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -3457,7 +3457,7 @@
<!-- Flag indicating whether the assist disclosure can be disabled using
ASSIST_DISCLOSURE_ENABLED. -->
- <bool name="config_allowDisablingAssistDisclosure">false</bool>
+ <bool name="config_allowDisablingAssistDisclosure">true</bool>
<!-- True if the device supports system navigation keys. -->
<bool name="config_supportSystemNavigationKeys">false</bool>
diff --git a/core/res/res/values/locale_config.xml b/core/res/res/values/locale_config.xml
index d6c0a10..3c65caf 100644
--- a/core/res/res/values/locale_config.xml
+++ b/core/res/res/values/locale_config.xml
@@ -78,6 +78,7 @@
<item>ar-YE</item> <!-- Arabic (Yemen) -->
<item>ar-YE-u-nu-latn</item> <!-- Arabic (Yemen, Western Digits) -->
<item>as-IN</item> <!-- Assamese (India) -->
+ <item>as-IN-u-nu-latn</item> <!-- Assamese (India, Western Digits) -->
<item>asa-TZ</item> <!-- Asu (Tanzania) -->
<item>ast-ES</item> <!-- Asturian (Spain) -->
<item>az-Cyrl-AZ</item> <!-- Azerbaijani (Cyrillic, Azerbaijan) -->
diff --git a/core/tests/coretests/src/android/view/textclassifier/TextClassifierEventTest.java b/core/tests/coretests/src/android/view/textclassifier/TextClassifierEventTest.java
new file mode 100644
index 0000000..11eb567
--- /dev/null
+++ b/core/tests/coretests/src/android/view/textclassifier/TextClassifierEventTest.java
@@ -0,0 +1,294 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.view.textclassifier;
+
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import android.annotation.Nullable;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public final class TextClassifierEventTest {
+
+ private static final TextClassificationContext TC_CONTEXT =
+ new TextClassificationContext.Builder("pkg", TextClassifier.WIDGET_TYPE_TEXTVIEW)
+ .build();
+
+ private static final TextSelection TEXT_SELECTION = new TextSelection.Builder(10, 20)
+ .setEntityType(TextClassifier.TYPE_ADDRESS, 1)
+ .setId("id1")
+ .build();
+
+ private static final TextClassification TEXT_CLASSIFICATION = new TextClassification.Builder()
+ .setEntityType(TextClassifier.TYPE_DATE, 1)
+ .setId("id2")
+ .build();
+
+ @Test
+ public void toSelectionEvent_selectionStarted() {
+ final TextClassificationSessionId sessionId = new TextClassificationSessionId();
+ final SelectionEvent expected = SelectionEvent.createSelectionStartedEvent(
+ SelectionEvent.INVOCATION_MANUAL, 0);
+ expected.setTextClassificationSessionContext(TC_CONTEXT);
+ expected.setSessionId(sessionId);
+
+ final TextClassifierEvent event = new TextClassifierEvent.TextSelectionEvent.Builder(
+ TextClassifierEvent.TYPE_SELECTION_STARTED)
+ .setEventContext(TC_CONTEXT)
+ .build();
+ event.mHiddenTempSessionId = sessionId;
+
+ assertEquals(expected, event.toSelectionEvent());
+ }
+
+ @Test
+ public void toSelectionEvent_smartSelectionMulti() {
+ final int start = -1;
+ final int end = 2;
+ final int eventIndex = 1;
+ final SelectionEvent expected = SelectionEvent.createSelectionModifiedEvent(
+ 0, 3, TEXT_SELECTION);
+ expected.setInvocationMethod(SelectionEvent.INVOCATION_MANUAL);
+ expected.setEventType(SelectionEvent.EVENT_SMART_SELECTION_MULTI);
+ expected.setStart(start);
+ expected.setEnd(end);
+ expected.setEventIndex(eventIndex);
+ expected.setTextClassificationSessionContext(TC_CONTEXT);
+
+ final String entityType = TEXT_SELECTION.getEntity(0);
+ final TextClassifierEvent event = new TextClassifierEvent.TextSelectionEvent.Builder(
+ TextClassifierEvent.TYPE_SMART_SELECTION_MULTI)
+ .setEventContext(TC_CONTEXT)
+ .setResultId(TEXT_SELECTION.getId())
+ .setRelativeWordStartIndex(start)
+ .setRelativeWordEndIndex(end)
+ .setEntityTypes(entityType)
+ .setScores(TEXT_SELECTION.getConfidenceScore(entityType))
+ .setEventIndex(eventIndex)
+ .build();
+
+ assertEquals(expected, event.toSelectionEvent());
+ }
+
+ @Test
+ public void toSelectionEvent_smartSelectionSingle() {
+ final int start = 0;
+ final int end = 1;
+ final int eventIndex = 2;
+ final SelectionEvent expected = SelectionEvent.createSelectionModifiedEvent(
+ 0, 1, TEXT_SELECTION);
+ expected.setInvocationMethod(SelectionEvent.INVOCATION_MANUAL);
+ expected.setEventType(SelectionEvent.EVENT_SMART_SELECTION_SINGLE);
+ expected.setStart(start);
+ expected.setEnd(end);
+ expected.setEventIndex(eventIndex);
+ expected.setTextClassificationSessionContext(TC_CONTEXT);
+
+ final String entityType = TEXT_SELECTION.getEntity(0);
+ final TextClassifierEvent event = new TextClassifierEvent.TextSelectionEvent.Builder(
+ TextClassifierEvent.TYPE_SMART_SELECTION_SINGLE)
+ .setEventContext(TC_CONTEXT)
+ .setResultId(TEXT_SELECTION.getId())
+ .setRelativeWordStartIndex(start)
+ .setRelativeWordEndIndex(end)
+ .setEntityTypes(entityType)
+ .setScores(TEXT_SELECTION.getConfidenceScore(entityType))
+ .setEventIndex(eventIndex)
+ .build();
+
+ assertEquals(expected, event.toSelectionEvent());
+ }
+
+ @Test
+ public void toSelectionEvent_resetSelection() {
+ final int start = 0;
+ final int end = 1;
+ final int smartStart = -1;
+ final int smartEnd = 2;
+ final int eventIndex = 3;
+ final SelectionEvent expected = SelectionEvent.createSelectionActionEvent(
+ 0, 1, SelectionEvent.ACTION_RESET, TEXT_CLASSIFICATION);
+ expected.setInvocationMethod(SelectionEvent.INVOCATION_MANUAL);
+ expected.setStart(start);
+ expected.setEnd(end);
+ expected.setSmartStart(smartStart);
+ expected.setSmartEnd(smartEnd);
+ expected.setEventIndex(eventIndex);
+ expected.setTextClassificationSessionContext(TC_CONTEXT);
+
+ final String entityType = TEXT_CLASSIFICATION.getEntity(0);
+ final TextClassifierEvent event = new TextClassifierEvent.TextSelectionEvent.Builder(
+ TextClassifierEvent.TYPE_SELECTION_RESET)
+ .setEventContext(TC_CONTEXT)
+ .setResultId(TEXT_CLASSIFICATION.getId())
+ .setRelativeSuggestedWordStartIndex(smartStart)
+ .setRelativeSuggestedWordEndIndex(smartEnd)
+ .setRelativeWordStartIndex(start)
+ .setRelativeWordEndIndex(end)
+ .setEntityTypes(TEXT_CLASSIFICATION.getEntity(0))
+ .setScores(TEXT_CLASSIFICATION.getConfidenceScore(entityType))
+ .setEventIndex(eventIndex)
+ .build();
+
+ assertEquals(expected, event.toSelectionEvent());
+ }
+
+ @Test
+ public void toSelectionEvent_modifySelection() {
+ final int start = -1;
+ final int end = 5;
+ final int eventIndex = 4;
+ final SelectionEvent expected = SelectionEvent.createSelectionModifiedEvent(0, 1);
+ expected.setInvocationMethod(SelectionEvent.INVOCATION_MANUAL);
+ expected.setStart(start);
+ expected.setEnd(end);
+ expected.setEventIndex(eventIndex);
+ expected.setTextClassificationSessionContext(TC_CONTEXT);
+
+ final TextClassifierEvent event = new TextClassifierEvent.TextSelectionEvent.Builder(
+ TextClassifierEvent.TYPE_SELECTION_MODIFIED)
+ .setEventContext(TC_CONTEXT)
+ .setRelativeWordStartIndex(start)
+ .setRelativeWordEndIndex(end)
+ .setEventIndex(eventIndex)
+ .build();
+
+ assertEquals(expected, event.toSelectionEvent());
+ }
+
+ @Test
+ public void toSelectionEvent_copyAction() {
+ final int start = 3;
+ final int end = 4;
+ final int eventIndex = 5;
+ final SelectionEvent expected = SelectionEvent.createSelectionActionEvent(
+ 5, 6, SelectionEvent.ACTION_COPY);
+ expected.setInvocationMethod(SelectionEvent.INVOCATION_MANUAL);
+ expected.setStart(start);
+ expected.setEnd(end);
+ expected.setEventIndex(eventIndex);
+ expected.setTextClassificationSessionContext(TC_CONTEXT);
+
+ final TextClassifierEvent event = new TextClassifierEvent.TextSelectionEvent.Builder(
+ TextClassifierEvent.TYPE_COPY_ACTION)
+ .setEventContext(TC_CONTEXT)
+ .setRelativeWordStartIndex(start)
+ .setRelativeWordEndIndex(end)
+ .setEventIndex(eventIndex)
+ .build();
+
+ assertEquals(expected, event.toSelectionEvent());
+ }
+
+ @Test
+ public void toSelectionEvent_selectionDismissed() {
+ final int eventIndex = 6;
+ final SelectionEvent expected = SelectionEvent.createSelectionActionEvent(
+ 0, 1, SelectionEvent.ACTION_ABANDON);
+ expected.setInvocationMethod(SelectionEvent.INVOCATION_MANUAL);
+ expected.setEventIndex(eventIndex);
+
+ final TextClassifierEvent event = new TextClassifierEvent.TextSelectionEvent.Builder(
+ TextClassifierEvent.TYPE_SELECTION_DESTROYED)
+ .setEventIndex(eventIndex)
+ .build();
+
+ assertEquals(expected, event.toSelectionEvent());
+ }
+
+ @Test
+ public void toSelectionEvent_link_smartAction() {
+ final int eventIndex = 2;
+ final SelectionEvent expected = SelectionEvent.createSelectionActionEvent(
+ 1, 9, SelectionEvent.ACTION_SMART_SHARE, TEXT_CLASSIFICATION);
+ expected.setInvocationMethod(SelectionEvent.INVOCATION_LINK);
+ // TODO: TextLinkifyEvent API is missing APIs to set text indices. See related comment in
+ // TextClassifierEvent.
+ expected.setEventIndex(eventIndex);
+ expected.setTextClassificationSessionContext(TC_CONTEXT);
+
+ final String entityType = TEXT_CLASSIFICATION.getEntity(0);
+ final TextClassifierEvent event = new TextClassifierEvent.TextLinkifyEvent.Builder(
+ TextClassifierEvent.TYPE_SMART_ACTION)
+ .setEventContext(TC_CONTEXT)
+ .setResultId(TEXT_CLASSIFICATION.getId())
+ .setEntityTypes(entityType)
+ .setScores(TEXT_CLASSIFICATION.getConfidenceScore(entityType))
+ .setActionIndices(0)
+ .setEventIndex(eventIndex)
+ .build();
+
+ assertEquals(expected, event.toSelectionEvent());
+ }
+
+ @Test
+ public void toSelectionEvent_nonSelectionOrLinkifyEvent() {
+ final TextClassifierEvent convActionEvent =
+ new TextClassifierEvent.ConversationActionsEvent.Builder(
+ TextClassifierEvent.TYPE_ACTIONS_GENERATED)
+ .build();
+ assertWithMessage("conversation action event")
+ .that(convActionEvent.toSelectionEvent()).isNull();
+
+ final TextClassifierEvent langDetEvent =
+ new TextClassifierEvent.ConversationActionsEvent.Builder(
+ TextClassifierEvent.TYPE_ACTIONS_GENERATED)
+ .setEventContext(TC_CONTEXT)
+ .build();
+ assertWithMessage("language detection event")
+ .that(langDetEvent.toSelectionEvent()).isNull();
+ }
+
+ private static void assertEquals(
+ @Nullable SelectionEvent expected, @Nullable SelectionEvent actual) {
+ if (expected == null && actual == null) return;
+ if (expected == actual) return;
+ assertWithMessage("actual").that(actual).isNotNull();
+ assertWithMessage("expected").that(expected).isNotNull();
+ assertWithMessage("eventType")
+ .that(actual.getEventType()).isEqualTo(expected.getEventType());
+ assertWithMessage("packageName")
+ .that(actual.getPackageName()).isEqualTo(expected.getPackageName());
+ assertWithMessage("widgetType")
+ .that(actual.getWidgetType()).isEqualTo(expected.getWidgetType());
+ assertWithMessage("widgetVersion")
+ .that(actual.getWidgetVersion()).isEqualTo(expected.getWidgetVersion());
+ assertWithMessage("invocationMethod")
+ .that(actual.getInvocationMethod()).isEqualTo(expected.getInvocationMethod());
+ assertWithMessage("resultId")
+ .that(actual.getResultId()).isEqualTo(expected.getResultId());
+ assertWithMessage("sessionId")
+ .that(actual.getSessionId()).isEqualTo(expected.getSessionId());
+ assertWithMessage("entityType")
+ .that(actual.getEntityType()).isEqualTo(expected.getEntityType());
+ assertWithMessage("eventIndex")
+ .that(actual.getEventIndex()).isEqualTo(expected.getEventIndex());
+ assertWithMessage("start")
+ .that(actual.getStart()).isEqualTo(expected.getStart());
+ assertWithMessage("end")
+ .that(actual.getEnd()).isEqualTo(expected.getEnd());
+ assertWithMessage("smartStart")
+ .that(actual.getSmartStart()).isEqualTo(expected.getSmartStart());
+ assertWithMessage("smartEnd")
+ .that(actual.getSmartEnd()).isEqualTo(expected.getSmartEnd());
+ }
+}
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index d4d5ae7..5648b85 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -559,6 +559,16 @@
}
/**
+ * @hide
+ * @param saveCount The save level to restore to.
+ * @param paint This is copied and is applied to the area within the unclipped layer's
+ * bounds (i.e. equivalent to a drawPaint()) before restore() is called.
+ */
+ public void restoreUnclippedLayer(int saveCount, Paint paint) {
+ nRestoreUnclippedLayer(mNativeCanvasWrapper, saveCount, paint.getNativeInstance());
+ }
+
+ /**
* Helper version of saveLayer() that takes 4 values rather than a RectF.
*
* As of API Level API level {@value Build.VERSION_CODES#P} the only valid
@@ -1398,6 +1408,9 @@
@CriticalNative
private static native int nSaveUnclippedLayer(long nativeCanvas, int l, int t, int r, int b);
@CriticalNative
+ private static native void nRestoreUnclippedLayer(long nativeCanvas, int saveCount,
+ long nativePaint);
+ @CriticalNative
private static native boolean nRestore(long canvasHandle);
@CriticalNative
private static native void nRestoreToCount(long canvasHandle, int saveCount);
diff --git a/libs/hwui/DisplayListOps.in b/libs/hwui/DisplayListOps.in
index 14e3a32..2deb565 100644
--- a/libs/hwui/DisplayListOps.in
+++ b/libs/hwui/DisplayListOps.in
@@ -26,7 +26,8 @@
X(ClipRect)
X(ClipRRect)
X(ClipRegion)
-X(DrawPaint)
+X(DrawPaint)
+X(DrawBehind)
X(DrawPath)
X(DrawRect)
X(DrawRegion)
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
index 8594766..e58fbbe 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -20,6 +20,7 @@
#include "SkAndroidFrameworkUtils.h"
#include "SkCanvas.h"
+#include "SkCanvasPriv.h"
#include "SkData.h"
#include "SkDrawShadowInfo.h"
#include "SkImage.h"
@@ -187,6 +188,12 @@
SkPaint paint;
void draw(SkCanvas* c, const SkMatrix&) const { c->drawPaint(paint); }
};
+struct DrawBehind final : Op {
+ static const auto kType = Type::DrawBehind;
+ DrawBehind(const SkPaint& paint) : paint(paint) {}
+ SkPaint paint;
+ void draw(SkCanvas* c, const SkMatrix&) const { SkCanvasPriv::DrawBehind(c, paint); }
+};
struct DrawPath final : Op {
static const auto kType = Type::DrawPath;
DrawPath(const SkPath& path, const SkPaint& paint) : path(path), paint(paint) {}
@@ -565,6 +572,9 @@
void DisplayListData::drawPaint(const SkPaint& paint) {
this->push<DrawPaint>(0, paint);
}
+void DisplayListData::drawBehind(const SkPaint& paint) {
+ this->push<DrawBehind>(0, paint);
+}
void DisplayListData::drawPath(const SkPath& path, const SkPaint& paint) {
this->push<DrawPath>(0, path, paint);
}
@@ -834,6 +844,9 @@
void RecordingCanvas::onDrawPaint(const SkPaint& paint) {
fDL->drawPaint(paint);
}
+void RecordingCanvas::onDrawBehind(const SkPaint& paint) {
+ fDL->drawBehind(paint);
+}
void RecordingCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
fDL->drawPath(path, paint);
}
diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h
index 3a76ca1..7269bca 100644
--- a/libs/hwui/RecordingCanvas.h
+++ b/libs/hwui/RecordingCanvas.h
@@ -89,6 +89,7 @@
void clipRegion(const SkRegion&, SkClipOp);
void drawPaint(const SkPaint&);
+ void drawBehind(const SkPaint&);
void drawPath(const SkPath&, const SkPaint&);
void drawRect(const SkRect&, const SkPaint&);
void drawRegion(const SkRegion&, const SkPaint&);
@@ -157,6 +158,7 @@
void onClipRegion(const SkRegion&, SkClipOp) override;
void onDrawPaint(const SkPaint&) override;
+ void onDrawBehind(const SkPaint&) override;
void onDrawPath(const SkPath&, const SkPaint&) override;
void onDrawRect(const SkRect&, const SkPaint&) override;
void onDrawRegion(const SkRegion&, const SkPaint&) override;
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index f328a53..bebda852 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -26,6 +26,7 @@
#include <SkAndroidFrameworkUtils.h>
#include <SkAnimatedImage.h>
+#include <SkCanvasPriv.h>
#include <SkCanvasStateUtils.h>
#include <SkColorFilter.h>
#include <SkDeque.h>
@@ -191,6 +192,18 @@
return SkAndroidFrameworkUtils::SaveBehind(mCanvas, &bounds);
}
+void SkiaCanvas::restoreUnclippedLayer(int restoreCount, const SkPaint& paint) {
+
+ while (mCanvas->getSaveCount() > restoreCount + 1) {
+ this->restore();
+ }
+
+ if (mCanvas->getSaveCount() == restoreCount + 1) {
+ SkCanvasPriv::DrawBehind(mCanvas, *filterPaint(paint));
+ this->restore();
+ }
+}
+
class SkiaCanvas::Clip {
public:
Clip(const SkRect& rect, SkClipOp op, const SkMatrix& m)
diff --git a/libs/hwui/SkiaCanvas.h b/libs/hwui/SkiaCanvas.h
index 3fe2bce..bbe91eb 100644
--- a/libs/hwui/SkiaCanvas.h
+++ b/libs/hwui/SkiaCanvas.h
@@ -69,6 +69,7 @@
virtual int save(SaveFlags::Flags flags) override;
virtual void restore() override;
virtual void restoreToCount(int saveCount) override;
+ virtual void restoreUnclippedLayer(int saveCount, const SkPaint& paint) override;
virtual int saveLayer(float left, float top, float right, float bottom, const SkPaint* paint,
SaveFlags::Flags flags) override;
diff --git a/libs/hwui/hwui/Canvas.h b/libs/hwui/hwui/Canvas.h
index 11e8579..ac8db21 100644
--- a/libs/hwui/hwui/Canvas.h
+++ b/libs/hwui/hwui/Canvas.h
@@ -191,6 +191,7 @@
virtual int save(SaveFlags::Flags flags) = 0;
virtual void restore() = 0;
virtual void restoreToCount(int saveCount) = 0;
+ virtual void restoreUnclippedLayer(int saveCount, const SkPaint& paint) = 0;
virtual int saveLayer(float left, float top, float right, float bottom, const SkPaint* paint,
SaveFlags::Flags flags) = 0;
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
index ccc1701..1f9ab5a 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
@@ -176,7 +176,7 @@
// position
Matrix4 windowTransform;
damageAccumulator.computeCurrentTransform(&windowTransform);
- node->getSkiaLayer()->inverseTransformInWindow = windowTransform;
+ node->getSkiaLayer()->inverseTransformInWindow.loadInverse(windowTransform);
} else {
String8 cachesOutput;
mRenderThread.cacheManager().dumpMemoryUsage(cachesOutput,
diff --git a/packages/CtsShim/apk/arm/CtsShim.apk b/packages/CtsShim/apk/arm/CtsShim.apk
index a911603..7d9f8e3 100644
--- a/packages/CtsShim/apk/arm/CtsShim.apk
+++ b/packages/CtsShim/apk/arm/CtsShim.apk
Binary files differ
diff --git a/packages/CtsShim/apk/arm/CtsShimPriv.apk b/packages/CtsShim/apk/arm/CtsShimPriv.apk
index 845d781..dcccada 100644
--- a/packages/CtsShim/apk/arm/CtsShimPriv.apk
+++ b/packages/CtsShim/apk/arm/CtsShimPriv.apk
Binary files differ
diff --git a/packages/CtsShim/apk/x86/CtsShim.apk b/packages/CtsShim/apk/x86/CtsShim.apk
index a911603..7d9f8e3 100644
--- a/packages/CtsShim/apk/x86/CtsShim.apk
+++ b/packages/CtsShim/apk/x86/CtsShim.apk
Binary files differ
diff --git a/packages/CtsShim/apk/x86/CtsShimPriv.apk b/packages/CtsShim/apk/x86/CtsShimPriv.apk
index 2fc9a94..3501fa4 100644
--- a/packages/CtsShim/apk/x86/CtsShimPriv.apk
+++ b/packages/CtsShim/apk/x86/CtsShimPriv.apk
Binary files differ
diff --git a/packages/NetworkStack/Android.bp b/packages/NetworkStack/Android.bp
index aefa882..c013b8c 100644
--- a/packages/NetworkStack/Android.bp
+++ b/packages/NetworkStack/Android.bp
@@ -42,8 +42,8 @@
static_libs: [
"androidx.annotation_annotation",
"ipmemorystore-client",
- "netd_aidl_interface-java",
- "networkstack-aidl-interfaces-java",
+ "netd_aidl_interface-V2-java",
+ "networkstack-aidl-interfaces-V3-java",
"datastallprotosnano",
"networkstackprotosnano",
"captiveportal-lib",
diff --git a/packages/NetworkStack/src/com/android/server/NetworkStackService.java b/packages/NetworkStack/src/com/android/server/NetworkStackService.java
index c394d4c..2fae0c7 100644
--- a/packages/NetworkStack/src/com/android/server/NetworkStackService.java
+++ b/packages/NetworkStack/src/com/android/server/NetworkStackService.java
@@ -49,6 +49,7 @@
import android.net.util.SharedLog;
import android.os.IBinder;
import android.os.RemoteException;
+import android.util.ArraySet;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.IndentingPrintWriter;
@@ -62,7 +63,6 @@
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
-import java.util.concurrent.atomic.AtomicInteger;
/**
* Android service used to start the network stack when bound to via an intent.
@@ -118,14 +118,12 @@
@GuardedBy("mValidationLogs")
private final ArrayDeque<SharedLog> mValidationLogs = new ArrayDeque<>(MAX_VALIDATION_LOGS);
- private static final int VERSION_UNKNOWN = 0;
private static final String DUMPSYS_ARG_VERSION = "version";
- /** Version of the AIDL interfaces observed on the system */
- private final AtomicInteger mSystemAidlVersion = new AtomicInteger(VERSION_UNKNOWN);
-
- /** Whether different versions have been observed on interfaces provided by the system */
- private volatile boolean mConflictingSystemAidlVersions = false;
+ /** Version of the framework AIDL interfaces observed. Should hold only one value. */
+ @GuardedBy("mFrameworkAidlVersions")
+ private final ArraySet<Integer> mFrameworkAidlVersions = new ArraySet<>(1);
+ private final int mNetdAidlVersion;
private SharedLog addValidationLogs(Network network, String name) {
final SharedLog log = new SharedLog(NUM_VALIDATION_LOG_LINES, network + " - " + name);
@@ -146,6 +144,15 @@
mCm = context.getSystemService(ConnectivityManager.class);
mIpMemoryStoreService = new IpMemoryStoreService(context);
+ int netdVersion;
+ try {
+ netdVersion = mNetd.getInterfaceVersion();
+ } catch (RemoteException e) {
+ mLog.e("Error obtaining INetd version", e);
+ netdVersion = -1;
+ }
+ mNetdAidlVersion = netdVersion;
+
try {
mObserverRegistry.register(mNetd);
} catch (RemoteException e) {
@@ -154,9 +161,8 @@
}
private void updateSystemAidlVersion(final int version) {
- final int previousVersion = mSystemAidlVersion.getAndSet(version);
- if (previousVersion != VERSION_UNKNOWN && previousVersion != version) {
- mConflictingSystemAidlVersions = true;
+ synchronized (mFrameworkAidlVersions) {
+ mFrameworkAidlVersions.add(version);
}
}
@@ -230,12 +236,16 @@
protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter fout,
@Nullable String[] args) {
checkDumpPermission();
+
+ final IndentingPrintWriter pw = new IndentingPrintWriter(fout, " ");
+ pw.println("NetworkStack version:");
+ dumpVersion(pw);
+ pw.println();
+
if (args != null && args.length >= 1 && DUMPSYS_ARG_VERSION.equals(args[0])) {
- dumpVersion(fout);
return;
}
- final IndentingPrintWriter pw = new IndentingPrintWriter(fout, " ");
pw.println("NetworkStack logs:");
mLog.dump(fd, pw, args);
@@ -283,8 +293,10 @@
*/
private void dumpVersion(@NonNull PrintWriter fout) {
fout.println("NetworkStackConnector: " + this.VERSION);
- fout.println("SystemServer: " + mSystemAidlVersion);
- fout.println("SystemServerConflicts: " + mConflictingSystemAidlVersions);
+ synchronized (mFrameworkAidlVersions) {
+ fout.println("SystemServer: " + mFrameworkAidlVersions);
+ }
+ fout.println("Netd: " + mNetdAidlVersion);
}
@Override
diff --git a/packages/NetworkStack/tests/Android.bp b/packages/NetworkStack/tests/unit/Android.bp
similarity index 96%
rename from packages/NetworkStack/tests/Android.bp
rename to packages/NetworkStack/tests/unit/Android.bp
index 039f6bf..6cc80543 100644
--- a/packages/NetworkStack/tests/Android.bp
+++ b/packages/NetworkStack/tests/unit/Android.bp
@@ -72,7 +72,7 @@
"libutilscallstack",
"libziparchive",
"libz",
- "netd_aidl_interface-cpp",
+ "netd_aidl_interface-V2-cpp",
],
}
@@ -94,7 +94,7 @@
"liblog",
"libcutils",
"libnativehelper",
- "netd_aidl_interface-cpp",
+ "netd_aidl_interface-V2-cpp",
],
static_libs: [
"libapf",
diff --git a/packages/NetworkStack/tests/AndroidManifest.xml b/packages/NetworkStack/tests/unit/AndroidManifest.xml
similarity index 100%
rename from packages/NetworkStack/tests/AndroidManifest.xml
rename to packages/NetworkStack/tests/unit/AndroidManifest.xml
diff --git a/packages/NetworkStack/tests/AndroidTest.xml b/packages/NetworkStack/tests/unit/AndroidTest.xml
similarity index 100%
rename from packages/NetworkStack/tests/AndroidTest.xml
rename to packages/NetworkStack/tests/unit/AndroidTest.xml
diff --git a/packages/NetworkStack/tests/jni/apf_jni.cpp b/packages/NetworkStack/tests/unit/jni/apf_jni.cpp
similarity index 100%
rename from packages/NetworkStack/tests/jni/apf_jni.cpp
rename to packages/NetworkStack/tests/unit/jni/apf_jni.cpp
diff --git a/packages/NetworkStack/tests/res/raw/apf.pcap b/packages/NetworkStack/tests/unit/res/raw/apf.pcap
similarity index 100%
rename from packages/NetworkStack/tests/res/raw/apf.pcap
rename to packages/NetworkStack/tests/unit/res/raw/apf.pcap
Binary files differ
diff --git a/packages/NetworkStack/tests/res/raw/apfPcap.pcap b/packages/NetworkStack/tests/unit/res/raw/apfPcap.pcap
similarity index 100%
rename from packages/NetworkStack/tests/res/raw/apfPcap.pcap
rename to packages/NetworkStack/tests/unit/res/raw/apfPcap.pcap
Binary files differ
diff --git a/packages/NetworkStack/tests/src/android/net/apf/ApfTest.java b/packages/NetworkStack/tests/unit/src/android/net/apf/ApfTest.java
similarity index 100%
rename from packages/NetworkStack/tests/src/android/net/apf/ApfTest.java
rename to packages/NetworkStack/tests/unit/src/android/net/apf/ApfTest.java
diff --git a/packages/NetworkStack/tests/src/android/net/apf/Bpf2Apf.java b/packages/NetworkStack/tests/unit/src/android/net/apf/Bpf2Apf.java
similarity index 100%
rename from packages/NetworkStack/tests/src/android/net/apf/Bpf2Apf.java
rename to packages/NetworkStack/tests/unit/src/android/net/apf/Bpf2Apf.java
diff --git a/packages/NetworkStack/tests/src/android/net/captiveportal/CaptivePortalProbeSpecTest.java b/packages/NetworkStack/tests/unit/src/android/net/captiveportal/CaptivePortalProbeSpecTest.java
similarity index 100%
rename from packages/NetworkStack/tests/src/android/net/captiveportal/CaptivePortalProbeSpecTest.java
rename to packages/NetworkStack/tests/unit/src/android/net/captiveportal/CaptivePortalProbeSpecTest.java
diff --git a/packages/NetworkStack/tests/src/android/net/dhcp/DhcpLeaseRepositoryTest.java b/packages/NetworkStack/tests/unit/src/android/net/dhcp/DhcpLeaseRepositoryTest.java
similarity index 100%
rename from packages/NetworkStack/tests/src/android/net/dhcp/DhcpLeaseRepositoryTest.java
rename to packages/NetworkStack/tests/unit/src/android/net/dhcp/DhcpLeaseRepositoryTest.java
diff --git a/packages/NetworkStack/tests/src/android/net/dhcp/DhcpPacketTest.java b/packages/NetworkStack/tests/unit/src/android/net/dhcp/DhcpPacketTest.java
similarity index 100%
rename from packages/NetworkStack/tests/src/android/net/dhcp/DhcpPacketTest.java
rename to packages/NetworkStack/tests/unit/src/android/net/dhcp/DhcpPacketTest.java
diff --git a/packages/NetworkStack/tests/src/android/net/dhcp/DhcpServerTest.java b/packages/NetworkStack/tests/unit/src/android/net/dhcp/DhcpServerTest.java
similarity index 100%
rename from packages/NetworkStack/tests/src/android/net/dhcp/DhcpServerTest.java
rename to packages/NetworkStack/tests/unit/src/android/net/dhcp/DhcpServerTest.java
diff --git a/packages/NetworkStack/tests/src/android/net/dhcp/DhcpServingParamsTest.java b/packages/NetworkStack/tests/unit/src/android/net/dhcp/DhcpServingParamsTest.java
similarity index 100%
rename from packages/NetworkStack/tests/src/android/net/dhcp/DhcpServingParamsTest.java
rename to packages/NetworkStack/tests/unit/src/android/net/dhcp/DhcpServingParamsTest.java
diff --git a/packages/NetworkStack/tests/src/android/net/ip/IpClientTest.java b/packages/NetworkStack/tests/unit/src/android/net/ip/IpClientTest.java
similarity index 100%
rename from packages/NetworkStack/tests/src/android/net/ip/IpClientTest.java
rename to packages/NetworkStack/tests/unit/src/android/net/ip/IpClientTest.java
diff --git a/packages/NetworkStack/tests/src/android/net/ip/IpReachabilityMonitorTest.java b/packages/NetworkStack/tests/unit/src/android/net/ip/IpReachabilityMonitorTest.java
similarity index 100%
rename from packages/NetworkStack/tests/src/android/net/ip/IpReachabilityMonitorTest.java
rename to packages/NetworkStack/tests/unit/src/android/net/ip/IpReachabilityMonitorTest.java
diff --git a/packages/NetworkStack/tests/src/android/net/util/ConnectivityPacketSummaryTest.java b/packages/NetworkStack/tests/unit/src/android/net/util/ConnectivityPacketSummaryTest.java
similarity index 100%
rename from packages/NetworkStack/tests/src/android/net/util/ConnectivityPacketSummaryTest.java
rename to packages/NetworkStack/tests/unit/src/android/net/util/ConnectivityPacketSummaryTest.java
diff --git a/packages/NetworkStack/tests/src/android/net/util/PacketReaderTest.java b/packages/NetworkStack/tests/unit/src/android/net/util/PacketReaderTest.java
similarity index 100%
rename from packages/NetworkStack/tests/src/android/net/util/PacketReaderTest.java
rename to packages/NetworkStack/tests/unit/src/android/net/util/PacketReaderTest.java
diff --git a/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java b/packages/NetworkStack/tests/unit/src/com/android/server/connectivity/NetworkMonitorTest.java
similarity index 99%
rename from packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java
rename to packages/NetworkStack/tests/unit/src/com/android/server/connectivity/NetworkMonitorTest.java
index 2618675..832b712 100644
--- a/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java
+++ b/packages/NetworkStack/tests/unit/src/com/android/server/connectivity/NetworkMonitorTest.java
@@ -297,6 +297,7 @@
setOtherFallbackUrls(TEST_OTHER_FALLBACK_URL);
setFallbackSpecs(null); // Test with no fallback spec by default
when(mRandom.nextInt()).thenReturn(0);
+
// DNS probe timeout should not be defined more than half of HANDLER_TIMEOUT_MS. Otherwise,
// it will fail the test because of timeout expired for querying AAAA and A sequentially.
when(mResources.getInteger(eq(R.integer.config_captive_portal_dns_probe_timeout)))
diff --git a/packages/NetworkStack/tests/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreServiceTest.java b/packages/NetworkStack/tests/unit/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreServiceTest.java
similarity index 100%
rename from packages/NetworkStack/tests/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreServiceTest.java
rename to packages/NetworkStack/tests/unit/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreServiceTest.java
diff --git a/packages/NetworkStack/tests/src/com/android/server/connectivity/ipmemorystore/RelevanceUtilsTests.java b/packages/NetworkStack/tests/unit/src/com/android/server/connectivity/ipmemorystore/RelevanceUtilsTests.java
similarity index 100%
rename from packages/NetworkStack/tests/src/com/android/server/connectivity/ipmemorystore/RelevanceUtilsTests.java
rename to packages/NetworkStack/tests/unit/src/com/android/server/connectivity/ipmemorystore/RelevanceUtilsTests.java
diff --git a/packages/NetworkStack/tests/src/com/android/server/util/SharedLogTest.java b/packages/NetworkStack/tests/unit/src/com/android/server/util/SharedLogTest.java
similarity index 100%
rename from packages/NetworkStack/tests/src/com/android/server/util/SharedLogTest.java
rename to packages/NetworkStack/tests/unit/src/com/android/server/util/SharedLogTest.java
diff --git a/packages/SystemUI/res-keyguard/values/styles.xml b/packages/SystemUI/res-keyguard/values/styles.xml
index 1c8e141..17923cd 100644
--- a/packages/SystemUI/res-keyguard/values/styles.xml
+++ b/packages/SystemUI/res-keyguard/values/styles.xml
@@ -65,6 +65,8 @@
<item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
<item name="android:fontFeatureSettings">@*android:string/config_headlineFontFeatureSettings</item>
<item name="android:ellipsize">none</item>
+ <item name="android:shadowColor">@color/keyguard_shadow_color</item>
+ <item name="android:shadowRadius">@dimen/keyguard_shadow_radius</item>
</style>
<style name="widget_title_bold">
<item name="android:textStyle">bold</item>
@@ -72,6 +74,8 @@
<item name="android:paddingBottom">@dimen/widget_vertical_padding_clock</item>
<item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
<item name="android:ellipsize">none</item>
+ <item name="android:shadowColor">@color/keyguard_shadow_color</item>
+ <item name="android:shadowRadius">@dimen/keyguard_shadow_radius</item>
</style>
<style name="widget_small_bold">
<item name="android:textStyle">bold</item>
@@ -79,6 +83,8 @@
<item name="android:paddingBottom">@dimen/bottom_text_spacing_digital</item>
<item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
<item name="android:ellipsize">none</item>
+ <item name="android:shadowColor">@color/keyguard_shadow_color</item>
+ <item name="android:shadowRadius">@dimen/keyguard_shadow_radius</item>
</style>
<style name="BouncerSecurityContainer">
@@ -108,6 +114,8 @@
<item name="android:ellipsize">end</item>
<item name="android:maxLines">2</item>
<item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
+ <item name="android:shadowColor">@color/keyguard_shadow_color</item>
+ <item name="android:shadowRadius">@dimen/keyguard_shadow_radius</item>
</style>
<style name="TextAppearance.Keyguard.Secondary">
@@ -121,6 +129,8 @@
<item name="android:textSize">16sp</item>
<item name="android:maxLines">1</item>
<item name="android:textColor">?attr/wallpaperTextColor</item>
+ <item name="android:shadowColor">@color/keyguard_shadow_color</item>
+ <item name="android:shadowRadius">@dimen/keyguard_shadow_radius</item>
</style>
</resources>
diff --git a/packages/SystemUI/res/drawable/ic_arrow_back.xml b/packages/SystemUI/res/drawable/ic_arrow_back.xml
index 374f16b..d9c0434 100644
--- a/packages/SystemUI/res/drawable/ic_arrow_back.xml
+++ b/packages/SystemUI/res/drawable/ic_arrow_back.xml
@@ -14,6 +14,7 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:autoMirrored="true"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
diff --git a/packages/SystemUI/res/drawable/ic_brightness_thumb.xml b/packages/SystemUI/res/drawable/ic_brightness_thumb.xml
index 6f3da75..d721988 100644
--- a/packages/SystemUI/res/drawable/ic_brightness_thumb.xml
+++ b/packages/SystemUI/res/drawable/ic_brightness_thumb.xml
@@ -21,7 +21,7 @@
<path
android:pathData="M18,14.48V18h-3.52L12,20.48L9.52,18H6v-3.52L3.52,12L6,9.52V6h3.52L12,3.52L14.48,6H18v3.52L20.48,12L18,14.48z"
- android:fillColor="?android:attr/colorPrimary" />
+ android:fillColor="?android:attr/colorBackgroundFloating" />
<path
android:pathData=" M20,8.69 V4h-4.69L12,0.69L8.69,4H4v4.69L0.69,12L4,15.31V20h4.69L12,23.31L15.31,20H20v-4.69L23.31,12L20,8.69z M18,14.48V18h-3.52L12,20.48L9.52,18H6v-3.52L3.52,12L6,9.52V6h3.52L12,3.52L14.48,6H18v3.52L20.48,12L18,14.48z M12,7c-2.76,0 -5,2.24 -5,5s2.24,5 5,5s5,-2.24 5,-5S14.76,7 12,7z"
diff --git a/packages/SystemUI/res/layout/keyguard_bottom_area.xml b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
index 2792a01..7fc2066 100644
--- a/packages/SystemUI/res/layout/keyguard_bottom_area.xml
+++ b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
@@ -26,7 +26,6 @@
<LinearLayout
android:id="@+id/keyguard_indication_area"
- android:forceHasOverlappingRendering="false"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/keyguard_indication_margin_bottom"
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 490473ce..811f1a3 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -55,6 +55,9 @@
<color name="keyguard_affordance">#ffffffff</color>
+ <!-- Shadows under the clock, date and other keyguard text fields -->
+ <color name="keyguard_shadow_color">#B2000000</color>
+
<!-- The color of the legacy notification background -->
<color name="notification_legacy_background_color">#ff1a1a1a</color>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index fb226c7..ec538ff 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -181,6 +181,9 @@
<!-- The padding on the bottom of the notifications on the keyguard -->
<dimen name="keyguard_indication_bottom_padding">12sp</dimen>
+ <!-- Shadows under the clock, date and other keyguard text fields -->
+ <dimen name="keyguard_shadow_radius">5</dimen>
+
<!-- Minimum layouted height of a notification in the statusbar-->
<dimen name="min_notification_layout_height">48dp</dimen>
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
index 1dc3474..a7fe607 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
@@ -319,11 +319,6 @@
refreshFormat();
}
- @Override
- public boolean hasOverlappingRendering() {
- return false;
- }
-
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("KeyguardStatusView:");
pw.println(" mOwnerInfo: " + (mOwnerInfo == null
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
index 51bd9f8..f0c38fb 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
@@ -169,7 +169,7 @@
}
protected boolean shouldShowOrb() {
- return true;
+ return false;
}
public void startAssist(Bundle args) {
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index 7e016bb..04637ad 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -35,7 +35,6 @@
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.SOURCE;
-import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.ActivityTaskManager;
@@ -61,6 +60,7 @@
import androidx.annotation.IntDef;
import androidx.annotation.MainThread;
+import androidx.annotation.Nullable;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.statusbar.IStatusBarService;
@@ -139,7 +139,7 @@
@Nullable private BubbleStackView.SurfaceSynchronizer mSurfaceSynchronizer;
private BubbleData mBubbleData;
- private BubbleStackView mStackView;
+ @Nullable private BubbleStackView mStackView;
// Bubbles get added to the status bar view
private final StatusBarWindowController mStatusBarWindowController;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java
index 812c9a7..689d161 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java
@@ -212,7 +212,7 @@
return;
}
mMobileDrawable.setTintList(
- ColorStateList.valueOf(mDualToneHandler.getFillColor(darkIntensity)));
+ ColorStateList.valueOf(mDualToneHandler.getSingleColor(darkIntensity)));
ColorStateList color = ColorStateList.valueOf(getTint(area, this, tint));
mIn.setImageTintList(color);
mOut.setImageTintList(color);
@@ -238,7 +238,7 @@
// We want the ability to change the theme from the one set by SignalDrawable in certain
// surfaces. In this way, we can pass a theme to the view.
mMobileDrawable.setTintList(
- ColorStateList.valueOf(mDualToneHandler.getFillColor(intensity)));
+ ColorStateList.valueOf(mDualToneHandler.getSingleColor(intensity)));
mIn.setImageTintList(list);
mOut.setImageTintList(list);
mMobileType.setImageTintList(list);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
index ce8463e..4d4818d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
@@ -433,7 +433,8 @@
public void onBiometricError(int msgId, String errString,
BiometricSourceType biometricSourceType) {
mMetricsLogger.write(new LogMaker(MetricsEvent.BIOMETRIC_AUTH)
- .setType(MetricsEvent.TYPE_ERROR).setSubtype(toSubtype(biometricSourceType)));
+ .setType(MetricsEvent.TYPE_ERROR).setSubtype(toSubtype(biometricSourceType))
+ .addTaggedData(MetricsEvent.FIELD_BIOMETRIC_AUTH_ERROR, msgId));
cleanup();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
index aba64bdf..f221865 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
@@ -121,8 +121,8 @@
private final int mEdgeWidth;
// The slop to distinguish between horizontal and vertical motion
private final float mTouchSlop;
- // Minimum distance to move so that is can be considerd as a back swipe
- private final float mSwipeThreshold;
+ // Duration after which we consider the event as longpress.
+ private final int mLongPressTimeout;
// The threshold where the touch needs to be at most, such that the arrow is displayed above the
// finger, otherwise it will be below
private final int mMinArrowPosition;
@@ -164,8 +164,9 @@
// TODO: Get this for the current user
mEdgeWidth = res.getDimensionPixelSize(
com.android.internal.R.dimen.config_backGestureInset);
+
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
- mSwipeThreshold = res.getDimension(R.dimen.navigation_edge_action_drag_threshold);
+ mLongPressTimeout = ViewConfiguration.getLongPressTimeout();
mNavBarHeight = res.getDimensionPixelSize(R.dimen.navigation_bar_frame_height);
mMinArrowPosition = res.getDimensionPixelSize(
@@ -308,8 +309,18 @@
return !isInExcludedRegion;
}
+ private void cancelGesture(MotionEvent ev) {
+ // Send action cancel to reset all the touch events
+ mAllowGesture = false;
+ MotionEvent cancelEv = MotionEvent.obtain(ev);
+ cancelEv.setAction(MotionEvent.ACTION_CANCEL);
+ mEdgePanel.handleTouch(cancelEv);
+ cancelEv.recycle();
+ }
+
private void onMotionEvent(MotionEvent ev) {
- if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+ int action = ev.getActionMasked();
+ if (action == MotionEvent.ACTION_DOWN) {
// Verify if this is in within the touch region and we aren't in immersive mode, and
// either the bouncer is showing or the notification panel is hidden
int stateFlags = mOverviewProxyService.getSystemUiStateFlags();
@@ -330,29 +341,35 @@
mThresholdCrossed = false;
}
} else if (mAllowGesture) {
- if (!mThresholdCrossed && ev.getAction() == MotionEvent.ACTION_MOVE) {
- float dx = Math.abs(ev.getX() - mDownPoint.x);
- float dy = Math.abs(ev.getY() - mDownPoint.y);
- if (dy > dx && dy > mTouchSlop) {
- // Send action cancel to reset all the touch events
- mAllowGesture = false;
- MotionEvent cancelEv = MotionEvent.obtain(ev);
- cancelEv.setAction(MotionEvent.ACTION_CANCEL);
- mEdgePanel.handleTouch(cancelEv);
- cancelEv.recycle();
+ if (!mThresholdCrossed) {
+ if (action == MotionEvent.ACTION_POINTER_DOWN) {
+ // We do not support multi touch for back gesture
+ cancelGesture(ev);
return;
+ } else if (action == MotionEvent.ACTION_MOVE) {
+ if ((ev.getEventTime() - ev.getDownTime()) > mLongPressTimeout) {
+ cancelGesture(ev);
+ return;
+ }
+ float dx = Math.abs(ev.getX() - mDownPoint.x);
+ float dy = Math.abs(ev.getY() - mDownPoint.y);
+ if (dy > dx && dy > mTouchSlop) {
+ cancelGesture(ev);
+ return;
- } else if (dx > dy && dx > mTouchSlop) {
- mThresholdCrossed = true;
- // Capture inputs
- mInputMonitor.pilferPointers();
+ } else if (dx > dy && dx > mTouchSlop) {
+ mThresholdCrossed = true;
+ // Capture inputs
+ mInputMonitor.pilferPointers();
+ }
}
+
}
// forward touch
mEdgePanel.handleTouch(ev);
- boolean isUp = ev.getAction() == MotionEvent.ACTION_UP;
+ boolean isUp = action == MotionEvent.ACTION_UP;
if (isUp) {
boolean performAction = mEdgePanel.shouldTriggerBack();
if (performAction) {
@@ -363,7 +380,7 @@
mOverviewProxyService.notifyBackAction(performAction, (int) mDownPoint.x,
(int) mDownPoint.y, false /* isButton */, !mIsOnLeftEdge);
}
- if (isUp || ev.getAction() == MotionEvent.ACTION_CANCEL) {
+ if (isUp || action == MotionEvent.ACTION_CANCEL) {
mRegionSamplingHelper.stop();
} else {
updateSamplingRect();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
index b8887c4..61a3940 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
@@ -95,6 +95,7 @@
private boolean mWasPulsingOnThisFrame;
private boolean mWakeAndUnlockRunning;
private boolean mKeyguardShowing;
+ private boolean mShowingLaunchAffordance;
private final KeyguardMonitor.Callback mKeyguardMonitorCallback =
new KeyguardMonitor.Callback() {
@@ -299,7 +300,8 @@
}
boolean onAodNotPulsingOrDocked = mDozing && (!mPulsing || mDocked);
- boolean invisible = onAodNotPulsingOrDocked || mWakeAndUnlockRunning;
+ boolean invisible = onAodNotPulsingOrDocked || mWakeAndUnlockRunning
+ || mShowingLaunchAffordance;
setVisibility(invisible ? INVISIBLE : VISIBLE);
updateClickability();
}
@@ -485,6 +487,14 @@
}
/**
+ * When we're launching an affordance, like double pressing power to open camera.
+ */
+ public void onShowingLaunchAffordanceChanged(boolean showing) {
+ mShowingLaunchAffordance = showing;
+ update();
+ }
+
+ /**
* Called whenever the scrims become opaque, transparent or semi-transparent.
*/
public void onScrimVisibilityChanged(@ScrimVisibility int scrimsVisible) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java
index 6e56854..36050ac 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java
@@ -17,12 +17,15 @@
package com.android.systemui.statusbar.phone;
import static android.content.Intent.ACTION_OVERLAY_CHANGED;
+import static android.content.Intent.ACTION_PREFERRED_ACTIVITY_CHANGED;
import static android.os.UserHandle.USER_CURRENT;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON_OVERLAY;
+import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY;
import android.content.BroadcastReceiver;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -56,7 +59,7 @@
public class NavigationModeController implements Dumpable {
private static final String TAG = NavigationModeController.class.getSimpleName();
- private static final boolean DEBUG = true;
+ private static final boolean DEBUG = false;
public interface ModeChangedListener {
void onNavigationModeChanged(int mode);
@@ -76,11 +79,19 @@
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- if (intent.getAction().equals(ACTION_OVERLAY_CHANGED)) {
- if (DEBUG) {
- Log.d(TAG, "ACTION_OVERLAY_CHANGED");
- }
- updateCurrentInteractionMode(true /* notify */);
+ switch (intent.getAction()) {
+ case ACTION_OVERLAY_CHANGED:
+ if (DEBUG) {
+ Log.d(TAG, "ACTION_OVERLAY_CHANGED");
+ }
+ updateCurrentInteractionMode(true /* notify */);
+ break;
+ case ACTION_PREFERRED_ACTIVITY_CHANGED:
+ if (DEBUG) {
+ Log.d(TAG, "ACTION_PREFERRED_ACTIVITY_CHANGED");
+ }
+ switchFromGestureNavModeIfNotSupportedByDefaultLauncher();
+ break;
}
}
};
@@ -116,6 +127,7 @@
// Update the nav mode for the current user
updateCurrentInteractionMode(true /* notify */);
+ switchFromGestureNavModeIfNotSupportedByDefaultLauncher();
// When switching users, defer enabling the gestural nav overlay until the user
// is all set up
@@ -140,7 +152,12 @@
overlayFilter.addDataSchemeSpecificPart("android", PatternMatcher.PATTERN_LITERAL);
mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, overlayFilter, null, null);
+ IntentFilter preferredActivityFilter = new IntentFilter(ACTION_PREFERRED_ACTIVITY_CHANGED);
+ mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, preferredActivityFilter, null,
+ null);
+
updateCurrentInteractionMode(false /* notify */);
+ switchFromGestureNavModeIfNotSupportedByDefaultLauncher();
// Check if we need to defer enabling gestural nav
deferGesturalNavOverlayIfNecessary();
@@ -175,6 +192,10 @@
private int getCurrentInteractionMode(Context context) {
int mode = context.getResources().getInteger(
com.android.internal.R.integer.config_navBarInteractionMode);
+ if (DEBUG) {
+ Log.d(TAG, "getCurrentInteractionMode: mode=" + mMode
+ + " contextUser=" + context.getUserId());
+ }
return mode;
}
@@ -250,6 +271,10 @@
mUiOffloadThread.submit(() -> {
try {
mOverlayManager.setEnabledExclusiveInCategory(overlayPkg, userId);
+ if (DEBUG) {
+ Log.d(TAG, "setModeOverlay: overlayPackage=" + overlayPkg
+ + " userId=" + userId);
+ }
} catch (RemoteException e) {
Log.e(TAG, "Failed to enable overlay " + overlayPkg + " for user " + userId);
}
@@ -277,4 +302,27 @@
Log.d(TAG, " " + a.getAssetPath());
}
}
+
+ private void switchFromGestureNavModeIfNotSupportedByDefaultLauncher() {
+ if (getCurrentInteractionMode(mCurrentUserContext) == NAV_BAR_MODE_GESTURAL
+ && !isGestureNavSupportedByDefaultLauncher(mCurrentUserContext)) {
+ setModeOverlay(NAV_BAR_MODE_3BUTTON_OVERLAY, USER_CURRENT);
+ }
+ }
+
+ private boolean isGestureNavSupportedByDefaultLauncher(Context context) {
+ final ComponentName cn = context.getPackageManager().getHomeActivities(new ArrayList<>());
+ if (cn == null) {
+ // There is no default home app set for the current user, don't make any changes yet.
+ return true;
+ }
+ if (DEBUG) {
+ Log.d(TAG, "isGestureNavSupportedByDefaultLauncher: launcher=" + cn.getPackageName()
+ + " contextUser=" + context.getUserId());
+ }
+
+ ComponentName recentsComponentName = ComponentName.unflattenFromString(context.getString(
+ com.android.internal.R.string.config_recentsComponentName));
+ return recentsComponentName.getPackageName().equals(cn.getPackageName());
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 3fe7f36..9da75b6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -151,7 +151,8 @@
private final NotificationWakeUpCoordinator mWakeUpCoordinator;
private final PulseExpansionHandler mPulseExpansionHandler;
- private KeyguardAffordanceHelper mAffordanceHelper;
+ @VisibleForTesting
+ protected KeyguardAffordanceHelper mAffordanceHelper;
private KeyguardUserSwitcher mKeyguardUserSwitcher;
@VisibleForTesting
protected KeyguardStatusBarView mKeyguardStatusBar;
@@ -340,6 +341,7 @@
*/
private int mThemeResId;
private KeyguardIndicationController mKeyguardIndicationController;
+ private Consumer<Boolean> mAffordanceLaunchListener;
@Inject
public NotificationPanelView(@Named(VIEW_CONTEXT) Context context, AttributeSet attrs,
@@ -447,6 +449,14 @@
R.dimen.qs_notification_padding);
}
+ /**
+ * @see #launchCamera(boolean, int)
+ * @see #setLaunchingAffordance(boolean)
+ */
+ public void setLaunchAffordanceListener(Consumer<Boolean> listener) {
+ mAffordanceLaunchListener = listener;
+ }
+
public void updateResources() {
Resources res = getResources();
int qsWidth = res.getDimensionPixelSize(R.dimen.qs_panel_width);
@@ -2743,6 +2753,9 @@
private void setLaunchingAffordance(boolean launchingAffordance) {
getLeftIcon().setLaunchingAffordance(launchingAffordance);
getRightIcon().setLaunchingAffordance(launchingAffordance);
+ if (mAffordanceLaunchListener != null) {
+ mAffordanceLaunchListener.accept(launchingAffordance);
+ }
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 72726b3..4e8f584 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -951,6 +951,9 @@
createUserSwitcher();
}
+ mNotificationPanel.setLaunchAffordanceListener(
+ mStatusBarWindow::onShowingLaunchAffordanceChanged);
+
// Set up the quick settings tile panel
View container = mStatusBarWindow.findViewById(R.id.qs_frame);
if (container != null) {
@@ -3636,6 +3639,7 @@
@Override
public void onStartedGoingToSleep() {
+ updateNotificationPanelTouchState();
notifyHeadsUpGoingToSleep();
dismissVolumeDialog();
}
@@ -3668,7 +3672,10 @@
* Keyguard.
*/
private void updateNotificationPanelTouchState() {
- mNotificationPanel.setTouchAndAnimationDisabled(!mDeviceInteractive && !mPulsing);
+ boolean goingToSleepWithoutAnimation = isGoingToSleep()
+ && !DozeParameters.getInstance(mContext).shouldControlScreenOff();
+ mNotificationPanel.setTouchAndAnimationDisabled((!mDeviceInteractive && !mPulsing)
+ || goingToSleepWithoutAnimation);
}
final ScreenLifecycle.Observer mScreenObserver = new ScreenLifecycle.Observer() {
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 049972e..7d5f23b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -510,6 +510,15 @@
}
}
+ /**
+ * When we're launching an affordance, like double pressing power to open camera.
+ */
+ public void onShowingLaunchAffordanceChanged(boolean showing) {
+ if (mLockIcon != null) {
+ mLockIcon.onShowingLaunchAffordanceChanged(showing);
+ }
+ }
+
public class LayoutParams extends FrameLayout.LayoutParams {
public boolean ignoreRightInset;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
index 2f9d892..1b7ca95 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
@@ -21,9 +21,11 @@
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.StatusBarManager;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.view.MotionEvent;
@@ -36,6 +38,7 @@
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.AmbientPulseManager;
+import com.android.systemui.statusbar.KeyguardAffordanceView;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.PulseExpansionHandler;
@@ -55,6 +58,8 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.util.function.Consumer;
+
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
@@ -90,6 +95,8 @@
private HeadsUpTouchHelper.Callback mHeadsUpCallback;
@Mock
private PanelBar mPanelBar;
+ @Mock
+ private KeyguardAffordanceHelper mAffordanceHelper;
private NotificationPanelView mNotificationPanelView;
@Before
@@ -112,6 +119,9 @@
mNotificationPanelView = new TestableNotificationPanelView(coordinator, expansionHandler);
mNotificationPanelView.setHeadsUpManager(mHeadsUpManager);
mNotificationPanelView.setBar(mPanelBar);
+
+ when(mKeyguardBottomArea.getLeftView()).thenReturn(mock(KeyguardAffordanceView.class));
+ when(mKeyguardBottomArea.getRightView()).thenReturn(mock(KeyguardAffordanceView.class));
}
@Test
@@ -129,6 +139,19 @@
}
@Test
+ public void testAffordanceLaunchingListener() {
+ Consumer<Boolean> listener = spy((showing) -> { });
+ mNotificationPanelView.setExpandedFraction(1f);
+ mNotificationPanelView.setLaunchAffordanceListener(listener);
+ mNotificationPanelView.launchCamera(false /* animate */,
+ StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP);
+ verify(listener).accept(eq(true));
+
+ mNotificationPanelView.onAffordanceLaunchEnded();
+ verify(listener).accept(eq(false));
+ }
+
+ @Test
public void testOnTouchEvent_expansionCanBeBlocked() {
mNotificationPanelView.onTouchEvent(MotionEvent.obtain(0L /* downTime */,
0L /* eventTime */, MotionEvent.ACTION_DOWN, 0f /* x */, 0f /* y */,
@@ -166,6 +189,7 @@
mKeyguardBottomArea = NotificationPanelViewTest.this.mKeyguardBottomArea;
mBigClockContainer = NotificationPanelViewTest.this.mBigClockContainer;
mQsFrame = NotificationPanelViewTest.this.mQsFrame;
+ mAffordanceHelper = NotificationPanelViewTest.this.mAffordanceHelper;
initDependencies(NotificationPanelViewTest.this.mStatusBar,
NotificationPanelViewTest.this.mGroupManager,
NotificationPanelViewTest.this.mNotificationShelf,
diff --git a/proto/src/metrics_constants/metrics_constants.proto b/proto/src/metrics_constants/metrics_constants.proto
index 2616466..71d03a8 100644
--- a/proto/src/metrics_constants/metrics_constants.proto
+++ b/proto/src/metrics_constants/metrics_constants.proto
@@ -7371,6 +7371,11 @@
// Note: Only shows up on first time toggle
DIALOG_DARK_UI_INFO = 1740;
+ // FIELD - Detailed reason in biometric authentication error.
+ // One of the constant value in BiometricConstants.java file.
+ // OS: Q
+ FIELD_BIOMETRIC_AUTH_ERROR = 1741;
+
// ---- End Q Constants, all Q constants go above this line ----
// Add new aosp constants above this line.
// END OF AOSP CONSTANTS
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 9e1b3b8..9855e4e 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -51,8 +51,8 @@
"android.hardware.configstore-V1.0-java",
"android.hardware.contexthub-V1.0-java",
"android.hidl.manager-V1.2-java",
- "dnsresolver_aidl_interface-java",
- "netd_aidl_interface-java",
+ "dnsresolver_aidl_interface-V2-java",
+ "netd_aidl_interface-V2-java",
"netd_event_listener_interface-java",
],
}
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index cb61259..dfbb55a 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -1698,8 +1698,6 @@
return;
}
- type = fixTypeIfAuto(type);
-
// Sanity check the window length. This will catch people mistakenly
// trying to pass an end-of-window timestamp rather than a duration.
if (windowLength > AlarmManager.INTERVAL_HALF_DAY) {
@@ -1815,21 +1813,6 @@
}
/**
- * In case of cars, we need to avoid scheduling wakeup alarms, since we don't want the system
- * to wake up from suspend arbitrarily to perform app work.
- */
- private int fixTypeIfAuto(int type) {
- if (mInjector.isAutomotive()) {
- if (type == AlarmManager.ELAPSED_REALTIME_WAKEUP) {
- type = AlarmManager.ELAPSED_REALTIME;
- } else if (type == AlarmManager.RTC_WAKEUP) {
- type = AlarmManager.RTC;
- }
- }
- return type;
- }
-
- /**
* Return the minimum time that should elapse before an app in the specified bucket
* can receive alarms again
*/
@@ -2232,7 +2215,6 @@
pw.print(" mLastTickSet="); pw.println(sdf.format(new Date(mLastTickSet)));
pw.print(" mLastTickAdded="); pw.println(sdf.format(new Date(mLastTickAdded)));
pw.print(" mLastTickRemoved="); pw.println(sdf.format(new Date(mLastTickRemoved)));
- pw.print(" mIsAutomotive="); pw.println(mInjector.isAutomotive());
if (RECORD_ALARMS_IN_HISTORY) {
pw.println();
@@ -3899,12 +3881,9 @@
static class Injector {
private long mNativeData;
private Context mContext;
- private final boolean mIsAutomotive;
Injector(Context context) {
mContext = context;
- mIsAutomotive = context.getPackageManager().hasSystemFeature(
- PackageManager.FEATURE_AUTOMOTIVE);
}
void init() {
@@ -3993,10 +3972,6 @@
ClockReceiver getClockReceiver(AlarmManagerService service) {
return service.new ClockReceiver();
}
-
- boolean isAutomotive() {
- return mIsAutomotive;
- }
}
private class AlarmThread extends Thread
diff --git a/services/core/java/com/android/server/GestureLauncherService.java b/services/core/java/com/android/server/GestureLauncherService.java
index 8077e34..de96aaa 100644
--- a/services/core/java/com/android/server/GestureLauncherService.java
+++ b/services/core/java/com/android/server/GestureLauncherService.java
@@ -35,6 +35,7 @@
import android.os.PowerManager.WakeLock;
import android.os.SystemClock;
import android.os.SystemProperties;
+import android.os.Trace;
import android.os.UserHandle;
import android.provider.Settings;
import android.util.MutableBoolean;
@@ -404,26 +405,35 @@
*/
@VisibleForTesting
boolean handleCameraGesture(boolean useWakelock, int source) {
- boolean userSetupComplete = Settings.Secure.getIntForUser(mContext.getContentResolver(),
- Settings.Secure.USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) != 0;
- if (!userSetupComplete) {
- if (DBG) Slog.d(TAG, String.format(
- "userSetupComplete = %s, ignoring camera gesture.",
- userSetupComplete));
- return false;
- }
- if (DBG) Slog.d(TAG, String.format(
- "userSetupComplete = %s, performing camera gesture.",
- userSetupComplete));
+ Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "GestureLauncher:handleCameraGesture");
+ try {
+ boolean userSetupComplete = Settings.Secure.getIntForUser(mContext.getContentResolver(),
+ Settings.Secure.USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) != 0;
+ if (!userSetupComplete) {
+ if (DBG) {
+ Slog.d(TAG, String.format(
+ "userSetupComplete = %s, ignoring camera gesture.",
+ userSetupComplete));
+ }
+ return false;
+ }
+ if (DBG) {
+ Slog.d(TAG, String.format(
+ "userSetupComplete = %s, performing camera gesture.",
+ userSetupComplete));
+ }
- if (useWakelock) {
- // Make sure we don't sleep too early
- mWakeLock.acquire(500L);
+ if (useWakelock) {
+ // Make sure we don't sleep too early
+ mWakeLock.acquire(500L);
+ }
+ StatusBarManagerInternal service = LocalServices.getService(
+ StatusBarManagerInternal.class);
+ service.onCameraLaunchGestureDetected(source);
+ return true;
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
- StatusBarManagerInternal service = LocalServices.getService(
- StatusBarManagerInternal.class);
- service.onCameraLaunchGestureDetected(source);
- return true;
}
private final BroadcastReceiver mUserReceiver = new BroadcastReceiver() {
diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java
index 0da39e7..104cadc 100644
--- a/services/core/java/com/android/server/am/ActivityManagerConstants.java
+++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java
@@ -120,7 +120,7 @@
/**
* Default value for mFlagBackgroundActivityStartsEnabled if not explicitly set in
* Settings.Global. This allows it to be set experimentally unless it has been
- * enabled/disabled in developer options. Defaults to true.
+ * enabled/disabled in developer options. Defaults to false.
*/
private static final String KEY_DEFAULT_BACKGROUND_ACTIVITY_STARTS_ENABLED =
"default_background_activity_starts_enabled";
@@ -497,7 +497,7 @@
boolean enabledInDeviceConfig = DeviceConfig.getBoolean(
DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
KEY_DEFAULT_BACKGROUND_ACTIVITY_STARTS_ENABLED,
- /*defaultValue*/ true);
+ /*defaultValue*/ false);
mFlagBackgroundActivityStartsEnabled = enabledInDeviceConfig;
if (!enabledInDeviceConfig) {
whitelistedPackageNames = DeviceConfig.getProperty(
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index a809d21..7a93753 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -8457,18 +8457,43 @@
}
}
- if (DEBUG_POWER) {
- Slog.w(TAG, "noteWakupAlarm[ sourcePkg=" + sourcePkg + ", sourceUid=" + sourceUid
- + ", workSource=" + workSource + ", tag=" + tag + "]");
- }
+ int standbyBucket = 0;
mBatteryStatsService.noteWakupAlarm(sourcePkg, sourceUid, workSource, tag);
if (workSource != null) {
- StatsLog.write(StatsLog.WAKEUP_ALARM_OCCURRED, workSource, tag, sourcePkg);
+ String workSourcePackage = workSource.getName(0);
+ int workSourceUid = workSource.getAttributionUid();
+ if (workSourcePackage == null) {
+ workSourcePackage = sourcePkg;
+ workSourceUid = sourceUid;
+ }
+
+ if (mUsageStatsService != null) {
+ standbyBucket = mUsageStatsService.getAppStandbyBucket(workSourcePackage,
+ UserHandle.getUserId(workSourceUid), SystemClock.elapsedRealtime());
+ }
+
+ StatsLog.write(StatsLog.WAKEUP_ALARM_OCCURRED, workSource, tag, sourcePkg,
+ standbyBucket);
+ if (DEBUG_POWER) {
+ Slog.w(TAG, "noteWakeupAlarm[ sourcePkg=" + sourcePkg + ", sourceUid=" + sourceUid
+ + ", workSource=" + workSource + ", tag=" + tag + ", standbyBucket="
+ + standbyBucket + " wsName=" + workSourcePackage + ")]");
+ }
} else {
+ if (mUsageStatsService != null) {
+ standbyBucket = mUsageStatsService.getAppStandbyBucket(sourcePkg,
+ UserHandle.getUserId(sourceUid), SystemClock.elapsedRealtime());
+ }
StatsLog.write_non_chained(StatsLog.WAKEUP_ALARM_OCCURRED, sourceUid, null, tag,
- sourcePkg);
+ sourcePkg, standbyBucket);
+ if (DEBUG_POWER) {
+ Slog.w(TAG, "noteWakeupAlarm[ sourcePkg=" + sourcePkg + ", sourceUid=" + sourceUid
+ + ", workSource=" + workSource + ", tag=" + tag + ", standbyBucket="
+ + standbyBucket + "]");
+ }
}
+
}
@Override
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index 2f1b22e..446b128 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -551,12 +551,10 @@
.removeAllowBackgroundActivityStartsToken(this);
ams.mHandler.removeCallbacks(mStartedWhitelistingBgActivityStartsCleanUp);
}
- mAppForStartedWhitelistingBgActivityStarts = null;
}
- if (mHasStartedWhitelistingBgActivityStarts) {
- // Make sure the cleanup callback knows about the new process.
- mAppForStartedWhitelistingBgActivityStarts = _proc;
- }
+ // Make sure the cleanup callback knows about the new process.
+ mAppForStartedWhitelistingBgActivityStarts = mHasStartedWhitelistingBgActivityStarts
+ ? _proc : null;
if (mHasStartedWhitelistingBgActivityStarts
|| mHasBindingWhitelistingBgActivityStarts) {
_proc.addAllowBackgroundActivityStartsToken(this);
@@ -656,6 +654,9 @@
*/
void whitelistBgActivityStartsOnServiceStart() {
setHasStartedWhitelistingBgActivityStarts(true);
+ if (app != null) {
+ mAppForStartedWhitelistingBgActivityStarts = app;
+ }
// This callback is stateless, so we create it once when we first need it.
if (mStartedWhitelistingBgActivityStartsCleanUp == null) {
diff --git a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
index e40949b..dbc339b 100644
--- a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
+++ b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
@@ -27,21 +27,19 @@
import android.net.metrics.ConnectStats;
import android.net.metrics.DnsEvent;
import android.net.metrics.INetdEventListener;
-import android.net.metrics.IpConnectivityLog;
import android.net.metrics.NetworkMetrics;
import android.net.metrics.WakeupEvent;
import android.net.metrics.WakeupStats;
import android.os.RemoteException;
import android.text.format.DateUtils;
-import android.util.Log;
import android.util.ArrayMap;
+import android.util.Log;
import android.util.SparseArray;
import android.util.StatsLog;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.BitUtils;
-import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.RingBuffer;
import com.android.internal.util.TokenBucket;
import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityEvent;
@@ -307,6 +305,11 @@
}
}
+ @Override
+ public int getInterfaceVersion() throws RemoteException {
+ return this.VERSION;
+ }
+
private void addWakeupEvent(WakeupEvent event) {
String iface = event.iface;
mWakeupEvents.append(event);
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index d8b7c2e..fa8c48b 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -1170,7 +1170,7 @@
}
private void removeSyncsForAuthority(EndPoint info, String why) {
- mLogger.log("removeSyncsForAuthority: ", info);
+ mLogger.log("removeSyncsForAuthority: ", info, why);
verifyJobScheduler();
List<SyncOperation> ops = getAllPendingSyncs();
for (SyncOperation op: ops) {
diff --git a/services/core/java/com/android/server/content/SyncStorageEngine.java b/services/core/java/com/android/server/content/SyncStorageEngine.java
index c7a3f4b..e09c661 100644
--- a/services/core/java/com/android/server/content/SyncStorageEngine.java
+++ b/services/core/java/com/android/server/content/SyncStorageEngine.java
@@ -1027,7 +1027,7 @@
* Called when the set of account has changed, given the new array of
* active accounts.
*/
- public void removeStaleAccounts(@Nullable Account[] accounts, int userId) {
+ public void removeStaleAccounts(@Nullable Account[] currentAccounts, int userId) {
synchronized (mAuthorities) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Slog.v(TAG, "Updating for new accounts...");
@@ -1036,9 +1036,11 @@
Iterator<AccountInfo> accIt = mAccounts.values().iterator();
while (accIt.hasNext()) {
AccountInfo acc = accIt.next();
- if ((accounts == null) || (
- (acc.accountAndUser.userId == userId)
- && !ArrayUtils.contains(accounts, acc.accountAndUser.account))) {
+ if (acc.accountAndUser.userId != userId) {
+ continue; // Irrelevant user.
+ }
+ if ((currentAccounts == null)
+ || !ArrayUtils.contains(currentAccounts, acc.accountAndUser.account)) {
// This account no longer exists...
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Slog.v(TAG, "Account removed: " + acc.accountAndUser);
diff --git a/services/core/java/com/android/server/location/GnssVisibilityControl.java b/services/core/java/com/android/server/location/GnssVisibilityControl.java
index b7e0a0f..8d4ad7f 100644
--- a/services/core/java/com/android/server/location/GnssVisibilityControl.java
+++ b/services/core/java/com/android/server/location/GnssVisibilityControl.java
@@ -16,6 +16,7 @@
package com.android.server.location;
+import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.app.AppOpsManager;
import android.app.Notification;
@@ -27,6 +28,7 @@
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.location.LocationManager;
import android.os.Handler;
import android.os.Looper;
import android.os.PowerManager;
@@ -62,6 +64,9 @@
// Max wait time for synchronous method onGpsEnabledChanged() to run.
private static final long ON_GPS_ENABLED_CHANGED_TIMEOUT_MILLIS = 3 * 1000;
+ // How long to display location icon for each non-framework non-emergency location request.
+ private static final long LOCATION_ICON_DISPLAY_DURATION_MILLIS = 5 * 1000;
+
// Wakelocks
private static final String WAKELOCK_KEY = TAG;
private static final long WAKELOCK_TIMEOUT_MILLIS = 60 * 1000;
@@ -77,10 +82,19 @@
private boolean mIsGpsEnabled;
+ private static final class ProxyAppState {
+ private boolean mHasLocationPermission;
+ private boolean mIsLocationIconOn;
+
+ private ProxyAppState(boolean hasLocationPermission) {
+ mHasLocationPermission = hasLocationPermission;
+ }
+ }
+
// 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;
- private ArrayMap<String, Boolean> mProxyAppToLocationPermissions = new ArrayMap<>(
- ARRAY_MAP_INITIAL_CAPACITY_PROXY_APP_TO_LOCATION_PERMISSIONS);
+ private static final int ARRAY_MAP_INITIAL_CAPACITY_PROXY_APPS_STATE = 5;
+ private ArrayMap<String, ProxyAppState> mProxyAppsState = new ArrayMap<>(
+ ARRAY_MAP_INITIAL_CAPACITY_PROXY_APPS_STATE);
private PackageManager.OnPermissionsChangedListener mOnPermissionsChangedListener =
uid -> runOnHandler(() -> handlePermissionsChanged(uid));
@@ -173,18 +187,18 @@
}
private void handleProxyAppPackageUpdate(String pkgName, String action) {
- final Boolean locationPermission = mProxyAppToLocationPermissions.get(pkgName);
- if (locationPermission == null) {
+ final ProxyAppState proxyAppState = mProxyAppsState.get(pkgName);
+ if (proxyAppState == null) {
return; // ignore, pkgName is not one of the proxy apps in our list.
}
if (DEBUG) Log.d(TAG, "Proxy app " + pkgName + " package changed: " + action);
final boolean updatedLocationPermission = shouldEnableLocationPermissionInGnssHal(pkgName);
- if (locationPermission != updatedLocationPermission) {
+ if (proxyAppState.mHasLocationPermission != updatedLocationPermission) {
// Permission changed. So, update the GNSS HAL with the updated list.
Log.i(TAG, "Proxy app " + pkgName + " location permission changed."
+ " IsLocationPermissionEnabled: " + updatedLocationPermission);
- mProxyAppToLocationPermissions.put(pkgName, updatedLocationPermission);
+ proxyAppState.mHasLocationPermission = updatedLocationPermission;
updateNfwLocationAccessProxyAppsInGnssHal();
}
}
@@ -196,35 +210,53 @@
if (nfwLocationAccessProxyApps.isEmpty()) {
// Stop listening for app permission changes. Clear the app list in GNSS HAL.
- if (!mProxyAppToLocationPermissions.isEmpty()) {
+ if (!mProxyAppsState.isEmpty()) {
mPackageManager.removeOnPermissionsChangeListener(mOnPermissionsChangedListener);
- mProxyAppToLocationPermissions.clear();
+ resetProxyAppsState();
updateNfwLocationAccessProxyAppsInGnssHal();
}
return;
}
- if (mProxyAppToLocationPermissions.isEmpty()) {
+ if (mProxyAppsState.isEmpty()) {
mPackageManager.addOnPermissionsChangeListener(mOnPermissionsChangedListener);
} else {
- mProxyAppToLocationPermissions.clear();
+ resetProxyAppsState();
}
for (String proxyAppPkgName : nfwLocationAccessProxyApps) {
- mProxyAppToLocationPermissions.put(proxyAppPkgName,
- shouldEnableLocationPermissionInGnssHal(proxyAppPkgName));
+ ProxyAppState proxyAppState = new ProxyAppState(shouldEnableLocationPermissionInGnssHal(
+ proxyAppPkgName));
+ mProxyAppsState.put(proxyAppPkgName, proxyAppState);
}
updateNfwLocationAccessProxyAppsInGnssHal();
}
+ private void resetProxyAppsState() {
+ // Clear location icons displayed.
+ for (Map.Entry<String, ProxyAppState> entry : mProxyAppsState.entrySet()) {
+ ProxyAppState proxyAppState = entry.getValue();
+ if (!proxyAppState.mIsLocationIconOn) {
+ continue;
+ }
+
+ mHandler.removeCallbacksAndMessages(proxyAppState);
+ final ApplicationInfo proxyAppInfo = getProxyAppInfo(entry.getKey());
+ if (proxyAppInfo != null) {
+ clearLocationIcon(proxyAppState, proxyAppInfo.uid, entry.getKey());
+ }
+ }
+ mProxyAppsState.clear();
+ }
+
private boolean isProxyAppListUpdated(List<String> nfwLocationAccessProxyApps) {
- if (nfwLocationAccessProxyApps.size() != mProxyAppToLocationPermissions.size()) {
+ if (nfwLocationAccessProxyApps.size() != mProxyAppsState.size()) {
return true;
}
for (String nfwLocationAccessProxyApp : nfwLocationAccessProxyApps) {
- if (!mProxyAppToLocationPermissions.containsKey(nfwLocationAccessProxyApp)) {
+ if (!mProxyAppsState.containsKey(nfwLocationAccessProxyApp)) {
return true;
}
}
@@ -326,11 +358,11 @@
}
private void handlePermissionsChanged(int uid) {
- if (mProxyAppToLocationPermissions.isEmpty()) {
+ if (mProxyAppsState.isEmpty()) {
return;
}
- for (Map.Entry<String, Boolean> entry : mProxyAppToLocationPermissions.entrySet()) {
+ for (Map.Entry<String, ProxyAppState> entry : mProxyAppsState.entrySet()) {
final String proxyAppPkgName = entry.getKey();
final ApplicationInfo proxyAppInfo = getProxyAppInfo(proxyAppPkgName);
if (proxyAppInfo == null || proxyAppInfo.uid != uid) {
@@ -339,10 +371,11 @@
final boolean isLocationPermissionEnabled = shouldEnableLocationPermissionInGnssHal(
proxyAppPkgName);
- if (isLocationPermissionEnabled != entry.getValue()) {
+ ProxyAppState proxyAppState = entry.getValue();
+ if (isLocationPermissionEnabled != proxyAppState.mHasLocationPermission) {
Log.i(TAG, "Proxy app " + proxyAppPkgName + " location permission changed."
+ " IsLocationPermissionEnabled: " + isLocationPermissionEnabled);
- entry.setValue(isLocationPermissionEnabled);
+ proxyAppState.mHasLocationPermission = isLocationPermissionEnabled;
updateNfwLocationAccessProxyAppsInGnssHal();
}
return;
@@ -394,8 +427,8 @@
private String[] getLocationPermissionEnabledProxyApps() {
// Get a count of proxy apps with location permission enabled for array creation size.
int countLocationPermissionEnabledProxyApps = 0;
- for (Boolean hasLocationPermissionEnabled : mProxyAppToLocationPermissions.values()) {
- if (hasLocationPermissionEnabled) {
+ for (ProxyAppState proxyAppState : mProxyAppsState.values()) {
+ if (proxyAppState.mHasLocationPermission) {
++countLocationPermissionEnabledProxyApps;
}
}
@@ -403,10 +436,9 @@
int i = 0;
String[] locationPermissionEnabledProxyApps =
new String[countLocationPermissionEnabledProxyApps];
- for (Map.Entry<String, Boolean> entry : mProxyAppToLocationPermissions.entrySet()) {
+ for (Map.Entry<String, ProxyAppState> entry : mProxyAppsState.entrySet()) {
final String proxyApp = entry.getKey();
- final boolean hasLocationPermissionEnabled = entry.getValue();
- if (hasLocationPermissionEnabled) {
+ if (entry.getValue().mHasLocationPermission) {
locationPermissionEnabledProxyApps[i++] = proxyApp;
}
}
@@ -422,12 +454,11 @@
}
final String proxyAppPkgName = nfwNotification.mProxyAppPackageName;
- final Boolean isLocationPermissionEnabled = mProxyAppToLocationPermissions.get(
- proxyAppPkgName);
+ final ProxyAppState proxyAppState = mProxyAppsState.get(proxyAppPkgName);
final boolean isLocationRequestAccepted = nfwNotification.isRequestAccepted();
final boolean isPermissionMismatched =
- (isLocationPermissionEnabled == null) ? isLocationRequestAccepted
- : (isLocationPermissionEnabled != isLocationRequestAccepted);
+ (proxyAppState == null) ? isLocationRequestAccepted
+ : (proxyAppState.mHasLocationPermission != isLocationRequestAccepted);
logEvent(nfwNotification, isPermissionMismatched);
if (!nfwNotification.isRequestAttributedToProxyApp()) {
@@ -442,7 +473,7 @@
if (DEBUG) {
Log.d(TAG, "Non-framework location request rejected. ProxyAppPackageName field"
+ " is not set in the notification: " + nfwNotification + ". Number of"
- + " configured proxy apps: " + mProxyAppToLocationPermissions.size());
+ + " configured proxy apps: " + mProxyAppsState.size());
}
return;
}
@@ -452,7 +483,7 @@
return;
}
- if (isLocationPermissionEnabled == null) {
+ if (proxyAppState == null) {
Log.w(TAG, "Could not find proxy app " + proxyAppPkgName + " in the value specified for"
+ " config parameter: " + GnssConfiguration.CONFIG_NFW_PROXY_APPS
+ ". AppOps service not notified for notification: " + nfwNotification);
@@ -467,18 +498,99 @@
return;
}
- mAppOps.noteOpNoThrow(AppOpsManager.OP_FINE_LOCATION, proxyAppInfo.uid, proxyAppPkgName);
+ if (nfwNotification.isLocationProvided()) {
+ showLocationIcon(proxyAppState, nfwNotification, proxyAppInfo.uid, proxyAppPkgName);
+ mAppOps.noteOpNoThrow(AppOpsManager.OP_FINE_LOCATION, proxyAppInfo.uid,
+ proxyAppPkgName);
+ }
// Log proxy app permission mismatch between framework and GNSS HAL.
if (isPermissionMismatched) {
Log.w(TAG, "Permission mismatch. Framework proxy app " + proxyAppPkgName
- + " location permission is set to " + isLocationPermissionEnabled
+ + " location permission is set to " + proxyAppState.mHasLocationPermission
+ " but GNSS non-framework location access response type is "
+ nfwNotification.getResponseTypeAsString() + " for notification: "
+ nfwNotification);
}
}
+ private void showLocationIcon(ProxyAppState proxyAppState, NfwNotification nfwNotification,
+ int uid, String proxyAppPkgName) {
+ // If we receive a new NfwNotification before the location icon is turned off for the
+ // previous notification, update the timer to extend the location icon display duration.
+ final boolean isLocationIconOn = proxyAppState.mIsLocationIconOn;
+ if (!isLocationIconOn) {
+ if (!updateLocationIcon(/* displayLocationIcon = */ true, uid, proxyAppPkgName)) {
+ Log.w(TAG, "Failed to show Location icon for notification: " + nfwNotification);
+ return;
+ }
+ proxyAppState.mIsLocationIconOn = true;
+ } else {
+ // Extend timer by canceling the current one and starting a new one.
+ mHandler.removeCallbacksAndMessages(proxyAppState);
+ }
+
+ // Start timer to turn off location icon. proxyAppState is used as a token to cancel timer.
+ if (DEBUG) {
+ Log.d(TAG, "Location icon on. " + (isLocationIconOn ? "Extending" : "Setting")
+ + " icon display timer. Uid: " + uid + ", proxyAppPkgName: " + proxyAppPkgName);
+ }
+ if (!mHandler.postDelayed(() -> handleLocationIconTimeout(proxyAppPkgName),
+ /* token = */ proxyAppState, LOCATION_ICON_DISPLAY_DURATION_MILLIS)) {
+ clearLocationIcon(proxyAppState, uid, proxyAppPkgName);
+ Log.w(TAG, "Failed to show location icon for the full duration for notification: "
+ + nfwNotification);
+ }
+ }
+
+ private void handleLocationIconTimeout(String proxyAppPkgName) {
+ // Get uid again instead of using the one provided in startOp() call as the app could have
+ // been uninstalled and reinstalled during the timeout duration (unlikely in real world).
+ final ApplicationInfo proxyAppInfo = getProxyAppInfo(proxyAppPkgName);
+ if (proxyAppInfo != null) {
+ clearLocationIcon(mProxyAppsState.get(proxyAppPkgName), proxyAppInfo.uid,
+ proxyAppPkgName);
+ }
+ }
+
+ private void clearLocationIcon(@Nullable ProxyAppState proxyAppState, int uid,
+ String proxyAppPkgName) {
+ updateLocationIcon(/* displayLocationIcon = */ false, uid, proxyAppPkgName);
+ if (proxyAppState != null) proxyAppState.mIsLocationIconOn = false;
+ if (DEBUG) {
+ Log.d(TAG, "Location icon off. Uid: " + uid + ", proxyAppPkgName: " + proxyAppPkgName);
+ }
+ }
+
+ private boolean updateLocationIcon(boolean displayLocationIcon, int uid,
+ String proxyAppPkgName) {
+ if (displayLocationIcon) {
+ // Need two calls to startOp() here with different op code so that the proxy app shows
+ // up in the recent location requests page and also the location icon gets displayed.
+ if (mAppOps.startOpNoThrow(AppOpsManager.OP_MONITOR_LOCATION, uid,
+ proxyAppPkgName) != AppOpsManager.MODE_ALLOWED) {
+ return false;
+ }
+ if (mAppOps.startOpNoThrow(AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION, uid,
+ proxyAppPkgName) != AppOpsManager.MODE_ALLOWED) {
+ mAppOps.finishOp(AppOpsManager.OP_MONITOR_LOCATION, uid, proxyAppPkgName);
+ return false;
+ }
+ } else {
+ mAppOps.finishOp(AppOpsManager.OP_MONITOR_LOCATION, uid, proxyAppPkgName);
+ mAppOps.finishOp(AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION, uid, proxyAppPkgName);
+ }
+ sendHighPowerMonitoringBroadcast();
+ return true;
+ }
+
+ private void sendHighPowerMonitoringBroadcast() {
+ // Send an intent to notify that a high power request has been added/removed so that
+ // the SystemUi checks the state of AppOps and updates the location icon accordingly.
+ Intent intent = new Intent(LocationManager.HIGH_POWER_REQUEST_CHANGE_ACTION);
+ mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+ }
+
private void handleEmergencyNfwNotification(NfwNotification nfwNotification) {
boolean isPermissionMismatched = false;
if (!nfwNotification.isRequestAccepted()) {
diff --git a/services/core/java/com/android/server/pm/ModuleInfoProvider.java b/services/core/java/com/android/server/pm/ModuleInfoProvider.java
index 6499530..69510d9 100644
--- a/services/core/java/com/android/server/pm/ModuleInfoProvider.java
+++ b/services/core/java/com/android/server/pm/ModuleInfoProvider.java
@@ -64,6 +64,7 @@
// TODO: Move this to an earlier boot phase if anybody requires it then.
private volatile boolean mMetadataLoaded;
+ private volatile String mPackageName;
ModuleInfoProvider(Context context, IPackageManager packageManager) {
mContext = context;
@@ -81,9 +82,9 @@
/** Called by the {@code PackageManager} when it has completed its boot sequence */
public void systemReady() {
- final String packageName = mContext.getResources().getString(
+ mPackageName = mContext.getResources().getString(
R.string.config_defaultModuleMetadataProvider);
- if (TextUtils.isEmpty(packageName)) {
+ if (TextUtils.isEmpty(mPackageName)) {
Slog.w(TAG, "No configured module metadata provider.");
return;
}
@@ -91,13 +92,13 @@
final Resources packageResources;
final PackageInfo pi;
try {
- pi = mPackageManager.getPackageInfo(packageName,
+ pi = mPackageManager.getPackageInfo(mPackageName,
PackageManager.GET_META_DATA, UserHandle.USER_SYSTEM);
- Context packageContext = mContext.createPackageContext(packageName, 0);
+ Context packageContext = mContext.createPackageContext(mPackageName, 0);
packageResources = packageContext.getResources();
} catch (RemoteException | NameNotFoundException e) {
- Slog.w(TAG, "Unable to discover metadata package: " + packageName, e);
+ Slog.w(TAG, "Unable to discover metadata package: " + mPackageName, e);
return;
}
@@ -201,4 +202,11 @@
return mModuleInfo.get(packageName);
}
+
+ String getPackageName() {
+ if (!mMetadataLoaded) {
+ throw new IllegalStateException("Call to getVersion before metadata loaded");
+ }
+ return mPackageName;
+ }
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index e07a132..719e166 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -5646,9 +5646,11 @@
private int checkUidPermissionImpl(String permName, int uid) {
synchronized (mPackages) {
final String[] packageNames = getPackagesForUid(uid);
- final PackageParser.Package pkg = (packageNames != null && packageNames.length > 0)
- ? mPackages.get(packageNames[0])
- : null;
+ PackageParser.Package pkg = null;
+ final int N = packageNames == null ? 0 : packageNames.length;
+ for (int i = 0; pkg == null && i < N; i++) {
+ pkg = mPackages.get(packageNames[i]);
+ }
// Additional logs for b/111075456; ignore system UIDs
if (pkg == null && UserHandle.getAppId(uid) >= Process.FIRST_APPLICATION_UID) {
if (packageNames == null || packageNames.length < 2) {
@@ -6385,6 +6387,16 @@
}
}
+ /**
+ * <em>IMPORTANT:</em> Not all packages returned by this method may be known
+ * to the system. There are two conditions in which this may occur:
+ * <ol>
+ * <li>The package is on adoptable storage and the device has been removed</li>
+ * <li>The package is being removed and the internal structures are partially updated</li>
+ * </ol>
+ * The second is an artifact of the current data structures and should be fixed. See
+ * b/111075456 for one such instance.
+ */
@Override
public String[] getPackagesForUid(int uid) {
return getPackagesForUid_debug(uid, false);
@@ -24074,6 +24086,11 @@
| (appInfo.isVendor() ? IPackageManagerNative.LOCATION_VENDOR : 0)
| (appInfo.isProduct() ? IPackageManagerNative.LOCATION_PRODUCT : 0));
}
+
+ @Override
+ public String getModuleMetadataPackageName() throws RemoteException {
+ return PackageManagerService.this.mModuleInfoProvider.getPackageName();
+ }
}
private class PackageManagerInternalImpl extends PackageManagerInternal {
@@ -24767,6 +24784,12 @@
}
@Override
+ public void forEachInstalledPackage(@NonNull Consumer<PackageParser.Package> actionLocked,
+ @UserIdInt int userId) {
+ PackageManagerService.this.forEachInstalledPackage(actionLocked, userId);
+ }
+
+ @Override
public ArraySet<String> getEnabledComponents(String packageName, int userId) {
synchronized (mPackages) {
PackageSetting setting = mSettings.getPackageLPr(packageName);
@@ -25058,6 +25081,21 @@
}
}
+ void forEachInstalledPackage(@NonNull Consumer<PackageParser.Package> actionLocked,
+ @UserIdInt int userId) {
+ synchronized (mPackages) {
+ int numPackages = mPackages.size();
+ for (int i = 0; i < numPackages; i++) {
+ PackageParser.Package pkg = mPackages.valueAt(i);
+ PackageSetting setting = mSettings.getPackageLPr(pkg.packageName);
+ if (setting == null || !setting.getInstalled(userId)) {
+ continue;
+ }
+ actionLocked.accept(pkg);
+ }
+ }
+ }
+
private static void enforceSystemOrPhoneCaller(String tag) {
int callingUid = Binder.getCallingUid();
if (callingUid != Process.PHONE_UID && callingUid != Process.SYSTEM_UID) {
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 2b7691b8..2a1aee8 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -1347,6 +1347,7 @@
updatedUserIds);
updatedUserIds = setInitialGrantForNewImplicitPermissionsLocked(origPermissions,
permissionsState, pkg, newImplicitPermissions, updatedUserIds);
+ updatedUserIds = checkIfLegacyStorageOpsNeedToBeUpdated(pkg, replace, updatedUserIds);
}
// Persist the runtime permissions state for users with changes. If permissions
@@ -1473,6 +1474,28 @@
}
/**
+ * When the app has requested legacy storage we might need to update
+ * {@link android.app.AppOpsManager#OP_LEGACY_STORAGE}. Hence force an update in
+ * {@link com.android.server.policy.PermissionPolicyService#synchronizePackagePermissionsAndAppOpsForUser(Context, String, int)}
+ *
+ * @param pkg The package for which the permissions are updated
+ * @param replace If the app is being replaced
+ * @param updatedUserIds The ids of the users that already changed.
+ *
+ * @return The ids of the users that are changed
+ */
+ private @NonNull int[] checkIfLegacyStorageOpsNeedToBeUpdated(
+ @NonNull PackageParser.Package pkg, boolean replace, @NonNull int[] updatedUserIds) {
+ if (replace && pkg.applicationInfo.hasRequestedLegacyExternalStorage() && (
+ pkg.requestedPermissions.contains(READ_EXTERNAL_STORAGE)
+ || pkg.requestedPermissions.contains(WRITE_EXTERNAL_STORAGE))) {
+ return UserManagerService.getInstance().getUserIds();
+ }
+
+ return updatedUserIds;
+ }
+
+ /**
* Set the state of a implicit permission that is seen for the first time.
*
* @param origPs The permission state of the package before the split
diff --git a/services/core/java/com/android/server/policy/PermissionPolicyService.java b/services/core/java/com/android/server/policy/PermissionPolicyService.java
index c809aca..02911e2 100644
--- a/services/core/java/com/android/server/policy/PermissionPolicyService.java
+++ b/services/core/java/com/android/server/policy/PermissionPolicyService.java
@@ -229,6 +229,15 @@
*
* @see #syncRestrictedOps
*/
+ private final @NonNull ArrayList<OpToUnrestrict> mOpsToAllowIfDefault = new ArrayList<>();
+
+ /**
+ * All ops that need to be flipped to allow.
+ *
+ * Currently, only used by the restricted permissions logic.
+ *
+ * @see #syncRestrictedOps
+ */
private final @NonNull ArrayList<OpToUnrestrict> mOpsToAllow = new ArrayList<>();
/**
@@ -238,7 +247,7 @@
*
* @see #syncRestrictedOps
*/
- private final @NonNull ArrayList<OpToUnrestrict> mOpsToIgnore = new ArrayList<>();
+ private final @NonNull ArrayList<OpToUnrestrict> mOpsToIgnoreIfDefault = new ArrayList<>();
/**
* All foreground permissions
@@ -262,11 +271,16 @@
final int allowCount = mOpsToAllow.size();
for (int i = 0; i < allowCount; i++) {
final OpToUnrestrict op = mOpsToAllow.get(i);
+ setUidModeAllowed(op.code, op.uid);
+ }
+ final int allowIfDefaultCount = mOpsToAllowIfDefault.size();
+ for (int i = 0; i < allowIfDefaultCount; i++) {
+ final OpToUnrestrict op = mOpsToAllowIfDefault.get(i);
setUidModeAllowedIfDefault(op.code, op.uid, op.packageName);
}
- final int ignoreCount = mOpsToIgnore.size();
- for (int i = 0; i < ignoreCount; i++) {
- final OpToUnrestrict op = mOpsToIgnore.get(i);
+ final int ignoreIfDefaultCount = mOpsToIgnoreIfDefault.size();
+ for (int i = 0; i < ignoreIfDefaultCount; i++) {
+ final OpToUnrestrict op = mOpsToIgnoreIfDefault.get(i);
setUidModeIgnoredIfDefault(op.code, op.uid, op.packageName);
}
final int defaultCount = mOpsToDefault.size();
@@ -341,7 +355,7 @@
if (applyRestriction) {
mOpsToDefault.add(new OpToRestrict(uid, opCode));
} else {
- mOpsToAllow.add(new OpToUnrestrict(uid, pkg.packageName, opCode));
+ mOpsToAllowIfDefault.add(new OpToUnrestrict(uid, pkg.packageName, opCode));
}
} else if (permissionInfo.isSoftRestricted()) {
// Storage uses a special app op to decide the mount state and
@@ -356,7 +370,7 @@
mOpsToAllow.add(new OpToUnrestrict(uid, pkg.packageName,
AppOpsManager.OP_LEGACY_STORAGE));
} else {
- mOpsToIgnore.add(new OpToUnrestrict(uid, pkg.packageName,
+ mOpsToIgnoreIfDefault.add(new OpToUnrestrict(uid, pkg.packageName,
AppOpsManager.OP_LEGACY_STORAGE));
}
}
@@ -421,6 +435,10 @@
setUidModeIfDefault(opCode, uid, AppOpsManager.MODE_ALLOWED, packageName);
}
+ private void setUidModeAllowed(int opCode, int uid) {
+ mAppOpsManager.setUidMode(opCode, uid, AppOpsManager.MODE_ALLOWED);
+ }
+
private void setUidModeIgnoredIfDefault(int opCode, int uid, @NonNull String packageName) {
setUidModeIfDefault(opCode, uid, AppOpsManager.MODE_IGNORED, packageName);
}
diff --git a/services/core/java/com/android/server/role/RoleManagerService.java b/services/core/java/com/android/server/role/RoleManagerService.java
index 33803b7..9cd6b0d 100644
--- a/services/core/java/com/android/server/role/RoleManagerService.java
+++ b/services/core/java/com/android/server/role/RoleManagerService.java
@@ -280,7 +280,7 @@
PackageManagerInternal pm = LocalServices.getService(PackageManagerInternal.class);
ByteArrayOutputStream out = new ByteArrayOutputStream();
- pm.forEachPackage(FunctionalUtils.uncheckExceptions(pkg -> {
+ pm.forEachInstalledPackage(FunctionalUtils.uncheckExceptions(pkg -> {
out.write(pkg.packageName.getBytes());
out.write(BitUtils.toBytes(pkg.getLongVersionCode()));
out.write(pm.getApplicationEnabledState(pkg.packageName, userId));
@@ -288,6 +288,7 @@
ArraySet<String> enabledComponents =
pm.getEnabledComponents(pkg.packageName, userId);
int numComponents = CollectionUtils.size(enabledComponents);
+ out.write(numComponents);
for (int i = 0; i < numComponents; i++) {
out.write(enabledComponents.valueAt(i).getBytes());
}
@@ -301,7 +302,7 @@
for (Signature signature : pkg.mSigningDetails.signatures) {
out.write(signature.toByteArray());
}
- }));
+ }), userId);
return PackageUtils.computeSha256Digest(out.toByteArray());
}
diff --git a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
index da1c413..9c19aec 100644
--- a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
+++ b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
@@ -358,8 +358,8 @@
private static void logEvent(@Nullable VersionedPackage moduleMetadataPackage, int type) {
Slog.i(TAG, "Watchdog event occurred of type: " + type);
if (moduleMetadataPackage != null) {
- StatsLog.write(StatsLog.WATCHDOG_ROLLBACK_OCCURRED, type,
- moduleMetadataPackage.getPackageName(), moduleMetadataPackage.getVersionCode());
+ StatsLog.logWatchdogRollbackOccurred(type, moduleMetadataPackage.getPackageName(),
+ moduleMetadataPackage.getVersionCode());
}
}
diff --git a/services/core/java/com/android/server/rollback/TEST_MAPPING b/services/core/java/com/android/server/rollback/TEST_MAPPING
index 921b754..8c7b5ac 100644
--- a/services/core/java/com/android/server/rollback/TEST_MAPPING
+++ b/services/core/java/com/android/server/rollback/TEST_MAPPING
@@ -14,5 +14,13 @@
}
]
}
+ ],
+ "imports": [
+ {
+ "path": "cts/tests/rollback"
+ },
+ {
+ "path": "cts/hostsidetests/rollback"
+ }
]
}
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index c885c5e..1718ac6 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -161,7 +161,7 @@
private ActivityOptions mOptions;
// If it is true, background activity can only be started in an existing task that contains
- // an activity with same uid.
+ // an activity with same uid, or if activity starts are enabled in developer options.
private boolean mRestrictedBgActivity;
private int mLaunchMode;
@@ -921,7 +921,7 @@
|| stack.getResumedActivity().info.applicationInfo.uid != realCallingUid)) {
if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
realCallingPid, realCallingUid, "Activity start")) {
- if (!restrictedBgActivity) {
+ if (!(restrictedBgActivity && handleBackgroundActivityAbort(r))) {
mController.addPendingActivityLaunch(new PendingActivityLaunch(r,
sourceRecord, startFlags, stack, callerApp));
}
@@ -1916,7 +1916,7 @@
mNoAnimation = (mLaunchFlags & FLAG_ACTIVITY_NO_ANIMATION) != 0;
- if (restrictedBgActivity) {
+ if (mRestrictedBgActivity && !mService.isBackgroundActivityStartsEnabled()) {
mAvoidMoveToFront = true;
mDoResume = false;
}
@@ -2380,7 +2380,6 @@
if (handleBackgroundActivityAbort(mStartActivity)) {
return START_ABORTED;
}
- return START_ABORTED;
}
// We only want to allow changing stack in two cases:
// 1. If the target task is not the top one. Otherwise we would move the launching task to
@@ -2553,17 +2552,15 @@
if (handleBackgroundActivityAbort(mStartActivity)) {
return START_ABORTED;
}
- return START_ABORTED;
}
final TaskRecord task = (prev != null)
? prev.getTaskRecord() : mTargetStack.createTaskRecord(
mSupervisor.getNextTaskIdForUserLocked(mStartActivity.mUserId), mStartActivity.info,
mIntent, null, null, true, mStartActivity, mSourceRecord, mOptions);
- if (mRestrictedBgActivity && !task.containsAppUid(mCallingUid)) {
+ if (mRestrictedBgActivity && prev != null && !task.containsAppUid(mCallingUid)) {
if (handleBackgroundActivityAbort(mStartActivity)) {
return START_ABORTED;
}
- return START_ABORTED;
}
addOrReparentStartingActivity(task, "setTaskToCurrentTopOrCreateNewTask");
mTargetStack.positionChildWindowContainerAtTop(task);
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 772e5e6..765c9d0 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -311,6 +311,9 @@
public static final int KEY_DISPATCHING_TIMEOUT_MS = 5 * 1000;
// How long we wait until we timeout on key dispatching during instrumentation.
static final int INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT_MS = 60 * 1000;
+ // How long we permit background activity starts after an activity in the process
+ // started or finished.
+ static final long ACTIVITY_BG_START_GRACE_PERIOD_MS = 10 * 1000;
/** Used to indicate that an app transition should be animated. */
static final boolean ANIMATE = true;
@@ -1575,6 +1578,13 @@
}
}
}
+
+ // note down that the process has finished an activity and is in background activity
+ // starts grace period
+ if (r.app != null) {
+ r.app.setLastActivityFinishTimeIfNeeded(SystemClock.uptimeMillis());
+ }
+
final long origId = Binder.clearCallingIdentity();
try {
boolean res;
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index 12b62b9..2ad25cf 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -34,6 +34,7 @@
import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RELEASE;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.wm.ActivityTaskManagerService.ACTIVITY_BG_START_GRACE_PERIOD_MS;
import static com.android.server.wm.ActivityTaskManagerService.INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT_MS;
import static com.android.server.wm.ActivityTaskManagerService.KEY_DISPATCHING_TIMEOUT_MS;
import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_NONE;
@@ -50,6 +51,7 @@
import android.content.res.Configuration;
import android.os.Message;
import android.os.RemoteException;
+import android.os.SystemClock;
import android.util.ArraySet;
import android.util.Log;
import android.util.Slog;
@@ -163,6 +165,11 @@
private final ArrayList<TaskRecord> mRecentTasks = new ArrayList<>();
// The most recent top-most activity that was resumed in the process for pre-Q app.
private ActivityRecord mPreQTopResumedActivity = null;
+ // The last time an activity was launched in the process
+ private long mLastActivityLaunchTime;
+ // The last time an activity was finished in the process while the process participated
+ // in a visible task
+ private long mLastActivityFinishTime;
// Last configuration that was reported to the process.
private final Configuration mLastReportedConfiguration;
@@ -372,6 +379,20 @@
return mUsingWrapper;
}
+ void setLastActivityLaunchTime(long launchTime) {
+ if (launchTime <= mLastActivityLaunchTime) {
+ return;
+ }
+ mLastActivityLaunchTime = launchTime;
+ }
+
+ void setLastActivityFinishTimeIfNeeded(long finishTime) {
+ if (finishTime <= mLastActivityFinishTime || !hasActivityInVisibleTask()) {
+ return;
+ }
+ mLastActivityFinishTime = finishTime;
+ }
+
public void setAllowBackgroundActivityStarts(boolean allowBackgroundActivityStarts) {
mAllowBackgroundActivityStarts = allowBackgroundActivityStarts;
}
@@ -381,6 +402,12 @@
if (mAllowBackgroundActivityStarts) {
return true;
}
+ // allow if any activity in the caller has either started or finished very recently
+ final long now = SystemClock.uptimeMillis();
+ if (now - mLastActivityLaunchTime < ACTIVITY_BG_START_GRACE_PERIOD_MS
+ || now - mLastActivityFinishTime < ACTIVITY_BG_START_GRACE_PERIOD_MS) {
+ return true;
+ }
// allow if the proc is instrumenting with background activity starts privs
if (mInstrumentingWithBackgroundActivityStartPrivileges) {
return true;
@@ -457,6 +484,8 @@
}
void addActivityIfNeeded(ActivityRecord r) {
+ // even if we already track this activity, note down that it has been launched
+ setLastActivityLaunchTime(r.lastLaunchTime);
if (mActivities.contains(r)) {
return;
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/AbUpdateInstaller.java b/services/devicepolicy/java/com/android/server/devicepolicy/AbUpdateInstaller.java
index 5acf83a..a9662c9 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/AbUpdateInstaller.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/AbUpdateInstaller.java
@@ -85,6 +85,10 @@
map.put(
UpdateEngine.ErrorCodeConstants.PAYLOAD_HASH_MISMATCH_ERROR,
InstallSystemUpdateCallback.UPDATE_ERROR_UPDATE_FILE_INVALID);
+ // TODO(b/133396459): replace with a constant.
+ map.put(
+ 26 /* kDownloadMetadataSignatureMismatch */,
+ InstallSystemUpdateCallback.UPDATE_ERROR_UPDATE_FILE_INVALID);
// Error constants corresponding to errors related to devices bad state.
map.put(
diff --git a/services/net/Android.bp b/services/net/Android.bp
index 4b0a27b..fb548f9 100644
--- a/services/net/Android.bp
+++ b/services/net/Android.bp
@@ -65,10 +65,10 @@
name: "services.net",
srcs: ["java/**/*.java"],
static_libs: [
- "dnsresolver_aidl_interface-java",
+ "dnsresolver_aidl_interface-V2-java",
"ipmemorystore-client",
- "netd_aidl_interface-java",
- "networkstack-aidl-interfaces-java",
+ "netd_aidl_interface-V2-java",
+ "networkstack-aidl-interfaces-V3-java",
],
}
@@ -81,7 +81,7 @@
"java/android/net/ipmemorystore/**/*.java",
],
static_libs: [
- "ipmemorystore-aidl-interfaces-java",
+ "ipmemorystore-aidl-interfaces-V3-java",
],
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java
index 77e2517..cdcdf91 100644
--- a/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java
@@ -68,7 +68,6 @@
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
-import android.content.pm.PackageManager;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@@ -122,8 +121,6 @@
private AlarmManagerService.ClockReceiver mClockReceiver;
@Mock
private PowerManager.WakeLock mWakeLock;
- @Mock
- private PackageManager mMockPackageManager;
private MockitoSession mMockingSession;
private Injector mInjector;
@@ -241,11 +238,6 @@
PowerManager.WakeLock getAlarmWakeLock() {
return mWakeLock;
}
-
- @Override
- boolean isAutomotive() {
- return mIsAutomotiveOverride;
- }
}
@Before
@@ -272,7 +264,6 @@
when(mMockContext.getContentResolver()).thenReturn(mMockResolver);
doReturn("min_futurity=0,min_interval=0").when(() ->
Settings.Global.getString(mMockResolver, Settings.Global.ALARM_MANAGER_CONSTANTS));
- when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
mInjector = new Injector(mMockContext);
mService = new AlarmManagerService(mMockContext, mInjector);
@@ -1024,18 +1015,6 @@
assertAlarmTypeConversion(typesToSet, typesExpected);
}
- /**
- * Confirm that wakeup alarms are never set for automotive.
- */
- @Test
- public void alarmTypesForAuto() throws Exception {
- mInjector.mIsAutomotiveOverride = true;
- final int[] typesToSet = {ELAPSED_REALTIME_WAKEUP, ELAPSED_REALTIME, RTC_WAKEUP, RTC};
- final int[] typesExpected = {ELAPSED_REALTIME, ELAPSED_REALTIME, ELAPSED_REALTIME,
- ELAPSED_REALTIME};
- assertAlarmTypeConversion(typesToSet, typesExpected);
- }
-
private void assertAlarmTypeConversion(int[] typesToSet, int[] typesExpected) throws Exception {
for (int i = 0; i < typesToSet.length; i++) {
setTestAlarm(typesToSet[i], 1234, getNewMockPendingIntent());
diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp
index 1522a60..869913d 100644
--- a/services/tests/servicestests/Android.bp
+++ b/services/tests/servicestests/Android.bp
@@ -73,7 +73,7 @@
"libui",
"libunwindstack",
"libutils",
- "netd_aidl_interface-cpp",
+ "netd_aidl_interface-V2-cpp",
],
dxflags: ["--multi-dex"],
diff --git a/services/tests/uiservicestests/Android.bp b/services/tests/uiservicestests/Android.bp
index 92198fa..4a9cef1 100644
--- a/services/tests/uiservicestests/Android.bp
+++ b/services/tests/uiservicestests/Android.bp
@@ -55,6 +55,6 @@
"libui",
"libunwindstack",
"libutils",
- "netd_aidl_interface-cpp",
+ "netd_aidl_interface-V2-cpp",
],
}
diff --git a/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java b/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
index 1ab1f7e..74c3939 100644
--- a/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
+++ b/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
@@ -20,6 +20,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.ActivityManager;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context;
@@ -769,7 +770,7 @@
final Intent intent = createDeviceAttachedIntent(device);
// Send broadcast to running activity with registered intent
- mContext.sendBroadcast(intent);
+ mContext.sendBroadcastAsUser(intent, UserHandle.of(ActivityManager.getCurrentUser()));
ApplicationInfo appInfo;
try {
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index 55159c3..d77ea6e 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -51,8 +51,6 @@
import android.os.RemoteCallback;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
-import android.os.ResultReceiver;
-import android.os.ShellCallback;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
@@ -106,7 +104,6 @@
final ArraySet<Integer> mLoadedKeyphraseIds = new ArraySet<>();
ShortcutServiceInternal mShortcutServiceInternal;
SoundTriggerInternal mSoundTriggerInternal;
- private boolean mAllowInstantService;
private final RemoteCallbackList<IVoiceInteractionSessionListener>
mVoiceInteractionSessionListeners = new RemoteCallbackList<>();
@@ -173,14 +170,6 @@
mServiceStub.switchUser(userHandle);
}
- // Called by Shell cmd
- void setAllowInstantService(boolean allowed) {
- Log.i(TAG, "setAllowInstantService(): " + allowed);
- mContext.enforceCallingPermission(Manifest.permission.MANAGE_BIND_INSTANT_SERVICE,
- "setAllowInstantService");
- mAllowInstantService = allowed;
- }
-
class LocalService extends VoiceInteractionManagerInternal {
@Override
public void startLocalVoiceInteraction(IBinder callingActivity, Bundle options) {
@@ -234,7 +223,6 @@
new IVoiceInteractionSessionShowCallback.Stub() {
@Override
public void onFailed() {
- Slog.w(TAG, "startLocalVoiceInteraction() failed");
}
@Override
@@ -283,10 +271,7 @@
}
public void initForUser(int userHandle) {
- if (DEBUG) {
- Slog.d(TAG, "**************** initForUser user=" + userHandle
- + ", allowInstantService=" + mAllowInstantService);
- }
+ if (DEBUG) Slog.d(TAG, "**************** initForUser user=" + userHandle);
String curInteractorStr = Settings.Secure.getStringForUser(
mContext.getContentResolver(),
Settings.Secure.VOICE_INTERACTION_SERVICE, userHandle);
@@ -445,7 +430,6 @@
if (!mSafeMode) {
String curService = Settings.Secure.getStringForUser(
mResolver, Settings.Secure.VOICE_INTERACTION_SERVICE, mCurUser);
- if (DEBUG) Log.d(TAG, "Service for user " + mCurUser + ": " + curService);
ComponentName serviceComponent = null;
ServiceInfo serviceInfo = null;
if (curService != null && !curService.isEmpty()) {
@@ -482,8 +466,7 @@
}
if (hasComponent) {
setImplLocked(new VoiceInteractionManagerServiceImpl(mContext,
- UiThread.getHandler(), this, mCurUser, serviceComponent,
- mAllowInstantService));
+ UiThread.getHandler(), this, mCurUser, serviceComponent));
mImpl.startLocked();
} else {
setImplLocked(null);
@@ -1244,26 +1227,16 @@
synchronized (this) {
pw.println("VOICE INTERACTION MANAGER (dumpsys voiceinteraction)");
pw.println(" mEnableService: " + mEnableService);
- pw.println(" mAllowInstantService: " + mAllowInstantService);
if (mImpl == null) {
pw.println(" (No active implementation)");
return;
}
mImpl.dumpLocked(fd, pw, args);
}
-
mSoundTriggerInternal.dump(fd, pw, args);
}
@Override
- public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
- String[] args, ShellCallback callback, ResultReceiver resultReceiver)
- throws RemoteException {
- new VoiceInteractionManagerServiceShellCommand(VoiceInteractionManagerService.this)
- .exec(this, in, out, err, args, callback, resultReceiver);
- }
-
- @Override
public void setUiHints(IVoiceInteractionService service, Bundle hints) {
synchronized (this) {
enforceIsCurrentVoiceInteractionService(service);
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
index 4881ade..a1210cf 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
@@ -80,7 +80,6 @@
final VoiceInteractionServiceInfo mInfo;
final ComponentName mSessionComponentName;
final IWindowManager mIWindowManager;
- final boolean mAllowInstant;
boolean mBound = false;
IVoiceInteractionService mService;
@@ -126,7 +125,7 @@
VoiceInteractionManagerServiceImpl(Context context, Handler handler,
VoiceInteractionManagerService.VoiceInteractionManagerServiceStub stub,
- int userHandle, ComponentName service, boolean allowInstant) {
+ int userHandle, ComponentName service) {
mContext = context;
mHandler = handler;
mServiceStub = stub;
@@ -134,7 +133,6 @@
mComponent = service;
mAm = ActivityManager.getService();
mAtm = ActivityTaskManager.getService();
- mAllowInstant = allowInstant;
VoiceInteractionServiceInfo info;
try {
info = new VoiceInteractionServiceInfo(context.getPackageManager(), service, mUser);
@@ -169,7 +167,7 @@
if (mActiveSession == null) {
mActiveSession = new VoiceInteractionSessionConnection(mServiceStub,
mSessionComponentName, mUser, mContext, this,
- mInfo.getServiceInfo().applicationInfo.uid, mHandler, mAllowInstant);
+ mInfo.getServiceInfo().applicationInfo.uid, mHandler);
}
List<IBinder> activityTokens = null;
if (activityToken != null) {
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceShellCommand.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceShellCommand.java
deleted file mode 100644
index de1191f..0000000
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceShellCommand.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.server.voiceinteraction;
-
-import android.annotation.NonNull;
-import android.os.ShellCommand;
-
-import java.io.PrintWriter;
-
-final class VoiceInteractionManagerServiceShellCommand extends ShellCommand {
-
- private final VoiceInteractionManagerService mService;
-
- VoiceInteractionManagerServiceShellCommand(@NonNull VoiceInteractionManagerService service) {
- this.mService = service;
- }
-
- @Override
- public int onCommand(String cmd) {
- if (cmd == null) {
- return handleDefaultCommands(cmd);
- }
- final PrintWriter pw = getOutPrintWriter();
- switch (cmd) {
- case "set bind-instant-service-allowed":
- case "set":
- return requestSet(pw);
- default:
- return handleDefaultCommands(cmd);
- }
- }
-
- @Override
- public void onHelp() {
- try (PrintWriter pw = getOutPrintWriter();) {
- pw.println("VoiceInteraction Service (voiceinteraction) commands:");
- pw.println(" help");
- pw.println(" Prints this help text.");
- pw.println("");
- pw.println(" set bind-instant-service-allowed [true | false]");
- pw.println(" Sets whether binding to services provided by instant apps is allowed");
- pw.println("");
- }
- }
-
- private int requestSet(@NonNull PrintWriter pw) {
- final String what = getNextArgRequired();
-
- switch(what) {
- case "bind-instant-service-allowed":
- return setBindInstantService(pw);
- default:
- pw.println("Invalid set: " + what);
- return -1;
- }
- }
-
- private int setBindInstantService(@NonNull PrintWriter pw) {
- final String mode = getNextArgRequired();
- switch (mode.toLowerCase()) {
- case "true":
- mService.setAllowInstantService(true);
- return 0;
- case "false":
- mService.setAllowInstantService(false);
- return 0;
- default:
- pw.println("Invalid mode: " + mode);
- return -1;
- }
- }
-}
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
index 3c47044..f16dec6 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
@@ -138,8 +138,7 @@
};
public VoiceInteractionSessionConnection(Object lock, ComponentName component, int user,
- Context context, Callback callback, int callingUid, Handler handler,
- boolean allowInstant) {
+ Context context, Callback callback, int callingUid, Handler handler) {
mLock = lock;
mSessionComponentName = component;
mUser = user;
@@ -160,13 +159,10 @@
mPermissionOwner = permOwner;
mBindIntent = new Intent(VoiceInteractionService.SERVICE_INTERFACE);
mBindIntent.setComponent(mSessionComponentName);
- int flags = Context.BIND_AUTO_CREATE | Context.BIND_WAIVE_PRIORITY
- | Context.BIND_ALLOW_OOM_MANAGEMENT
- | Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS;
- if (allowInstant) {
- flags |= Context.BIND_ALLOW_INSTANT;
- }
- mBound = mContext.bindServiceAsUser(mBindIntent, this, flags, new UserHandle(mUser));
+ mBound = mContext.bindServiceAsUser(mBindIntent, this,
+ Context.BIND_AUTO_CREATE | Context.BIND_WAIVE_PRIORITY
+ | Context.BIND_ALLOW_OOM_MANAGEMENT
+ | Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS, new UserHandle(mUser));
if (mBound) {
try {
mIWindowManager.addWindowToken(mToken, TYPE_VOICE_INTERACTION, DEFAULT_DISPLAY);
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
index 8c20afe..6860235 100644
--- a/telephony/java/android/telephony/SmsManager.java
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -721,20 +721,17 @@
}
/**
- * Divide a message text into several fragments, none bigger than
- * the maximum SMS message size.
+ * Divide a message text into several fragments, none bigger than the maximum SMS message size.
*
- * @param text the original message. Must not be null.
- * @return an <code>ArrayList</code> of strings that, in order,
- * comprise the original message
- *
- * @throws IllegalArgumentException if text is null
+ * @param text the original message. Must not be null.
+ * @return an <code>ArrayList</code> of strings that, in order, comprise the original message.
+ * @throws IllegalArgumentException if text is null.
*/
public ArrayList<String> divideMessage(String text) {
if (null == text) {
throw new IllegalArgumentException("text is null");
}
- return SmsMessage.fragmentText(text);
+ return SmsMessage.fragmentText(text, getSubscriptionId());
}
/**
@@ -1965,16 +1962,22 @@
}
/**
- * Get default sms subscription id
+ * Get default sms subscription id.
*
- * @return the user-defined default SMS subscription id or
- * {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID} if no default is set.
+ * <p class="note"><strong>Note:</strong>This returns a value different from
+ * {@link SubscriptionManager#getDefaultSmsSubscriptionId} if the user has not chosen a default.
+ * In this case it returns the active subscription id if there's only one active subscription
+ * available.
+ *
+ * @return the user-defined default SMS subscription id, or the active subscription id if
+ * there's only one active subscription available, otherwise
+ * {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID}.
*/
public static int getDefaultSmsSubscriptionId() {
try {
- return SubscriptionManager.getDefaultSmsSubscriptionId();
- } catch (NullPointerException ex) {
- return -1;
+ return getISmsServiceOrThrow().getPreferredSmsSubscription();
+ } catch (RemoteException e) {
+ return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
}
}
diff --git a/telephony/java/android/telephony/SmsMessage.java b/telephony/java/android/telephony/SmsMessage.java
index 2aa4768..7d4bcb7 100644
--- a/telephony/java/android/telephony/SmsMessage.java
+++ b/telephony/java/android/telephony/SmsMessage.java
@@ -337,27 +337,45 @@
*/
/**
- * Calculates the number of SMS's required to encode the message body and
- * the number of characters remaining until the next message.
+ * Calculates the number of SMS's required to encode the message body and the number of
+ * characters remaining until the next message.
*
* @param msgBody the message to encode
- * @param use7bitOnly if true, characters that are not part of the
- * radio-specific 7-bit encoding are counted as single
- * space chars. If false, and if the messageBody contains
- * non-7-bit encodable characters, length is calculated
- * using a 16-bit encoding.
- * @return an int[4] with int[0] being the number of SMS's
- * required, int[1] the number of code units used, and
- * int[2] is the number of code units remaining until the
- * next message. int[3] is an indicator of the encoding
- * code unit size (see the ENCODING_* definitions in SmsConstants)
+ * @param use7bitOnly if true, characters that are not part of the radio-specific 7-bit encoding
+ * are counted as single space chars. If false, and if the messageBody contains non-7-bit
+ * encodable characters, length is calculated using a 16-bit encoding.
+ * @return an int[4] with int[0] being the number of SMS's required, int[1] the number of code
+ * units used, and int[2] is the number of code units remaining until the next message.
+ * int[3] is an indicator of the encoding code unit size (see the ENCODING_* definitions in
+ * SmsConstants).
*/
public static int[] calculateLength(CharSequence msgBody, boolean use7bitOnly) {
+ return calculateLength(msgBody, use7bitOnly, SmsManager.getDefaultSmsSubscriptionId());
+ }
+
+ /**
+ * Calculates the number of SMS's required to encode the message body and the number of
+ * characters remaining until the next message.
+ *
+ * @param msgBody the message to encode
+ * @param use7bitOnly if true, characters that are not part of the radio-specific 7-bit encoding
+ * are counted as single space chars. If false, and if the messageBody contains non-7-bit
+ * encodable characters, length is calculated using a 16-bit encoding.
+ * @param subId Subscription to take SMS format.
+ * @return an int[4] with int[0] being the number of SMS's required, int[1] the number of code
+ * units used, and int[2] is the number of code units remaining until the next message.
+ * int[3] is an indicator of the encoding code unit size (see the ENCODING_* definitions in
+ * SmsConstants).
+ * @hide
+ */
+ public static int[] calculateLength(CharSequence msgBody, boolean use7bitOnly, int subId) {
// this function is for MO SMS
- TextEncodingDetails ted = (useCdmaFormatForMoSms()) ?
- com.android.internal.telephony.cdma.SmsMessage.calculateLength(msgBody, use7bitOnly,
- true) :
- com.android.internal.telephony.gsm.SmsMessage.calculateLength(msgBody, use7bitOnly);
+ TextEncodingDetails ted =
+ useCdmaFormatForMoSms(subId)
+ ? com.android.internal.telephony.cdma.SmsMessage.calculateLength(
+ msgBody, use7bitOnly, true)
+ : com.android.internal.telephony.gsm.SmsMessage.calculateLength(
+ msgBody, use7bitOnly);
int ret[] = new int[4];
ret[0] = ted.msgCount;
ret[1] = ted.codeUnitCount;
@@ -367,21 +385,37 @@
}
/**
- * Divide a message text into several fragments, none bigger than
- * the maximum SMS message text size.
+ * Divide a message text into several fragments, none bigger than the maximum SMS message text
+ * size.
*
* @param text text, must not be null.
- * @return an <code>ArrayList</code> of strings that, in order,
- * comprise the original msg text
- *
+ * @return an <code>ArrayList</code> of strings that, in order, comprise the original msg text.
* @hide
*/
@UnsupportedAppUsage
public static ArrayList<String> fragmentText(String text) {
+ return fragmentText(text, SmsManager.getDefaultSmsSubscriptionId());
+ }
+
+ /**
+ * Divide a message text into several fragments, none bigger than the maximum SMS message text
+ * size.
+ *
+ * @param text text, must not be null.
+ * @param subId Subscription to take SMS format.
+ * @return an <code>ArrayList</code> of strings that, in order, comprise the original msg text.
+ * @hide
+ */
+ public static ArrayList<String> fragmentText(String text, int subId) {
// This function is for MO SMS
- TextEncodingDetails ted = (useCdmaFormatForMoSms()) ?
- com.android.internal.telephony.cdma.SmsMessage.calculateLength(text, false, true) :
- com.android.internal.telephony.gsm.SmsMessage.calculateLength(text, false);
+ final boolean isCdma = useCdmaFormatForMoSms(subId);
+
+ TextEncodingDetails ted =
+ isCdma
+ ? com.android.internal.telephony.cdma.SmsMessage.calculateLength(
+ text, false, true)
+ : com.android.internal.telephony.gsm.SmsMessage.calculateLength(
+ text, false);
// TODO(cleanup): The code here could be rolled into the logic
// below cleanly if these MAX_* constants were defined more
@@ -427,18 +461,19 @@
String newMsgBody = null;
Resources r = Resources.getSystem();
if (r.getBoolean(com.android.internal.R.bool.config_sms_force_7bit_encoding)) {
- newMsgBody = Sms7BitEncodingTranslator.translate(text);
+ newMsgBody = Sms7BitEncodingTranslator.translate(text, isCdma);
}
if (TextUtils.isEmpty(newMsgBody)) {
newMsgBody = text;
}
+
int pos = 0; // Index in code units.
int textLen = newMsgBody.length();
ArrayList<String> result = new ArrayList<String>(ted.msgCount);
while (pos < textLen) {
int nextPos = 0; // Counts code units.
if (ted.codeUnitSize == SmsConstants.ENCODING_7BIT) {
- if (useCdmaFormatForMoSms() && ted.msgCount == 1) {
+ if (isCdma && ted.msgCount == 1) {
// For a singleton CDMA message, the encoding must be ASCII...
nextPos = pos + Math.min(limit, textLen - pos);
} else {
@@ -461,25 +496,39 @@
}
/**
- * Calculates the number of SMS's required to encode the message body and
- * the number of characters remaining until the next message, given the
- * current encoding.
+ * Calculates the number of SMS's required to encode the message body and the number of
+ * characters remaining until the next message, given the current encoding.
*
* @param messageBody the message to encode
- * @param use7bitOnly if true, characters that are not part of the radio
- * specific (GSM / CDMA) alphabet encoding are converted to as a
- * single space characters. If false, a messageBody containing
- * non-GSM or non-CDMA alphabet characters are encoded using
- * 16-bit encoding.
- * @return an int[4] with int[0] being the number of SMS's required, int[1]
- * the number of code units used, and int[2] is the number of code
- * units remaining until the next message. int[3] is the encoding
- * type that should be used for the message.
+ * @param use7bitOnly if true, characters that are not part of the radio specific (GSM / CDMA)
+ * alphabet encoding are converted to as a single space characters. If false, a messageBody
+ * containing non-GSM or non-CDMA alphabet characters are encoded using 16-bit encoding.
+ * @return an int[4] with int[0] being the number of SMS's required, int[1] the number of code
+ * units used, and int[2] is the number of code units remaining until the next message.
+ * int[3] is the encoding type that should be used for the message.
*/
public static int[] calculateLength(String messageBody, boolean use7bitOnly) {
return calculateLength((CharSequence)messageBody, use7bitOnly);
}
+ /**
+ * Calculates the number of SMS's required to encode the message body and the number of
+ * characters remaining until the next message, given the current encoding.
+ *
+ * @param messageBody the message to encode
+ * @param use7bitOnly if true, characters that are not part of the radio specific (GSM / CDMA)
+ * alphabet encoding are converted to as a single space characters. If false, a messageBody
+ * containing non-GSM or non-CDMA alphabet characters are encoded using 16-bit encoding.
+ * @param subId Subscription to take SMS format.
+ * @return an int[4] with int[0] being the number of SMS's required, int[1] the number of code
+ * units used, and int[2] is the number of code units remaining until the next message.
+ * int[3] is the encoding type that should be used for the message.
+ * @hide
+ */
+ public static int[] calculateLength(String messageBody, boolean use7bitOnly, int subId) {
+ return calculateLength((CharSequence) messageBody, use7bitOnly, subId);
+ }
+
/*
* TODO(cleanup): It looks like there is now no useful reason why
* apps should generate pdus themselves using these routines,
@@ -510,8 +559,12 @@
*/
public static SubmitPdu getSubmitPdu(String scAddress,
String destinationAddress, String message, boolean statusReportRequested) {
- return getSubmitPdu(scAddress, destinationAddress, message, statusReportRequested,
- SubscriptionManager.getDefaultSmsSubscriptionId());
+ return getSubmitPdu(
+ scAddress,
+ destinationAddress,
+ message,
+ statusReportRequested,
+ SmsManager.getDefaultSmsSubscriptionId());
}
/**
@@ -834,7 +887,7 @@
@UnsupportedAppUsage
private static boolean useCdmaFormatForMoSms() {
// IMS is registered with SMS support, check the SMS format supported
- return useCdmaFormatForMoSms(SubscriptionManager.getDefaultSmsSubscriptionId());
+ return useCdmaFormatForMoSms(SmsManager.getDefaultSmsSubscriptionId());
}
/**
@@ -863,7 +916,7 @@
* @return true if current phone type is cdma, false otherwise.
*/
private static boolean isCdmaVoice() {
- return isCdmaVoice(SubscriptionManager.getDefaultSmsSubscriptionId());
+ return isCdmaVoice(SmsManager.getDefaultSmsSubscriptionId());
}
/**
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index dab1e6f..d63c37a 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -93,6 +93,8 @@
import com.android.internal.telephony.RILConstants;
import com.android.internal.telephony.TelephonyProperties;
+import dalvik.system.VMRuntime;
+
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.annotation.Retention;
@@ -108,8 +110,6 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import dalvik.system.VMRuntime;
-
/**
* Provides access to information about the telephony services on
* the device. Applications can use the methods in this class to
@@ -1551,6 +1551,17 @@
* href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner
* access is deprecated and will be removed in a future release.
*
+ * <p>If the calling app does not meet one of these requirements then this method will behave
+ * as follows:
+ *
+ * <ul>
+ * <li>If the calling app's target SDK is API level 28 or lower and the app has the
+ * READ_PHONE_STATE permission then null is returned.</li>
+ * <li>If the calling app's target SDK is API level 28 or lower and the app does not have
+ * the READ_PHONE_STATE permission, or if the calling app is targeting API level 29 or
+ * higher, then a SecurityException is thrown.</li>
+ * </ul>
+ *
* @deprecated Use (@link getImei} which returns IMEI for GSM or (@link getMeid} which returns
* MEID for CDMA.
*/
@@ -1581,6 +1592,17 @@
* href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner
* access is deprecated and will be removed in a future release.
*
+ * <p>If the calling app does not meet one of these requirements then this method will behave
+ * as follows:
+ *
+ * <ul>
+ * <li>If the calling app's target SDK is API level 28 or lower and the app has the
+ * READ_PHONE_STATE permission then null is returned.</li>
+ * <li>If the calling app's target SDK is API level 28 or lower and the app does not have
+ * the READ_PHONE_STATE permission, or if the calling app is targeting API level 29 or
+ * higher, then a SecurityException is thrown.</li>
+ * </ul>
+ *
* @param slotIndex of which deviceID is returned
*
* @deprecated Use (@link getImei} which returns IMEI for GSM or (@link getMeid} which returns
@@ -1613,6 +1635,17 @@
* managed profile on the device; for more details see <a
* href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner
* access is deprecated and will be removed in a future release.
+ *
+ * <p>If the calling app does not meet one of these requirements then this method will behave
+ * as follows:
+ *
+ * <ul>
+ * <li>If the calling app's target SDK is API level 28 or lower and the app has the
+ * READ_PHONE_STATE permission then null is returned.</li>
+ * <li>If the calling app's target SDK is API level 28 or lower and the app does not have
+ * the READ_PHONE_STATE permission, or if the calling app is targeting API level 29 or
+ * higher, then a SecurityException is thrown.</li>
+ * </ul>
*/
@SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
@@ -1631,6 +1664,17 @@
* href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner
* access is deprecated and will be removed in a future release.
*
+ * <p>If the calling app does not meet one of these requirements then this method will behave
+ * as follows:
+ *
+ * <ul>
+ * <li>If the calling app's target SDK is API level 28 or lower and the app has the
+ * READ_PHONE_STATE permission then null is returned.</li>
+ * <li>If the calling app's target SDK is API level 28 or lower and the app does not have
+ * the READ_PHONE_STATE permission, or if the calling app is targeting API level 29 or
+ * higher, then a SecurityException is thrown.</li>
+ * </ul>
+ *
* @param slotIndex of which IMEI is returned
*/
@SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
@@ -1686,6 +1730,17 @@
* managed profile on the device; for more details see <a
* href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner
* access is deprecated and will be removed in a future release.
+ *
+ * <p>If the calling app does not meet one of these requirements then this method will behave
+ * as follows:
+ *
+ * <ul>
+ * <li>If the calling app's target SDK is API level 28 or lower and the app has the
+ * READ_PHONE_STATE permission then null is returned.</li>
+ * <li>If the calling app's target SDK is API level 28 or lower and the app does not have
+ * the READ_PHONE_STATE permission, or if the calling app is targeting API level 29 or
+ * higher, then a SecurityException is thrown.</li>
+ * </ul>
*/
@SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
@@ -1703,6 +1758,17 @@
* href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner
* access is deprecated and will be removed in a future release.
*
+ * <p>If the calling app does not meet one of these requirements then this method will behave
+ * as follows:
+ *
+ * <ul>
+ * <li>If the calling app's target SDK is API level 28 or lower and the app has the
+ * READ_PHONE_STATE permission then null is returned.</li>
+ * <li>If the calling app's target SDK is API level 28 or lower and the app does not have
+ * the READ_PHONE_STATE permission, or if the calling app is targeting API level 29 or
+ * higher, then a SecurityException is thrown.</li>
+ * </ul>
+ *
* @param slotIndex of which MEID is returned
*/
@SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
@@ -2246,7 +2312,7 @@
@UnsupportedAppUsage
public String getNetworkOperatorForPhone(int phoneId) {
return getTelephonyProperty(phoneId, TelephonyProperties.PROPERTY_OPERATOR_NUMERIC, "");
- }
+ }
/**
@@ -2446,21 +2512,7 @@
* @return the NETWORK_TYPE_xxxx for current data connection.
*/
public @NetworkType int getNetworkType() {
- try {
- ITelephony telephony = getITelephony();
- if (telephony != null) {
- return telephony.getNetworkType();
- } else {
- // This can happen when the ITelephony interface is not up yet.
- return NETWORK_TYPE_UNKNOWN;
- }
- } catch(RemoteException ex) {
- // This shouldn't happen in the normal case
- return NETWORK_TYPE_UNKNOWN;
- } catch (NullPointerException ex) {
- // This could happen before phone restarts due to crashing
- return NETWORK_TYPE_UNKNOWN;
- }
+ return getNetworkType(getSubId(SubscriptionManager.getDefaultDataSubscriptionId()));
}
/**
@@ -2491,7 +2543,7 @@
* @hide
*/
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
public int getNetworkType(int subId) {
try {
ITelephony telephony = getITelephony();
@@ -3217,6 +3269,17 @@
* managed profile on the device; for more details see <a
* href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner
* access is deprecated and will be removed in a future release.
+ *
+ * <p>If the calling app does not meet one of these requirements then this method will behave
+ * as follows:
+ *
+ * <ul>
+ * <li>If the calling app's target SDK is API level 28 or lower and the app has the
+ * READ_PHONE_STATE permission then null is returned.</li>
+ * <li>If the calling app's target SDK is API level 28 or lower and the app does not have
+ * the READ_PHONE_STATE permission, or if the calling app is targeting API level 29 or
+ * higher, then a SecurityException is thrown.</li>
+ * </ul>
*/
@SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
@@ -3235,6 +3298,17 @@
* href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner
* access is deprecated and will be removed in a future release.
*
+ * <p>If the calling app does not meet one of these requirements then this method will behave
+ * as follows:
+ *
+ * <ul>
+ * <li>If the calling app's target SDK is API level 28 or lower and the app has the
+ * READ_PHONE_STATE permission then null is returned.</li>
+ * <li>If the calling app's target SDK is API level 28 or lower and the app does not have
+ * the READ_PHONE_STATE permission, or if the calling app is targeting API level 29 or
+ * higher, then a SecurityException is thrown.</li>
+ * </ul>
+ *
* @param subId for which Sim Serial number is returned
* @hide
*/
@@ -3466,6 +3540,17 @@
* managed profile on the device; for more details see <a
* href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner
* access is deprecated and will be removed in a future release.
+ *
+ * <p>If the calling app does not meet one of these requirements then this method will behave
+ * as follows:
+ *
+ * <ul>
+ * <li>If the calling app's target SDK is API level 28 or lower and the app has the
+ * READ_PHONE_STATE permission then null is returned.</li>
+ * <li>If the calling app's target SDK is API level 28 or lower and the app does not have
+ * the READ_PHONE_STATE permission, or if the calling app is targeting API level 29 or
+ * higher, then a SecurityException is thrown.</li>
+ * </ul>
*/
@SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
@@ -3485,6 +3570,17 @@
* href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner
* access is deprecated and will be removed in a future release.
*
+ * <p>If the calling app does not meet one of these requirements then this method will behave
+ * as follows:
+ *
+ * <ul>
+ * <li>If the calling app's target SDK is API level 28 or lower and the app has the
+ * READ_PHONE_STATE permission then null is returned.</li>
+ * <li>If the calling app's target SDK is API level 28 or lower and the app does not have
+ * the READ_PHONE_STATE permission, or if the calling app is targeting API level 29 or
+ * higher, then a SecurityException is thrown.</li>
+ * </ul>
+ *
* @param subId whose subscriber id is returned
* @hide
*/
@@ -5261,7 +5357,7 @@
*/
public String getMmsUserAgent() {
if (mContext == null) return null;
- return mContext.getResources().getString(
+ return SubscriptionManager.getResourcesForSubId(mContext, getSubId()).getString(
com.android.internal.R.string.config_mms_user_agent);
}
@@ -5270,7 +5366,7 @@
*/
public String getMmsUAProfUrl() {
if (mContext == null) return null;
- return mContext.getResources().getString(
+ return SubscriptionManager.getResourcesForSubId(mContext, getSubId()).getString(
com.android.internal.R.string.config_mms_user_agent_profile_url);
}
diff --git a/telephony/java/com/android/internal/telephony/GsmAlphabet.java b/telephony/java/com/android/internal/telephony/GsmAlphabet.java
index a774cdc..8797589 100644
--- a/telephony/java/com/android/internal/telephony/GsmAlphabet.java
+++ b/telephony/java/com/android/internal/telephony/GsmAlphabet.java
@@ -16,19 +16,17 @@
package com.android.internal.telephony;
+import android.annotation.UnsupportedAppUsage;
import android.content.res.Resources;
+import android.os.Build;
+import android.telephony.Rlog;
import android.text.TextUtils;
import android.util.SparseIntArray;
-import android.annotation.UnsupportedAppUsage;
-import android.os.Build;
-import android.telephony.Rlog;
+import com.android.internal.R;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
-import com.android.internal.telephony.SmsConstants;
-import com.android.internal.R;
-
import java.util.ArrayList;
import java.util.List;
@@ -868,7 +866,6 @@
ted.msgCount = 1;
ted.codeUnitsRemaining = SmsConstants.MAX_USER_DATA_SEPTETS - septets;
}
- ted.codeUnitSize = SmsConstants.ENCODING_7BIT;
return ted;
}
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 68fd9ac..63aded1 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -460,13 +460,6 @@
void sendDialerSpecialCode(String callingPackageName, String inputCode);
/**
- * Returns the network type for data transmission
- * Legacy call, permission-free
- */
- @UnsupportedAppUsage
- int getNetworkType();
-
- /**
* Returns the network type of a subId.
* @param subId user preferred subId.
* @param callingPackage package making the call.
diff --git a/telephony/java/com/android/internal/telephony/Sms7BitEncodingTranslator.java b/telephony/java/com/android/internal/telephony/Sms7BitEncodingTranslator.java
index 439eaea..a360c64 100644
--- a/telephony/java/com/android/internal/telephony/Sms7BitEncodingTranslator.java
+++ b/telephony/java/com/android/internal/telephony/Sms7BitEncodingTranslator.java
@@ -16,19 +16,14 @@
package com.android.internal.telephony;
-import android.telephony.Rlog;
-import android.os.Build;
-import android.util.SparseIntArray;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
-import android.telephony.SmsManager;
-import android.telephony.TelephonyManager;
+import android.os.Build;
+import android.telephony.Rlog;
+import android.util.SparseIntArray;
-import com.android.internal.util.XmlUtils;
import com.android.internal.telephony.cdma.sms.UserData;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
+import com.android.internal.util.XmlUtils;
public class Sms7BitEncodingTranslator {
private static final String TAG = "Sms7BitEncodingTranslator";
@@ -47,17 +42,14 @@
private static final String XML_TO_TAG = "to";
/**
- * Translates each message character that is not supported by GSM 7bit
- * alphabet into a supported one
+ * Translates each message character that is not supported by GSM 7bit alphabet into a supported
+ * one.
*
- * @param message
- * message to be translated
- * @param throwsException
- * if true and some error occurs during translation, an exception
- * is thrown; otherwise a null String is returned
- * @return translated message or null if some error occur
+ * @param message message to be translated.
+ * @param isCdmaFormat true if cdma format should be used.
+ * @return translated message or null if some error occur.
*/
- public static String translate(CharSequence message) {
+ public static String translate(CharSequence message, boolean isCdmaFormat) {
if (message == null) {
Rlog.w(TAG, "Null message can not be translated");
return null;
@@ -80,7 +72,6 @@
(mTranslationTableGSM != null && mTranslationTableGSM.size() > 0) ||
(mTranslationTableCDMA != null && mTranslationTableCDMA.size() > 0)) {
char[] output = new char[size];
- boolean isCdmaFormat = useCdmaFormatForMoSms();
for (int i = 0; i < size; i++) {
output[i] = translateIfNeeded(message.charAt(i), isCdmaFormat);
}
@@ -159,16 +150,6 @@
}
}
- private static boolean useCdmaFormatForMoSms() {
- if (!SmsManager.getDefault().isImsSmsSupported()) {
- // use Voice technology to determine SMS format.
- return TelephonyManager.getDefault().getCurrentPhoneType()
- == PhoneConstants.PHONE_TYPE_CDMA;
- }
- // IMS is registered with SMS support, check the SMS format supported
- return (SmsConstants.FORMAT_3GPP2.equals(SmsManager.getDefault().getImsSmsFormat()));
- }
-
/**
* Load the whole translation table file from the framework resource
* encoded in XML.
diff --git a/telephony/java/com/android/internal/telephony/TelephonyPermissions.java b/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
index 2552f04..e8e2a3d 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
@@ -102,6 +102,16 @@
callingPackage, message);
}
+ /** Identical to checkCallingOrSelfReadPhoneState but never throws SecurityException */
+ public static boolean checkCallingOrSelfReadPhoneStateNoThrow(
+ Context context, int subId, String callingPackage, String message) {
+ try {
+ return checkCallingOrSelfReadPhoneState(context, subId, callingPackage, message);
+ } catch (SecurityException se) {
+ return false;
+ }
+ }
+
/**
* Check whether the app with the given pid/uid can read phone state.
*
diff --git a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
index a31fa0b..f2ebc98 100644
--- a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
+++ b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
@@ -16,18 +16,18 @@
package com.android.internal.telephony.cdma;
-import android.os.Parcel;
+import android.content.res.Resources;
import android.os.SystemProperties;
import android.telephony.PhoneNumberUtils;
+import android.telephony.Rlog;
import android.telephony.SmsCbLocation;
import android.telephony.SmsCbMessage;
import android.telephony.cdma.CdmaSmsCbProgramData;
-import android.telephony.Rlog;
-import android.util.Log;
import android.text.TextUtils;
-import android.content.res.Resources;
+import android.util.Log;
import com.android.internal.telephony.GsmAlphabet.TextEncodingDetails;
+import com.android.internal.telephony.Sms7BitEncodingTranslator;
import com.android.internal.telephony.SmsAddress;
import com.android.internal.telephony.SmsConstants;
import com.android.internal.telephony.SmsHeader;
@@ -41,7 +41,6 @@
import com.android.internal.telephony.uicc.IccUtils;
import com.android.internal.util.BitwiseInputStream;
import com.android.internal.util.HexDump;
-import com.android.internal.telephony.Sms7BitEncodingTranslator;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
@@ -418,7 +417,7 @@
CharSequence newMsgBody = null;
Resources r = Resources.getSystem();
if (r.getBoolean(com.android.internal.R.bool.config_sms_force_7bit_encoding)) {
- newMsgBody = Sms7BitEncodingTranslator.translate(messageBody);
+ newMsgBody = Sms7BitEncodingTranslator.translate(messageBody, true);
}
if (TextUtils.isEmpty(newMsgBody)) {
newMsgBody = messageBody;
diff --git a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java
index 19465a4..e236571 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java
@@ -16,34 +16,33 @@
package com.android.internal.telephony.gsm;
-import android.telephony.PhoneNumberUtils;
-import android.text.format.Time;
-import android.telephony.Rlog;
+import static com.android.internal.telephony.SmsConstants.ENCODING_16BIT;
+import static com.android.internal.telephony.SmsConstants.ENCODING_7BIT;
+import static com.android.internal.telephony.SmsConstants.ENCODING_8BIT;
+import static com.android.internal.telephony.SmsConstants.ENCODING_KSC5601;
+import static com.android.internal.telephony.SmsConstants.ENCODING_UNKNOWN;
+import static com.android.internal.telephony.SmsConstants.MAX_USER_DATA_BYTES;
+import static com.android.internal.telephony.SmsConstants.MAX_USER_DATA_SEPTETS;
+import static com.android.internal.telephony.SmsConstants.MessageClass;
+
import android.content.res.Resources;
+import android.telephony.PhoneNumberUtils;
+import android.telephony.Rlog;
import android.text.TextUtils;
+import android.text.format.Time;
import com.android.internal.telephony.EncodeException;
import com.android.internal.telephony.GsmAlphabet;
import com.android.internal.telephony.GsmAlphabet.TextEncodingDetails;
-import com.android.internal.telephony.uicc.IccUtils;
+import com.android.internal.telephony.Sms7BitEncodingTranslator;
import com.android.internal.telephony.SmsHeader;
import com.android.internal.telephony.SmsMessageBase;
-import com.android.internal.telephony.Sms7BitEncodingTranslator;
+import com.android.internal.telephony.uicc.IccUtils;
import java.io.ByteArrayOutputStream;
import java.io.UnsupportedEncodingException;
import java.text.ParseException;
-import static com.android.internal.telephony.SmsConstants.MessageClass;
-import static com.android.internal.telephony.SmsConstants.ENCODING_UNKNOWN;
-import static com.android.internal.telephony.SmsConstants.ENCODING_7BIT;
-import static com.android.internal.telephony.SmsConstants.ENCODING_8BIT;
-import static com.android.internal.telephony.SmsConstants.ENCODING_16BIT;
-import static com.android.internal.telephony.SmsConstants.ENCODING_KSC5601;
-import static com.android.internal.telephony.SmsConstants.MAX_USER_DATA_SEPTETS;
-import static com.android.internal.telephony.SmsConstants.MAX_USER_DATA_BYTES;
-import static com.android.internal.telephony.SmsConstants.MAX_USER_DATA_BYTES_WITH_HEADER;
-
/**
* A Short Message Service message.
*
@@ -914,7 +913,7 @@
CharSequence newMsgBody = null;
Resources r = Resources.getSystem();
if (r.getBoolean(com.android.internal.R.bool.config_sms_force_7bit_encoding)) {
- newMsgBody = Sms7BitEncodingTranslator.translate(msgBody);
+ newMsgBody = Sms7BitEncodingTranslator.translate(msgBody, false);
}
if (TextUtils.isEmpty(newMsgBody)) {
newMsgBody = msgBody;
diff --git a/tests/RollbackTest/Android.bp b/tests/RollbackTest/Android.bp
index 1932871..1cf3d36 100644
--- a/tests/RollbackTest/Android.bp
+++ b/tests/RollbackTest/Android.bp
@@ -78,45 +78,6 @@
package_splits: ["anydpi"],
}
-apex {
- name: "com.android.tests.rollback.testapex.RollbackTestApexV1",
- manifest: "TestApex/RollbackTestApexV1.json",
- file_contexts: "apex.test",
- prebuilts: ["RollbackTestApex.prebuilt.txt"],
- key: "RollbackTestApex.key",
- installable: false,
-}
-
-apex {
- name: "com.android.tests.rollback.testapex.RollbackTestApexV2",
- manifest: "TestApex/RollbackTestApexV2.json",
- file_contexts: "apex.test",
- prebuilts: ["RollbackTestApex.prebuilt.txt"],
- key: "RollbackTestApex.key",
- installable: false,
-}
-
-apex {
- name: "com.android.tests.rollback.testapex.RollbackTestApexV3",
- manifest: "TestApex/RollbackTestApexV3.json",
- file_contexts: "apex.test",
- prebuilts: ["RollbackTestApex.prebuilt.txt"],
- key: "RollbackTestApex.key",
- installable: false,
-}
-
-apex_key {
- name: "RollbackTestApex.key",
- public_key: "TestApex/com.android.tests.rollback.testapex.avbpubkey",
- private_key: "TestApex/com.android.tests.rollback.testapex.pem",
- installable: false,
-}
-
-prebuilt_etc {
- name: "RollbackTestApex.prebuilt.txt",
- src: "TestApex/RollbackTestApex.prebuilt.txt",
-}
-
android_test {
name: "RollbackTest",
manifest: "RollbackTest/AndroidManifest.xml",
@@ -132,9 +93,6 @@
":RollbackTestAppBv2",
":RollbackTestAppASplitV1",
":RollbackTestAppASplitV2",
- ":com.android.tests.rollback.testapex.RollbackTestApexV1",
- ":com.android.tests.rollback.testapex.RollbackTestApexV2",
- ":com.android.tests.rollback.testapex.RollbackTestApexV3",
],
test_config: "RollbackTest.xml",
sdk_version: "test_current",
diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
index b3a9f49..1ddfa6e 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
@@ -17,7 +17,6 @@
package com.android.tests.rollback;
import static com.android.tests.rollback.RollbackTestUtils.assertRollbackInfoEquals;
-import static com.android.tests.rollback.RollbackTestUtils.getRecentlyCommittedRollbackInfoById;
import static com.android.tests.rollback.RollbackTestUtils.getUniqueRollbackInfoForPackage;
import android.Manifest;
@@ -31,7 +30,6 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -55,15 +53,7 @@
private static final String TAG = "RollbackTest";
private static final String TEST_APP_A = "com.android.tests.rollback.testapp.A";
private static final String TEST_APP_A_V1 = "RollbackTestAppAv1.apk";
- private static final String TEST_APP_A_V2 = "RollbackTestAppAv2.apk";
private static final String TEST_APP_A_CRASHING_V2 = "RollbackTestAppACrashingV2.apk";
- private static final String TEST_APEX_PKG = "com.android.tests.rollback.testapex";
- private static final String TEST_APEX_V1 =
- "com.android.tests.rollback.testapex.RollbackTestApexV1.apex";
- private static final String TEST_APEX_V2 =
- "com.android.tests.rollback.testapex.RollbackTestApexV2.apex";
- private static final String TEST_APEX_V3 =
- "com.android.tests.rollback.testapex.RollbackTestApexV3.apex";
/**
* Adopts common shell permissions needed for rollback tests.
@@ -85,59 +75,6 @@
RollbackTestUtils.dropShellPermissionIdentity();
}
-
- /**
- * Test rollbacks of staged installs involving only apks.
- * Enable rollback phase.
- */
- @Test
- public void testApkOnlyEnableRollback() throws Exception {
- RollbackTestUtils.uninstall(TEST_APP_A);
- assertEquals(-1, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
-
- RollbackTestUtils.install(TEST_APP_A_V1, false);
- assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
- RollbackTestUtils.processUserData(TEST_APP_A);
-
- RollbackTestUtils.installStaged(true, TEST_APP_A_V2);
-
- // At this point, the host test driver will reboot the device and run
- // testApkOnlyCommitRollback().
- }
-
- /**
- * Test rollbacks of staged installs involving only apks.
- * Commit rollback phase.
- */
- @Test
- public void testApkOnlyCommitRollback() throws Exception {
- assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
- RollbackTestUtils.processUserData(TEST_APP_A);
-
- RollbackManager rm = RollbackTestUtils.getRollbackManager();
- RollbackInfo rollback = getUniqueRollbackInfoForPackage(
- rm.getAvailableRollbacks(), TEST_APP_A);
- assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollback);
- assertTrue(rollback.isStaged());
-
- RollbackTestUtils.rollback(rollback.getRollbackId(),
- new VersionedPackage(TEST_APP_A, 2));
-
- rollback = getUniqueRollbackInfoForPackage(
- rm.getRecentlyCommittedRollbacks(), TEST_APP_A);
- assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollback, new VersionedPackage(TEST_APP_A, 2));
- assertTrue(rollback.isStaged());
- assertNotEquals(-1, rollback.getCommittedSessionId());
-
- RollbackTestUtils.waitForSessionReady(rollback.getCommittedSessionId());
-
- // The app should not be rolled back until after reboot.
- assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
-
- // At this point, the host test driver will reboot the device and run
- // testApkOnlyConfirmRollback().
- }
-
/**
* Test rollbacks of staged installs involving only apks with bad update.
* Enable rollback phase.
@@ -209,7 +146,7 @@
* Confirm rollback phase.
*/
@Test
- public void testApkOnlyConfirmRollback() throws Exception {
+ public void testBadApkOnlyConfirmRollback() throws Exception {
assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
RollbackTestUtils.processUserData(TEST_APP_A);
@@ -220,171 +157,4 @@
assertTrue(rollback.isStaged());
assertNotEquals(-1, rollback.getCommittedSessionId());
}
-
- /**
- * Test rollbacks of staged installs an apk and an apex.
- * Enable rollback phase.
- */
- @Test
- public void testApkAndApexEnableRollback() throws Exception {
- RollbackTestUtils.uninstall(TEST_APP_A);
- RollbackTestUtils.install(TEST_APP_A_V1, false);
-
- assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APEX_PKG));
- assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
-
- RollbackTestUtils.installStaged(true, TEST_APP_A_V2, TEST_APEX_V2);
-
- // At this point, the host test driver will reboot the device and run
- // testApkAndApexCommitRollback().
- }
-
- /**
- * Test rollbacks of staged installs an apk and an apex.
- * Commit rollback phase.
- */
- @Test
- public void testApkAndApexCommitRollback() throws Exception {
- assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APEX_PKG));
- assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
-
- RollbackTestUtils.processUserData(TEST_APP_A);
-
- RollbackManager rm = RollbackTestUtils.getRollbackManager();
-
- RollbackInfo rollback = getUniqueRollbackInfoForPackage(
- rm.getAvailableRollbacks(), TEST_APP_A);
- String[] packagesNames = {TEST_APEX_PKG, TEST_APP_A};
- assertRollbackInfoEquals(packagesNames, 2, 1, rollback);
- assertTrue(rollback.isStaged());
-
- RollbackTestUtils.rollback(rollback.getRollbackId());
-
- RollbackInfo committed = getRecentlyCommittedRollbackInfoById(rollback.getRollbackId());
-
- assertRollbackInfoEquals(packagesNames, 2, 1, committed);
- assertTrue(committed.isStaged());
- assertNotEquals(-1, committed.getCommittedSessionId());
-
- RollbackTestUtils.waitForSessionReady(committed.getCommittedSessionId());
-
- // The apex and apk should not be rolled back until after reboot.
- assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APEX_PKG));
- assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
-
- // At this point, the host test driver will reboot the device and run
- // testApkAndApexConfirmRollback().
- }
-
- /**
- * Test rollbacks of staged installs an apk and an apex.
- * Confirm rollback phase.
- */
- @Test
- public void testApkAndApexConfirmRollback() throws Exception {
- assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APEX_PKG));
- assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
-
- RollbackTestUtils.processUserData(TEST_APP_A);
- }
-
- /**
- * Test rollbacks of staged installs involving only apex.
- * Enable rollback phase.
- */
- @Test
- public void testApexOnlyEnableRollback() throws Exception {
- assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APEX_PKG));
- RollbackTestUtils.installStaged(true, TEST_APEX_V2);
-
- // At this point, the host test driver will reboot the device and run
- // testApexOnlyCommitRollback().
- }
-
- /**
- * Test rollbacks of staged installs involving only apex.
- * Commit rollback phase.
- */
- @Test
- public void testApexOnlyCommitRollback() throws Exception {
- assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APEX_PKG));
-
- RollbackManager rm = RollbackTestUtils.getRollbackManager();
- RollbackInfo rollback = getUniqueRollbackInfoForPackage(
- rm.getAvailableRollbacks(), TEST_APEX_PKG);
- assertRollbackInfoEquals(TEST_APEX_PKG, 2, 1, rollback);
- assertTrue(rollback.isStaged());
-
- RollbackTestUtils.rollback(rollback.getRollbackId());
-
- RollbackInfo committed = getRecentlyCommittedRollbackInfoById(rollback.getRollbackId());
-
- assertRollbackInfoEquals(TEST_APEX_PKG, 2, 1, committed);
- assertTrue(committed.isStaged());
- assertNotEquals(-1, committed.getCommittedSessionId());
-
- RollbackTestUtils.waitForSessionReady(committed.getCommittedSessionId());
-
- // The apex should not be rolled back until after reboot.
- assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APEX_PKG));
-
- // At this point, the host test driver will reboot the device and run
- // testApexOnlyConfirmRollback().
- }
-
- /**
- * Test rollbacks of staged installs involving only apex.
- * Confirm rollback phase.
- */
- @Test
- public void testApexOnlyConfirmRollback() throws Exception {
- assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APEX_PKG));
- }
-
- /**
- * Tests that apex update expires existing rollbacks for that apex.
- * Enable rollback phase.
- */
- @Test
- public void testApexRollbackExpirationEnableRollback() throws Exception {
- assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APEX_PKG));
- RollbackTestUtils.installStaged(true, TEST_APEX_V2);
-
- // At this point, the host test driver will reboot the device and run
- // testApexRollbackExpirationUpdateApex().
- }
-
- /**
- * Tests that apex update expires existing rollbacks for that apex.
- * Update apex phase.
- */
- @Test
- public void testApexRollbackExpirationUpdateApex() throws Exception {
- assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APEX_PKG));
- RollbackTestUtils.installStaged(false, TEST_APEX_V3);
-
- // At this point, the host test driver will reboot the device and run
- // testApexRollbackExpirationConfirmExpiration().
- }
-
- /**
- * Tests that apex update expires existing rollbacks for that apex.
- * Confirm expiration phase.
- */
- @Test
- public void testApexRollbackExpirationConfirmExpiration() throws Exception {
- assertEquals(3, RollbackTestUtils.getInstalledVersion(TEST_APEX_PKG));
-
- RollbackManager rm = RollbackTestUtils.getRollbackManager();
- assertNull(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TEST_APEX_PKG));
- }
-
- /**
- * Helper function called by the host test to install v1 of the test apex,
- * assuming the test apex is not installed.
- */
- @Test
- public void installTestApexV1() throws Exception {
- RollbackTestUtils.installStaged(false, TEST_APEX_V1);
- }
}
diff --git a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
index 2433434..75a95ad 100644
--- a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
+++ b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
@@ -19,7 +19,6 @@
import static org.junit.Assert.assertTrue;
import com.android.ddmlib.Log.LogLevel;
-import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
@@ -32,9 +31,6 @@
*/
@RunWith(DeviceJUnit4ClassRunner.class)
public class StagedRollbackTest extends BaseHostJUnit4Test {
-
- private static final String TEST_APEX_PKG = "com.android.tests.rollback.testapex";
-
/**
* Runs the given phase of a test by calling into the device.
* Throws an exception if the test phase fails.
@@ -48,18 +44,6 @@
}
/**
- * Tests staged rollbacks involving only apks.
- */
- @Test
- public void testApkOnly() throws Exception {
- runPhase("testApkOnlyEnableRollback");
- getDevice().reboot();
- runPhase("testApkOnlyCommitRollback");
- getDevice().reboot();
- runPhase("testApkOnlyConfirmRollback");
- }
-
- /**
* Tests watchdog triggered staged rollbacks involving only apks.
*/
@Test
@@ -79,66 +63,6 @@
}
getDevice().waitForDeviceAvailable();
- runPhase("testApkOnlyConfirmRollback");
- }
-
- /**
- * Tests staged rollbacks involving only apex.
- */
- @Test
- public void testApexOnly() throws Exception {
- installTestApexV1();
- runPhase("testApexOnlyEnableRollback");
- getDevice().reboot();
- runPhase("testApexOnlyCommitRollback");
- getDevice().reboot();
- runPhase("testApexOnlyConfirmRollback");
- }
-
- /**
- * Tests staged rollbacks involving apk and apex.
- */
- @Test
- public void testApkAndApex() throws Exception {
- installTestApexV1();
- runPhase("testApkAndApexEnableRollback");
- getDevice().reboot();
- runPhase("testApkAndApexCommitRollback");
- getDevice().reboot();
- runPhase("testApkAndApexConfirmRollback");
- }
-
- /**
- * Tests that apex update expires existing rollbacks for that apex.
- */
- @Test
- public void testApexRollbackExpiration() throws Exception {
- installTestApexV1();
- runPhase("testApexRollbackExpirationEnableRollback");
- getDevice().reboot();
- runPhase("testApexRollbackExpirationUpdateApex");
- getDevice().reboot();
- runPhase("testApexRollbackExpirationConfirmExpiration");
- }
-
- /**
- * Do whatever is necessary to get version 1 of the test apex installed on
- * the device. Try to do so without extra reboots where possible to keep
- * the test execution time down.
- */
- private void installTestApexV1() throws Exception {
- for (ITestDevice.ApexInfo apexInfo : getDevice().getActiveApexes()) {
- if (TEST_APEX_PKG.equals(apexInfo.name)) {
- if (apexInfo.versionCode == 1) {
- return;
- }
- getDevice().uninstallPackage(TEST_APEX_PKG);
- getDevice().reboot();
- break;
- }
- }
-
- runPhase("installTestApexV1");
- getDevice().reboot();
+ runPhase("testBadApkOnlyConfirmRollback");
}
}
diff --git a/tests/RollbackTest/TestApex/RollbackTestApex.prebuilt.txt b/tests/RollbackTest/TestApex/RollbackTestApex.prebuilt.txt
deleted file mode 100644
index e871146..0000000
--- a/tests/RollbackTest/TestApex/RollbackTestApex.prebuilt.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-
-This file contains dummy content to include in the RollbackTestApex.
-
diff --git a/tests/RollbackTest/TestApex/RollbackTestApexV1.json b/tests/RollbackTest/TestApex/RollbackTestApexV1.json
deleted file mode 100644
index c3239ca..0000000
--- a/tests/RollbackTest/TestApex/RollbackTestApexV1.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "name": "com.android.tests.rollback.testapex",
- "version": 1
-}
diff --git a/tests/RollbackTest/TestApex/RollbackTestApexV2.json b/tests/RollbackTest/TestApex/RollbackTestApexV2.json
deleted file mode 100644
index 9de3f45..0000000
--- a/tests/RollbackTest/TestApex/RollbackTestApexV2.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "name": "com.android.tests.rollback.testapex",
- "version": 2
-}
diff --git a/tests/RollbackTest/TestApex/RollbackTestApexV3.json b/tests/RollbackTest/TestApex/RollbackTestApexV3.json
deleted file mode 100644
index 87a2c9d..0000000
--- a/tests/RollbackTest/TestApex/RollbackTestApexV3.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "name": "com.android.tests.rollback.testapex",
- "version": 3
-}
diff --git a/tests/RollbackTest/TestApex/com.android.tests.rollback.testapex.avbpubkey b/tests/RollbackTest/TestApex/com.android.tests.rollback.testapex.avbpubkey
deleted file mode 100644
index b347331..0000000
--- a/tests/RollbackTest/TestApex/com.android.tests.rollback.testapex.avbpubkey
+++ /dev/null
Binary files differ
diff --git a/tests/RollbackTest/TestApex/com.android.tests.rollback.testapex.pem b/tests/RollbackTest/TestApex/com.android.tests.rollback.testapex.pem
deleted file mode 100644
index 7181ce5..0000000
--- a/tests/RollbackTest/TestApex/com.android.tests.rollback.testapex.pem
+++ /dev/null
@@ -1,51 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIIJKQIBAAKCAgEArBLX+v6RMiK6soQFgbc0RZ+wticTD5sCbu9Q5B5WT7UnV1Wt
-cNI/n2bjks3UYNxTneOzMQOVjd4ln0BYZoNvoDtrc1BsYABpt4FywSq1zz/3sp3L
-3Vp8vaUyRsx0Da+PcOdYHPFs1WPX3Shw3MSPhUO/72KTm6GhO/cHEPEzSQLaw/zO
-8FiPpDdRqILqVJlu1DZ+i1DO+To9mKt59uLlxy3F+HAMnQaNW6+2NCV/vdCxQrEL
-m7PpsM6DymsFKcvVra1Il4apKkYNgcgTQ+AlmyPxGo6twfZvRMrU3bcrUmrg3OAx
-tMD7MufXlKkoFMlT5clrQ7P2ErKoFxhTVWhBL5ZJv/lKwaTfxCLyNvYQ7JALKtOL
-9xx4c77NdyYVjxMDAJ7E+Uj3QjdOv3FxM38Fcvt0zN4SSlmDjEDtm2e2w53Ztgz1
-zHAuNllIW1zGdPqa+ROoa9JLJePlyNXG9Rn1sSkjM9WwteaJ3nrdje6uBsvo7I9g
-1MWab2XNXQwJNHACICtyU7QPryGP4U/lyHqWEkdoXrs8O36gmTGU/EsJYSIVILax
-0HZC3zkmxHgiN95ZvD+Y5Y9HDXAN04kT8O1V/QD4QUCP8MGXNrkQP/JZAnu5Y2D1
-Wrn/7Tft2ON3OpH5vUgR99bKR549LcRrYgxeTnci3xkOsnTjZRxEUJFQgVUCAwEA
-AQKCAgEAlBzIMbDLk+cW4rAG+WeTo9ZXygKKQqV/i7OM4j5GtudMTL1fxDwFLZTn
-kCaBhzo+8ynaxPa71ViA87n0HZFHFRnwXFq+XkgctyrCdwjnY9RAxktS/l5z/t1i
-EFTOFDWod1t6mbcpoegGF8RGmZDLpL7zR/+G5LBUU4RHXcrwBQli+s3x5imkwoon
-TLAbOeSz5BBgDlTpQtdhy7bWDa+ybya0QCtagBLyvBfb8rjQYrduzOQOBODw5xJr
-mGFUGWztqUf9swfjNpMD71EjXApk9EwUrXJgmBMiJYmdfpa6wH9kvFpyDo8J6gBr
-rPeJm5LMF3+vR6Bw0Bld3DtBB8PsTrockOdeJNHfnY54480e7AahfM5gkeuIYC4P
-E3CIbyAgpS8+OLpsXP207AOjFz1TLiOqyDUDsBqSMNEQ7QbIPTQw8UZ/o0vEoqEv
-RrJAvIAv0KUcFNUL0t6VX2OXbV+i+T85wPey3XqK9P8Zzc8NUEGJ2paDUkSuemKC
-nF9/siGaoBHXsNUkQuV9xYo4co66MHDGAx/OdUM5lPiUcrF/bR+ZUA3p1BLUQXbQ
-aJD9uKlvJ4ZRSwhR/fQc5UiVWl3l76k+0Ia/Ddd1ArphVhbvGPOsm3W7wJ6KukSk
-rBJh1PPV1HnA+icS2Wvu2kVdz9+39cQUYJIICO1uwWfPIb/R5MUCggEBAOSwkwXs
-jqewNc6X4mc19RGKIMUvOrRrQkOOY33pI+BjoqI8cl+NOHNB7F8/gVnHIfhZpOG6
-WD5St1/qlSPT1Nte+38P+woAp5mdclZyRgYb4MjZybZihUPIPVgUbxiZTDHy1Sw0
-kRgmvaV3ccvG9/9bBUKNr9Z+XySsIhq5DzY+yIZ33vhLB/0g05x2HVIsSlsRWzri
-lw0iX/v07bdIRUIv7QB8xcLY/23pIbHAXS8DaknN8YxpKtjilOnUWVp/dx4SIcJY
-6PtSBfPcwVJ2MA/xXWBvDP82/XxvbxKnjj8lvkbfqMC6jrXJBw3NT/he8b932IBb
-PwLGU4hoKvjXfUcCggEBAMCfa4N1KUXW0Mo3BcDk2Hk8zVYuTPDNTWg1Mxb46sn+
-HNVJKU0OrejM2hNNCwzJG7eVQBorJj5XefhaQFTvWoLKbf1YZuWKaQrRwKkHEqDi
-edplA2RkpUebeS4KYIr22rzu3ZrZqiJmRU5kAS9hwOzwFvnXUgGy7IoZKXhpo0HK
-xvwylb/C5FXh97tecDdH/5evB/DC515TIhPzUQ5tpT0oAl9MU7Pe1E/opzrD/0sR
-dqKVJcl9vBRbtcAIkCOVpLoA9T2VvisafZAJaRXc3ACFMceewgpVAtBCsWUtLfvW
-fHMHWfti5je19SWg7bUK56uHJ0vdAI+irkfpe1t0aoMCggEAR5cPL3eSYOREs9vQ
-QEcf5NG82H2kfv5kzAkzFCN7267VJryNgWQQG+SzPk3/DD/OXpSRjShsn3X9ecVR
-0tlpdRMS3//8snDqBqjHNlCnoxnvEHE9OB83YLS6n2wmKykyNSCzoxcBpPHbxITT
-1tr+n626w87fEOKWnkBUnND59h1JYO79mfTDF3bDR+Oh4iuDS2bvjEuKxc3RBmry
-T8IMDGA8bT6iGhEcRSgKKD7z7NfA2kHiL/ZsN2EXBOw43J+yhnNephx3MtXGj0S4
-MDxXZ2ZDuQCKrQpl6CJqPwi8+v+xxTYW+d5s9nNsBeIT+sieHTZDTEtEOnYjiDwz
-15p92QKCAQEAkMwGNQawpOhLgYcFEzC0LcbwEFWzztx10N0U77LkRD16jTZ3Do73
-WmYLlLC4mr7e0A0o58MB96EodfHaJD7dSi5Dqkt25hw6xEBS1H0Vms1EjlCa0S/7
-Mq4D1QFF+5B/c8EX4ty20S8R8FCqt2SDc1kz3FHpOo+20kUB8Jtwdveox1J7UXB+
-1rSL1lSyhEviLbMMhAbvh+90UYz5pJ/1s9hMmDi3PyJFdWBNvZYyZcrV5He7tRCI
-fsFGCfol6CoIby5jLA1Rq/M46jq4vQ+ObfGyLv3/nWa0O7u2wHjK9WIRoSKomJmK
-t9xXURb9Obfd2Qo7FwMl9dNzsWkpKuGDYwKCAQB+hiWu2C+0foJ4Z8auM1SK8be4
-waplfD7qIvONE/vtl+VAN+eVpz5kkQJfXiafktAHahgEdSx43bofR0Kv0/R7IRs3
-M1WYAr0w+19TXLXkuh2oYIbcoGrIN3HMmlKMv44xh/QUhRe337cCLejP0SESNN+k
-5wT91SbJwuCw/QsG3sD6NIMtCNWdcsAQq/ruhz7pQ/JZUFOueV0tkzbK+oNHWbNU
-lS99qjPaVCXZFlz/t2/89cljh9mtRjcfXIBfuTijN9sXNcLTXsfLsyHJ86eEbI2U
-o2JQ7Sjs10LpiwBbNNHBmulARgRONNMgik6tpNIS0tk9eke0lCX42bDFtAD4
------END RSA PRIVATE KEY-----
diff --git a/tests/net/Android.bp b/tests/net/Android.bp
index 1fbb658..306cc51 100644
--- a/tests/net/Android.bp
+++ b/tests/net/Android.bp
@@ -56,7 +56,7 @@
"libutilscallstack",
"libziparchive",
"libz",
- "netd_aidl_interface-cpp",
+ "netd_aidl_interface-V2-cpp",
"libnetworkstatsfactorytestjni",
],
}
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index b0cc207..fa059fa 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -3816,11 +3816,20 @@
networkCallback.assertNoCallback();
}
+ @Test
+ public void testUnfulfillableNetworkRequest() throws Exception {
+ runUnfulfillableNetworkRequest(false);
+ }
+
+ @Test
+ public void testUnfulfillableNetworkRequestAfterUnregister() throws Exception {
+ runUnfulfillableNetworkRequest(true);
+ }
+
/**
* Validate the callback flow for a factory releasing a request as unfulfillable.
*/
- @Test
- public void testUnfulfillableNetworkRequest() throws Exception {
+ private void runUnfulfillableNetworkRequest(boolean preUnregister) throws Exception {
NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
NetworkCapabilities.TRANSPORT_WIFI).build();
final TestNetworkCallback networkCallback = new TestNetworkCallback();
@@ -3855,14 +3864,25 @@
}
}
- // Simulate the factory releasing the request as unfulfillable and expect onUnavailable!
testFactory.expectRemoveRequests(1);
- testFactory.triggerUnfulfillable(requests.get(newRequestId));
- networkCallback.expectCallback(CallbackState.UNAVAILABLE, null);
- testFactory.waitForRequests();
+ if (preUnregister) {
+ mCm.unregisterNetworkCallback(networkCallback);
- // unregister network callback - a no-op, but should not fail
- mCm.unregisterNetworkCallback(networkCallback);
+ // Simulate the factory releasing the request as unfulfillable: no-op since
+ // the callback has already been unregistered (but a test that no exceptions are
+ // thrown).
+ testFactory.triggerUnfulfillable(requests.get(newRequestId));
+ } else {
+ // Simulate the factory releasing the request as unfulfillable and expect onUnavailable!
+ testFactory.triggerUnfulfillable(requests.get(newRequestId));
+
+ networkCallback.expectCallback(CallbackState.UNAVAILABLE, null);
+ testFactory.waitForRequests();
+
+ // unregister network callback - a no-op (since already freed by the
+ // on-unavailable), but should not fail or throw exceptions.
+ mCm.unregisterNetworkCallback(networkCallback);
+ }
testFactory.unregister();
handlerThread.quit();