Merge "Override hashcode, equals function for PnoNetwork" into rvc-dev
diff --git a/Android.bp b/Android.bp
index 7f6a7c1..11f5c41 100644
--- a/Android.bp
+++ b/Android.bp
@@ -472,7 +472,7 @@
"framework-sdkextensions-stubs-systemapi",
"framework-statsd-stubs-module_libs_api",
"framework-permission-stubs-systemapi",
- "framework-wifi-stubs",
+ "framework-wifi-stubs-systemapi",
"framework-tethering-stubs",
],
installable: true,
@@ -522,7 +522,7 @@
"framework-permission-stubs-systemapi",
"framework-sdkextensions-stubs-systemapi",
"framework-statsd-stubs-module_libs_api",
- "framework-wifi-stubs",
+ "framework-wifi-stubs-systemapi",
"framework-tethering-stubs",
// TODO (b/147688669) should be framework-telephony-stubs
"framework-telephony",
diff --git a/api/current.txt b/api/current.txt
index c8a7956..1227006 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5943,7 +5943,7 @@
method public boolean isImportantConversation();
method public void setAllowBubbles(boolean);
method public void setBypassDnd(boolean);
- method public void setConversationId(@Nullable String, @Nullable String);
+ method public void setConversationId(@NonNull String, @NonNull String);
method public void setDescription(String);
method public void setGroup(String);
method public void setImportance(int);
@@ -5956,7 +5956,6 @@
method public boolean shouldShowLights();
method public boolean shouldVibrate();
method public void writeToParcel(android.os.Parcel, int);
- field public static final String CONVERSATION_CHANNEL_ID_FORMAT = "%1$s : %2$s";
field @NonNull public static final android.os.Parcelable.Creator<android.app.NotificationChannel> CREATOR;
field public static final String DEFAULT_CHANNEL_ID = "miscellaneous";
}
diff --git a/api/system-current.txt b/api/system-current.txt
index 85ad66f..f84b415 100755
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -7199,9 +7199,9 @@
}
public final class SoftApCapability implements android.os.Parcelable {
+ method public boolean areFeaturesSupported(long);
method public int describeContents();
method public int getMaxSupportedClients();
- method public boolean isFeatureSupported(long);
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.SoftApCapability> CREATOR;
field public static final long SOFTAP_FEATURE_ACS_OFFLOAD = 1L; // 0x1L
diff --git a/cmds/incidentd/src/Section.cpp b/cmds/incidentd/src/Section.cpp
index 2229e1c..d79123b 100644
--- a/cmds/incidentd/src/Section.cpp
+++ b/cmds/incidentd/src/Section.cpp
@@ -20,9 +20,9 @@
#include <dirent.h>
#include <errno.h>
-
#include <mutex>
#include <set>
+#include <thread>
#include <android-base/file.h>
#include <android-base/properties.h>
@@ -42,6 +42,7 @@
#include "frameworks/base/core/proto/android/os/backtrace.proto.h"
#include "frameworks/base/core/proto/android/os/data.proto.h"
#include "frameworks/base/core/proto/android/util/log.proto.h"
+#include "frameworks/base/core/proto/android/util/textdump.proto.h"
#include "incidentd_util.h"
namespace android {
@@ -135,7 +136,7 @@
status_t ihStatus = wait_child(pid);
if (ihStatus != NO_ERROR) {
ALOGW("[%s] abnormal child process: %s", this->name.string(), strerror(-ihStatus));
- return ihStatus;
+ return OK; // Not a fatal error.
}
return writer->writeSection(buffer);
@@ -234,7 +235,7 @@
Fpipe pipe;
// Lock protects these fields
- mutex lock;
+ std::mutex lock;
bool workerDone;
status_t workerError;
@@ -261,83 +262,47 @@
}
}
-static void* worker_thread_func(void* cookie) {
- // Don't crash the service if we write to a closed pipe (which can happen if
- // dumping times out).
- signal(SIGPIPE, sigpipe_handler);
-
- WorkerThreadData* data = (WorkerThreadData*)cookie;
- status_t err = data->section->BlockingCall(data->pipe.writeFd());
-
- {
- unique_lock<mutex> lock(data->lock);
- data->workerDone = true;
- data->workerError = err;
- }
-
- data->pipe.writeFd().reset();
- data->decStrong(data->section);
- // data might be gone now. don't use it after this point in this thread.
- return NULL;
-}
-
status_t WorkerThreadSection::Execute(ReportWriter* writer) const {
status_t err = NO_ERROR;
- pthread_t thread;
- pthread_attr_t attr;
bool workerDone = false;
FdBuffer buffer;
- // Data shared between this thread and the worker thread.
- sp<WorkerThreadData> data = new WorkerThreadData(this);
-
- // Create the pipe
- if (!data->pipe.init()) {
+ // Create shared data and pipe
+ WorkerThreadData data(this);
+ if (!data.pipe.init()) {
return -errno;
}
- // Create the thread
- err = pthread_attr_init(&attr);
- if (err != 0) {
- return -err;
- }
- // TODO: Do we need to tweak thread priority?
- err = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- if (err != 0) {
- pthread_attr_destroy(&attr);
- return -err;
- }
-
- // The worker thread needs a reference and we can't let the count go to zero
- // if that thread is slow to start.
- data->incStrong(this);
-
- err = pthread_create(&thread, &attr, worker_thread_func, (void*)data.get());
- pthread_attr_destroy(&attr);
- if (err != 0) {
- data->decStrong(this);
- return -err;
- }
+ std::thread([&]() {
+ // Don't crash the service if writing to a closed pipe (may happen if dumping times out)
+ signal(SIGPIPE, sigpipe_handler);
+ status_t err = data.section->BlockingCall(data.pipe.writeFd());
+ {
+ std::unique_lock<std::mutex> lock(data.lock);
+ data.workerDone = true;
+ data.workerError = err;
+ // unique_fd is not thread safe. If we don't lock it, reset() may pause half way while
+ // the other thread executes to the end, calling ~Fpipe, which is a race condition.
+ data.pipe.writeFd().reset();
+ }
+ }).detach();
// Loop reading until either the timeout or the worker side is done (i.e. eof).
- err = buffer.read(data->pipe.readFd().get(), this->timeoutMs);
+ err = buffer.read(data.pipe.readFd().get(), this->timeoutMs);
if (err != NO_ERROR) {
ALOGE("[%s] reader failed with error '%s'", this->name.string(), strerror(-err));
}
- // Done with the read fd. The worker thread closes the write one so
- // we never race and get here first.
- data->pipe.readFd().reset();
-
// If the worker side is finished, then return its error (which may overwrite
// our possible error -- but it's more interesting anyway). If not, then we timed out.
{
- unique_lock<mutex> lock(data->lock);
- if (data->workerError != NO_ERROR) {
- err = data->workerError;
+ std::unique_lock<std::mutex> lock(data.lock);
+ data.pipe.close();
+ if (data.workerError != NO_ERROR) {
+ err = data.workerError;
ALOGE("[%s] worker failed with error '%s'", this->name.string(), strerror(-err));
}
- workerDone = data->workerDone;
+ workerDone = data.workerDone;
}
writer->setSectionStats(buffer);
@@ -473,6 +438,77 @@
}
// ================================================================================
+TextDumpsysSection::TextDumpsysSection(int id, const char* service, ...)
+ : WorkerThreadSection(id, REMOTE_CALL_TIMEOUT_MS), mService(service) {
+ name = "dumpsys ";
+ name += service;
+
+ va_list args;
+ va_start(args, service);
+ while (true) {
+ const char* arg = va_arg(args, const char*);
+ if (arg == NULL) {
+ break;
+ }
+ mArgs.add(String16(arg));
+ name += " ";
+ name += arg;
+ }
+ va_end(args);
+}
+
+TextDumpsysSection::~TextDumpsysSection() {}
+
+status_t TextDumpsysSection::BlockingCall(unique_fd& pipeWriteFd) const {
+ // checkService won't wait for the service to show up like getService will.
+ sp<IBinder> service = defaultServiceManager()->checkService(mService);
+ if (service == NULL) {
+ ALOGW("TextDumpsysSection: Can't lookup service: %s", String8(mService).string());
+ return NAME_NOT_FOUND;
+ }
+
+ // Create pipe
+ Fpipe dumpPipe;
+ if (!dumpPipe.init()) {
+ ALOGW("[%s] failed to setup pipe", this->name.string());
+ return -errno;
+ }
+
+ // Run dumping thread
+ const uint64_t start = Nanotime();
+ std::thread worker([&]() {
+ // Don't crash the service if writing to a closed pipe (may happen if dumping times out)
+ signal(SIGPIPE, sigpipe_handler);
+ status_t err = service->dump(dumpPipe.writeFd().get(), mArgs);
+ if (err != OK) {
+ ALOGW("[%s] dump thread failed. Error: %s", this->name.string(), strerror(-err));
+ }
+ dumpPipe.writeFd().reset();
+ });
+
+ // Collect dump content
+ std::string content;
+ bool success = ReadFdToString(dumpPipe.readFd(), &content);
+ worker.join(); // Wait for worker to finish
+ dumpPipe.readFd().reset();
+ if (!success) {
+ ALOGW("[%s] failed to read data from pipe", this->name.string());
+ return -1;
+ }
+
+ ProtoOutputStream proto;
+ proto.write(util::TextDumpProto::COMMAND, std::string(name.string()));
+ proto.write(util::TextDumpProto::CONTENT, content);
+ proto.write(util::TextDumpProto::DUMP_DURATION_NS, int64_t(Nanotime() - start));
+
+ if (!proto.flush(pipeWriteFd.get()) && errno == EPIPE) {
+ ALOGE("[%s] wrote to a broken pipe\n", this->name.string());
+ return EPIPE;
+ }
+ return OK;
+}
+
+// ================================================================================
// initialization only once in Section.cpp.
map<log_id_t, log_time> LogSection::gLastLogsRetrieved;
diff --git a/cmds/incidentd/src/Section.h b/cmds/incidentd/src/Section.h
index 0bb9da9..6162b3a 100644
--- a/cmds/incidentd/src/Section.h
+++ b/cmds/incidentd/src/Section.h
@@ -112,7 +112,8 @@
};
/**
- * Section that calls dumpsys on a system service.
+ * Section that calls protobuf dumpsys on a system service, usually
+ * "dumpsys [service_name] --proto".
*/
class DumpsysSection : public WorkerThreadSection {
public:
@@ -127,6 +128,21 @@
};
/**
+ * Section that calls text dumpsys on a system service, usually "dumpsys [service_name]".
+ */
+class TextDumpsysSection : public WorkerThreadSection {
+public:
+ TextDumpsysSection(int id, const char* service, ...);
+ virtual ~TextDumpsysSection();
+
+ virtual status_t BlockingCall(unique_fd& pipeWriteFd) const;
+
+private:
+ String16 mService;
+ Vector<String16> mArgs;
+};
+
+/**
* Section that calls dumpsys on a system service.
*/
class SystemPropertyDumpsysSection : public WorkerThreadSection {
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 1b0e51e..2575542 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -397,7 +397,7 @@
}
// Pulled events will start at field 10000.
- // Next: 10075
+ // Next: 10076
oneof pulled {
WifiBytesTransfer wifi_bytes_transfer = 10000 [(module) = "framework"];
WifiBytesTransferByFgBg wifi_bytes_transfer_by_fg_bg = 10001 [(module) = "framework"];
@@ -479,6 +479,7 @@
PackageNotificationChannelGroupPreferences package_notification_channel_group_preferences =
10073 [(module) = "framework"];
GnssStats gnss_stats = 10074 [(module) = "framework"];
+ AppFeaturesOps app_features_ops = 10075 [(module) = "framework"];
}
// DO NOT USE field numbers above 100,000 in AOSP.
@@ -7548,6 +7549,51 @@
}
/**
+ * Historical app ops data per package and features.
+ */
+message AppFeaturesOps {
+ // Uid of the package requesting the op
+ optional int32 uid = 1 [(is_uid) = true];
+
+ // Name of the package performing the op
+ optional string package_name = 2;
+
+ // feature id; provided by developer when accessing related API, limited at 50 chars by API.
+ // Features must be provided through manifest using <feature> tag available in R and above.
+ optional string feature_id = 3;
+
+ // operation id; maps to the OPSTR_* constants in AppOpsManager.java
+ optional string op = 4;
+
+ // The number of times the op was granted while the app was in the
+ // foreground (only for trusted requests)
+ optional int64 trusted_foreground_granted_count = 5;
+
+ // The number of times the op was granted while the app was in the
+ // background (only for trusted requests)
+ optional int64 trusted_background_granted_count = 6;
+
+ // The number of times the op was rejected while the app was in the
+ // foreground (only for trusted requests)
+ optional int64 trusted_foreground_rejected_count = 7;
+
+ // The number of times the op was rejected while the app was in the
+ // background (only for trusted requests)
+ optional int64 trusted_background_rejected_count = 8;
+
+ // For long-running operations, total duration of the operation
+ // while the app was in the foreground (only for trusted requests)
+ optional int64 trusted_foreground_duration_millis = 9;
+
+ // For long-running operations, total duration of the operation
+ // while the app was in the background (only for trusted requests)
+ optional int64 trusted_background_duration_millis = 10;
+
+ // Whether AppOps is guarded by Runtime permission
+ optional bool is_runtime_permission = 11;
+}
+
+/**
* Location Manager API Usage information(e.g. API under usage,
* API call's parameters).
* Logged from:
diff --git a/core/java/android/app/NotificationChannel.java b/core/java/android/app/NotificationChannel.java
index 7212be8..3f2ec44 100644
--- a/core/java/android/app/NotificationChannel.java
+++ b/core/java/android/app/NotificationChannel.java
@@ -15,6 +15,7 @@
*/
package android.app;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
@@ -63,6 +64,7 @@
* string takes two arguments, in this order: the
* {@link #getId()} of the original notification channel, and the
* {@link ShortcutInfo#getId() id} of the conversation.
+ * @hide
*/
public static final String CONVERSATION_CHANNEL_ID_FORMAT = "%1$s : %2$s";
@@ -554,8 +556,8 @@
}
/**
- * Sets this channel as being person-centric. Different settings and functionality may be
- * exposed for people-centric channels.
+ * Sets this channel as being converastion-centric. Different settings and functionality may be
+ * exposed for conversation-centric channels.
*
* @param parentChannelId The {@link #getId()} id} of the generic channel that notifications of
* this type would be posted to in absence of a specific conversation id.
@@ -564,8 +566,8 @@
* @param conversationId The {@link ShortcutInfo#getId()} of the shortcut representing this
* channel's conversation.
*/
- public void setConversationId(@Nullable String parentChannelId,
- @Nullable String conversationId) {
+ public void setConversationId(@NonNull String parentChannelId,
+ @NonNull String conversationId) {
mParentId = parentChannelId;
mConversationId = conversationId;
}
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 88edb05..cbbdf63 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -1573,6 +1573,15 @@
PRIORITY_CATEGORY_CONVERSATIONS,
};
+ /** @hide */
+ @IntDef(prefix = { "PRIORITY_SENDERS_" }, value = {
+ PRIORITY_SENDERS_ANY,
+ PRIORITY_SENDERS_CONTACTS,
+ PRIORITY_SENDERS_STARRED,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface PrioritySenders {}
+
/** Any sender is prioritized. */
public static final int PRIORITY_SENDERS_ANY = 0;
/** Saved contacts are prioritized. */
@@ -1816,8 +1825,9 @@
* @param suppressedVisualEffects which visual interruptions should be suppressed from
* notifications that are filtered by DND.
*/
- public Policy(int priorityCategories, int priorityCallSenders, int priorityMessageSenders,
- int suppressedVisualEffects, int priorityConversationSenders) {
+ public Policy(int priorityCategories, @PrioritySenders int priorityCallSenders,
+ @PrioritySenders int priorityMessageSenders,
+ int suppressedVisualEffects, @ConversationSenders int priorityConversationSenders) {
this(priorityCategories, priorityCallSenders, priorityMessageSenders,
suppressedVisualEffects, STATE_UNSET, priorityConversationSenders);
}
diff --git a/core/java/android/service/autofill/IInlineSuggestionRenderService.aidl b/core/java/android/service/autofill/IInlineSuggestionRenderService.aidl
index c389b1a..dd434b4 100644
--- a/core/java/android/service/autofill/IInlineSuggestionRenderService.aidl
+++ b/core/java/android/service/autofill/IInlineSuggestionRenderService.aidl
@@ -28,5 +28,5 @@
oneway interface IInlineSuggestionRenderService {
void renderSuggestion(in IInlineSuggestionUiCallback callback,
in InlinePresentation presentation, int width, int height,
- in IBinder hostInputToken);
+ in IBinder hostInputToken, int displayId);
}
diff --git a/core/java/android/service/autofill/InlineSuggestionRenderService.java b/core/java/android/service/autofill/InlineSuggestionRenderService.java
index 29069e7..17e0456 100644
--- a/core/java/android/service/autofill/InlineSuggestionRenderService.java
+++ b/core/java/android/service/autofill/InlineSuggestionRenderService.java
@@ -23,14 +23,18 @@
import android.annotation.TestApi;
import android.app.Service;
import android.app.slice.Slice;
+import android.content.Context;
import android.content.Intent;
import android.graphics.PixelFormat;
+import android.hardware.display.DisplayManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
+import android.util.DisplayMetrics;
import android.util.Log;
+import android.view.Display;
import android.view.SurfaceControl;
import android.view.SurfaceControlViewHost;
import android.view.View;
@@ -61,7 +65,8 @@
private final Handler mHandler = new Handler(Looper.getMainLooper(), null, true);
private void handleRenderSuggestion(IInlineSuggestionUiCallback callback,
- InlinePresentation presentation, int width, int height, IBinder hostInputToken) {
+ InlinePresentation presentation, int width, int height, IBinder hostInputToken,
+ int displayId) {
if (hostInputToken == null) {
try {
callback.onError();
@@ -70,8 +75,17 @@
}
return;
}
- final SurfaceControlViewHost host = new SurfaceControlViewHost(this, this.getDisplay(),
- hostInputToken);
+
+ final DisplayManager displayManager = getSystemService(DisplayManager.class);
+ final Display targetDisplay = displayManager.getDisplay(displayId);
+ if (targetDisplay == null) {
+ sendResult(callback, /*surface*/ null);
+ return;
+ }
+ final Context displayContext = createDisplayContext(targetDisplay);
+
+ final SurfaceControlViewHost host = new SurfaceControlViewHost(displayContext,
+ displayContext.getDisplay(), hostInputToken);
final SurfaceControl surface = host.getSurfacePackage().getSurfaceControl();
final View suggestionView = onRenderSuggestion(presentation, width, height);
@@ -90,6 +104,11 @@
new WindowManager.LayoutParams(width, height,
WindowManager.LayoutParams.TYPE_APPLICATION, 0, PixelFormat.TRANSPARENT);
host.addView(suggestionRoot, lp);
+ sendResult(callback, surface);
+ }
+
+ private void sendResult(@NonNull IInlineSuggestionUiCallback callback,
+ @Nullable SurfaceControl surface) {
try {
callback.onContent(surface);
} catch (RemoteException e) {
@@ -105,11 +124,11 @@
@Override
public void renderSuggestion(@NonNull IInlineSuggestionUiCallback callback,
@NonNull InlinePresentation presentation, int width, int height,
- @Nullable IBinder hostInputToken) {
+ @Nullable IBinder hostInputToken, int displayId) {
mHandler.sendMessage(obtainMessage(
InlineSuggestionRenderService::handleRenderSuggestion,
InlineSuggestionRenderService.this, callback, presentation,
- width, height, hostInputToken));
+ width, height, hostInputToken, displayId));
}
}.asBinder();
}
diff --git a/core/java/android/view/SurfaceControlViewHost.java b/core/java/android/view/SurfaceControlViewHost.java
index 680a878..4badede 100644
--- a/core/java/android/view/SurfaceControlViewHost.java
+++ b/core/java/android/view/SurfaceControlViewHost.java
@@ -111,6 +111,7 @@
@NonNull WindowlessWindowManager wwm) {
mWm = wwm;
mViewRoot = new ViewRootImpl(c, d, mWm);
+ mViewRoot.forceDisableBLAST();
mAccessibilityEmbeddedConnection = mViewRoot.getAccessibilityEmbeddedConnection();
}
@@ -135,6 +136,7 @@
mWm = new WindowlessWindowManager(context.getResources().getConfiguration(),
mSurfaceControl, hostToken);
mViewRoot = new ViewRootImpl(context, display, mWm);
+ mViewRoot.forceDisableBLAST();
mAccessibilityEmbeddedConnection = mViewRoot.getAccessibilityEmbeddedConnection();
}
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 73707ca..fb7c04a 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -392,7 +392,7 @@
* This gets called on a RenderThread worker thread, so members accessed here must
* be protected by a lock.
*/
- final boolean useBLAST = WindowManagerGlobal.useBLAST();
+ final boolean useBLAST = viewRoot.useBLAST();
viewRoot.registerRtFrameCallback(frame -> {
try {
final SurfaceControl.Transaction t = useBLAST ?
@@ -930,7 +930,7 @@
mSurfaceHeight);
}
} else if ((layoutSizeChanged || positionChanged) &&
- WindowManagerGlobal.useBLAST()) {
+ viewRoot.useBLAST()) {
viewRoot.setUseBLASTSyncTransaction();
}
mTmpTransaction.setCornerRadius(mSurfaceControl, mCornerRadius);
@@ -1132,9 +1132,8 @@
private void applySurfaceTransforms(SurfaceControl surface, SurfaceControl.Transaction t,
Rect position, long frameNumber) {
- if (frameNumber > 0 && !WindowManagerGlobal.useBLAST()) {
- final ViewRootImpl viewRoot = getViewRootImpl();
-
+ final ViewRootImpl viewRoot = getViewRootImpl();
+ if (frameNumber > 0 && viewRoot != null && !viewRoot.useBLAST()) {
t.deferTransactionUntil(surface, viewRoot.getRenderSurfaceControl(),
frameNumber);
}
@@ -1150,8 +1149,8 @@
}
private void setParentSpaceRectangle(Rect position, long frameNumber) {
- final boolean useBLAST = WindowManagerGlobal.useBLAST();
final ViewRootImpl viewRoot = getViewRootImpl();
+ final boolean useBLAST = viewRoot.useBLAST();
final SurfaceControl.Transaction t = useBLAST ? viewRoot.getBLASTSyncTransaction() :
mRtTransaction;
@@ -1211,7 +1210,8 @@
@Override
public void positionLost(long frameNumber) {
- boolean useBLAST = WindowManagerGlobal.useBLAST();
+ final ViewRootImpl viewRoot = getViewRootImpl();
+ boolean useBLAST = viewRoot != null && viewRoot.useBLAST();
if (DEBUG) {
Log.d(TAG, String.format("%d windowPositionLost, frameNr = %d",
System.identityHashCode(this), frameNumber));
@@ -1222,8 +1222,6 @@
return;
}
- final ViewRootImpl viewRoot = getViewRootImpl();
-
final SurfaceControl.Transaction t = useBLAST ?
(viewRoot != null ? viewRoot.getBLASTSyncTransaction() : mRtTransaction) :
mRtTransaction;
@@ -1646,7 +1644,7 @@
}
private void updateScreenMatrixForEmbeddedHierarchy() {
- getBoundsOnScreen(mTmpRect, true);
+ getBoundsOnScreen(mTmpRect);
mTmpMatrix.reset();
mTmpMatrix.setTranslate(mTmpRect.left, mTmpRect.top);
mTmpMatrix.postScale(mScreenRect.width() / (float) mSurfaceWidth,
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 148b327..4a093e6 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -322,7 +322,7 @@
*/
private boolean mForceNextConfigUpdate;
- private final boolean mUseBLASTAdapter;
+ private boolean mUseBLASTAdapter;
/**
* Signals that compatibility booleans have been initialized according to
@@ -9639,4 +9639,16 @@
public void onDescendantUnbufferedRequested() {
mUnbufferedInputSource = mView.mUnbufferedInputSource;
}
+
+ /**
+ * Force disabling use of the BLAST adapter regardless of the system
+ * flag. Needs to be called before addView.
+ */
+ void forceDisableBLAST() {
+ mUseBLASTAdapter = false;
+ }
+
+ boolean useBLAST() {
+ return mUseBLASTAdapter;
+ }
}
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java
index d40f505..6435b42 100644
--- a/core/java/android/view/WindowManagerImpl.java
+++ b/core/java/android/view/WindowManagerImpl.java
@@ -16,6 +16,11 @@
package android.view;
+import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
+import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
+import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
+import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
+
import android.annotation.NonNull;
import android.app.ResourcesManager;
import android.compat.annotation.UnsupportedAppUsage;
@@ -67,10 +72,6 @@
private IBinder mDefaultToken;
- private boolean mIsViewAdded;
- private View mLastView;
- private WindowManager.LayoutParams mLastParams;
-
public WindowManagerImpl(Context context) {
this(context, null);
}
@@ -102,9 +103,6 @@
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
applyDefaultToken(params);
mGlobal.addView(view, params, mContext.getDisplayNoVerify(), mParentWindow);
- mIsViewAdded = true;
- mLastView = view;
- mLastParams = (WindowManager.LayoutParams) params;
}
@Override
@@ -247,21 +245,19 @@
}
private WindowInsets computeWindowInsets() {
- // TODO(window-context): This can only be properly implemented
+ // TODO(b/118118435): This can only be properly implemented
// once we flip the new insets mode flag.
- if (mParentWindow != null) {
- if (mParentWindow.getDecorView().isAttachedToWindow()) {
- return mParentWindow.getDecorView().getViewRootImpl()
- .getWindowInsets(true /* forceConstruct */);
- }
- return getWindowInsetsFromServer(mParentWindow.getAttributes());
- }
- if (mIsViewAdded) {
- return mLastView.getViewRootImpl().getWindowInsets(true /* forceConstruct */);
- } else {
- return getWindowInsetsFromServer(new WindowManager.LayoutParams());
- }
+ // Initialize params which used for obtaining all system insets.
+ final WindowManager.LayoutParams params = new WindowManager.LayoutParams();
+ params.flags = FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
+ params.token = (mParentWindow != null) ? mParentWindow.getContext().getActivityToken()
+ : mContext.getActivityToken();
+ params.systemUiVisibility = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+ | SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
+ params.setFitInsetsTypes(0);
+ params.setFitInsetsSides(0);
+ return getWindowInsetsFromServer(params);
}
private WindowInsets getWindowInsetsFromServer(WindowManager.LayoutParams attrs) {
diff --git a/core/java/android/view/WindowMetrics.java b/core/java/android/view/WindowMetrics.java
index 8caf5b7..ab5a06e 100644
--- a/core/java/android/view/WindowMetrics.java
+++ b/core/java/android/view/WindowMetrics.java
@@ -17,6 +17,7 @@
package android.view;
import android.annotation.NonNull;
+import android.graphics.Point;
import android.util.Size;
/**
@@ -40,6 +41,30 @@
/**
* Returns the size of the window.
+ * <p>
+ * <b>Note that this reports a different size than {@link Display#getSize(Point)}.</b>
+ * This method reports the window size including all system bars area, while
+ * {@link Display#getSize(Point)} reports the area excluding navigation bars and display cutout
+ * areas. The value reported by {@link Display#getSize(Point)} can be obtained by using:
+ * <pre class="prettyprint">
+ * final WindowMetrics metrics = windowManager.getCurrentMetrics();
+ * // Gets all excluding insets
+ * final WindowInsets windowInsets = metrics.getWindowInsets();
+ * Insets insets = windowInsets.getInsets(WindowInsets.Type.navigationBars());
+ * final DisplayCutout cutout = windowInsets.getCutout();
+ * if (cutout != null) {
+ * final Insets cutoutSafeInsets = Insets.of(cutout.getSafeInsetsLeft(), ...);
+ * insets = insets.max(insets, cutoutSafeInsets);
+ * }
+ *
+ * int insetsWidth = insets.right + insets.left;
+ * int insetsHeight = insets.top + insets.bottom;
+ *
+ * // Legacy size that Display#getSize reports
+ * final Size legacySize = new Size(metrics.getWidth() - insetsWidth,
+ * metrics.getHeight() - insetsHeight);
+ * </pre>
+ * </p>
*
* @return window size in pixel.
*/
diff --git a/core/java/android/view/inputmethod/InlineSuggestionsRequest.java b/core/java/android/view/inputmethod/InlineSuggestionsRequest.java
index 5700dda..e50da40 100644
--- a/core/java/android/view/inputmethod/InlineSuggestionsRequest.java
+++ b/core/java/android/view/inputmethod/InlineSuggestionsRequest.java
@@ -22,7 +22,9 @@
import android.os.Bundle;
import android.os.IBinder;
import android.os.LocaleList;
+import android.os.Parcel;
import android.os.Parcelable;
+import android.view.Display;
import android.view.inline.InlinePresentationSpec;
import com.android.internal.util.DataClass;
@@ -67,7 +69,11 @@
*/
private @NonNull LocaleList mSupportedLocales;
- // TODO(b/149609075): the generated code needs to be manually fixed due to the bug.
+ /**
+ * The extras state propagated from the IME to pass extra data.
+ */
+ private @Nullable Bundle mExtras;
+
/**
* The host input token of the IME that made the request. This will be set by the system for
* safety reasons.
@@ -77,9 +83,12 @@
private @Nullable IBinder mHostInputToken;
/**
- * The extras state propagated from the IME to pass extra data.
+ * The host display id of the IME that made the request. This will be set by the system for
+ * safety reasons.
+ *
+ * @hide
*/
- private @Nullable Bundle mExtras;
+ private int mHostDisplayId;
/**
* @hide
@@ -89,6 +98,24 @@
mHostInputToken = hostInputToken;
}
+ // TODO(b/149609075): remove once IBinder parcelling is natively supported
+ private void parcelHostInputToken(@NonNull Parcel parcel, int flags) {
+ parcel.writeStrongBinder(mHostInputToken);
+ }
+
+ // TODO(b/149609075): remove once IBinder parcelling is natively supported
+ private @Nullable IBinder unparcelHostInputToken(Parcel parcel) {
+ return parcel.readStrongBinder();
+ }
+
+ /**
+ * @hide
+ * @see {@link #mHostDisplayId}.
+ */
+ public void setHostDisplayId(int hostDisplayId) {
+ mHostDisplayId = hostDisplayId;
+ }
+
private void onConstructed() {
Preconditions.checkState(mMaxSuggestionCount >= mPresentationSpecs.size());
}
@@ -111,10 +138,17 @@
}
@Nullable
+ private static int defaultHostDisplayId() {
+ return Display.INVALID_DISPLAY;
+ }
+
+ @Nullable
private static Bundle defaultExtras() {
return null;
}
+
+
/** @hide */
abstract static class BaseBuilder {
abstract Builder setPresentationSpecs(@NonNull List<InlinePresentationSpec> value);
@@ -122,6 +156,8 @@
abstract Builder setHostPackageName(@Nullable String value);
abstract Builder setHostInputToken(IBinder hostInputToken);
+
+ abstract Builder setHostDisplayId(int value);
}
@@ -145,8 +181,9 @@
@NonNull List<InlinePresentationSpec> presentationSpecs,
@NonNull String hostPackageName,
@NonNull LocaleList supportedLocales,
+ @Nullable Bundle extras,
@Nullable IBinder hostInputToken,
- @Nullable Bundle extras) {
+ int hostDisplayId) {
this.mMaxSuggestionCount = maxSuggestionCount;
this.mPresentationSpecs = presentationSpecs;
com.android.internal.util.AnnotationValidations.validate(
@@ -157,8 +194,9 @@
this.mSupportedLocales = supportedLocales;
com.android.internal.util.AnnotationValidations.validate(
NonNull.class, null, mSupportedLocales);
- this.mHostInputToken = hostInputToken;
this.mExtras = extras;
+ this.mHostInputToken = hostInputToken;
+ this.mHostDisplayId = hostDisplayId;
onConstructed();
}
@@ -202,6 +240,14 @@
}
/**
+ * The extras state propagated from the IME to pass extra data.
+ */
+ @DataClass.Generated.Member
+ public @Nullable Bundle getExtras() {
+ return mExtras;
+ }
+
+ /**
* The host input token of the IME that made the request. This will be set by the system for
* safety reasons.
*
@@ -213,11 +259,14 @@
}
/**
- * The extras state propagated from the IME to pass extra data.
+ * The host display id of the IME that made the request. This will be set by the system for
+ * safety reasons.
+ *
+ * @hide
*/
@DataClass.Generated.Member
- public @Nullable Bundle getExtras() {
- return mExtras;
+ public int getHostDisplayId() {
+ return mHostDisplayId;
}
@Override
@@ -231,8 +280,9 @@
"presentationSpecs = " + mPresentationSpecs + ", " +
"hostPackageName = " + mHostPackageName + ", " +
"supportedLocales = " + mSupportedLocales + ", " +
+ "extras = " + mExtras + ", " +
"hostInputToken = " + mHostInputToken + ", " +
- "extras = " + mExtras +
+ "hostDisplayId = " + mHostDisplayId +
" }";
}
@@ -253,8 +303,9 @@
&& java.util.Objects.equals(mPresentationSpecs, that.mPresentationSpecs)
&& java.util.Objects.equals(mHostPackageName, that.mHostPackageName)
&& java.util.Objects.equals(mSupportedLocales, that.mSupportedLocales)
+ && java.util.Objects.equals(mExtras, that.mExtras)
&& java.util.Objects.equals(mHostInputToken, that.mHostInputToken)
- && java.util.Objects.equals(mExtras, that.mExtras);
+ && mHostDisplayId == that.mHostDisplayId;
}
@Override
@@ -268,27 +319,29 @@
_hash = 31 * _hash + java.util.Objects.hashCode(mPresentationSpecs);
_hash = 31 * _hash + java.util.Objects.hashCode(mHostPackageName);
_hash = 31 * _hash + java.util.Objects.hashCode(mSupportedLocales);
- _hash = 31 * _hash + java.util.Objects.hashCode(mHostInputToken);
_hash = 31 * _hash + java.util.Objects.hashCode(mExtras);
+ _hash = 31 * _hash + java.util.Objects.hashCode(mHostInputToken);
+ _hash = 31 * _hash + mHostDisplayId;
return _hash;
}
@Override
@DataClass.Generated.Member
- public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
// You can override field parcelling by defining methods like:
// void parcelFieldName(Parcel dest, int flags) { ... }
byte flg = 0;
- if (mHostInputToken != null) flg |= 0x10;
- if (mExtras != null) flg |= 0x20;
+ if (mExtras != null) flg |= 0x10;
+ if (mHostInputToken != null) flg |= 0x20;
dest.writeByte(flg);
dest.writeInt(mMaxSuggestionCount);
dest.writeParcelableList(mPresentationSpecs, flags);
dest.writeString(mHostPackageName);
dest.writeTypedObject(mSupportedLocales, flags);
- if (mHostInputToken != null) dest.writeStrongBinder(mHostInputToken);
if (mExtras != null) dest.writeBundle(mExtras);
+ parcelHostInputToken(dest, flags);
+ dest.writeInt(mHostDisplayId);
}
@Override
@@ -298,7 +351,7 @@
/** @hide */
@SuppressWarnings({"unchecked", "RedundantCast"})
@DataClass.Generated.Member
- /* package-private */ InlineSuggestionsRequest(@NonNull android.os.Parcel in) {
+ /* package-private */ InlineSuggestionsRequest(@NonNull Parcel in) {
// You can override field unparcelling by defining methods like:
// static FieldType unparcelFieldName(Parcel in) { ... }
@@ -308,8 +361,9 @@
in.readParcelableList(presentationSpecs, InlinePresentationSpec.class.getClassLoader());
String hostPackageName = in.readString();
LocaleList supportedLocales = (LocaleList) in.readTypedObject(LocaleList.CREATOR);
- IBinder hostInputToken = (flg & 0x10) == 0 ? null : in.readStrongBinder();
- Bundle extras = (flg & 0x20) == 0 ? null : in.readBundle();
+ Bundle extras = (flg & 0x10) == 0 ? null : in.readBundle();
+ IBinder hostInputToken = unparcelHostInputToken(in);
+ int hostDisplayId = in.readInt();
this.mMaxSuggestionCount = maxSuggestionCount;
this.mPresentationSpecs = presentationSpecs;
@@ -321,8 +375,9 @@
this.mSupportedLocales = supportedLocales;
com.android.internal.util.AnnotationValidations.validate(
NonNull.class, null, mSupportedLocales);
- this.mHostInputToken = hostInputToken;
this.mExtras = extras;
+ this.mHostInputToken = hostInputToken;
+ this.mHostDisplayId = hostDisplayId;
onConstructed();
}
@@ -336,7 +391,7 @@
}
@Override
- public InlineSuggestionsRequest createFromParcel(@NonNull android.os.Parcel in) {
+ public InlineSuggestionsRequest createFromParcel(@NonNull Parcel in) {
return new InlineSuggestionsRequest(in);
}
};
@@ -352,8 +407,9 @@
private @NonNull List<InlinePresentationSpec> mPresentationSpecs;
private @NonNull String mHostPackageName;
private @NonNull LocaleList mSupportedLocales;
- private @Nullable IBinder mHostInputToken;
private @Nullable Bundle mExtras;
+ private @Nullable IBinder mHostInputToken;
+ private int mHostDisplayId;
private long mBuilderFieldsSet = 0L;
@@ -436,6 +492,17 @@
}
/**
+ * The extras state propagated from the IME to pass extra data.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setExtras(@Nullable Bundle value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x10;
+ mExtras = value;
+ return this;
+ }
+
+ /**
* The host input token of the IME that made the request. This will be set by the system for
* safety reasons.
*
@@ -445,26 +512,30 @@
@Override
@NonNull Builder setHostInputToken(@Nullable IBinder value) {
checkNotUsed();
- mBuilderFieldsSet |= 0x10;
+ mBuilderFieldsSet |= 0x20;
mHostInputToken = value;
return this;
}
/**
- * The extras state propagated from the IME to pass extra data.
+ * The host display id of the IME that made the request. This will be set by the system for
+ * safety reasons.
+ *
+ * @hide
*/
@DataClass.Generated.Member
- public @NonNull Builder setExtras(@Nullable Bundle value) {
+ @Override
+ @NonNull Builder setHostDisplayId(int value) {
checkNotUsed();
- mBuilderFieldsSet |= 0x20;
- mExtras = value;
+ mBuilderFieldsSet |= 0x40;
+ mHostDisplayId = value;
return this;
}
/** Builds the instance. This builder should not be touched after calling this! */
public @NonNull InlineSuggestionsRequest build() {
checkNotUsed();
- mBuilderFieldsSet |= 0x40; // Mark builder used
+ mBuilderFieldsSet |= 0x80; // Mark builder used
if ((mBuilderFieldsSet & 0x1) == 0) {
mMaxSuggestionCount = defaultMaxSuggestionCount();
@@ -476,23 +547,27 @@
mSupportedLocales = defaultSupportedLocales();
}
if ((mBuilderFieldsSet & 0x10) == 0) {
- mHostInputToken = defaultHostInputToken();
+ mExtras = defaultExtras();
}
if ((mBuilderFieldsSet & 0x20) == 0) {
- mExtras = defaultExtras();
+ mHostInputToken = defaultHostInputToken();
+ }
+ if ((mBuilderFieldsSet & 0x40) == 0) {
+ mHostDisplayId = defaultHostDisplayId();
}
InlineSuggestionsRequest o = new InlineSuggestionsRequest(
mMaxSuggestionCount,
mPresentationSpecs,
mHostPackageName,
mSupportedLocales,
+ mExtras,
mHostInputToken,
- mExtras);
+ mHostDisplayId);
return o;
}
private void checkNotUsed() {
- if ((mBuilderFieldsSet & 0x40) != 0) {
+ if ((mBuilderFieldsSet & 0x80) != 0) {
throw new IllegalStateException(
"This Builder should not be reused. Use a new Builder instance instead");
}
@@ -500,10 +575,10 @@
}
@DataClass.Generated(
- time = 1581747892762L,
+ time = 1582339908980L,
codegenVersion = "1.0.14",
sourceFile = "frameworks/base/core/java/android/view/inputmethod/InlineSuggestionsRequest.java",
- inputSignatures = "public static final int SUGGESTION_COUNT_UNLIMITED\nprivate final int mMaxSuggestionCount\nprivate final @android.annotation.NonNull java.util.List<android.view.inline.InlinePresentationSpec> mPresentationSpecs\nprivate @android.annotation.NonNull java.lang.String mHostPackageName\nprivate @android.annotation.NonNull android.os.LocaleList mSupportedLocales\nprivate @android.annotation.Nullable android.os.IBinder mHostInputToken\nprivate @android.annotation.Nullable android.os.Bundle mExtras\npublic void setHostInputToken(android.os.IBinder)\nprivate void onConstructed()\nprivate static int defaultMaxSuggestionCount()\nprivate static java.lang.String defaultHostPackageName()\nprivate static android.os.LocaleList defaultSupportedLocales()\nprivate static @android.annotation.Nullable android.os.IBinder defaultHostInputToken()\nprivate static @android.annotation.Nullable android.os.Bundle defaultExtras()\nclass InlineSuggestionsRequest extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genBuilder=true)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setPresentationSpecs(java.util.List<android.view.inline.InlinePresentationSpec>)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setHostPackageName(java.lang.String)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setHostInputToken(android.os.IBinder)\nclass BaseBuilder extends java.lang.Object implements []")
+ inputSignatures = "public static final int SUGGESTION_COUNT_UNLIMITED\nprivate final int mMaxSuggestionCount\nprivate final @android.annotation.NonNull java.util.List<android.view.inline.InlinePresentationSpec> mPresentationSpecs\nprivate @android.annotation.NonNull java.lang.String mHostPackageName\nprivate @android.annotation.NonNull android.os.LocaleList mSupportedLocales\nprivate @android.annotation.Nullable android.os.Bundle mExtras\nprivate @android.annotation.Nullable android.os.IBinder mHostInputToken\nprivate int mHostDisplayId\npublic void setHostInputToken(android.os.IBinder)\nprivate void parcelHostInputToken(android.os.Parcel,int)\nprivate @android.annotation.Nullable android.os.IBinder unparcelHostInputToken(android.os.Parcel)\npublic void setHostDisplayId(int)\nprivate void onConstructed()\nprivate static int defaultMaxSuggestionCount()\nprivate static java.lang.String defaultHostPackageName()\nprivate static android.os.LocaleList defaultSupportedLocales()\nprivate static @android.annotation.Nullable android.os.IBinder defaultHostInputToken()\nprivate static @android.annotation.Nullable int defaultHostDisplayId()\nprivate static @android.annotation.Nullable android.os.Bundle defaultExtras()\nclass InlineSuggestionsRequest extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genBuilder=true)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setPresentationSpecs(java.util.List<android.view.inline.InlinePresentationSpec>)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setHostPackageName(java.lang.String)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setHostInputToken(android.os.IBinder)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setHostDisplayId(int)\nclass BaseBuilder extends java.lang.Object implements []")
@Deprecated
private void __metadata() {}
diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto
index 7d1cf5d..d6687f0 100644
--- a/core/proto/android/os/incident.proto
+++ b/core/proto/android/os/incident.proto
@@ -58,6 +58,7 @@
import "frameworks/base/core/proto/android/service/usb.proto";
import "frameworks/base/core/proto/android/util/event_log_tags.proto";
import "frameworks/base/core/proto/android/util/log.proto";
+import "frameworks/base/core/proto/android/util/textdump.proto";
import "frameworks/base/core/proto/android/privacy.proto";
import "frameworks/base/core/proto/android/section.proto";
import "frameworks/base/proto/src/ipconnectivity.proto";
@@ -510,6 +511,17 @@
(section).args = "sensorservice --proto"
];
+ // Dumps in text format (on userdebug and eng builds only): 4000 ~ 4999
+ optional android.util.TextDumpProto textdump_wifi = 4000 [
+ (section).type = SECTION_TEXT_DUMPSYS,
+ (section).args = "wifi"
+ ];
+
+ optional android.util.TextDumpProto textdump_bluetooth = 4001 [
+ (section).type = SECTION_TEXT_DUMPSYS,
+ (section).args = "bluetooth_manager"
+ ];
+
// Reserved for OEMs.
extensions 50000 to 100000;
}
diff --git a/core/proto/android/section.proto b/core/proto/android/section.proto
index 5afe22a..299d6f9a 100644
--- a/core/proto/android/section.proto
+++ b/core/proto/android/section.proto
@@ -46,6 +46,10 @@
// incidentd calls tombstoned for annotated field
SECTION_TOMBSTONE = 6;
+
+ // incidentd calls legacy text dumpsys for annotated field. The section will only be generated
+ // on userdebug and eng builds.
+ SECTION_TEXT_DUMPSYS = 7;
}
message SectionFlags {
diff --git a/core/proto/android/util/textdump.proto b/core/proto/android/util/textdump.proto
new file mode 100644
index 0000000..6118487
--- /dev/null
+++ b/core/proto/android/util/textdump.proto
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+syntax = "proto2";
+package android.util;
+
+import "frameworks/base/core/proto/android/privacy.proto";
+
+option java_multiple_files = true;
+
+message TextDumpProto {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ // The command that was executed
+ optional string command = 1;
+ // The content that was dumped
+ optional string content = 2;
+ // The duration of the dump process
+ optional int64 dump_duration_ns = 3;
+}
diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml
index 718ca46..b42fce0 100644
--- a/core/tests/coretests/AndroidManifest.xml
+++ b/core/tests/coretests/AndroidManifest.xml
@@ -138,6 +138,9 @@
<!-- vr test permissions -->
<uses-permission android:name="android.permission.RESTRICTED_VR_ACCESS" />
+ <!-- WindowMetricsTest permissions -->
+ <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
+
<application android:theme="@style/Theme" android:supportsRtl="true">
<uses-library android:name="android.test.runner" />
<uses-library android:name="org.apache.http.legacy" android:required="false" />
diff --git a/core/tests/coretests/src/android/view/WindowMetricsTest.java b/core/tests/coretests/src/android/view/WindowMetricsTest.java
new file mode 100644
index 0000000..fa68860
--- /dev/null
+++ b/core/tests/coretests/src/android/view/WindowMetricsTest.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2020 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;
+
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+
+import static org.junit.Assert.assertTrue;
+
+import android.content.Context;
+import android.hardware.display.DisplayManager;
+import android.os.Handler;
+import android.platform.test.annotations.Presubmit;
+import android.util.Size;
+
+import androidx.test.filters.FlakyTest;
+import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Tests for {@link WindowManager#getCurrentWindowMetrics()} and
+ * {@link WindowManager#getMaximumWindowMetrics()}.
+ *
+ * <p>Build/Install/Run:
+ * atest FrameworksCoreTests:WindowMetricsTest
+ *
+ * <p>This test class is a part of Window Manager Service tests and specified in
+ * {@link com.android.server.wm.test.filters.FrameworksTestsFilter}.
+ */
+@FlakyTest(bugId = 148789183, detail = "Remove after confirmed it's stable.")
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+@Presubmit
+public class WindowMetricsTest {
+ private Context mWindowContext;
+ private WindowManager mWm;
+
+ @Before
+ public void setUp() {
+ final Context insetContext = InstrumentationRegistry.getInstrumentation()
+ .getTargetContext();
+ final Display display = insetContext.getSystemService(DisplayManager.class)
+ .getDisplay(DEFAULT_DISPLAY);
+ mWindowContext = insetContext.createDisplayContext(display)
+ .createWindowContext(TYPE_APPLICATION_OVERLAY, null /* options */);
+ mWm = mWindowContext.getSystemService(WindowManager.class);
+ }
+
+ @Test
+ public void testAddViewANdRemoveView_GetMetrics_DoNotCrash() {
+ final View view = new View(mWindowContext);
+ final WindowManager.LayoutParams params =
+ new WindowManager.LayoutParams(TYPE_APPLICATION_OVERLAY);
+ Handler.getMain().runWithScissors(() -> {
+ mWm.addView(view, params);
+ // Check get metrics do not crash.
+ WindowMetrics currentMetrics = mWm.getCurrentWindowMetrics();
+ WindowMetrics maxMetrics = mWm.getMaximumWindowMetrics();
+ verifyMetricsSanity(currentMetrics, maxMetrics);
+
+ mWm.removeViewImmediate(view);
+ // Check get metrics do not crash.
+ currentMetrics = mWm.getCurrentWindowMetrics();
+ maxMetrics = mWm.getMaximumWindowMetrics();
+ verifyMetricsSanity(currentMetrics, maxMetrics);
+ }, 0);
+ }
+
+ private static void verifyMetricsSanity(WindowMetrics currentMetrics,
+ WindowMetrics maxMetrics) {
+ Size currentSize = currentMetrics.getSize();
+ Size maxSize = maxMetrics.getSize();
+
+ assertTrue(maxSize.getWidth() >= currentSize.getWidth());
+ assertTrue(maxSize.getHeight() >= currentSize.getHeight());
+ }
+}
diff --git a/packages/Tethering/tests/unit/Android.bp b/packages/Tethering/tests/unit/Android.bp
index c6905ec..59681e9 100644
--- a/packages/Tethering/tests/unit/Android.bp
+++ b/packages/Tethering/tests/unit/Android.bp
@@ -41,7 +41,7 @@
"framework-minus-apex",
"ext",
"framework-res",
- "framework-wifi-stubs",
+ "framework-wifi-stubs-module_libs_api",
"framework-telephony-stubs",
"android.test.runner",
"android.test.base",
diff --git a/proto/src/system_messages.proto b/proto/src/system_messages.proto
index cff5504..c5a5d34 100644
--- a/proto/src/system_messages.proto
+++ b/proto/src/system_messages.proto
@@ -255,6 +255,10 @@
// Inform the user a foreground service while-in-use permission is restricted.
NOTE_FOREGROUND_SERVICE_WHILE_IN_USE_PERMISSION = 61;
+ // Display the Android Debug Protocol status
+ // Package: android
+ NOTE_ADB_WIFI_ACTIVE = 62;
+
// ADD_NEW_IDS_ABOVE_THIS_LINE
// Legacy IDs with arbitrary values appear below
// Legacy IDs existed as stable non-conflicting constants prior to the O release
diff --git a/services/api/current.txt b/services/api/current.txt
index 4a0a0d8..8c90165 100644
--- a/services/api/current.txt
+++ b/services/api/current.txt
@@ -49,14 +49,15 @@
public abstract class SystemService {
ctor public SystemService(@NonNull android.content.Context);
method @NonNull public final android.content.Context getContext();
- method public boolean isSupportedUser(@NonNull com.android.server.SystemService.TargetUser);
+ method public boolean isUserSupported(@NonNull com.android.server.SystemService.TargetUser);
method public void onBootPhase(int);
- method public void onCleanupUser(@NonNull com.android.server.SystemService.TargetUser);
method public abstract void onStart();
- method public void onStartUser(@NonNull com.android.server.SystemService.TargetUser);
- method public void onStopUser(@NonNull com.android.server.SystemService.TargetUser);
- method public void onSwitchUser(@Nullable com.android.server.SystemService.TargetUser, @NonNull com.android.server.SystemService.TargetUser);
- method public void onUnlockUser(@NonNull com.android.server.SystemService.TargetUser);
+ method public void onUserStarting(@NonNull com.android.server.SystemService.TargetUser);
+ method public void onUserStopped(@NonNull com.android.server.SystemService.TargetUser);
+ method public void onUserStopping(@NonNull com.android.server.SystemService.TargetUser);
+ method public void onUserSwitching(@Nullable com.android.server.SystemService.TargetUser, @NonNull com.android.server.SystemService.TargetUser);
+ method public void onUserUnlocked(@NonNull com.android.server.SystemService.TargetUser);
+ method public void onUserUnlocking(@NonNull com.android.server.SystemService.TargetUser);
method protected final void publishBinderService(@NonNull String, @NonNull android.os.IBinder);
method protected final void publishBinderService(@NonNull String, @NonNull android.os.IBinder, boolean);
field public static final int PHASE_ACTIVITY_MANAGER_READY = 550; // 0x226
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index 5405fc7..e49c1ed 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -331,7 +331,7 @@
}
@Override // from SystemService
- public boolean isSupportedUser(TargetUser user) {
+ public boolean isUserSupported(TargetUser user) {
return user.getUserInfo().isFull() || user.getUserInfo().isManagedProfile();
}
diff --git a/services/autofill/java/com/android/server/autofill/RemoteInlineSuggestionRenderService.java b/services/autofill/java/com/android/server/autofill/RemoteInlineSuggestionRenderService.java
index 5d5af53..7ad5632 100644
--- a/services/autofill/java/com/android/server/autofill/RemoteInlineSuggestionRenderService.java
+++ b/services/autofill/java/com/android/server/autofill/RemoteInlineSuggestionRenderService.java
@@ -86,9 +86,9 @@
*/
public void renderSuggestion(@NonNull IInlineSuggestionUiCallback callback,
@NonNull InlinePresentation presentation, int width, int height,
- @Nullable IBinder hostInputToken) {
- scheduleAsyncRequest(
- (s) -> s.renderSuggestion(callback, presentation, width, height, hostInputToken));
+ @Nullable IBinder hostInputToken, int displayId) {
+ scheduleAsyncRequest((s) -> s.renderSuggestion(callback, presentation, width, height,
+ hostInputToken, displayId));
}
@Nullable
diff --git a/services/autofill/java/com/android/server/autofill/ui/InlineSuggestionFactory.java b/services/autofill/java/com/android/server/autofill/ui/InlineSuggestionFactory.java
index 0d8c89b..56e8707 100644
--- a/services/autofill/java/com/android/server/autofill/ui/InlineSuggestionFactory.java
+++ b/services/autofill/java/com/android/server/autofill/ui/InlineSuggestionFactory.java
@@ -134,7 +134,7 @@
if (inlineAuthentication != null) {
InlineSuggestion inlineAuthSuggestion = createInlineAuthSuggestion(inlineAuthentication,
remoteRenderService, onClickFactory, onErrorCallback,
- request.getHostInputToken());
+ request.getHostInputToken(), request.getHostDisplayId());
inlineSuggestions.add(inlineAuthSuggestion);
return new InlineSuggestionsResponse(inlineSuggestions);
@@ -164,7 +164,7 @@
InlineSuggestion inlineSuggestion = createInlineSuggestion(isAugmented, dataset,
fieldIndex, mergedInlinePresentation(request, datasetIndex, inlinePresentation),
onClickFactory, remoteRenderService, onErrorCallback,
- request.getHostInputToken());
+ request.getHostInputToken(), request.getHostDisplayId());
inlineSuggestions.add(inlineSuggestion);
}
@@ -172,7 +172,8 @@
for (InlinePresentation inlinePresentation : inlineActions) {
final InlineSuggestion inlineAction = createInlineAction(isAugmented, context,
mergedInlinePresentation(request, 0, inlinePresentation),
- remoteRenderService, onErrorCallback, request.getHostInputToken());
+ remoteRenderService, onErrorCallback, request.getHostInputToken(),
+ request.getHostDisplayId());
inlineSuggestions.add(inlineAction);
}
}
@@ -215,7 +216,8 @@
@NonNull Context context,
@NonNull InlinePresentation inlinePresentation,
@Nullable RemoteInlineSuggestionRenderService remoteRenderService,
- @NonNull Runnable onErrorCallback, @Nullable IBinder hostInputToken) {
+ @NonNull Runnable onErrorCallback, @Nullable IBinder hostInputToken,
+ int displayId) {
// TODO(b/146453195): fill in the autofill hint properly.
final InlineSuggestionInfo inlineSuggestionInfo = new InlineSuggestionInfo(
inlinePresentation.getInlinePresentationSpec(),
@@ -227,7 +229,7 @@
};
return new InlineSuggestion(inlineSuggestionInfo,
createInlineContentProvider(inlinePresentation, onClickAction, onErrorCallback,
- remoteRenderService, hostInputToken));
+ remoteRenderService, hostInputToken, displayId));
}
private static InlineSuggestion createInlineSuggestion(boolean isAugmented,
@@ -235,7 +237,8 @@
@NonNull InlinePresentation inlinePresentation,
@NonNull BiConsumer<Dataset, Integer> onClickFactory,
@NonNull RemoteInlineSuggestionRenderService remoteRenderService,
- @NonNull Runnable onErrorCallback, @Nullable IBinder hostInputToken) {
+ @NonNull Runnable onErrorCallback, @Nullable IBinder hostInputToken,
+ int displayId) {
// TODO(b/146453195): fill in the autofill hint properly.
final InlineSuggestionInfo inlineSuggestionInfo = new InlineSuggestionInfo(
inlinePresentation.getInlinePresentationSpec(),
@@ -246,7 +249,7 @@
final InlineSuggestion inlineSuggestion = new InlineSuggestion(inlineSuggestionInfo,
createInlineContentProvider(inlinePresentation,
() -> onClickFactory.accept(dataset, datasetIndex), onErrorCallback,
- remoteRenderService, hostInputToken));
+ remoteRenderService, hostInputToken, displayId));
return inlineSuggestion;
}
@@ -255,7 +258,7 @@
@NonNull InlinePresentation inlinePresentation,
@NonNull RemoteInlineSuggestionRenderService remoteRenderService,
@NonNull BiConsumer<Dataset, Integer> onClickFactory, @NonNull Runnable onErrorCallback,
- @Nullable IBinder hostInputToken) {
+ @Nullable IBinder hostInputToken, int displayId) {
final InlineSuggestionInfo inlineSuggestionInfo = new InlineSuggestionInfo(
inlinePresentation.getInlinePresentationSpec(),
InlineSuggestionInfo.SOURCE_AUTOFILL, null, InlineSuggestionInfo.TYPE_SUGGESTION);
@@ -264,7 +267,7 @@
createInlineContentProvider(inlinePresentation,
() -> onClickFactory.accept(null,
AutofillManager.AUTHENTICATION_ID_DATASET_ID_UNDEFINED),
- onErrorCallback, remoteRenderService, hostInputToken));
+ onErrorCallback, remoteRenderService, hostInputToken, displayId));
}
/**
@@ -291,7 +294,8 @@
@NonNull InlinePresentation inlinePresentation, @Nullable Runnable onClickAction,
@NonNull Runnable onErrorCallback,
@Nullable RemoteInlineSuggestionRenderService remoteRenderService,
- @Nullable IBinder hostInputToken) {
+ @Nullable IBinder hostInputToken,
+ int displayId) {
return new IInlineContentProvider.Stub() {
@Override
public void provideContent(int width, int height, IInlineContentCallback callback) {
@@ -305,7 +309,7 @@
}
remoteRenderService.renderSuggestion(uiCallback, inlinePresentation,
- width, height, hostInputToken);
+ width, height, hostInputToken, displayId);
});
}
};
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
index 9a33fc9..5d2b9f3 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
@@ -201,7 +201,7 @@
}
@Override // from SystemService
- public boolean isSupportedUser(TargetUser user) {
+ public boolean isUserSupported(TargetUser user) {
return user.getUserInfo().isFull() || user.getUserInfo().isManagedProfile();
}
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index d86b223..b1cb138 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -279,7 +279,7 @@
}
@Override
- public void onStartUser(TargetUser user) {
+ public void onUserStarting(TargetUser user) {
mStorageManagerService.snapshotAndMonitorLegacyStorageAppOp(user.getUserHandle());
}
}
diff --git a/services/core/java/com/android/server/SystemService.java b/services/core/java/com/android/server/SystemService.java
index aabe98b..e5c0540 100644
--- a/services/core/java/com/android/server/SystemService.java
+++ b/services/core/java/com/android/server/SystemService.java
@@ -238,12 +238,12 @@
* <p>By default returns {@code true}, but subclasses should extend for optimization, if they
* don't support some types (like headless system user).
*/
- public boolean isSupportedUser(@NonNull TargetUser user) {
+ public boolean isUserSupported(@NonNull TargetUser user) {
return true;
}
/**
- * Helper method used to dump which users are {@link #onStartUser(TargetUser) supported}.
+ * Helper method used to dump which users are {@link #onUserStarting(TargetUser) supported}.
*
* @hide
*/
@@ -264,7 +264,7 @@
}
/**
- * @deprecated subclasses should extend {@link #onStartUser(TargetUser)} instead
+ * @deprecated subclasses should extend {@link #onUserStarting(TargetUser)} instead
* (which by default calls this method).
*
* @hide
@@ -273,7 +273,7 @@
public void onStartUser(@UserIdInt int userId) {}
/**
- * @deprecated subclasses should extend {@link #onStartUser(TargetUser)} instead
+ * @deprecated subclasses should extend {@link #onUserStarting(TargetUser)} instead
* (which by default calls this method).
*
* @hide
@@ -287,17 +287,17 @@
* Called when a new user is starting, for system services to initialize any per-user
* state they maintain for running users.
*
- * <p>This method is only called when the service {@link #isSupportedUser(TargetUser) supports}
+ * <p>This method is only called when the service {@link #isUserSupported(TargetUser) supports}
* this user.
*
* @param user target user
*/
- public void onStartUser(@NonNull TargetUser user) {
+ public void onUserStarting(@NonNull TargetUser user) {
onStartUser(user.getUserInfo());
}
/**
- * @deprecated subclasses should extend {@link #onUnlockUser(TargetUser)} instead (which by
+ * @deprecated subclasses should extend {@link #onUserUnlocking(TargetUser)} instead (which by
* default calls this method).
*
* @hide
@@ -306,7 +306,7 @@
public void onUnlockUser(@UserIdInt int userId) {}
/**
- * @deprecated subclasses should extend {@link #onUnlockUser(TargetUser)} instead (which by
+ * @deprecated subclasses should extend {@link #onUserUnlocking(TargetUser)} instead (which by
* default calls this method).
*
* @hide
@@ -326,19 +326,30 @@
* the user will transition into the {@code STATE_RUNNING_UNLOCKED} state.
* Code written inside system services should use
* {@link UserManager#isUserUnlockingOrUnlocked(int)} to handle both of
- * these states.
+ * these states, or use {@link #onUserUnlocked(TargetUser)} instead.
* <p>
- * This method is only called when the service {@link #isSupportedUser(TargetUser) supports}
+ * This method is only called when the service {@link #isUserSupported(TargetUser) supports}
* this user.
*
* @param user target user
*/
- public void onUnlockUser(@NonNull TargetUser user) {
+ public void onUserUnlocking(@NonNull TargetUser user) {
onUnlockUser(user.getUserInfo());
}
/**
- * @deprecated subclasses should extend {@link #onSwitchUser(TargetUser, TargetUser)} instead
+ * Called after an existing user is unlocked.
+ *
+ * <p>This method is only called when the service {@link #isUserSupported(TargetUser) supports}
+ * this user.
+ *
+ * @param user target user
+ */
+ public void onUserUnlocked(@NonNull TargetUser user) {
+ }
+
+ /**
+ * @deprecated subclasses should extend {@link #onUserSwitching(TargetUser, TargetUser)} instead
* (which by default calls this method).
*
* @hide
@@ -347,7 +358,7 @@
public void onSwitchUser(@UserIdInt int toUserId) {}
/**
- * @deprecated subclasses should extend {@link #onSwitchUser(TargetUser, TargetUser)} instead
+ * @deprecated subclasses should extend {@link #onUserSwitching(TargetUser, TargetUser)} instead
* (which by default calls this method).
*
* @hide
@@ -362,7 +373,7 @@
* special behavior for whichever user is currently in the foreground. This is called
* before any application processes are aware of the new user.
*
- * <p>This method is only called when the service {@link #isSupportedUser(TargetUser) supports}
+ * <p>This method is only called when the service {@link #isUserSupported(TargetUser) supports}
* either of the users ({@code from} or {@code to}).
*
* <b>NOTE: </b> both {@code from} and {@code to} are "live" objects
@@ -371,12 +382,12 @@
* @param from the user switching from
* @param to the user switching to
*/
- public void onSwitchUser(@Nullable TargetUser from, @NonNull TargetUser to) {
+ public void onUserSwitching(@Nullable TargetUser from, @NonNull TargetUser to) {
onSwitchUser((from == null ? null : from.getUserInfo()), to.getUserInfo());
}
/**
- * @deprecated subclasses should extend {@link #onStopUser(TargetUser)} instead
+ * @deprecated subclasses should extend {@link #onUserStopping(TargetUser)} instead
* (which by default calls this method).
*
* @hide
@@ -385,7 +396,7 @@
public void onStopUser(@UserIdInt int userId) {}
/**
- * @deprecated subclasses should extend {@link #onStopUser(TargetUser)} instead
+ * @deprecated subclasses should extend {@link #onUserStopping(TargetUser)} instead
* (which by default calls this method).
*
* @hide
@@ -402,19 +413,19 @@
* broadcast to the user; it is a good place to stop making use of any resources of that
* user (such as binding to a service running in the user).
*
- * <p>This method is only called when the service {@link #isSupportedUser(TargetUser) supports}
+ * <p>This method is only called when the service {@link #isUserSupported(TargetUser) supports}
* this user.
*
* <p>NOTE: This is the last callback where the callee may access the target user's CE storage.
*
* @param user target user
*/
- public void onStopUser(@NonNull TargetUser user) {
+ public void onUserStopping(@NonNull TargetUser user) {
onStopUser(user.getUserInfo());
}
/**
- * @deprecated subclasses should extend {@link #onCleanupUser(TargetUser)} instead (which by
+ * @deprecated subclasses should extend {@link #onUserStopped(TargetUser)} instead (which by
* default calls this method).
*
* @hide
@@ -423,7 +434,7 @@
public void onCleanupUser(@UserIdInt int userId) {}
/**
- * @deprecated subclasses should extend {@link #onCleanupUser(TargetUser)} instead (which by
+ * @deprecated subclasses should extend {@link #onUserStopped(TargetUser)} instead (which by
* default calls this method).
*
* @hide
@@ -434,20 +445,16 @@
}
/**
- * Called when an existing user is stopping, for system services to finalize any per-user
- * state they maintain for running users. This is called after all application process
- * teardown of the user is complete.
+ * Called after an existing user is stopped.
*
- * <p>This method is only called when the service {@link #isSupportedUser(TargetUser) supports}
+ * <p>This is called after all application process teardown of the user is complete.
+ *
+ * <p>This method is only called when the service {@link #isUserSupported(TargetUser) supports}
* this user.
*
- * <p>NOTE: When this callback is called, the CE storage for the target user may not be
- * accessible already. Use {@link #onStopUser(TargetUser)} instead if you need to access the CE
- * storage.
- *
* @param user target user
*/
- public void onCleanupUser(@NonNull TargetUser user) {
+ public void onUserStopped(@NonNull TargetUser user) {
onCleanupUser(user.getUserInfo());
}
diff --git a/services/core/java/com/android/server/SystemServiceManager.java b/services/core/java/com/android/server/SystemServiceManager.java
index e7f7846..f16f6ef 100644
--- a/services/core/java/com/android/server/SystemServiceManager.java
+++ b/services/core/java/com/android/server/SystemServiceManager.java
@@ -51,7 +51,8 @@
// Constants used on onUser(...)
private static final String START = "Start";
- private static final String UNLOCK = "Unlock";
+ private static final String UNLOCKING = "Unlocking";
+ private static final String UNLOCKED = "Unlocked";
private static final String SWITCH = "Switch";
private static final String STOP = "Stop";
private static final String CLEANUP = "Cleanup";
@@ -260,7 +261,14 @@
* Unlocks the given user.
*/
public void unlockUser(final @UserIdInt int userHandle) {
- onUser(UNLOCK, userHandle);
+ onUser(UNLOCKING, userHandle);
+ }
+
+ /**
+ * Called after the user was unlocked.
+ */
+ public void onUserUnlocked(final @UserIdInt int userHandle) {
+ onUser(UNLOCKED, userHandle);
}
/**
@@ -304,12 +312,12 @@
for (int i = 0; i < serviceLen; i++) {
final SystemService service = mServices.get(i);
final String serviceName = service.getClass().getName();
- boolean supported = service.isSupportedUser(curUser);
+ boolean supported = service.isUserSupported(curUser);
// Must check if either curUser or prevUser is supported (for example, if switching from
// unsupported to supported, we still need to notify the services)
if (!supported && prevUser != null) {
- supported = service.isSupportedUser(prevUser);
+ supported = service.isUserSupported(prevUser);
}
if (!supported) {
@@ -328,19 +336,22 @@
try {
switch (onWhat) {
case SWITCH:
- service.onSwitchUser(prevUser, curUser);
+ service.onUserSwitching(prevUser, curUser);
break;
case START:
- service.onStartUser(curUser);
+ service.onUserStarting(curUser);
break;
- case UNLOCK:
- service.onUnlockUser(curUser);
+ case UNLOCKING:
+ service.onUserUnlocking(curUser);
+ break;
+ case UNLOCKED:
+ service.onUserUnlocked(curUser);
break;
case STOP:
- service.onStopUser(curUser);
+ service.onUserStopping(curUser);
break;
case CLEANUP:
- service.onCleanupUser(curUser);
+ service.onUserStopped(curUser);
break;
default:
throw new IllegalArgumentException(onWhat + " what?");
diff --git a/services/core/java/com/android/server/UserspaceRebootLogger.java b/services/core/java/com/android/server/UserspaceRebootLogger.java
index 74f113f..9a9374c 100644
--- a/services/core/java/com/android/server/UserspaceRebootLogger.java
+++ b/services/core/java/com/android/server/UserspaceRebootLogger.java
@@ -26,6 +26,7 @@
import android.os.SystemClock;
import android.os.SystemProperties;
+import android.text.TextUtils;
import android.util.Slog;
import com.android.internal.util.FrameworkStatsLog;
@@ -45,7 +46,7 @@
"sys.userspace_reboot.log.last_started";
private static final String USERSPACE_REBOOT_LAST_FINISHED_PROPERTY =
"sys.userspace_reboot.log.last_finished";
- private static final String BOOT_REASON_PROPERTY = "sys.boot.reason";
+ private static final String LAST_BOOT_REASON_PROPERTY = "sys.boot.reason.last";
private UserspaceRebootLogger() {}
@@ -111,26 +112,28 @@
if (SystemProperties.getLong(USERSPACE_REBOOT_LAST_STARTED_PROPERTY, -1) != -1) {
return USERSPACE_REBOOT_REPORTED__OUTCOME__SUCCESS;
}
- String reason = SystemProperties.get(BOOT_REASON_PROPERTY, "");
+ String reason = TextUtils.emptyIfNull(SystemProperties.get(LAST_BOOT_REASON_PROPERTY, ""));
if (reason.startsWith("reboot,")) {
reason = reason.substring("reboot".length());
}
- switch (reason) {
- case "userspace_failed,watchdog_fork":
- // Since fork happens before shutdown sequence, attribute it to
- // USERSPACE_REBOOT_REPORTED__OUTCOME__FAILED_SHUTDOWN_SEQUENCE_ABORTED.
- case "userspace_failed,shutdown_aborted":
- return USERSPACE_REBOOT_REPORTED__OUTCOME__FAILED_SHUTDOWN_SEQUENCE_ABORTED;
- case "userspace_failed,init_user0_failed":
- // init_user0 will fail if userdata wasn't remounted correctly, attribute to
- // USERSPACE_REBOOT_REPORTED__OUTCOME__FAILED_USERDATA_REMOUNT.
- case "mount_userdata_failed":
- return USERSPACE_REBOOT_REPORTED__OUTCOME__FAILED_USERDATA_REMOUNT;
- case "userspace_failed,watchdog_triggered":
- return
- USERSPACE_REBOOT_REPORTED__OUTCOME__FAILED_USERSPACE_REBOOT_WATCHDOG_TRIGGERED;
- default:
- return USERSPACE_REBOOT_REPORTED__OUTCOME__OUTCOME_UNKNOWN;
+ if (reason.startsWith("userspace_failed,watchdog_fork")) {
+ return USERSPACE_REBOOT_REPORTED__OUTCOME__FAILED_SHUTDOWN_SEQUENCE_ABORTED;
}
+ if (reason.startsWith("userspace_failed,shutdown_aborted")) {
+ return USERSPACE_REBOOT_REPORTED__OUTCOME__FAILED_SHUTDOWN_SEQUENCE_ABORTED;
+ }
+ if (reason.startsWith("mount_userdata_failed")) {
+ return USERSPACE_REBOOT_REPORTED__OUTCOME__FAILED_USERDATA_REMOUNT;
+ }
+ if (reason.startsWith("userspace_failed,init_user0")) {
+ return USERSPACE_REBOOT_REPORTED__OUTCOME__FAILED_USERDATA_REMOUNT;
+ }
+ if (reason.startsWith("userspace_failed,enablefilecrypto")) {
+ return USERSPACE_REBOOT_REPORTED__OUTCOME__FAILED_USERDATA_REMOUNT;
+ }
+ if (reason.startsWith("userspace_failed,watchdog_triggered")) {
+ return USERSPACE_REBOOT_REPORTED__OUTCOME__FAILED_USERSPACE_REBOOT_WATCHDOG_TRIGGERED;
+ }
+ return USERSPACE_REBOOT_REPORTED__OUTCOME__OUTCOME_UNKNOWN;
}
}
diff --git a/services/core/java/com/android/server/adb/AdbDebuggingManager.java b/services/core/java/com/android/server/adb/AdbDebuggingManager.java
index f16e3ce..6c68c31 100644
--- a/services/core/java/com/android/server/adb/AdbDebuggingManager.java
+++ b/services/core/java/com/android/server/adb/AdbDebuggingManager.java
@@ -20,19 +20,36 @@
import android.annotation.TestApi;
import android.app.ActivityManager;
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
import android.content.ActivityNotFoundException;
+import android.content.BroadcastReceiver;
import android.content.ComponentName;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.database.ContentObserver;
+import android.debug.AdbManager;
import android.debug.AdbProtoEnums;
import android.debug.AdbTransportType;
+import android.debug.PairDevice;
+import android.net.ConnectivityManager;
import android.net.LocalSocket;
import android.net.LocalSocketAddress;
+import android.net.NetworkInfo;
import android.net.Uri;
+import android.net.nsd.NsdManager;
+import android.net.nsd.NsdServiceInfo;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiManager;
+import android.os.Bundle;
import android.os.Environment;
import android.os.FileUtils;
import android.os.Handler;
@@ -51,6 +68,8 @@
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
+import com.android.internal.notification.SystemNotificationChannels;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.XmlUtils;
@@ -71,6 +90,8 @@
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
+import java.security.SecureRandom;
+import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@@ -79,6 +100,7 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
/**
* Provides communication to the Android Debug Bridge daemon to allow, deny, or clear public keysi
@@ -87,6 +109,7 @@
public class AdbDebuggingManager {
private static final String TAG = "AdbDebuggingManager";
private static final boolean DEBUG = false;
+ private static final boolean MDNS_DEBUG = false;
private static final String ADBD_SOCKET = "adbd";
private static final String ADB_DIRECTORY = "misc/adb";
@@ -98,19 +121,39 @@
private static final int BUFFER_SIZE = 65536;
private final Context mContext;
+ private final ContentResolver mContentResolver;
private final Handler mHandler;
private AdbDebuggingThread mThread;
- private boolean mAdbEnabled = false;
+ private boolean mAdbUsbEnabled = false;
+ private boolean mAdbWifiEnabled = false;
private String mFingerprints;
- private final List<String> mConnectedKeys;
+ // A key can be used more than once (e.g. USB, wifi), so need to keep a refcount
+ private final Map<String, Integer> mConnectedKeys;
private String mConfirmComponent;
private final File mTestUserKeyFile;
+ private static final String WIFI_PERSISTENT_CONFIG_PROPERTY =
+ "persist.adb.tls_server.enable";
+ private static final String WIFI_PERSISTENT_GUID =
+ "persist.adb.wifi.guid";
+ private static final int PAIRING_CODE_LENGTH = 6;
+ private PairingThread mPairingThread = null;
+ // A list of keys connected via wifi
+ private final Set<String> mWifiConnectedKeys;
+ // The current info of the adbwifi connection.
+ private AdbConnectionInfo mAdbConnectionInfo;
+ // Polls for a tls port property when adb wifi is enabled
+ private AdbConnectionPortPoller mConnectionPortPoller;
+ private final PortListenerImpl mPortListener = new PortListenerImpl();
+
public AdbDebuggingManager(Context context) {
mHandler = new AdbDebuggingHandler(FgThread.get().getLooper());
mContext = context;
+ mContentResolver = mContext.getContentResolver();
mTestUserKeyFile = null;
- mConnectedKeys = new ArrayList<>(1);
+ mConnectedKeys = new HashMap<String, Integer>();
+ mWifiConnectedKeys = new HashSet<String>();
+ mAdbConnectionInfo = new AdbConnectionInfo();
}
/**
@@ -121,9 +164,178 @@
protected AdbDebuggingManager(Context context, String confirmComponent, File testUserKeyFile) {
mHandler = new AdbDebuggingHandler(FgThread.get().getLooper());
mContext = context;
+ mContentResolver = mContext.getContentResolver();
mConfirmComponent = confirmComponent;
mTestUserKeyFile = testUserKeyFile;
- mConnectedKeys = new ArrayList<>();
+ mConnectedKeys = new HashMap<String, Integer>();
+ mWifiConnectedKeys = new HashSet<String>();
+ mAdbConnectionInfo = new AdbConnectionInfo();
+ }
+
+ class PairingThread extends Thread implements NsdManager.RegistrationListener {
+ private NsdManager mNsdManager;
+ private String mPublicKey;
+ private String mPairingCode;
+ private String mGuid;
+ private String mServiceName;
+ private final String mServiceType = "_adb_secure_pairing._tcp.";
+ private int mPort;
+
+ private native int native_pairing_start(String guid, String password);
+ private native void native_pairing_cancel();
+ private native boolean native_pairing_wait();
+
+ PairingThread(String pairingCode, String serviceName) {
+ super(TAG);
+ mPairingCode = pairingCode;
+ mGuid = SystemProperties.get(WIFI_PERSISTENT_GUID);
+ mServiceName = serviceName;
+ if (serviceName == null || serviceName.isEmpty()) {
+ mServiceName = mGuid;
+ }
+ mPort = -1;
+ mNsdManager = (NsdManager) mContext.getSystemService(Context.NSD_SERVICE);
+ }
+
+ @Override
+ public void run() {
+ if (mGuid.isEmpty()) {
+ Slog.e(TAG, "adbwifi guid was not set");
+ return;
+ }
+ mPort = native_pairing_start(mGuid, mPairingCode);
+ if (mPort <= 0 || mPort > 65535) {
+ Slog.e(TAG, "Unable to start pairing server");
+ return;
+ }
+
+ // Register the mdns service
+ NsdServiceInfo serviceInfo = new NsdServiceInfo();
+ serviceInfo.setServiceName(mServiceName);
+ serviceInfo.setServiceType(mServiceType);
+ serviceInfo.setPort(mPort);
+ mNsdManager.registerService(serviceInfo, NsdManager.PROTOCOL_DNS_SD, this);
+
+ // Send pairing port to UI
+ Message msg = mHandler.obtainMessage(
+ AdbDebuggingHandler.MSG_RESPONSE_PAIRING_PORT);
+ msg.obj = mPort;
+ mHandler.sendMessage(msg);
+
+ boolean paired = native_pairing_wait();
+ if (DEBUG) {
+ if (mPublicKey != null) {
+ Slog.i(TAG, "Pairing succeeded key=" + mPublicKey);
+ } else {
+ Slog.i(TAG, "Pairing failed");
+ }
+ }
+
+ mNsdManager.unregisterService(this);
+
+ Bundle bundle = new Bundle();
+ bundle.putString("publicKey", paired ? mPublicKey : null);
+ Message message = Message.obtain(mHandler,
+ AdbDebuggingHandler.MSG_RESPONSE_PAIRING_RESULT,
+ bundle);
+ mHandler.sendMessage(message);
+ }
+
+ public void cancelPairing() {
+ native_pairing_cancel();
+ }
+
+ @Override
+ public void onServiceRegistered(NsdServiceInfo serviceInfo) {
+ if (MDNS_DEBUG) Slog.i(TAG, "Registered pairing service: " + serviceInfo);
+ }
+
+ @Override
+ public void onRegistrationFailed(NsdServiceInfo serviceInfo, int errorCode) {
+ Slog.e(TAG, "Failed to register pairing service(err=" + errorCode
+ + "): " + serviceInfo);
+ cancelPairing();
+ }
+
+ @Override
+ public void onServiceUnregistered(NsdServiceInfo serviceInfo) {
+ if (MDNS_DEBUG) Slog.i(TAG, "Unregistered pairing service: " + serviceInfo);
+ }
+
+ @Override
+ public void onUnregistrationFailed(NsdServiceInfo serviceInfo, int errorCode) {
+ Slog.w(TAG, "Failed to unregister pairing service(err=" + errorCode
+ + "): " + serviceInfo);
+ }
+ }
+
+ interface AdbConnectionPortListener {
+ void onPortReceived(int port);
+ }
+
+ /**
+ * This class will poll for a period of time for adbd to write the port
+ * it connected to.
+ *
+ * TODO(joshuaduong): The port is being sent via system property because the adbd socket
+ * (AdbDebuggingManager) is not created when ro.adb.secure=0. Thus, we must communicate the
+ * port through different means. A better fix would be to always start AdbDebuggingManager, but
+ * it needs to adjust accordingly on whether ro.adb.secure is set.
+ */
+ static class AdbConnectionPortPoller extends Thread {
+ private final String mAdbPortProp = "service.adb.tls.port";
+ private AdbConnectionPortListener mListener;
+ private final int mDurationSecs = 10;
+ private AtomicBoolean mCanceled = new AtomicBoolean(false);
+
+ AdbConnectionPortPoller(AdbConnectionPortListener listener) {
+ mListener = listener;
+ }
+
+ @Override
+ public void run() {
+ if (DEBUG) Slog.d(TAG, "Starting adb port property poller");
+ // Once adbwifi is enabled, we poll the service.adb.tls.port
+ // system property until we get the port, or -1 on failure.
+ // Let's also limit the polling to 10 seconds, just in case
+ // something went wrong.
+ for (int i = 0; i < mDurationSecs; ++i) {
+ if (mCanceled.get()) {
+ return;
+ }
+
+ // If the property is set to -1, then that means adbd has failed
+ // to start the server. Otherwise we should have a valid port.
+ int port = SystemProperties.getInt(mAdbPortProp, Integer.MAX_VALUE);
+ if (port == -1 || (port > 0 && port <= 65535)) {
+ mListener.onPortReceived(port);
+ return;
+ }
+ SystemClock.sleep(1000);
+ }
+ Slog.w(TAG, "Failed to receive adb connection port");
+ mListener.onPortReceived(-1);
+ }
+
+ public void cancelAndWait() {
+ mCanceled.set(true);
+ if (this.isAlive()) {
+ try {
+ this.join();
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+ }
+
+ class PortListenerImpl implements AdbConnectionPortListener {
+ public void onPortReceived(int port) {
+ Message msg = mHandler.obtainMessage(port > 0
+ ? AdbDebuggingHandler.MSG_SERVER_CONNECTED
+ : AdbDebuggingHandler.MSG_SERVER_DISCONNECTED);
+ msg.obj = port;
+ mHandler.sendMessage(msg);
+ }
}
class AdbDebuggingThread extends Thread {
@@ -213,6 +425,46 @@
AdbDebuggingHandler.MESSAGE_ADB_CONNECTED_KEY);
msg.obj = key;
mHandler.sendMessage(msg);
+ } else if (buffer[0] == 'W' && buffer[1] == 'E') {
+ // adbd_auth.h and AdbTransportType.aidl need to be kept in
+ // sync.
+ byte transportType = buffer[2];
+ String key = new String(Arrays.copyOfRange(buffer, 3, count));
+ if (transportType == AdbTransportType.USB) {
+ Slog.d(TAG, "Received USB TLS connected key message: " + key);
+ Message msg = mHandler.obtainMessage(
+ AdbDebuggingHandler.MESSAGE_ADB_CONNECTED_KEY);
+ msg.obj = key;
+ mHandler.sendMessage(msg);
+ } else if (transportType == AdbTransportType.WIFI) {
+ Slog.d(TAG, "Received WIFI TLS connected key message: " + key);
+ Message msg = mHandler.obtainMessage(
+ AdbDebuggingHandler.MSG_WIFI_DEVICE_CONNECTED);
+ msg.obj = key;
+ mHandler.sendMessage(msg);
+ } else {
+ Slog.e(TAG, "Got unknown transport type from adbd (" + transportType
+ + ")");
+ }
+ } else if (buffer[0] == 'W' && buffer[1] == 'F') {
+ byte transportType = buffer[2];
+ String key = new String(Arrays.copyOfRange(buffer, 3, count));
+ if (transportType == AdbTransportType.USB) {
+ Slog.d(TAG, "Received USB TLS disconnect message: " + key);
+ Message msg = mHandler.obtainMessage(
+ AdbDebuggingHandler.MESSAGE_ADB_DISCONNECT);
+ msg.obj = key;
+ mHandler.sendMessage(msg);
+ } else if (transportType == AdbTransportType.WIFI) {
+ Slog.d(TAG, "Received WIFI TLS disconnect key message: " + key);
+ Message msg = mHandler.obtainMessage(
+ AdbDebuggingHandler.MSG_WIFI_DEVICE_DISCONNECTED);
+ msg.obj = key;
+ mHandler.sendMessage(msg);
+ } else {
+ Slog.e(TAG, "Got unknown transport type from adbd (" + transportType
+ + ")");
+ }
} else {
Slog.e(TAG, "Wrong message: "
+ (new String(Arrays.copyOfRange(buffer, 0, 2))));
@@ -268,7 +520,156 @@
}
}
+ class AdbConnectionInfo {
+ private String mBssid;
+ private String mSsid;
+ private int mPort;
+
+ AdbConnectionInfo() {
+ mBssid = "";
+ mSsid = "";
+ mPort = -1;
+ }
+
+ AdbConnectionInfo(String bssid, String ssid) {
+ mBssid = bssid;
+ mSsid = ssid;
+ }
+
+ AdbConnectionInfo(AdbConnectionInfo other) {
+ mBssid = other.mBssid;
+ mSsid = other.mSsid;
+ mPort = other.mPort;
+ }
+
+ public String getBSSID() {
+ return mBssid;
+ }
+
+ public String getSSID() {
+ return mSsid;
+ }
+
+ public int getPort() {
+ return mPort;
+ }
+
+ public void setPort(int port) {
+ mPort = port;
+ }
+
+ public void clear() {
+ mBssid = "";
+ mSsid = "";
+ mPort = -1;
+ }
+ }
+
+ private void setAdbConnectionInfo(AdbConnectionInfo info) {
+ synchronized (mAdbConnectionInfo) {
+ if (info == null) {
+ mAdbConnectionInfo.clear();
+ return;
+ }
+ mAdbConnectionInfo = info;
+ }
+ }
+
+ private AdbConnectionInfo getAdbConnectionInfo() {
+ synchronized (mAdbConnectionInfo) {
+ return new AdbConnectionInfo(mAdbConnectionInfo);
+ }
+ }
+
class AdbDebuggingHandler extends Handler {
+ private NotificationManager mNotificationManager;
+ private boolean mAdbNotificationShown;
+
+ private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ // We only care about when wifi is disabled, and when there is a wifi network
+ // change.
+ if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) {
+ int state = intent.getIntExtra(
+ WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_DISABLED);
+ if (state == WifiManager.WIFI_STATE_DISABLED) {
+ Slog.i(TAG, "Wifi disabled. Disabling adbwifi.");
+ Settings.Global.putInt(mContentResolver,
+ Settings.Global.ADB_WIFI_ENABLED, 0);
+ }
+ } else if (WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(action)) {
+ // We only care about wifi type connections
+ NetworkInfo networkInfo = (NetworkInfo) intent.getParcelableExtra(
+ WifiManager.EXTRA_NETWORK_INFO);
+ if (networkInfo.getType() == ConnectivityManager.TYPE_WIFI) {
+ // Check for network disconnect
+ if (!networkInfo.isConnected()) {
+ Slog.i(TAG, "Network disconnected. Disabling adbwifi.");
+ Settings.Global.putInt(mContentResolver,
+ Settings.Global.ADB_WIFI_ENABLED, 0);
+ return;
+ }
+
+ WifiManager wifiManager =
+ (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
+ WifiInfo wifiInfo = wifiManager.getConnectionInfo();
+ if (wifiInfo == null || wifiInfo.getNetworkId() == -1) {
+ Slog.i(TAG, "Not connected to any wireless network."
+ + " Not enabling adbwifi.");
+ Settings.Global.putInt(mContentResolver,
+ Settings.Global.ADB_WIFI_ENABLED, 0);
+ }
+
+ // Check for network change
+ String bssid = wifiInfo.getBSSID();
+ if (bssid == null || bssid.isEmpty()) {
+ Slog.e(TAG, "Unable to get the wifi ap's BSSID. Disabling adbwifi.");
+ Settings.Global.putInt(mContentResolver,
+ Settings.Global.ADB_WIFI_ENABLED, 0);
+ }
+ synchronized (mAdbConnectionInfo) {
+ if (!bssid.equals(mAdbConnectionInfo.getBSSID())) {
+ Slog.i(TAG, "Detected wifi network change. Disabling adbwifi.");
+ Settings.Global.putInt(mContentResolver,
+ Settings.Global.ADB_WIFI_ENABLED, 0);
+ }
+ }
+ }
+ }
+ }
+ };
+
+ private static final String ADB_NOTIFICATION_CHANNEL_ID_TV = "usbdevicemanager.adb.tv";
+
+ private boolean isTv() {
+ return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK);
+ }
+
+ private void setupNotifications() {
+ if (mNotificationManager != null) {
+ return;
+ }
+ mNotificationManager = (NotificationManager)
+ mContext.getSystemService(Context.NOTIFICATION_SERVICE);
+ if (mNotificationManager == null) {
+ Slog.e(TAG, "Unable to setup notifications for wireless debugging");
+ return;
+ }
+
+ // Ensure that the notification channels are set up
+ if (isTv()) {
+ // TV-specific notification channel
+ mNotificationManager.createNotificationChannel(
+ new NotificationChannel(ADB_NOTIFICATION_CHANNEL_ID_TV,
+ mContext.getString(
+ com.android.internal.R.string
+ .adb_debugging_notification_channel_tv),
+ NotificationManager.IMPORTANCE_HIGH));
+ }
+ }
+
// The default time to schedule the job to keep the keystore updated with a currently
// connected key as well as to removed expired keys.
static final long UPDATE_KEYSTORE_JOB_INTERVAL = 86400000;
@@ -288,8 +689,50 @@
static final int MESSAGE_ADB_UPDATE_KEYSTORE = 9;
static final int MESSAGE_ADB_CONNECTED_KEY = 10;
+ // === Messages from the UI ==============
+ // UI asks adbd to enable adbdwifi
+ static final int MSG_ADBDWIFI_ENABLE = 11;
+ // UI asks adbd to disable adbdwifi
+ static final int MSG_ADBDWIFI_DISABLE = 12;
+ // Cancel pairing
+ static final int MSG_PAIRING_CANCEL = 14;
+ // Enable pairing by pairing code
+ static final int MSG_PAIR_PAIRING_CODE = 15;
+ // Enable pairing by QR code
+ static final int MSG_PAIR_QR_CODE = 16;
+ // UI asks to unpair (forget) a device.
+ static final int MSG_REQ_UNPAIR = 17;
+ // User allows debugging on the current network
+ static final int MSG_ADBWIFI_ALLOW = 18;
+ // User denies debugging on the current network
+ static final int MSG_ADBWIFI_DENY = 19;
+
+ // === Messages from the PairingThread ===========
+ // Result of the pairing
+ static final int MSG_RESPONSE_PAIRING_RESULT = 20;
+ // The port opened for pairing
+ static final int MSG_RESPONSE_PAIRING_PORT = 21;
+
+ // === Messages from adbd ================
+ // Notifies us a wifi device connected.
+ static final int MSG_WIFI_DEVICE_CONNECTED = 22;
+ // Notifies us a wifi device disconnected.
+ static final int MSG_WIFI_DEVICE_DISCONNECTED = 23;
+ // Notifies us the TLS server is connected and listening
+ static final int MSG_SERVER_CONNECTED = 24;
+ // Notifies us the TLS server is disconnected
+ static final int MSG_SERVER_DISCONNECTED = 25;
+
+ // === Messages we can send to adbd ===========
+ static final String MSG_DISCONNECT_DEVICE = "DD";
+ static final String MSG_DISABLE_ADBDWIFI = "DA";
+
private AdbKeyStore mAdbKeyStore;
+ // Usb, Wi-Fi transports can be enabled together or separately, so don't break the framework
+ // connection unless all transport types are disconnected.
+ private int mAdbEnabledRefCount = 0;
+
private ContentObserver mAuthTimeObserver = new ContentObserver(this) {
@Override
public void onChange(boolean selfChange, Uri uri) {
@@ -314,44 +757,111 @@
mAdbKeyStore = adbKeyStore;
}
+ // Show when at least one device is connected.
+ public void showAdbConnectedNotification(boolean show) {
+ final int id = SystemMessage.NOTE_ADB_WIFI_ACTIVE;
+ final int titleRes = com.android.internal.R.string.adbwifi_active_notification_title;
+ if (show == mAdbNotificationShown) {
+ return;
+ }
+ setupNotifications();
+ if (!mAdbNotificationShown) {
+ Resources r = mContext.getResources();
+ CharSequence title = r.getText(titleRes);
+ CharSequence message = r.getText(
+ com.android.internal.R.string.adbwifi_active_notification_message);
+
+ Intent intent = new Intent(Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ PendingIntent pi = PendingIntent.getActivityAsUser(mContext, 0,
+ intent, 0, null, UserHandle.CURRENT);
+
+ Notification notification =
+ new Notification.Builder(mContext, SystemNotificationChannels.DEVELOPER)
+ .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
+ .setWhen(0)
+ .setOngoing(true)
+ .setTicker(title)
+ .setDefaults(0) // please be quiet
+ .setColor(mContext.getColor(
+ com.android.internal.R.color
+ .system_notification_accent_color))
+ .setContentTitle(title)
+ .setContentText(message)
+ .setContentIntent(pi)
+ .setVisibility(Notification.VISIBILITY_PUBLIC)
+ .extend(new Notification.TvExtender()
+ .setChannelId(ADB_NOTIFICATION_CHANNEL_ID_TV))
+ .build();
+ mAdbNotificationShown = true;
+ mNotificationManager.notifyAsUser(null, id, notification,
+ UserHandle.ALL);
+ } else {
+ mAdbNotificationShown = false;
+ mNotificationManager.cancelAsUser(null, id, UserHandle.ALL);
+ }
+ }
+
+ private void startAdbDebuggingThread() {
+ ++mAdbEnabledRefCount;
+ if (DEBUG) Slog.i(TAG, "startAdbDebuggingThread ref=" + mAdbEnabledRefCount);
+ if (mAdbEnabledRefCount > 1) {
+ return;
+ }
+
+ registerForAuthTimeChanges();
+ mThread = new AdbDebuggingThread();
+ mThread.start();
+
+ mAdbKeyStore.updateKeyStore();
+ scheduleJobToUpdateAdbKeyStore();
+ }
+
+ private void stopAdbDebuggingThread() {
+ --mAdbEnabledRefCount;
+ if (DEBUG) Slog.i(TAG, "stopAdbDebuggingThread ref=" + mAdbEnabledRefCount);
+ if (mAdbEnabledRefCount > 0) {
+ return;
+ }
+
+ if (mThread != null) {
+ mThread.stopListening();
+ mThread = null;
+ }
+
+ if (!mConnectedKeys.isEmpty()) {
+ for (Map.Entry<String, Integer> entry : mConnectedKeys.entrySet()) {
+ mAdbKeyStore.setLastConnectionTime(entry.getKey(),
+ System.currentTimeMillis());
+ }
+ sendPersistKeyStoreMessage();
+ mConnectedKeys.clear();
+ mWifiConnectedKeys.clear();
+ }
+ scheduleJobToUpdateAdbKeyStore();
+ }
+
public void handleMessage(Message msg) {
+ if (mAdbKeyStore == null) {
+ mAdbKeyStore = new AdbKeyStore();
+ }
+
switch (msg.what) {
case MESSAGE_ADB_ENABLED:
- if (mAdbEnabled) {
+ if (mAdbUsbEnabled) {
break;
}
- registerForAuthTimeChanges();
- mAdbEnabled = true;
-
- mThread = new AdbDebuggingThread();
- mThread.start();
-
- mAdbKeyStore = new AdbKeyStore();
- mAdbKeyStore.updateKeyStore();
- scheduleJobToUpdateAdbKeyStore();
+ startAdbDebuggingThread();
+ mAdbUsbEnabled = true;
break;
case MESSAGE_ADB_DISABLED:
- if (!mAdbEnabled) {
+ if (!mAdbUsbEnabled) {
break;
}
-
- mAdbEnabled = false;
-
- if (mThread != null) {
- mThread.stopListening();
- mThread = null;
- }
-
- if (!mConnectedKeys.isEmpty()) {
- for (String connectedKey : mConnectedKeys) {
- mAdbKeyStore.setLastConnectionTime(connectedKey,
- System.currentTimeMillis());
- }
- sendPersistKeyStoreMessage();
- mConnectedKeys.clear();
- }
- scheduleJobToUpdateAdbKeyStore();
+ stopAdbDebuggingThread();
+ mAdbUsbEnabled = false;
break;
case MESSAGE_ADB_ALLOW: {
@@ -367,8 +877,8 @@
if (mThread != null) {
mThread.sendResponse("OK");
if (alwaysAllow) {
- if (!mConnectedKeys.contains(key)) {
- mConnectedKeys.add(key);
+ if (!mConnectedKeys.containsKey(key)) {
+ mConnectedKeys.put(key, 1);
}
mAdbKeyStore.setLastConnectionTime(key, System.currentTimeMillis());
sendPersistKeyStoreMessage();
@@ -407,7 +917,7 @@
}
logAdbConnectionChanged(key, AdbProtoEnums.AWAITING_USER_APPROVAL, false);
mFingerprints = fingerprints;
- startConfirmation(key, mFingerprints);
+ startConfirmationForKey(key, mFingerprints);
break;
}
@@ -419,6 +929,7 @@
if (mAdbKeyStore == null) {
mAdbKeyStore = new AdbKeyStore();
}
+ mWifiConnectedKeys.clear();
mAdbKeyStore.deleteKeyStore();
cancelJobToUpdateAdbKeyStore();
break;
@@ -428,12 +939,17 @@
String key = (String) msg.obj;
boolean alwaysAllow = false;
if (key != null && key.length() > 0) {
- if (mConnectedKeys.contains(key)) {
+ if (mConnectedKeys.containsKey(key)) {
alwaysAllow = true;
- mAdbKeyStore.setLastConnectionTime(key, System.currentTimeMillis());
- sendPersistKeyStoreMessage();
- scheduleJobToUpdateAdbKeyStore();
- mConnectedKeys.remove(key);
+ int refcount = mConnectedKeys.get(key) - 1;
+ if (refcount == 0) {
+ mAdbKeyStore.setLastConnectionTime(key, System.currentTimeMillis());
+ sendPersistKeyStoreMessage();
+ scheduleJobToUpdateAdbKeyStore();
+ mConnectedKeys.remove(key);
+ } else {
+ mConnectedKeys.put(key, refcount);
+ }
}
} else {
Slog.w(TAG, "Received a disconnected key message with an empty key");
@@ -451,8 +967,8 @@
case MESSAGE_ADB_UPDATE_KEYSTORE: {
if (!mConnectedKeys.isEmpty()) {
- for (String connectedKey : mConnectedKeys) {
- mAdbKeyStore.setLastConnectionTime(connectedKey,
+ for (Map.Entry<String, Integer> entry : mConnectedKeys.entrySet()) {
+ mAdbKeyStore.setLastConnectionTime(entry.getKey(),
System.currentTimeMillis());
}
sendPersistKeyStoreMessage();
@@ -469,8 +985,10 @@
if (key == null || key.length() == 0) {
Slog.w(TAG, "Received a connected key message with an empty key");
} else {
- if (!mConnectedKeys.contains(key)) {
- mConnectedKeys.add(key);
+ if (!mConnectedKeys.containsKey(key)) {
+ mConnectedKeys.put(key, 1);
+ } else {
+ mConnectedKeys.put(key, mConnectedKeys.get(key) + 1);
}
mAdbKeyStore.setLastConnectionTime(key, System.currentTimeMillis());
sendPersistKeyStoreMessage();
@@ -479,6 +997,199 @@
}
break;
}
+ case MSG_ADBDWIFI_ENABLE: {
+ if (mAdbWifiEnabled) {
+ break;
+ }
+
+ AdbConnectionInfo currentInfo = getCurrentWifiApInfo();
+ if (currentInfo == null) {
+ Settings.Global.putInt(mContentResolver,
+ Settings.Global.ADB_WIFI_ENABLED, 0);
+ break;
+ }
+
+ if (!verifyWifiNetwork(currentInfo.getBSSID(),
+ currentInfo.getSSID())) {
+ // This means that the network is not in the list of trusted networks.
+ // We'll give user a prompt on whether to allow wireless debugging on
+ // the current wifi network.
+ Settings.Global.putInt(mContentResolver,
+ Settings.Global.ADB_WIFI_ENABLED, 0);
+ break;
+ }
+
+ setAdbConnectionInfo(currentInfo);
+ IntentFilter intentFilter =
+ new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION);
+ intentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
+ mContext.registerReceiver(mBroadcastReceiver, intentFilter);
+
+ SystemProperties.set(WIFI_PERSISTENT_CONFIG_PROPERTY, "1");
+ mConnectionPortPoller =
+ new AdbDebuggingManager.AdbConnectionPortPoller(mPortListener);
+ mConnectionPortPoller.start();
+
+ startAdbDebuggingThread();
+ mAdbWifiEnabled = true;
+
+ if (DEBUG) Slog.i(TAG, "adb start wireless adb");
+ break;
+ }
+ case MSG_ADBDWIFI_DISABLE:
+ if (!mAdbWifiEnabled) {
+ break;
+ }
+ mAdbWifiEnabled = false;
+ setAdbConnectionInfo(null);
+ mContext.unregisterReceiver(mBroadcastReceiver);
+
+ if (mThread != null) {
+ mThread.sendResponse(MSG_DISABLE_ADBDWIFI);
+ }
+ onAdbdWifiServerDisconnected(-1);
+ stopAdbDebuggingThread();
+ break;
+ case MSG_ADBWIFI_ALLOW:
+ if (mAdbWifiEnabled) {
+ break;
+ }
+ String bssid = (String) msg.obj;
+ boolean alwaysAllow = msg.arg1 == 1;
+ if (alwaysAllow) {
+ mAdbKeyStore.addTrustedNetwork(bssid);
+ }
+
+ // Let's check again to make sure we didn't switch networks while verifying
+ // the wifi bssid.
+ AdbConnectionInfo newInfo = getCurrentWifiApInfo();
+ if (newInfo == null || !bssid.equals(newInfo.getBSSID())) {
+ break;
+ }
+
+ setAdbConnectionInfo(newInfo);
+ Settings.Global.putInt(mContentResolver,
+ Settings.Global.ADB_WIFI_ENABLED, 1);
+ IntentFilter intentFilter =
+ new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION);
+ intentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
+ mContext.registerReceiver(mBroadcastReceiver, intentFilter);
+
+ SystemProperties.set(WIFI_PERSISTENT_CONFIG_PROPERTY, "1");
+ mConnectionPortPoller =
+ new AdbDebuggingManager.AdbConnectionPortPoller(mPortListener);
+ mConnectionPortPoller.start();
+
+ startAdbDebuggingThread();
+ mAdbWifiEnabled = true;
+
+ if (DEBUG) Slog.i(TAG, "adb start wireless adb");
+ break;
+ case MSG_ADBWIFI_DENY:
+ Settings.Global.putInt(mContentResolver,
+ Settings.Global.ADB_WIFI_ENABLED, 0);
+ sendServerConnectionState(false, -1);
+ break;
+ case MSG_REQ_UNPAIR: {
+ String fingerprint = (String) msg.obj;
+ // Tell adbd to disconnect the device if connected.
+ String publicKey = mAdbKeyStore.findKeyFromFingerprint(fingerprint);
+ if (publicKey == null || publicKey.isEmpty()) {
+ Slog.e(TAG, "Not a known fingerprint [" + fingerprint + "]");
+ break;
+ }
+ String cmdStr = MSG_DISCONNECT_DEVICE + publicKey;
+ if (mThread != null) {
+ mThread.sendResponse(cmdStr);
+ }
+ mAdbKeyStore.removeKey(publicKey);
+ // Send the updated paired devices list to the UI.
+ sendPairedDevicesToUI(mAdbKeyStore.getPairedDevices());
+ break;
+ }
+ case MSG_RESPONSE_PAIRING_RESULT: {
+ Bundle bundle = (Bundle) msg.obj;
+ String publicKey = bundle.getString("publicKey");
+ onPairingResult(publicKey);
+ // Send the updated paired devices list to the UI.
+ sendPairedDevicesToUI(mAdbKeyStore.getPairedDevices());
+ break;
+ }
+ case MSG_RESPONSE_PAIRING_PORT: {
+ int port = (int) msg.obj;
+ sendPairingPortToUI(port);
+ break;
+ }
+ case MSG_PAIR_PAIRING_CODE: {
+ String pairingCode = createPairingCode(PAIRING_CODE_LENGTH);
+ updateUIPairCode(pairingCode);
+ mPairingThread = new PairingThread(pairingCode, null);
+ mPairingThread.start();
+ break;
+ }
+ case MSG_PAIR_QR_CODE: {
+ Bundle bundle = (Bundle) msg.obj;
+ String serviceName = bundle.getString("serviceName");
+ String password = bundle.getString("password");
+ mPairingThread = new PairingThread(password, serviceName);
+ mPairingThread.start();
+ break;
+ }
+ case MSG_PAIRING_CANCEL:
+ if (mPairingThread != null) {
+ mPairingThread.cancelPairing();
+ try {
+ mPairingThread.join();
+ } catch (InterruptedException e) {
+ Slog.w(TAG, "Error while waiting for pairing thread to quit.");
+ e.printStackTrace();
+ }
+ mPairingThread = null;
+ }
+ break;
+ case MSG_WIFI_DEVICE_CONNECTED: {
+ String key = (String) msg.obj;
+ if (mWifiConnectedKeys.add(key)) {
+ sendPairedDevicesToUI(mAdbKeyStore.getPairedDevices());
+ showAdbConnectedNotification(true);
+ }
+ break;
+ }
+ case MSG_WIFI_DEVICE_DISCONNECTED: {
+ String key = (String) msg.obj;
+ if (mWifiConnectedKeys.remove(key)) {
+ sendPairedDevicesToUI(mAdbKeyStore.getPairedDevices());
+ if (mWifiConnectedKeys.isEmpty()) {
+ showAdbConnectedNotification(false);
+ }
+ }
+ break;
+ }
+ case MSG_SERVER_CONNECTED: {
+ int port = (int) msg.obj;
+ onAdbdWifiServerConnected(port);
+ synchronized (mAdbConnectionInfo) {
+ mAdbConnectionInfo.setPort(port);
+ }
+ Settings.Global.putInt(mContentResolver,
+ Settings.Global.ADB_WIFI_ENABLED, 1);
+ break;
+ }
+ case MSG_SERVER_DISCONNECTED: {
+ if (!mAdbWifiEnabled) {
+ break;
+ }
+ int port = (int) msg.obj;
+ onAdbdWifiServerDisconnected(port);
+ Settings.Global.putInt(mContentResolver,
+ Settings.Global.ADB_WIFI_ENABLED, 0);
+ stopAdbDebuggingThread();
+ if (mConnectionPortPoller != null) {
+ mConnectionPortPoller.cancelAndWait();
+ mConnectionPortPoller = null;
+ }
+ break;
+ }
}
}
@@ -540,6 +1251,142 @@
private void cancelJobToUpdateAdbKeyStore() {
removeMessages(AdbDebuggingHandler.MESSAGE_ADB_UPDATE_KEYSTORE);
}
+
+ // Generates a random string of digits with size |size|.
+ private String createPairingCode(int size) {
+ String res = "";
+ SecureRandom rand = new SecureRandom();
+ for (int i = 0; i < size; ++i) {
+ res += rand.nextInt(10);
+ }
+
+ return res;
+ }
+
+ private void sendServerConnectionState(boolean connected, int port) {
+ Intent intent = new Intent(AdbManager.WIRELESS_DEBUG_STATE_CHANGED_ACTION);
+ intent.putExtra(AdbManager.WIRELESS_STATUS_EXTRA, connected
+ ? AdbManager.WIRELESS_STATUS_CONNECTED
+ : AdbManager.WIRELESS_STATUS_DISCONNECTED);
+ intent.putExtra(AdbManager.WIRELESS_DEBUG_PORT_EXTRA, port);
+ mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+ }
+
+ private void onAdbdWifiServerConnected(int port) {
+ // Send the paired devices list to the UI
+ sendPairedDevicesToUI(mAdbKeyStore.getPairedDevices());
+ sendServerConnectionState(true, port);
+ }
+
+ private void onAdbdWifiServerDisconnected(int port) {
+ // The TLS server disconnected while we had wireless debugging enabled.
+ // Let's disable it.
+ mWifiConnectedKeys.clear();
+ showAdbConnectedNotification(false);
+ sendServerConnectionState(false, port);
+ }
+
+ /**
+ * Returns the [bssid, ssid] of the current access point.
+ */
+ private AdbConnectionInfo getCurrentWifiApInfo() {
+ WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
+ WifiInfo wifiInfo = wifiManager.getConnectionInfo();
+ if (wifiInfo == null || wifiInfo.getNetworkId() == -1) {
+ Slog.i(TAG, "Not connected to any wireless network. Not enabling adbwifi.");
+ return null;
+ }
+
+ String ssid = null;
+ if (wifiInfo.isPasspointAp() || wifiInfo.isOsuAp()) {
+ ssid = wifiInfo.getPasspointProviderFriendlyName();
+ } else {
+ ssid = wifiInfo.getSSID();
+ if (ssid == null || WifiManager.UNKNOWN_SSID.equals(ssid)) {
+ // OK, it's not in the connectionInfo; we have to go hunting for it
+ List<WifiConfiguration> networks = wifiManager.getConfiguredNetworks();
+ int length = networks.size();
+ for (int i = 0; i < length; i++) {
+ if (networks.get(i).networkId == wifiInfo.getNetworkId()) {
+ ssid = networks.get(i).SSID;
+ }
+ }
+ if (ssid == null) {
+ Slog.e(TAG, "Unable to get ssid of the wifi AP.");
+ return null;
+ }
+ }
+ }
+
+ String bssid = wifiInfo.getBSSID();
+ if (bssid == null || bssid.isEmpty()) {
+ Slog.e(TAG, "Unable to get the wifi ap's BSSID.");
+ return null;
+ }
+ return new AdbConnectionInfo(bssid, ssid);
+ }
+
+ private boolean verifyWifiNetwork(String bssid, String ssid) {
+ // Check against a list of user-trusted networks.
+ if (mAdbKeyStore.isTrustedNetwork(bssid)) {
+ return true;
+ }
+
+ // Ask user to confirm using wireless debugging on this network.
+ startConfirmationForNetwork(ssid, bssid);
+ return false;
+ }
+
+ private void onPairingResult(String publicKey) {
+ if (publicKey == null) {
+ Intent intent = new Intent(AdbManager.WIRELESS_DEBUG_PAIRING_RESULT_ACTION);
+ intent.putExtra(AdbManager.WIRELESS_STATUS_EXTRA, AdbManager.WIRELESS_STATUS_FAIL);
+ mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+ } else {
+ Intent intent = new Intent(AdbManager.WIRELESS_DEBUG_PAIRING_RESULT_ACTION);
+ intent.putExtra(AdbManager.WIRELESS_STATUS_EXTRA,
+ AdbManager.WIRELESS_STATUS_SUCCESS);
+ String fingerprints = getFingerprints(publicKey);
+ String hostname = "nouser@nohostname";
+ String[] args = publicKey.split("\\s+");
+ if (args.length > 1) {
+ hostname = args[1];
+ }
+ PairDevice device = new PairDevice(fingerprints, hostname, false);
+ intent.putExtra(AdbManager.WIRELESS_PAIR_DEVICE_EXTRA, device);
+ mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+ // Add the key into the keystore
+ mAdbKeyStore.setLastConnectionTime(publicKey,
+ System.currentTimeMillis());
+ sendPersistKeyStoreMessage();
+ scheduleJobToUpdateAdbKeyStore();
+ }
+ }
+
+ private void sendPairingPortToUI(int port) {
+ Intent intent = new Intent(AdbManager.WIRELESS_DEBUG_PAIRING_RESULT_ACTION);
+ intent.putExtra(AdbManager.WIRELESS_STATUS_EXTRA,
+ AdbManager.WIRELESS_STATUS_CONNECTED);
+ intent.putExtra(AdbManager.WIRELESS_DEBUG_PORT_EXTRA, port);
+ mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+ }
+
+ private void sendPairedDevicesToUI(Map<String, PairDevice> devices) {
+ Intent intent = new Intent(AdbManager.WIRELESS_DEBUG_PAIRED_DEVICES_ACTION);
+ // Map is not serializable, so need to downcast
+ intent.putExtra(AdbManager.WIRELESS_DEVICES_EXTRA, (HashMap) devices);
+ mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+ }
+
+ private void updateUIPairCode(String code) {
+ if (DEBUG) Slog.i(TAG, "updateUIPairCode: " + code);
+
+ Intent intent = new Intent(AdbManager.WIRELESS_DEBUG_PAIRING_RESULT_ACTION);
+ intent.putExtra(AdbManager.WIRELESS_PAIRING_CODE_EXTRA, code);
+ intent.putExtra(AdbManager.WIRELESS_STATUS_EXTRA,
+ AdbManager.WIRELESS_STATUS_PAIRING_CODE);
+ mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+ }
}
private String getFingerprints(String key) {
@@ -576,7 +1423,34 @@
return sb.toString();
}
- private void startConfirmation(String key, String fingerprints) {
+ private void startConfirmationForNetwork(String ssid, String bssid) {
+ List<Map.Entry<String, String>> extras = new ArrayList<Map.Entry<String, String>>();
+ extras.add(new AbstractMap.SimpleEntry<String, String>("ssid", ssid));
+ extras.add(new AbstractMap.SimpleEntry<String, String>("bssid", bssid));
+ int currentUserId = ActivityManager.getCurrentUser();
+ UserInfo userInfo = UserManager.get(mContext).getUserInfo(currentUserId);
+ String componentString;
+ if (userInfo.isAdmin()) {
+ componentString = Resources.getSystem().getString(
+ com.android.internal.R.string.config_customAdbWifiNetworkConfirmationComponent);
+ } else {
+ componentString = Resources.getSystem().getString(
+ com.android.internal.R.string.config_customAdbWifiNetworkConfirmationComponent);
+ }
+ ComponentName componentName = ComponentName.unflattenFromString(componentString);
+ if (startConfirmationActivity(componentName, userInfo.getUserHandle(), extras)
+ || startConfirmationService(componentName, userInfo.getUserHandle(),
+ extras)) {
+ return;
+ }
+ Slog.e(TAG, "Unable to start customAdbWifiNetworkConfirmation[SecondaryUser]Component "
+ + componentString + " as an Activity or a Service");
+ }
+
+ private void startConfirmationForKey(String key, String fingerprints) {
+ List<Map.Entry<String, String>> extras = new ArrayList<Map.Entry<String, String>>();
+ extras.add(new AbstractMap.SimpleEntry<String, String>("key", key));
+ extras.add(new AbstractMap.SimpleEntry<String, String>("fingerprints", fingerprints));
int currentUserId = ActivityManager.getCurrentUser();
UserInfo userInfo = UserManager.get(mContext).getUserInfo(currentUserId);
String componentString;
@@ -591,9 +1465,9 @@
R.string.config_customAdbPublicKeyConfirmationSecondaryUserComponent);
}
ComponentName componentName = ComponentName.unflattenFromString(componentString);
- if (startConfirmationActivity(componentName, userInfo.getUserHandle(), key, fingerprints)
+ if (startConfirmationActivity(componentName, userInfo.getUserHandle(), extras)
|| startConfirmationService(componentName, userInfo.getUserHandle(),
- key, fingerprints)) {
+ extras)) {
return;
}
Slog.e(TAG, "unable to start customAdbPublicKeyConfirmation[SecondaryUser]Component "
@@ -604,9 +1478,9 @@
* @return true if the componentName led to an Activity that was started.
*/
private boolean startConfirmationActivity(ComponentName componentName, UserHandle userHandle,
- String key, String fingerprints) {
+ List<Map.Entry<String, String>> extras) {
PackageManager packageManager = mContext.getPackageManager();
- Intent intent = createConfirmationIntent(componentName, key, fingerprints);
+ Intent intent = createConfirmationIntent(componentName, extras);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (packageManager.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY) != null) {
try {
@@ -623,8 +1497,8 @@
* @return true if the componentName led to a Service that was started.
*/
private boolean startConfirmationService(ComponentName componentName, UserHandle userHandle,
- String key, String fingerprints) {
- Intent intent = createConfirmationIntent(componentName, key, fingerprints);
+ List<Map.Entry<String, String>> extras) {
+ Intent intent = createConfirmationIntent(componentName, extras);
try {
if (mContext.startServiceAsUser(intent, userHandle) != null) {
return true;
@@ -635,12 +1509,13 @@
return false;
}
- private Intent createConfirmationIntent(ComponentName componentName, String key,
- String fingerprints) {
+ private Intent createConfirmationIntent(ComponentName componentName,
+ List<Map.Entry<String, String>> extras) {
Intent intent = new Intent();
intent.setClassName(componentName.getPackageName(), componentName.getClassName());
- intent.putExtra("key", key);
- intent.putExtra("fingerprints", fingerprints);
+ for (Map.Entry<String, String> entry : extras) {
+ intent.putExtra(entry.getKey(), entry.getValue());
+ }
return intent;
}
@@ -733,7 +1608,8 @@
mHandler.sendEmptyMessage(enabled ? AdbDebuggingHandler.MESSAGE_ADB_ENABLED
: AdbDebuggingHandler.MESSAGE_ADB_DISABLED);
} else if (transportType == AdbTransportType.WIFI) {
- // TODO(joshuaduong): Not implemented
+ mHandler.sendEmptyMessage(enabled ? AdbDebuggingHandler.MSG_ADBDWIFI_ENABLE
+ : AdbDebuggingHandler.MSG_ADBDWIFI_DISABLE);
} else {
throw new IllegalArgumentException(
"setAdbEnabled called with unimplemented transport type=" + transportType);
@@ -767,6 +1643,87 @@
}
/**
+ * Allows wireless debugging on the network identified by {@code bssid} either once
+ * or always if {@code alwaysAllow} is {@code true}.
+ */
+ public void allowWirelessDebugging(boolean alwaysAllow, String bssid) {
+ Message msg = mHandler.obtainMessage(AdbDebuggingHandler.MSG_ADBWIFI_ALLOW);
+ msg.arg1 = alwaysAllow ? 1 : 0;
+ msg.obj = bssid;
+ mHandler.sendMessage(msg);
+ }
+
+ /**
+ * Denies wireless debugging connection on the last requested network.
+ */
+ public void denyWirelessDebugging() {
+ mHandler.sendEmptyMessage(AdbDebuggingHandler.MSG_ADBWIFI_DENY);
+ }
+
+ /**
+ * Returns the port adbwifi is currently opened on.
+ */
+ public int getAdbWirelessPort() {
+ AdbConnectionInfo info = getAdbConnectionInfo();
+ if (info == null) {
+ return 0;
+ }
+ return info.getPort();
+ }
+
+ /**
+ * Returns the list of paired devices.
+ */
+ public Map<String, PairDevice> getPairedDevices() {
+ AdbKeyStore keystore = new AdbKeyStore();
+ return keystore.getPairedDevices();
+ }
+
+ /**
+ * Unpair with device
+ */
+ public void unpairDevice(String fingerprint) {
+ Message message = Message.obtain(mHandler,
+ AdbDebuggingHandler.MSG_REQ_UNPAIR,
+ fingerprint);
+ mHandler.sendMessage(message);
+ }
+
+ /**
+ * Enable pairing by pairing code
+ */
+ public void enablePairingByPairingCode() {
+ mHandler.sendEmptyMessage(AdbDebuggingHandler.MSG_PAIR_PAIRING_CODE);
+ }
+
+ /**
+ * Enable pairing by pairing code
+ */
+ public void enablePairingByQrCode(String serviceName, String password) {
+ Bundle bundle = new Bundle();
+ bundle.putString("serviceName", serviceName);
+ bundle.putString("password", password);
+ Message message = Message.obtain(mHandler,
+ AdbDebuggingHandler.MSG_PAIR_QR_CODE,
+ bundle);
+ mHandler.sendMessage(message);
+ }
+
+ /**
+ * Disables pairing
+ */
+ public void disablePairing() {
+ mHandler.sendEmptyMessage(AdbDebuggingHandler.MSG_PAIRING_CANCEL);
+ }
+
+ /**
+ * Status enabled/disabled check
+ */
+ public boolean isAdbWifiEnabled() {
+ return mAdbWifiEnabled;
+ }
+
+ /**
* Sends a message to the handler to persist the keystore.
*/
private void sendPersistKeyStoreMessage() {
@@ -819,9 +1776,19 @@
private File mKeyFile;
private AtomicFile mAtomicKeyFile;
+ private List<String> mTrustedNetworks;
+ private static final int KEYSTORE_VERSION = 1;
+ private static final int MAX_SUPPORTED_KEYSTORE_VERSION = 1;
+ private static final String XML_KEYSTORE_START_TAG = "keyStore";
+ private static final String XML_ATTRIBUTE_VERSION = "version";
private static final String XML_TAG_ADB_KEY = "adbKey";
private static final String XML_ATTRIBUTE_KEY = "key";
private static final String XML_ATTRIBUTE_LAST_CONNECTION = "lastConnection";
+ // A list of trusted networks a device can always wirelessly debug on (always allow).
+ // TODO: Move trusted networks list into a different file?
+ private static final String XML_TAG_WIFI_ACCESS_POINT = "wifiAP";
+ private static final String XML_ATTRIBUTE_WIFI_BSSID = "bssid";
+
private static final String SYSTEM_KEY_FILE = "/adb_keys";
/**
@@ -848,10 +1815,48 @@
private void init() {
initKeyFile();
mKeyMap = getKeyMap();
+ mTrustedNetworks = getTrustedNetworks();
mSystemKeys = getSystemKeysFromFile(SYSTEM_KEY_FILE);
addUserKeysToKeyStore();
}
+ public void addTrustedNetwork(String bssid) {
+ mTrustedNetworks.add(bssid);
+ sendPersistKeyStoreMessage();
+ }
+
+ public Map<String, PairDevice> getPairedDevices() {
+ Map<String, PairDevice> pairedDevices = new HashMap<String, PairDevice>();
+ for (Map.Entry<String, Long> keyEntry : mKeyMap.entrySet()) {
+ String fingerprints = getFingerprints(keyEntry.getKey());
+ String hostname = "nouser@nohostname";
+ String[] args = keyEntry.getKey().split("\\s+");
+ if (args.length > 1) {
+ hostname = args[1];
+ }
+ pairedDevices.put(keyEntry.getKey(), new PairDevice(
+ hostname, fingerprints, mWifiConnectedKeys.contains(keyEntry.getKey())));
+ }
+ return pairedDevices;
+ }
+
+ public String findKeyFromFingerprint(String fingerprint) {
+ for (Map.Entry<String, Long> entry : mKeyMap.entrySet()) {
+ String f = getFingerprints(entry.getKey());
+ if (fingerprint.equals(f)) {
+ return entry.getKey();
+ }
+ }
+ return null;
+ }
+
+ public void removeKey(String key) {
+ if (mKeyMap.containsKey(key)) {
+ mKeyMap.remove(key);
+ sendPersistKeyStoreMessage();
+ }
+ }
+
/**
* Initializes the key file that will be used to persist the adb grants.
*/
@@ -921,6 +1926,78 @@
try (FileInputStream keyStream = mAtomicKeyFile.openRead()) {
XmlPullParser parser = Xml.newPullParser();
parser.setInput(keyStream, StandardCharsets.UTF_8.name());
+ // Check for supported keystore version.
+ XmlUtils.beginDocument(parser, XML_KEYSTORE_START_TAG);
+ if (parser.next() != XmlPullParser.END_DOCUMENT) {
+ String tagName = parser.getName();
+ if (tagName == null || !XML_KEYSTORE_START_TAG.equals(tagName)) {
+ Slog.e(TAG, "Expected " + XML_KEYSTORE_START_TAG + ", but got tag="
+ + tagName);
+ return keyMap;
+ }
+ int keystoreVersion = Integer.parseInt(
+ parser.getAttributeValue(null, XML_ATTRIBUTE_VERSION));
+ if (keystoreVersion > MAX_SUPPORTED_KEYSTORE_VERSION) {
+ Slog.e(TAG, "Keystore version=" + keystoreVersion
+ + " not supported (max_supported="
+ + MAX_SUPPORTED_KEYSTORE_VERSION + ")");
+ return keyMap;
+ }
+ }
+ while (parser.next() != XmlPullParser.END_DOCUMENT) {
+ String tagName = parser.getName();
+ if (tagName == null) {
+ break;
+ } else if (!tagName.equals(XML_TAG_ADB_KEY)) {
+ XmlUtils.skipCurrentTag(parser);
+ continue;
+ }
+ String key = parser.getAttributeValue(null, XML_ATTRIBUTE_KEY);
+ long connectionTime;
+ try {
+ connectionTime = Long.valueOf(
+ parser.getAttributeValue(null, XML_ATTRIBUTE_LAST_CONNECTION));
+ } catch (NumberFormatException e) {
+ Slog.e(TAG,
+ "Caught a NumberFormatException parsing the last connection time: "
+ + e);
+ XmlUtils.skipCurrentTag(parser);
+ continue;
+ }
+ keyMap.put(key, connectionTime);
+ }
+ } catch (IOException e) {
+ Slog.e(TAG, "Caught an IOException parsing the XML key file: ", e);
+ } catch (XmlPullParserException e) {
+ Slog.w(TAG, "Caught XmlPullParserException parsing the XML key file: ", e);
+ // The file could be written in a format prior to introducing keystore tag.
+ return getKeyMapBeforeKeystoreVersion();
+ }
+ return keyMap;
+ }
+
+
+ /**
+ * Returns the key map with the keys and last connection times from the key file.
+ * This implementation was prior to adding the XML_KEYSTORE_START_TAG.
+ */
+ private Map<String, Long> getKeyMapBeforeKeystoreVersion() {
+ Map<String, Long> keyMap = new HashMap<String, Long>();
+ // if the AtomicFile could not be instantiated before attempt again; if it still fails
+ // return an empty key map.
+ if (mAtomicKeyFile == null) {
+ initKeyFile();
+ if (mAtomicKeyFile == null) {
+ Slog.e(TAG, "Unable to obtain the key file, " + mKeyFile + ", for reading");
+ return keyMap;
+ }
+ }
+ if (!mAtomicKeyFile.exists()) {
+ return keyMap;
+ }
+ try (FileInputStream keyStream = mAtomicKeyFile.openRead()) {
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(keyStream, StandardCharsets.UTF_8.name());
XmlUtils.beginDocument(parser, XML_TAG_ADB_KEY);
while (parser.next() != XmlPullParser.END_DOCUMENT) {
String tagName = parser.getName();
@@ -951,6 +2028,63 @@
}
/**
+ * Returns the map of trusted networks from the keystore file.
+ *
+ * This was implemented in keystore version 1.
+ */
+ private List<String> getTrustedNetworks() {
+ List<String> trustedNetworks = new ArrayList<String>();
+ // if the AtomicFile could not be instantiated before attempt again; if it still fails
+ // return an empty key map.
+ if (mAtomicKeyFile == null) {
+ initKeyFile();
+ if (mAtomicKeyFile == null) {
+ Slog.e(TAG, "Unable to obtain the key file, " + mKeyFile + ", for reading");
+ return trustedNetworks;
+ }
+ }
+ if (!mAtomicKeyFile.exists()) {
+ return trustedNetworks;
+ }
+ try (FileInputStream keyStream = mAtomicKeyFile.openRead()) {
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(keyStream, StandardCharsets.UTF_8.name());
+ // Check for supported keystore version.
+ XmlUtils.beginDocument(parser, XML_KEYSTORE_START_TAG);
+ if (parser.next() != XmlPullParser.END_DOCUMENT) {
+ String tagName = parser.getName();
+ if (tagName == null || !XML_KEYSTORE_START_TAG.equals(tagName)) {
+ Slog.e(TAG, "Expected " + XML_KEYSTORE_START_TAG + ", but got tag="
+ + tagName);
+ return trustedNetworks;
+ }
+ int keystoreVersion = Integer.parseInt(
+ parser.getAttributeValue(null, XML_ATTRIBUTE_VERSION));
+ if (keystoreVersion > MAX_SUPPORTED_KEYSTORE_VERSION) {
+ Slog.e(TAG, "Keystore version=" + keystoreVersion
+ + " not supported (max_supported="
+ + MAX_SUPPORTED_KEYSTORE_VERSION);
+ return trustedNetworks;
+ }
+ }
+ while (parser.next() != XmlPullParser.END_DOCUMENT) {
+ String tagName = parser.getName();
+ if (tagName == null) {
+ break;
+ } else if (!tagName.equals(XML_TAG_WIFI_ACCESS_POINT)) {
+ XmlUtils.skipCurrentTag(parser);
+ continue;
+ }
+ String bssid = parser.getAttributeValue(null, XML_ATTRIBUTE_WIFI_BSSID);
+ trustedNetworks.add(bssid);
+ }
+ } catch (IOException | XmlPullParserException | NumberFormatException e) {
+ Slog.e(TAG, "Caught an exception parsing the XML key file: ", e);
+ }
+ return trustedNetworks;
+ }
+
+ /**
* Updates the keystore with keys that were previously set to be always allowed before the
* connection time of keys was tracked.
*/
@@ -986,7 +2120,7 @@
// if there is nothing in the key map then ensure any keys left in the keystore files
// are deleted as well.
filterOutOldKeys();
- if (mKeyMap.isEmpty()) {
+ if (mKeyMap.isEmpty() && mTrustedNetworks.isEmpty()) {
deleteKeyStore();
return;
}
@@ -1004,6 +2138,8 @@
serializer.setOutput(keyStream, StandardCharsets.UTF_8.name());
serializer.startDocument(null, true);
+ serializer.startTag(null, XML_KEYSTORE_START_TAG);
+ serializer.attribute(null, XML_ATTRIBUTE_VERSION, String.valueOf(KEYSTORE_VERSION));
for (Map.Entry<String, Long> keyEntry : mKeyMap.entrySet()) {
serializer.startTag(null, XML_TAG_ADB_KEY);
serializer.attribute(null, XML_ATTRIBUTE_KEY, keyEntry.getKey());
@@ -1011,7 +2147,12 @@
String.valueOf(keyEntry.getValue()));
serializer.endTag(null, XML_TAG_ADB_KEY);
}
-
+ for (String bssid : mTrustedNetworks) {
+ serializer.startTag(null, XML_TAG_WIFI_ACCESS_POINT);
+ serializer.attribute(null, XML_ATTRIBUTE_WIFI_BSSID, bssid);
+ serializer.endTag(null, XML_TAG_WIFI_ACCESS_POINT);
+ }
+ serializer.endTag(null, XML_KEYSTORE_START_TAG);
serializer.endDocument();
mAtomicKeyFile.finishWrite(keyStream);
} catch (IOException e) {
@@ -1072,6 +2213,7 @@
*/
public void deleteKeyStore() {
mKeyMap.clear();
+ mTrustedNetworks.clear();
deleteKeyFile();
if (mAtomicKeyFile == null) {
return;
@@ -1153,5 +2295,14 @@
return false;
}
}
+
+ /**
+ * Returns whether the specified bssid is in the list of trusted networks. This requires
+ * that the user previously allowed wireless debugging on this network and selected the
+ * option to 'Always allow'.
+ */
+ public boolean isTrustedNetwork(String bssid) {
+ return mTrustedNetworks.contains(bssid);
+ }
}
}
diff --git a/services/core/java/com/android/server/adb/AdbService.java b/services/core/java/com/android/server/adb/AdbService.java
index 0d161b9..7ccb284 100644
--- a/services/core/java/com/android/server/adb/AdbService.java
+++ b/services/core/java/com/android/server/adb/AdbService.java
@@ -21,8 +21,10 @@
import android.annotation.UserIdInt;
import android.content.ContentResolver;
import android.content.Context;
+import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.ContentObserver;
+import android.debug.AdbManager;
import android.debug.AdbManagerInternal;
import android.debug.AdbTransportType;
import android.debug.IAdbManager;
@@ -34,6 +36,7 @@
import android.os.IBinder;
import android.os.RemoteException;
import android.os.SystemProperties;
+import android.os.UserHandle;
import android.provider.Settings;
import android.service.adb.AdbServiceDumpProto;
import android.sysprop.AdbProperties;
@@ -44,6 +47,7 @@
import com.android.internal.util.DumpUtils;
import com.android.internal.util.IndentingPrintWriter;
+import com.android.internal.util.Preconditions;
import com.android.internal.util.dump.DualDumpOutputStream;
import com.android.server.FgThread;
import com.android.server.LocalServices;
@@ -54,6 +58,7 @@
import java.io.PrintWriter;
import java.util.Collections;
import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
/**
* The Android Debug Bridge (ADB) service. This controls the availability of ADB and authorization
@@ -61,6 +66,27 @@
*/
public class AdbService extends IAdbManager.Stub {
/**
+ * Adb native daemon.
+ */
+ static final String ADBD = "adbd";
+
+ /**
+ * Command to start native service.
+ */
+ static final String CTL_START = "ctl.start";
+
+ /**
+ * Command to start native service.
+ */
+ static final String CTL_STOP = "ctl.stop";
+
+ // The tcp port adb is currently using
+ AtomicInteger mConnectionPort = new AtomicInteger(-1);
+
+ private final AdbConnectionPortListener mPortListener = new AdbConnectionPortListener();
+ private AdbDebuggingManager.AdbConnectionPortPoller mConnectionPortPoller;
+
+ /**
* Manages the service lifecycle for {@code AdbService} in {@code SystemServer}.
*/
public static class Lifecycle extends SystemService {
@@ -129,9 +155,8 @@
mIsAdbUsbEnabled = containsFunction(
SystemProperties.get(USB_PERSISTENT_CONFIG_PROPERTY, ""),
UsbManager.USB_FUNCTION_ADB);
- // TODO(joshuaduong): Read the adb wifi state from a persistent system
- // property (persist.sys.adb.wifi).
- mIsAdbWifiEnabled = false;
+ mIsAdbWifiEnabled = "1".equals(
+ SystemProperties.get(WIFI_PERSISTENT_CONFIG_PROPERTY, "0"));
// register observer to listen for settings changes
mObserver = new AdbSettingsObserver();
@@ -189,6 +214,7 @@
* May also contain vendor-specific default functions for testing purposes.
*/
private static final String USB_PERSISTENT_CONFIG_PROPERTY = "persist.sys.usb.config";
+ private static final String WIFI_PERSISTENT_CONFIG_PROPERTY = "persist.adb.tls_server.enable";
private final Context mContext;
private final ContentResolver mContentResolver;
@@ -245,8 +271,9 @@
}
@Override
- public void allowDebugging(boolean alwaysAllow, String publicKey) {
+ public void allowDebugging(boolean alwaysAllow, @NonNull String publicKey) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING, null);
+ Preconditions.checkStringNotEmpty(publicKey);
if (mDebuggingManager != null) {
mDebuggingManager.allowDebugging(alwaysAllow, publicKey);
}
@@ -296,53 +323,118 @@
}
@Override
- public void allowWirelessDebugging(boolean alwaysAllow, String bssid) {
+ public void allowWirelessDebugging(boolean alwaysAllow, @NonNull String bssid) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING, null);
- // TODO(joshuaduong): NOT IMPLEMENTED
+ Preconditions.checkStringNotEmpty(bssid);
+ if (mDebuggingManager != null) {
+ mDebuggingManager.allowWirelessDebugging(alwaysAllow, bssid);
+ }
}
@Override
public void denyWirelessDebugging() {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING, null);
- // TODO(joshuaduong): NOT IMPLEMENTED
+ if (mDebuggingManager != null) {
+ mDebuggingManager.denyWirelessDebugging();
+ }
}
@Override
public Map<String, PairDevice> getPairedDevices() {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING, null);
- // TODO(joshuaduong): NOT IMPLEMENTED
+ if (mDebuggingManager != null) {
+ return mDebuggingManager.getPairedDevices();
+ }
return null;
}
@Override
- public void unpairDevice(String fingerprint) {
+ public void unpairDevice(@NonNull String fingerprint) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING, null);
- // TODO(joshuaduong): NOT IMPLEMENTED
+ Preconditions.checkStringNotEmpty(fingerprint);
+ if (mDebuggingManager != null) {
+ mDebuggingManager.unpairDevice(fingerprint);
+ }
}
@Override
public void enablePairingByPairingCode() {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING, null);
- // TODO(joshuaduong): NOT IMPLEMENTED
+ if (mDebuggingManager != null) {
+ mDebuggingManager.enablePairingByPairingCode();
+ }
}
@Override
- public void enablePairingByQrCode(String serviceName, String password) {
+ public void enablePairingByQrCode(@NonNull String serviceName, @NonNull String password) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING, null);
- // TODO(joshuaduong): NOT IMPLEMENTED
+ Preconditions.checkStringNotEmpty(serviceName);
+ Preconditions.checkStringNotEmpty(password);
+ if (mDebuggingManager != null) {
+ mDebuggingManager.enablePairingByQrCode(serviceName, password);
+ }
}
@Override
public void disablePairing() {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING, null);
- // TODO(joshuaduong): NOT IMPLEMENTED
+ if (mDebuggingManager != null) {
+ mDebuggingManager.disablePairing();
+ }
}
@Override
public int getAdbWirelessPort() {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING, null);
- // TODO(joshuaduong): NOT IMPLEMENTED
- return 0;
+ if (mDebuggingManager != null) {
+ return mDebuggingManager.getAdbWirelessPort();
+ }
+ // If ro.adb.secure=0
+ return mConnectionPort.get();
+ }
+
+ /**
+ * This listener is only used when ro.adb.secure=0. Otherwise, AdbDebuggingManager will
+ * do this.
+ */
+ class AdbConnectionPortListener implements AdbDebuggingManager.AdbConnectionPortListener {
+ public void onPortReceived(int port) {
+ if (port > 0 && port <= 65535) {
+ mConnectionPort.set(port);
+ } else {
+ mConnectionPort.set(-1);
+ // Turn off wifi debugging, since the server did not start.
+ try {
+ Settings.Global.putInt(mContentResolver,
+ Settings.Global.ADB_WIFI_ENABLED, 0);
+ } catch (SecurityException e) {
+ // If UserManager.DISALLOW_DEBUGGING_FEATURES is on, that this setting can't
+ // be changed.
+ Slog.d(TAG, "ADB_ENABLED is restricted.");
+ }
+ }
+ broadcastPortInfo(mConnectionPort.get());
+ }
+ }
+
+ private void broadcastPortInfo(int port) {
+ Intent intent = new Intent(AdbManager.WIRELESS_DEBUG_STATE_CHANGED_ACTION);
+ intent.putExtra(AdbManager.WIRELESS_STATUS_EXTRA, (port >= 0)
+ ? AdbManager.WIRELESS_STATUS_CONNECTED
+ : AdbManager.WIRELESS_STATUS_DISCONNECTED);
+ intent.putExtra(AdbManager.WIRELESS_DEBUG_PORT_EXTRA, port);
+ mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+ Slog.i(TAG, "sent port broadcast port=" + port);
+ }
+
+ private void startAdbd() {
+ SystemProperties.set(CTL_START, ADBD);
+ }
+
+ private void stopAdbd() {
+ if (!mIsAdbUsbEnabled && !mIsAdbWifiEnabled) {
+ SystemProperties.set(CTL_STOP, ADBD);
+ }
}
private void setAdbEnabled(boolean enable, byte transportType) {
@@ -356,11 +448,33 @@
mIsAdbUsbEnabled = enable;
} else if (transportType == AdbTransportType.WIFI && enable != mIsAdbWifiEnabled) {
mIsAdbWifiEnabled = enable;
+ if (mIsAdbWifiEnabled) {
+ if (!AdbProperties.secure().orElse(false) && mDebuggingManager == null) {
+ // Start adbd. If this is secure adb, then we defer enabling adb over WiFi.
+ SystemProperties.set(WIFI_PERSISTENT_CONFIG_PROPERTY, "1");
+ mConnectionPortPoller =
+ new AdbDebuggingManager.AdbConnectionPortPoller(mPortListener);
+ mConnectionPortPoller.start();
+ }
+ } else {
+ // Stop adb over WiFi.
+ SystemProperties.set(WIFI_PERSISTENT_CONFIG_PROPERTY, "0");
+ if (mConnectionPortPoller != null) {
+ mConnectionPortPoller.cancelAndWait();
+ mConnectionPortPoller = null;
+ }
+ }
} else {
// No change
return;
}
+ if (enable) {
+ startAdbd();
+ } else {
+ stopAdbd();
+ }
+
for (IAdbTransport transport : mTransports.values()) {
try {
transport.onAdbEnabled(enable, transportType);
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index fb48db4..a7125b4 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -146,6 +146,7 @@
static final int REPORT_USER_SWITCH_COMPLETE_MSG = 80;
static final int USER_SWITCH_CALLBACKS_TIMEOUT_MSG = 90;
static final int USER_UNLOCK_MSG = 100;
+ static final int USER_UNLOCKED_MSG = 105;
static final int REPORT_LOCKED_BOOT_COMPLETE_MSG = 110;
static final int START_USER_SWITCH_FG_MSG = 120;
@@ -625,6 +626,9 @@
FrameworkStatsLog.BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__FRAMEWORK_BOOT_COMPLETED,
elapsedTimeMs);
}
+
+ mHandler.obtainMessage(USER_UNLOCKED_MSG, userId, 0).sendToTarget();
+
final Intent bootIntent = new Intent(Intent.ACTION_BOOT_COMPLETED, null);
bootIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
bootIntent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT
@@ -2366,6 +2370,9 @@
});
finishUserUnlocked((UserState) msg.obj);
break;
+ case USER_UNLOCKED_MSG:
+ mInjector.getSystemServiceManager().onUserUnlocked(msg.arg1);
+ break;
case USER_CURRENT_MSG:
mInjector.batteryStatsServiceNoteEvent(
BatteryStats.HistoryItem.EVENT_USER_FOREGROUND_FINISH,
diff --git a/services/core/java/com/android/server/infra/AbstractMasterSystemService.java b/services/core/java/com/android/server/infra/AbstractMasterSystemService.java
index 8206fef..2672f84 100644
--- a/services/core/java/com/android/server/infra/AbstractMasterSystemService.java
+++ b/services/core/java/com/android/server/infra/AbstractMasterSystemService.java
@@ -713,7 +713,7 @@
/**
* Gets a list of all supported users (i.e., those that pass the
- * {@link #isSupportedUser(TargetUser)}check).
+ * {@link #isUserSupported(TargetUser)}check).
*/
@NonNull
protected List<UserInfo> getSupportedUsers() {
@@ -722,7 +722,7 @@
final List<UserInfo> supportedUsers = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
final UserInfo userInfo = allUsers[i];
- if (isSupportedUser(new TargetUser(userInfo))) {
+ if (isUserSupported(new TargetUser(userInfo))) {
supportedUsers.add(userInfo);
}
}
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 87262a8..6f04af6 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -1882,7 +1882,7 @@
executeOrSendMessage(mCurMethod,
mCaller.obtainMessageOOO(MSG_INLINE_SUGGESTIONS_REQUEST, mCurMethod,
requestInfo, new InlineSuggestionsRequestCallbackDecorator(callback,
- imi.getPackageName())));
+ imi.getPackageName(), mCurTokenDisplayId)));
} else {
callback.onInlineSuggestionsUnsupported();
}
@@ -1902,11 +1902,14 @@
@NonNull
private final String mImePackageName;
+ private final int mImeDisplayId;
+
InlineSuggestionsRequestCallbackDecorator(
@NonNull IInlineSuggestionsRequestCallback callback,
- @NonNull String imePackageName) {
+ @NonNull String imePackageName, int displayId) {
mCallback = callback;
mImePackageName = imePackageName;
+ mImeDisplayId = displayId;
}
@Override
@@ -1923,6 +1926,7 @@
+ "] doesn't match the IME package name=[" + mImePackageName
+ "].");
}
+ request.setHostDisplayId(mImeDisplayId);
mCallback.onInlineSuggestionsRequest(request, callback);
}
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 077fc6f..2d88080 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -10969,10 +10969,10 @@
// to null here, only to reset them at a later point.
Settings.updatePackageSetting(pkgSetting, disabledPkgSetting, sharedUserSetting,
destCodeFile, destResourceFile, parsedPackage.getNativeLibraryDir(),
- AndroidPackageUtils.getRawPrimaryCpuAbi(parsedPackage),
- AndroidPackageUtils.getRawSecondaryCpuAbi(parsedPackage),
- PackageInfoWithoutStateUtils.appInfoFlags(parsedPackage),
- PackageInfoWithoutStateUtils.appInfoPrivateFlags(parsedPackage),
+ AndroidPackageUtils.getPrimaryCpuAbi(parsedPackage, pkgSetting),
+ AndroidPackageUtils.getSecondaryCpuAbi(parsedPackage, pkgSetting),
+ PackageInfoUtils.appInfoFlags(parsedPackage, pkgSetting),
+ PackageInfoUtils.appInfoPrivateFlags(parsedPackage, pkgSetting),
UserManagerService.getInstance(),
usesStaticLibraries, parsedPackage.getUsesStaticLibrariesVersions(),
parsedPackage.getMimeGroups());
@@ -11164,6 +11164,8 @@
// TODO(b/135203078): Remove, move to constructor
pkgSetting.pkg = parsedPackage;
pkgSetting.pkgFlags = PackageInfoUtils.appInfoFlags(parsedPackage, pkgSetting);
+ pkgSetting.pkgPrivateFlags =
+ PackageInfoUtils.appInfoPrivateFlags(parsedPackage, pkgSetting);
if (parsedPackage.getLongVersionCode() != pkgSetting.versionCode) {
pkgSetting.versionCode = parsedPackage.getLongVersionCode();
}
@@ -16954,6 +16956,7 @@
final boolean vendor = oldPackage.isVendor();
final boolean product = oldPackage.isProduct();
final boolean odm = oldPackage.isOdm();
+ final boolean systemExt = oldPackage.isSystemExt();
final @ParseFlags int systemParseFlags = parseFlags;
final @ScanFlags int systemScanFlags = scanFlags
| SCAN_AS_SYSTEM
@@ -16961,14 +16964,14 @@
| (oem ? SCAN_AS_OEM : 0)
| (vendor ? SCAN_AS_VENDOR : 0)
| (product ? SCAN_AS_PRODUCT : 0)
- | (odm ? SCAN_AS_ODM : 0);
+ | (odm ? SCAN_AS_ODM : 0)
+ | (systemExt ? SCAN_AS_SYSTEM_EXT : 0);
if (DEBUG_INSTALL) {
Slog.d(TAG, "replaceSystemPackageLI: new=" + parsedPackage
+ ", old=" + oldPackage);
}
res.setReturnCode(PackageManager.INSTALL_SUCCEEDED);
- ps.getPkgState().setUpdatedSystemApp(true);
targetParseFlags = systemParseFlags;
targetScanFlags = systemScanFlags;
} else { // non system replace
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index af5c536..2453318 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -521,6 +521,9 @@
p.secondaryCpuAbiString, p.cpuAbiOverrideString,
p.appId, p.versionCode, p.pkgFlags, p.pkgPrivateFlags,
p.usesStaticLibraries, p.usesStaticLibrariesVersions, p.mimeGroups);
+ if (ret != null) {
+ ret.getPkgState().setUpdatedSystemApp(false);
+ }
mDisabledSysPackages.remove(name);
return ret;
}
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 840c865d..f647b6a 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -2794,7 +2794,7 @@
}
if ((changedInstallPermission || replace) && !ps.areInstallPermissionsFixed() &&
- !ps.isSystem() || !ps.getPkgState().isUpdatedSystemApp()) {
+ !ps.isSystem() || ps.getPkgState().isUpdatedSystemApp()) {
// This is the first that we have heard about this package, so the
// permissions we have now selected are fixed until explicitly
// changed.
diff --git a/services/core/java/com/android/server/pm/pkg/PackageStateUnserialized.java b/services/core/java/com/android/server/pm/pkg/PackageStateUnserialized.java
index c008d93..e27bf48 100644
--- a/services/core/java/com/android/server/pm/pkg/PackageStateUnserialized.java
+++ b/services/core/java/com/android/server/pm/pkg/PackageStateUnserialized.java
@@ -35,6 +35,9 @@
*
* It is assumed that anything inside the package was not cached or written to disk, so none of
* these fields are either. They must be set on every boot from other state on the device.
+ *
+ * These fields are also not copied into any cloned PackageSetting, to preserve the old behavior
+ * where they would be lost implicitly by re-generating the package object.
*/
@DataClass(genSetters = true, genConstructor = false, genBuilder = false)
public class PackageStateUnserialized {
diff --git a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
index 8d090f1..801d75b 100644
--- a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
+++ b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
@@ -218,11 +218,7 @@
packageInstaller.getSessionInfo(sessionId);
if (sessionInfo.isStagedSessionReady() && markStagedSessionHandled(rollbackId)) {
mContext.unregisterReceiver(listener);
- if (logPackage != null) {
- // We save the rollback id so that after reboot, we can log if rollback was
- // successful or not. If logPackage is null, then there is nothing to log.
- saveStagedRollbackId(rollbackId);
- }
+ saveStagedRollbackId(rollbackId);
WatchdogRollbackLogger.logEvent(logPackage,
FrameworkStatsLog
.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_BOOT_TRIGGERED,
diff --git a/services/core/java/com/android/server/rollback/WatchdogRollbackLogger.java b/services/core/java/com/android/server/rollback/WatchdogRollbackLogger.java
index 1be6f22..659de00 100644
--- a/services/core/java/com/android/server/rollback/WatchdogRollbackLogger.java
+++ b/services/core/java/com/android/server/rollback/WatchdogRollbackLogger.java
@@ -159,6 +159,12 @@
return;
}
+ // If no logging packages are found, use a null package to ensure the rollback status
+ // is still logged.
+ if (oldLoggingPackages.isEmpty()) {
+ oldLoggingPackages.add(null);
+ }
+
for (VersionedPackage oldLoggingPackage : oldLoggingPackages) {
if (sessionInfo.isStagedSessionApplied()) {
logEvent(oldLoggingPackage,
diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
index aed2d9b..3c8ef6c 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -395,6 +395,8 @@
case FrameworkStatsLog.BATTERY_VOLTAGE:
case FrameworkStatsLog.BATTERY_CYCLE_COUNT:
return pullHealthHal(atomTag, data);
+ case FrameworkStatsLog.APP_FEATURES_OPS:
+ return pullAppFeaturesOps(atomTag, data);
default:
throw new UnsupportedOperationException("Unknown tagId=" + atomTag);
}
@@ -550,6 +552,7 @@
registerAppsOnExternalStorageInfo();
registerFaceSettings();
registerAppOps();
+ registerAppFeaturesOps();
registerRuntimeAppOpAccessMessage();
registerNotificationRemoteViews();
registerDangerousPermissionState();
@@ -2843,7 +2846,6 @@
BackgroundThread.getExecutor(),
mStatsCallbackImpl
);
-
}
private void registerRuntimeAppOpAccessMessage() {
@@ -2854,7 +2856,6 @@
BackgroundThread.getExecutor(),
mStatsCallbackImpl
);
-
}
int pullAppOps(int atomTag, List<StatsEvent> pulledData) {
@@ -2917,6 +2918,84 @@
return StatsManager.PULL_SUCCESS;
}
+ private void registerAppFeaturesOps() {
+ int tagId = FrameworkStatsLog.APP_FEATURES_OPS;
+ mStatsManager.registerPullAtomCallback(
+ tagId,
+ null, // use default PullAtomMetadata values
+ BackgroundThread.getExecutor(),
+ mStatsCallbackImpl
+ );
+ }
+
+ int pullAppFeaturesOps(int atomTag, List<StatsEvent> pulledData) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class);
+
+ CompletableFuture<HistoricalOps> ops = new CompletableFuture<>();
+ HistoricalOpsRequest histOpsRequest =
+ new HistoricalOpsRequest.Builder(0, Long.MAX_VALUE).setFlags(
+ OP_FLAGS_PULLED).build();
+ appOps.getHistoricalOps(histOpsRequest, mContext.getMainExecutor(), ops::complete);
+
+ HistoricalOps histOps = ops.get(EXTERNAL_STATS_SYNC_TIMEOUT_MILLIS,
+ TimeUnit.MILLISECONDS);
+
+ for (int uidIdx = 0; uidIdx < histOps.getUidCount(); uidIdx++) {
+ final HistoricalUidOps uidOps = histOps.getUidOpsAt(uidIdx);
+ final int uid = uidOps.getUid();
+ for (int pkgIdx = 0; pkgIdx < uidOps.getPackageCount(); pkgIdx++) {
+ final HistoricalPackageOps packageOps = uidOps.getPackageOpsAt(pkgIdx);
+ for (int featureIdx = 0; featureIdx < packageOps.getFeatureCount();
+ featureIdx++) {
+ final AppOpsManager.HistoricalFeatureOps featureOps =
+ packageOps.getFeatureOpsAt(featureIdx);
+ for (int opIdx = 0; opIdx < featureOps.getOpCount(); opIdx++) {
+ final AppOpsManager.HistoricalOp op = featureOps.getOpAt(opIdx);
+ StatsEvent.Builder e = StatsEvent.newBuilder();
+ e.setAtomId(atomTag);
+ e.writeInt(uid);
+ e.writeString(packageOps.getPackageName());
+ e.writeString(featureOps.getFeatureId());
+ e.writeString(op.getOpName());
+ e.writeLong(op.getForegroundAccessCount(OP_FLAGS_PULLED));
+ e.writeLong(op.getBackgroundAccessCount(OP_FLAGS_PULLED));
+ e.writeLong(op.getForegroundRejectCount(OP_FLAGS_PULLED));
+ e.writeLong(op.getBackgroundRejectCount(OP_FLAGS_PULLED));
+ e.writeLong(op.getForegroundAccessDuration(OP_FLAGS_PULLED));
+ e.writeLong(op.getBackgroundAccessDuration(OP_FLAGS_PULLED));
+
+ String perm = AppOpsManager.opToPermission(op.getOpCode());
+ if (perm == null) {
+ e.writeBoolean(false);
+ } else {
+ PermissionInfo permInfo;
+ try {
+ permInfo = mContext.getPackageManager().getPermissionInfo(perm,
+ 0);
+ e.writeBoolean(
+ permInfo.getProtection() == PROTECTION_DANGEROUS);
+ } catch (PackageManager.NameNotFoundException exception) {
+ e.writeBoolean(false);
+ }
+ }
+ pulledData.add(e.build());
+ }
+
+ }
+ }
+ }
+ } catch (Throwable t) {
+ // TODO: catch exceptions at a more granular level
+ Slog.e(TAG, "Could not read appops", t);
+ return StatsManager.PULL_SKIP;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ return StatsManager.PULL_SUCCESS;
+ }
+
int pullRuntimeAppOpAccessMessage(int atomTag, List<StatsEvent> pulledData) {
final long token = Binder.clearCallingIdentity();
try {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 9cb5ba7..e0f8f0e 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -8075,32 +8075,39 @@
public void getWindowInsets(WindowManager.LayoutParams attrs,
int displayId, Rect outContentInsets, Rect outStableInsets,
DisplayCutout.ParcelableWrapper displayCutout) {
- synchronized (mGlobalLock) {
- final DisplayContent dc = mRoot.getDisplayContentOrCreate(displayId);
- if (dc == null) {
- throw new WindowManager.InvalidDisplayException("Display#" + displayId
- + "could not be found!");
+ final long origId = Binder.clearCallingIdentity();
+ try {
+ synchronized (mGlobalLock) {
+ final DisplayContent dc = getDisplayContentOrCreate(displayId, attrs.token);
+ if (dc == null) {
+ throw new WindowManager.InvalidDisplayException("Display#" + displayId
+ + "could not be found!");
+ }
+ final WindowToken windowToken = dc.getWindowToken(attrs.token);
+ final ActivityRecord activity;
+ if (windowToken != null && windowToken.asActivityRecord() != null) {
+ activity = windowToken.asActivityRecord();
+ } else {
+ activity = null;
+ }
+ final Rect taskBounds;
+ final boolean floatingStack;
+ if (activity != null && activity.getTask() != null) {
+ final Task task = activity.getTask();
+ taskBounds = new Rect();
+ task.getBounds(taskBounds);
+ floatingStack = task.isFloating();
+ } else {
+ taskBounds = null;
+ floatingStack = false;
+ }
+ final DisplayFrames displayFrames = dc.mDisplayFrames;
+ final DisplayPolicy policy = dc.getDisplayPolicy();
+ policy.getLayoutHintLw(attrs, taskBounds, displayFrames, floatingStack,
+ new Rect(), outContentInsets, outStableInsets, displayCutout);
}
- final WindowToken windowToken = dc.getWindowToken(attrs.token);
- final ActivityRecord activity;
- if (windowToken != null && windowToken.asActivityRecord() != null) {
- activity = windowToken.asActivityRecord();
- } else {
- activity = null;
- }
- final Rect taskBounds = new Rect();
- final boolean floatingStack;
- if (activity != null && activity.getTask() != null) {
- final Task task = activity.getTask();
- task.getBounds(taskBounds);
- floatingStack = task.isFloating();
- } else {
- floatingStack = false;
- }
- final DisplayFrames displayFrames = dc.mDisplayFrames;
- final DisplayPolicy policy = dc.getDisplayPolicy();
- policy.getLayoutHintLw(attrs, taskBounds, displayFrames, floatingStack,
- new Rect(), outContentInsets, outStableInsets, displayCutout);
+ } finally {
+ Binder.restoreCallingIdentity(origId);
}
}
}
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index e888f2a..27bd58e 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -24,6 +24,7 @@
"BroadcastRadio/regions.cpp",
"stats/PowerStatsPuller.cpp",
"stats/SubsystemSleepStatePuller.cpp",
+ "com_android_server_adb_AdbDebuggingManager.cpp",
"com_android_server_am_BatteryStatsService.cpp",
"com_android_server_connectivity_Vpn.cpp",
"com_android_server_ConsumerIrService.cpp",
@@ -86,6 +87,8 @@
cc_defaults {
name: "libservices.core-libs",
shared_libs: [
+ "libadb_pairing_server",
+ "libadb_pairing_connection",
"libandroid_runtime",
"libandroidfw",
"libaudioclient",
diff --git a/services/core/jni/com_android_server_adb_AdbDebuggingManager.cpp b/services/core/jni/com_android_server_adb_AdbDebuggingManager.cpp
new file mode 100644
index 0000000..9c834aa
--- /dev/null
+++ b/services/core/jni/com_android_server_adb_AdbDebuggingManager.cpp
@@ -0,0 +1,168 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "AdbDebuggingManager-JNI"
+
+#define LOG_NDEBUG 0
+
+#include <algorithm>
+#include <condition_variable>
+#include <mutex>
+#include <optional>
+#include <random>
+#include <string>
+#include <vector>
+
+#include <adb/pairing/pairing_server.h>
+#include <android-base/properties.h>
+#include <utils/Log.h>
+
+#include <nativehelper/JNIHelp.h>
+#include "jni.h"
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+namespace {
+
+template <class T, class N>
+class JSmartWrapper {
+public:
+ JSmartWrapper(JNIEnv* env, T* jData) : mEnv(env), mJData(jData) {}
+
+ virtual ~JSmartWrapper() = default;
+
+ const N* data() const { return mRawData; }
+
+ jsize size() const { return mSize; }
+
+protected:
+ N* mRawData = nullptr;
+ JNIEnv* mEnv = nullptr;
+ T* mJData = nullptr;
+ jsize mSize = 0;
+}; // JSmartWrapper
+
+class JStringUTFWrapper : public JSmartWrapper<jstring, const char> {
+public:
+ explicit JStringUTFWrapper(JNIEnv* env, jstring* str) : JSmartWrapper(env, str) {
+ mRawData = env->GetStringUTFChars(*str, NULL);
+ mSize = env->GetStringUTFLength(*str);
+ }
+
+ virtual ~JStringUTFWrapper() {
+ if (data()) {
+ mEnv->ReleaseStringUTFChars(*mJData, mRawData);
+ }
+ }
+}; // JStringUTFWrapper
+
+struct ServerDeleter {
+ void operator()(PairingServerCtx* p) { pairing_server_destroy(p); }
+};
+using PairingServerPtr = std::unique_ptr<PairingServerCtx, ServerDeleter>;
+struct PairingResultWaiter {
+ std::mutex mutex_;
+ std::condition_variable cv_;
+ std::optional<bool> is_valid_;
+ PeerInfo peer_info_;
+
+ static void ResultCallback(const PeerInfo* peer_info, void* opaque) {
+ auto* p = reinterpret_cast<PairingResultWaiter*>(opaque);
+ {
+ std::unique_lock<std::mutex> lock(p->mutex_);
+ if (peer_info) {
+ memcpy(&(p->peer_info_), peer_info, sizeof(PeerInfo));
+ }
+ p->is_valid_ = (peer_info != nullptr);
+ }
+ p->cv_.notify_one();
+ }
+};
+
+PairingServerPtr sServer;
+std::unique_ptr<PairingResultWaiter> sWaiter;
+} // namespace
+
+static jint native_pairing_start(JNIEnv* env, jobject thiz, jstring guid, jstring password) {
+ // Server-side only sends its GUID on success.
+ PeerInfo system_info = {};
+ system_info.type = ADB_DEVICE_GUID;
+ JStringUTFWrapper guidWrapper(env, &guid);
+ memcpy(system_info.data, guidWrapper.data(), guidWrapper.size());
+
+ JStringUTFWrapper passwordWrapper(env, &password);
+
+ // Create the pairing server
+ sServer = PairingServerPtr(
+ pairing_server_new_no_cert(reinterpret_cast<const uint8_t*>(passwordWrapper.data()),
+ passwordWrapper.size(), &system_info, 0));
+
+ sWaiter.reset(new PairingResultWaiter);
+ uint16_t port = pairing_server_start(sServer.get(), sWaiter->ResultCallback, sWaiter.get());
+ if (port == 0) {
+ ALOGE("Failed to start pairing server");
+ return -1;
+ }
+
+ return port;
+}
+
+static void native_pairing_cancel(JNIEnv* /* env */, jclass /* clazz */) {
+ if (sServer != nullptr) {
+ sServer.reset();
+ }
+}
+
+static jboolean native_pairing_wait(JNIEnv* env, jobject thiz) {
+ ALOGI("Waiting for pairing server to complete");
+ std::unique_lock<std::mutex> lock(sWaiter->mutex_);
+ if (!sWaiter->is_valid_.has_value()) {
+ sWaiter->cv_.wait(lock, [&]() { return sWaiter->is_valid_.has_value(); });
+ }
+ if (!*(sWaiter->is_valid_)) {
+ return JNI_FALSE;
+ }
+
+ std::string peer_public_key = reinterpret_cast<char*>(sWaiter->peer_info_.data);
+ // Write to PairingThread's member variables
+ jclass clazz = env->GetObjectClass(thiz);
+ jfieldID mPublicKey = env->GetFieldID(clazz, "mPublicKey", "Ljava/lang/String;");
+ jstring jpublickey = env->NewStringUTF(peer_public_key.c_str());
+ env->SetObjectField(thiz, mPublicKey, jpublickey);
+ return JNI_TRUE;
+}
+
+// ----------------------------------------------------------------------------
+
+static const JNINativeMethod gPairingThreadMethods[] = {
+ /* name, signature, funcPtr */
+ {"native_pairing_start", "(Ljava/lang/String;Ljava/lang/String;)I",
+ (void*)native_pairing_start},
+ {"native_pairing_cancel", "()V", (void*)native_pairing_cancel},
+ {"native_pairing_wait", "()Z", (void*)native_pairing_wait},
+};
+
+int register_android_server_AdbDebuggingManager(JNIEnv* env) {
+ int res = jniRegisterNativeMethods(env,
+ "com/android/server/adb/AdbDebuggingManager$PairingThread",
+ gPairingThreadMethods, NELEM(gPairingThreadMethods));
+ (void)res; // Faked use when LOG_NDEBUG.
+ LOG_FATAL_IF(res < 0, "Unable to register native methods.");
+ return 0;
+}
+
+} /* namespace android */
diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp
index f9238e3..a5339a5 100644
--- a/services/core/jni/onload.cpp
+++ b/services/core/jni/onload.cpp
@@ -61,6 +61,7 @@
int register_android_server_incremental_IncrementalManagerService(JNIEnv* env);
int register_android_server_com_android_server_pm_PackageManagerShellCommandDataLoader(JNIEnv* env);
int register_android_server_stats_pull_StatsPullAtomService(JNIEnv* env);
+int register_android_server_AdbDebuggingManager(JNIEnv* env);
};
using namespace android;
@@ -115,5 +116,6 @@
register_android_server_incremental_IncrementalManagerService(env);
register_android_server_com_android_server_pm_PackageManagerShellCommandDataLoader(env);
register_android_server_stats_pull_StatsPullAtomService(env);
+ register_android_server_AdbDebuggingManager(env);
return JNI_VERSION_1_4;
}
diff --git a/services/people/java/com/android/server/people/PeopleService.java b/services/people/java/com/android/server/people/PeopleService.java
index 2499614..5d7f4e9 100644
--- a/services/people/java/com/android/server/people/PeopleService.java
+++ b/services/people/java/com/android/server/people/PeopleService.java
@@ -71,12 +71,12 @@
}
@Override
- public void onUnlockUser(@NonNull TargetUser targetUser) {
+ public void onUserUnlocking(@NonNull TargetUser targetUser) {
mDataManager.onUserUnlocked(targetUser.getUserIdentifier());
}
@Override
- public void onStopUser(@NonNull TargetUser targetUser) {
+ public void onUserStopping(@NonNull TargetUser targetUser) {
mDataManager.onUserStopped(targetUser.getUserIdentifier());
}
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 84f411f..07cc2d4 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -1720,21 +1720,6 @@
private static final int ENUMERATION_TIME_OUT_MS = 2000;
/**
- * Command to start native service.
- */
- protected static final String CTL_START = "ctl.start";
-
- /**
- * Command to start native service.
- */
- protected static final String CTL_STOP = "ctl.stop";
-
- /**
- * Adb native daemon.
- */
- protected static final String ADBD = "adbd";
-
- /**
* Gadget HAL fully qualified instance name for registering for ServiceNotification.
*/
protected static final String GADGET_HAL_FQ_NAME =
@@ -1932,17 +1917,7 @@
return;
}
try {
- if ((config & UsbManager.FUNCTION_ADB) != 0) {
- /**
- * Start adbd if ADB function is included in the configuration.
- */
- setSystemProperty(CTL_START, ADBD);
- } else {
- /**
- * Stop adbd otherwise.
- */
- setSystemProperty(CTL_STOP, ADBD);
- }
+ // Adbd will be started by AdbService once Global.ADB_ENABLED is set.
UsbGadgetCallback usbGadgetCallback = new UsbGadgetCallback(mCurrentRequest,
config, chargingFunctions);
mGadgetProxy.setCurrentUsbFunctions(config, usbGadgetCallback,
diff --git a/services/usb/java/com/android/server/usb/UsbService.java b/services/usb/java/com/android/server/usb/UsbService.java
index 61f2c50..14c7f04 100644
--- a/services/usb/java/com/android/server/usb/UsbService.java
+++ b/services/usb/java/com/android/server/usb/UsbService.java
@@ -110,18 +110,18 @@
}
@Override
- public void onSwitchUser(TargetUser from, TargetUser to) {
+ public void onUserSwitching(TargetUser from, TargetUser to) {
FgThread.getHandler()
.postAtFrontOfQueue(() -> mUsbService.onSwitchUser(to.getUserIdentifier()));
}
@Override
- public void onStopUser(TargetUser userInfo) {
+ public void onUserStopping(TargetUser userInfo) {
mUsbService.onStopUser(userInfo.getUserHandle());
}
@Override
- public void onUnlockUser(TargetUser userInfo) {
+ public void onUserUnlocking(TargetUser userInfo) {
mUsbService.onUnlockUser(userInfo.getUserIdentifier());
}
}
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index 8378d8e..3c0e0af 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -167,7 +167,7 @@
}
@Override
- public boolean isSupportedUser(TargetUser user) {
+ public boolean isUserSupported(TargetUser user) {
return isSupported(user.getUserInfo());
}
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 4604cd2..5f33a3d 100755
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -3358,7 +3358,6 @@
private boolean mImmutable = false;
public FailureSignalingConnection(DisconnectCause disconnectCause) {
setDisconnected(disconnectCause);
- mImmutable = true;
}
public void checkImmutable() {
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 5d7d649..7f4fcc0 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -330,6 +330,14 @@
"android.telecom.extra.CALL_CREATED_TIME_MILLIS";
/**
+ * Optional extra for incoming and outgoing calls containing a long which specifies the Epoch
+ * time the call was created.
+ * @hide
+ */
+ public static final String EXTRA_CALL_CREATED_EPOCH_TIME_MILLIS =
+ "android.telecom.extra.CALL_CREATED_EPOCH_TIME_MILLIS";
+
+ /**
* Optional extra for incoming and outgoing calls containing a long which specifies the time
* telecom began routing the call. This value is in milliseconds since boot.
* @hide
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index a7e52ea..9d77623 100755
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -3549,6 +3549,30 @@
public static final String KEY_SHOW_FORWARDED_NUMBER_BOOL =
"show_forwarded_number_bool";
+ /**
+ * The list of originating address of missed incoming call SMS. If the SMS has originator
+ * matched, the SMS will be treated as special SMS for notifying missed incoming call to the
+ * user.
+ *
+ * @hide
+ */
+ public static final String KEY_MISSED_INCOMING_CALL_SMS_ORIGINATOR_STRING_ARRAY =
+ "missed_incoming_call_sms_originator_string_array";
+
+ /**
+ * The patterns of missed incoming call sms. This is the regular expression used for
+ * matching the missed incoming call's date, time, and caller id. The pattern should match
+ * fields for at least month, day, hour, and minute. Year is optional although it is encouraged.
+ *
+ * An usable pattern should look like this:
+ * ^(?<month>0[1-9]|1[012])\/(?<day>0[1-9]|1[0-9]|2[0-9]|3[0-1]) (?<hour>[0-1][0-9]|2[0-3]):
+ * (?<minute>[0-5][0-9])\s*(?<callerId>[0-9]+)\s*$
+ *
+ * @hide
+ */
+ public static final String KEY_MISSED_INCOMING_CALL_SMS_PATTERN_STRING_ARRAY =
+ "missed_incoming_call_sms_pattern_string_array";
+
/** The default value for every variable. */
private final static PersistableBundle sDefaults;
@@ -4057,6 +4081,9 @@
sDefaults.putBoolean(ENABLE_EAP_METHOD_PREFIX_BOOL, false);
sDefaults.putBoolean(KEY_SHOW_FORWARDED_NUMBER_BOOL, false);
sDefaults.putLong(KEY_DATA_SWITCH_VALIDATION_MIN_GAP_LONG, TimeUnit.DAYS.toMillis(1));
+ sDefaults.putStringArray(KEY_MISSED_INCOMING_CALL_SMS_ORIGINATOR_STRING_ARRAY,
+ new String[0]);
+ sDefaults.putStringArray(KEY_MISSED_INCOMING_CALL_SMS_PATTERN_STRING_ARRAY, new String[0]);
}
/**
diff --git a/telephony/java/android/telephony/CellIdentityLte.java b/telephony/java/android/telephony/CellIdentityLte.java
index e4198d1..d672c77 100644
--- a/telephony/java/android/telephony/CellIdentityLte.java
+++ b/telephony/java/android/telephony/CellIdentityLte.java
@@ -25,6 +25,7 @@
import android.text.TextUtils;
import android.util.ArraySet;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -54,6 +55,8 @@
private final int mEarfcn;
// cell bandwidth, in kHz
private final int mBandwidth;
+ // cell bands
+ private final List<Integer> mBands;
// a list of additional PLMN-IDs reported for this cell
private final ArraySet<String> mAdditionalPlmns;
@@ -70,6 +73,7 @@
mPci = CellInfo.UNAVAILABLE;
mTac = CellInfo.UNAVAILABLE;
mEarfcn = CellInfo.UNAVAILABLE;
+ mBands = Collections.emptyList();
mBandwidth = CellInfo.UNAVAILABLE;
mAdditionalPlmns = new ArraySet<>();
mCsgInfo = null;
@@ -87,8 +91,9 @@
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
public CellIdentityLte(int mcc, int mnc, int ci, int pci, int tac) {
- this(ci, pci, tac, CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE, String.valueOf(mcc),
- String.valueOf(mnc), null, null, new ArraySet<>(), null);
+ this(ci, pci, tac, CellInfo.UNAVAILABLE, Collections.emptyList(), CellInfo.UNAVAILABLE,
+ String.valueOf(mcc), String.valueOf(mnc), null, null, new ArraySet<>(),
+ null);
}
/**
@@ -107,7 +112,7 @@
*
* @hide
*/
- public CellIdentityLte(int ci, int pci, int tac, int earfcn, int bandwidth,
+ public CellIdentityLte(int ci, int pci, int tac, int earfcn, List<Integer> bands, int bandwidth,
@Nullable String mccStr, @Nullable String mncStr, @Nullable String alphal,
@Nullable String alphas, @NonNull Collection<String> additionalPlmns,
@Nullable ClosedSubscriberGroupInfo csgInfo) {
@@ -116,6 +121,7 @@
mPci = inRangeOrUnavailable(pci, 0, MAX_PCI);
mTac = inRangeOrUnavailable(tac, 0, MAX_TAC);
mEarfcn = inRangeOrUnavailable(earfcn, 0, MAX_EARFCN);
+ mBands = new ArrayList<>(bands);
mBandwidth = inRangeOrUnavailable(bandwidth, 0, MAX_BANDWIDTH);
mAdditionalPlmns = new ArraySet<>(additionalPlmns.size());
for (String plmn : additionalPlmns) {
@@ -128,28 +134,28 @@
/** @hide */
public CellIdentityLte(@NonNull android.hardware.radio.V1_0.CellIdentityLte cid) {
- this(cid.ci, cid.pci, cid.tac, cid.earfcn,
+ this(cid.ci, cid.pci, cid.tac, cid.earfcn, Collections.emptyList(),
CellInfo.UNAVAILABLE, cid.mcc, cid.mnc, "", "", new ArraySet<>(), null);
}
/** @hide */
public CellIdentityLte(@NonNull android.hardware.radio.V1_2.CellIdentityLte cid) {
- this(cid.base.ci, cid.base.pci, cid.base.tac, cid.base.earfcn, cid.bandwidth,
- cid.base.mcc, cid.base.mnc, cid.operatorNames.alphaLong,
+ this(cid.base.ci, cid.base.pci, cid.base.tac, cid.base.earfcn, Collections.emptyList(),
+ cid.bandwidth, cid.base.mcc, cid.base.mnc, cid.operatorNames.alphaLong,
cid.operatorNames.alphaShort, new ArraySet<>(), null);
}
/** @hide */
public CellIdentityLte(@NonNull android.hardware.radio.V1_5.CellIdentityLte cid) {
this(cid.base.base.ci, cid.base.base.pci, cid.base.base.tac, cid.base.base.earfcn,
- cid.base.bandwidth, cid.base.base.mcc, cid.base.base.mnc,
+ cid.bands, cid.base.bandwidth, cid.base.base.mcc, cid.base.base.mnc,
cid.base.operatorNames.alphaLong, cid.base.operatorNames.alphaShort,
cid.additionalPlmns, cid.optionalCsgInfo.csgInfo() != null
? new ClosedSubscriberGroupInfo(cid.optionalCsgInfo.csgInfo()) : null);
}
private CellIdentityLte(@NonNull CellIdentityLte cid) {
- this(cid.mCi, cid.mPci, cid.mTac, cid.mEarfcn, cid.mBandwidth, cid.mMccStr,
+ this(cid.mCi, cid.mPci, cid.mTac, cid.mEarfcn, cid.mBands, cid.mBandwidth, cid.mMccStr,
cid.mMncStr, cid.mAlphaLong, cid.mAlphaShort, cid.mAdditionalPlmns, cid.mCsgInfo);
}
@@ -157,7 +163,7 @@
@Override
public @NonNull CellIdentityLte sanitizeLocationInfo() {
return new CellIdentityLte(CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE,
- CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE,
+ CellInfo.UNAVAILABLE, mBands, CellInfo.UNAVAILABLE,
mMccStr, mMncStr, mAlphaLong, mAlphaShort, mAdditionalPlmns, null);
}
@@ -226,8 +232,7 @@
*/
@NonNull
public List<Integer> getBands() {
- // Todo: Add actual support
- return Collections.emptyList();
+ return Collections.unmodifiableList(mBands);
}
/**
@@ -343,6 +348,7 @@
.append(" mPci=").append(mPci)
.append(" mTac=").append(mTac)
.append(" mEarfcn=").append(mEarfcn)
+ .append(" mBands=").append(mBands)
.append(" mBandwidth=").append(mBandwidth)
.append(" mMcc=").append(mMccStr)
.append(" mMnc=").append(mMncStr)
@@ -362,6 +368,7 @@
dest.writeInt(mPci);
dest.writeInt(mTac);
dest.writeInt(mEarfcn);
+ dest.writeList(mBands);
dest.writeInt(mBandwidth);
dest.writeArraySet(mAdditionalPlmns);
dest.writeParcelable(mCsgInfo, flags);
@@ -374,6 +381,7 @@
mPci = in.readInt();
mTac = in.readInt();
mEarfcn = in.readInt();
+ mBands = in.readArrayList(null);
mBandwidth = in.readInt();
mAdditionalPlmns = (ArraySet<String>) in.readArraySet(null);
mCsgInfo = in.readParcelable(null);
diff --git a/tests/RollbackTest/NetworkStagedRollbackTest/src/com/android/tests/rollback/host/NetworkStagedRollbackTest.java b/tests/RollbackTest/NetworkStagedRollbackTest/src/com/android/tests/rollback/host/NetworkStagedRollbackTest.java
index d4e34f9..f6dcff4 100644
--- a/tests/RollbackTest/NetworkStagedRollbackTest/src/com/android/tests/rollback/host/NetworkStagedRollbackTest.java
+++ b/tests/RollbackTest/NetworkStagedRollbackTest/src/com/android/tests/rollback/host/NetworkStagedRollbackTest.java
@@ -53,6 +53,7 @@
private static final String ROLLBACK_INITIATE = "ROLLBACK_INITIATE";
private static final String ROLLBACK_BOOT_TRIGGERED = "ROLLBACK_BOOT_TRIGGERED";
+ private static final String ROLLBACK_SUCCESS = "ROLLBACK_SUCCESS";
private WatchdogEventLogger mLogger = new WatchdogEventLogger();
@@ -93,6 +94,7 @@
REASON_EXPLICIT_HEALTH_CHECK, null));
assertTrue(watchdogEventOccurred(watchdogEvents, ROLLBACK_BOOT_TRIGGERED, null,
null, null));
+ assertTrue(watchdogEventOccurred(watchdogEvents, ROLLBACK_SUCCESS, null, null, null));
} finally {
// Reconnect internet again so we won't break tests which assume internet available
getDevice().executeShellCommand("svc wifi enable");
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 43759cf..4afebb5 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
@@ -76,10 +76,10 @@
private static final String REASON_APP_CRASH = "REASON_APP_CRASH";
private static final String REASON_NATIVE_CRASH = "REASON_NATIVE_CRASH";
- private static final String REASON_EXPLICIT_HEALTH_CHECK = "REASON_EXPLICIT_HEALTH_CHECK";
private static final String ROLLBACK_INITIATE = "ROLLBACK_INITIATE";
private static final String ROLLBACK_BOOT_TRIGGERED = "ROLLBACK_BOOT_TRIGGERED";
+ private static final String ROLLBACK_SUCCESS = "ROLLBACK_SUCCESS";
private WatchdogEventLogger mLogger = new WatchdogEventLogger();
@@ -146,6 +146,7 @@
REASON_APP_CRASH, TESTAPP_A));
assertTrue(watchdogEventOccurred(watchdogEvents, ROLLBACK_BOOT_TRIGGERED, null,
null, null));
+ assertTrue(watchdogEventOccurred(watchdogEvents, ROLLBACK_SUCCESS, null, null, null));
}
@Test
@@ -179,6 +180,7 @@
REASON_NATIVE_CRASH, null));
assertTrue(watchdogEventOccurred(watchdogEvents, ROLLBACK_BOOT_TRIGGERED, null,
null, null));
+ assertTrue(watchdogEventOccurred(watchdogEvents, ROLLBACK_SUCCESS, null, null, null));
}
@Test
@@ -219,6 +221,7 @@
REASON_NATIVE_CRASH, null));
assertTrue(watchdogEventOccurred(watchdogEvents, ROLLBACK_BOOT_TRIGGERED, null,
null, null));
+ assertTrue(watchdogEventOccurred(watchdogEvents, ROLLBACK_SUCCESS, null, null, null));
}
/**
@@ -290,6 +293,7 @@
REASON_APP_CRASH, TESTAPP_A));
assertTrue(watchdogEventOccurred(watchdogEvents, ROLLBACK_BOOT_TRIGGERED, null,
null, null));
+ assertTrue(watchdogEventOccurred(watchdogEvents, ROLLBACK_SUCCESS, null, null, null));
}
/**
diff --git a/tests/utils/testutils/java/com/android/server/wm/test/filters/FrameworksTestsFilter.java b/tests/utils/testutils/java/com/android/server/wm/test/filters/FrameworksTestsFilter.java
index 26916bc..aed62d0 100644
--- a/tests/utils/testutils/java/com/android/server/wm/test/filters/FrameworksTestsFilter.java
+++ b/tests/utils/testutils/java/com/android/server/wm/test/filters/FrameworksTestsFilter.java
@@ -46,6 +46,7 @@
"android.view.InsetsSourceTest",
"android.view.InsetsSourceConsumerTest",
"android.view.InsetsStateTest",
+ "android.view.WindowMetricsTest"
};
public FrameworksTestsFilter(Bundle testArgs) {
diff --git a/tools/incident_section_gen/main.cpp b/tools/incident_section_gen/main.cpp
index ded4b91..786223a 100644
--- a/tools/incident_section_gen/main.cpp
+++ b/tools/incident_section_gen/main.cpp
@@ -415,7 +415,7 @@
}
const SectionFlags s = getSectionFlags(field);
- if (s.userdebug_and_eng_only()) {
+ if (s.userdebug_and_eng_only() || s.type() == SECTION_TEXT_DUMPSYS) {
printf("#if ALLOW_RESTRICTED_SECTIONS\n");
}
@@ -449,8 +449,13 @@
printf(" new TombstoneSection(%d, \"%s\"),\n", field->number(),
s.args().c_str());
break;
+ case SECTION_TEXT_DUMPSYS:
+ printf(" new TextDumpsysSection(%d, ", field->number());
+ splitAndPrint(s.args());
+ printf(" NULL),\n");
+ break;
}
- if (s.userdebug_and_eng_only()) {
+ if (s.userdebug_and_eng_only() || s.type() == SECTION_TEXT_DUMPSYS) {
printf("#endif\n");
}
}
diff --git a/wifi/Android.bp b/wifi/Android.bp
index 0c6cf1c..e253d6d 100644
--- a/wifi/Android.bp
+++ b/wifi/Android.bp
@@ -132,27 +132,68 @@
],
}
-droidstubs {
- name: "framework-wifi-stubs-srcs",
+stubs_defaults {
+ name: "framework-wifi-stubs-srcs-defaults",
srcs: [
- ":framework-annotations",
":framework-wifi-updatable-sources",
+ ":framework-wifi-util-lib-aidls",
],
- // This is needed as IOnWifiActivityEnergyInfoListener.aidl in framework-wifi depends on
- // WifiActivityEnergyInfo.aidl in framework-minus-apex
- aidl: {
- include_dirs: ["frameworks/base/core/java"],
- },
- defaults: [ "framework-module-stubs-defaults-systemapi" ],
- sdk_version: "core_current",
- libs: ["android_system_stubs_current"],
+ libs: [ "framework-annotations-lib" ],
+ sdk_version: "module_current",
+}
+
+droidstubs {
+ name: "framework-wifi-stubs-srcs-publicapi",
+ defaults: [
+ "framework-module-stubs-defaults-publicapi",
+ "framework-wifi-stubs-srcs-defaults",
+ ],
+}
+
+droidstubs {
+ name: "framework-wifi-stubs-srcs-systemapi",
+ defaults: [
+ "framework-module-stubs-defaults-systemapi",
+ "framework-wifi-stubs-srcs-defaults",
+ ],
+}
+
+droidstubs {
+ name: "framework-wifi-api-module_libs_api",
+ defaults: [
+ "framework-module-api-defaults-module_libs_api",
+ "framework-wifi-stubs-srcs-defaults",
+ ],
+}
+
+droidstubs {
+ name: "framework-wifi-stubs-srcs-module_libs_api",
+ defaults: [
+ "framework-module-stubs-defaults-module_libs_api",
+ "framework-wifi-stubs-srcs-defaults",
+ ],
}
java_library {
- name: "framework-wifi-stubs",
- srcs: [":framework-wifi-stubs-srcs"],
- sdk_version: "core_current",
- libs: ["android_system_stubs_current"],
+ name: "framework-wifi-stubs-publicapi",
+ srcs: [":framework-wifi-stubs-srcs-publicapi"],
+ sdk_version: "module_current",
+ installable: false,
+}
+
+java_library {
+ name: "framework-wifi-stubs-systemapi",
+ srcs: [":framework-wifi-stubs-srcs-systemapi"],
+ sdk_version: "module_current",
+ libs: ["framework-annotations-lib"],
+ installable: false,
+}
+
+java_library {
+ name: "framework-wifi-stubs-module_libs_api",
+ srcs: [":framework-wifi-stubs-srcs-module_libs_api"],
+ sdk_version: "module_current",
+ libs: ["framework-annotations-lib"],
installable: false,
}
diff --git a/wifi/java/android/net/wifi/SoftApCapability.java b/wifi/java/android/net/wifi/SoftApCapability.java
index a831984..18b26db 100644
--- a/wifi/java/android/net/wifi/SoftApCapability.java
+++ b/wifi/java/android/net/wifi/SoftApCapability.java
@@ -100,12 +100,12 @@
}
/**
- * Returns true when feature supported, otherwise false.
+ * Returns true when all of the queried features are supported, otherwise false.
*
- * @param feature one of feature from {@link HotspotFeatures}
+ * @param features One or combination of the features from {@link @HotspotFeatures}
*/
- public boolean isFeatureSupported(@HotspotFeatures long feature) {
- return (mSupportedFeatures & feature) == feature;
+ public boolean areFeaturesSupported(@HotspotFeatures long features) {
+ return (mSupportedFeatures & features) == features;
}
/**
@@ -122,7 +122,7 @@
* Constructor with combination of the feature.
* Zero to no supported feature.
*
- * @param features One or combination of the feature from {@link @HotspotFeatures}.
+ * @param features One or combination of the features from {@link @HotspotFeatures}.
* @hide
*/
public SoftApCapability(@HotspotFeatures long features) {
diff --git a/wifi/java/android/net/wifi/SoftApConfiguration.java b/wifi/java/android/net/wifi/SoftApConfiguration.java
index ae5bf7d..2b47623 100644
--- a/wifi/java/android/net/wifi/SoftApConfiguration.java
+++ b/wifi/java/android/net/wifi/SoftApConfiguration.java
@@ -762,7 +762,8 @@
* {@link #setBand(@BandType int)}.
*
* The channel auto selection will offload to driver when
- * {@link SoftApCapability#isFeatureSupported(SoftApCapability.SOFTAP_FEATURE_ACS_OFFLOAD)}
+ * {@link SoftApCapability#areFeaturesSupported(
+ * SoftApCapability.SOFTAP_FEATURE_ACS_OFFLOAD)}
* return true. Driver will auto select best channel which based on environment
* interference to get best performance. Check {@link SoftApCapability} to get more detail.
*
@@ -807,7 +808,7 @@
*
* <p>
* Use {@link WifiManager.SoftApCallback#onCapabilityChanged(SoftApCapability)} and
- * {@link SoftApCapability#isFeatureSupported(int)}
+ * {@link SoftApCapability#areFeaturesSupported(int)}
* with {@link SoftApCapability.SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT} to determine whether
* or not this feature is supported.
*
@@ -882,7 +883,7 @@
* <p>
* This method requires hardware support. Hardware support can be determined using
* {@link WifiManager.SoftApCallback#onCapabilityChanged(SoftApCapability)} and
- * {@link SoftApCapability#isFeatureSupported(int)}
+ * {@link SoftApCapability#areFeaturesSupported(int)}
* with {@link SoftApCapability.SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT}
*
* <p>