summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.mk3
-rw-r--r--core/java/android/app/admin/ConnectEvent.aidl21
-rw-r--r--core/java/android/app/admin/ConnectEvent.java87
-rw-r--r--core/java/android/app/admin/DeviceAdminReceiver.java27
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java29
-rw-r--r--core/java/android/app/admin/DnsEvent.aidl21
-rw-r--r--core/java/android/app/admin/DnsEvent.java108
-rw-r--r--core/java/android/app/admin/IDevicePolicyManager.aidl2
-rw-r--r--core/java/android/app/admin/NetworkEvent.aidl21
-rw-r--r--core/java/android/app/admin/NetworkEvent.java85
-rw-r--r--core/java/android/content/pm/PackageManagerInternal.java13
-rw-r--r--core/jni/android_os_HwBinder.cpp46
-rw-r--r--core/jni/android_os_HwRemoteBinder.cpp1
-rw-r--r--core/res/AndroidManifest.xml5
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java5
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java8
-rw-r--r--services/core/java/com/android/server/wm/PinnedStackController.java7
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java13
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java20
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/NetworkLogger.java42
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/NetworkLoggingHandler.java113
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/NetworkEventTest.java62
-rw-r--r--tools/aapt/Command.cpp2
23 files changed, 698 insertions, 43 deletions
diff --git a/Android.mk b/Android.mk
index 44dd3dc9834e..2644ca1349f1 100644
--- a/Android.mk
+++ b/Android.mk
@@ -586,6 +586,9 @@ aidl_files := \
frameworks/base/graphics/java/android/graphics/drawable/Icon.aidl \
frameworks/base/core/java/android/accounts/AuthenticatorDescription.aidl \
frameworks/base/core/java/android/accounts/Account.aidl \
+ frameworks/base/core/java/android/app/admin/ConnectEvent.aidl \
+ frameworks/base/core/java/android/app/admin/DnsEvent.aidl \
+ frameworks/base/core/java/android/app/admin/NetworkEvent.aidl \
frameworks/base/core/java/android/app/admin/SystemUpdatePolicy.aidl \
frameworks/base/core/java/android/app/admin/PasswordMetrics.aidl \
frameworks/base/core/java/android/print/PrintDocumentInfo.aidl \
diff --git a/core/java/android/app/admin/ConnectEvent.aidl b/core/java/android/app/admin/ConnectEvent.aidl
new file mode 100644
index 000000000000..bab40f5add38
--- /dev/null
+++ b/core/java/android/app/admin/ConnectEvent.aidl
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2016 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.app.admin;
+
+/** {@hide} */
+parcelable ConnectEvent;
+
diff --git a/core/java/android/app/admin/ConnectEvent.java b/core/java/android/app/admin/ConnectEvent.java
new file mode 100644
index 000000000000..e05feafcc93c
--- /dev/null
+++ b/core/java/android/app/admin/ConnectEvent.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2016 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.app.admin;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * A class that represents a connect library call event.
+ * @hide
+ */
+public final class ConnectEvent extends NetworkEvent implements Parcelable {
+
+ /** The destination IP address. */
+ private final String ipAddress;
+
+ /** The destination port number. */
+ private final int port;
+
+ public ConnectEvent(String ipAddress, int port, String packageName, long timestamp) {
+ super(packageName, timestamp);
+ this.ipAddress = ipAddress;
+ this.port = port;
+ }
+
+ private ConnectEvent(Parcel in) {
+ this.ipAddress = in.readString();
+ this.port = in.readInt();
+ this.packageName = in.readString();
+ this.timestamp = in.readLong();
+ }
+
+ public String getIpAddress() {
+ return ipAddress;
+ }
+
+ public int getPort() {
+ return port;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("ConnectEvent(%s, %d, %d, %s)", ipAddress, port, timestamp,
+ packageName);
+ }
+
+ public static final Parcelable.Creator<ConnectEvent> CREATOR
+ = new Parcelable.Creator<ConnectEvent>() {
+ @Override
+ public ConnectEvent createFromParcel(Parcel in) {
+ if (in.readInt() != PARCEL_TOKEN_CONNECT_EVENT) {
+ return null;
+ }
+ return new ConnectEvent(in);
+ }
+
+ @Override
+ public ConnectEvent[] newArray(int size) {
+ return new ConnectEvent[size];
+ }
+ };
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ // write parcel token first
+ out.writeInt(PARCEL_TOKEN_CONNECT_EVENT);
+ out.writeString(ipAddress);
+ out.writeInt(port);
+ out.writeString(packageName);
+ out.writeLong(timestamp);
+ }
+}
+
diff --git a/core/java/android/app/admin/DeviceAdminReceiver.java b/core/java/android/app/admin/DeviceAdminReceiver.java
index dd70b5dfd1f0..360087c4dfe1 100644
--- a/core/java/android/app/admin/DeviceAdminReceiver.java
+++ b/core/java/android/app/admin/DeviceAdminReceiver.java
@@ -276,6 +276,15 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
= "android.app.action.SECURITY_LOGS_AVAILABLE";
/**
+ * Broadcast action: notify that a new batch of network logs is ready to be collected.
+ * @see DeviceAdminReceiver#onNetworkLogsAvailable
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_NETWORK_LOGS_AVAILABLE
+ = "android.app.action.NETWORK_LOGS_AVAILABLE";
+
+ /**
* A string containing the SHA-256 hash of the bugreport file.
*
* @see #ACTION_BUGREPORT_SHARE
@@ -635,6 +644,22 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
}
/**
+ * Called when a new batch of network logs can be retrieved. This callback method will only ever
+ * be called when network logging is enabled. The logs can only be retrieved while network
+ * logging is enabled.
+ *
+ * <p>This callback is only applicable to device owners.
+ *
+ * @param context The running context as per {@link #onReceive}.
+ * @param intent The received intent as per {@link #onReceive}.
+ * @see DevicePolicyManager#retrieveNetworkLogs(ComponentName)
+ *
+ * @hide
+ */
+ public void onNetworkLogsAvailable(Context context, Intent intent) {
+ }
+
+ /**
* Intercept standard device administrator broadcasts. Implementations
* should not override this method; it is better to implement the
* convenience callbacks for each action.
@@ -688,6 +713,8 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
onBugreportFailed(context, intent, failureCode);
} else if (ACTION_SECURITY_LOGS_AVAILABLE.equals(action)) {
onSecurityLogsAvailable(context, intent);
+ } else if (ACTION_NETWORK_LOGS_AVAILABLE.equals(action)) {
+ onNetworkLogsAvailable(context, intent);
}
}
}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 105a06444b31..538e52b97013 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -26,6 +26,7 @@ import android.annotation.SystemApi;
import android.annotation.UserIdInt;
import android.annotation.WorkerThread;
import android.app.Activity;
+import android.app.admin.NetworkEvent;
import android.app.admin.PasswordMetrics;
import android.app.admin.SecurityLog.SecurityEvent;
import android.content.ComponentName;
@@ -6650,6 +6651,7 @@ public class DevicePolicyManager {
* @throws {@link SecurityException} if {@code admin} is not a device owner.
* @throws {@link RemoteException} if network logging could not be enabled or disabled due to
* the logging service not being available
+ * @see #retrieveNetworkLogs
*
* @hide
*/
@@ -6679,4 +6681,31 @@ public class DevicePolicyManager {
throw re.rethrowFromSystemServer();
}
}
+
+ /**
+ * Called by device owner to retrieve a new batch of network logging events.
+ *
+ * <p> {@link NetworkEvent} can be one of {@link DnsEvent} or {@link ConnectEvent}.
+ *
+ * <p> The list of network events is sorted chronologically, and contains at most 1200 events.
+ *
+ * <p> Access to the logs is rate limited and this method will only return a new batch of logs
+ * after the device device owner has been notified via
+ * {@link DeviceAdminReceiver#onNetworkLogsAvailable}.
+ *
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+ * @return A new batch of network logs which is a list of {@link NetworkEvent}. Returns
+ * {@code null} if there's no batch currently awaiting for retrieval or if logging is disabled.
+ * @throws {@link SecurityException} if {@code admin} is not a device owner.
+ *
+ * @hide
+ */
+ public List<NetworkEvent> retrieveNetworkLogs(@NonNull ComponentName admin) {
+ throwIfParentInstance("retrieveNetworkLogs");
+ try {
+ return mService.retrieveNetworkLogs(admin);
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
}
diff --git a/core/java/android/app/admin/DnsEvent.aidl b/core/java/android/app/admin/DnsEvent.aidl
new file mode 100644
index 000000000000..6da962a0a828
--- /dev/null
+++ b/core/java/android/app/admin/DnsEvent.aidl
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2016 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.app.admin;
+
+/** {@hide} */
+parcelable DnsEvent;
+
diff --git a/core/java/android/app/admin/DnsEvent.java b/core/java/android/app/admin/DnsEvent.java
new file mode 100644
index 000000000000..0ec134acdad5
--- /dev/null
+++ b/core/java/android/app/admin/DnsEvent.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2016 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.app.admin;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * A class that represents a DNS lookup event.
+ * @hide
+ */
+public final class DnsEvent extends NetworkEvent implements Parcelable {
+
+ /** The hostname that was looked up. */
+ private final String hostname;
+
+ /** Contains (possibly a subset of) the IP addresses returned. */
+ private final String[] ipAddresses;
+
+ /**
+ * The number of IP addresses returned from the DNS lookup event. May be different from the
+ * length of ipAddresses if there were too many addresses to log.
+ */
+ private final int ipAddressesCount;
+
+ public DnsEvent(String hostname, String[] ipAddresses, int ipAddressesCount,
+ String packageName, long timestamp) {
+ super(packageName, timestamp);
+ this.hostname = hostname;
+ this.ipAddresses = ipAddresses;
+ this.ipAddressesCount = ipAddressesCount;
+ }
+
+ private DnsEvent(Parcel in) {
+ this.hostname = in.readString();
+ this.ipAddresses = in.createStringArray();
+ this.ipAddressesCount = in.readInt();
+ this.packageName = in.readString();
+ this.timestamp = in.readLong();
+ }
+
+ /** Returns the hostname that was looked up. */
+ public String getHostname() {
+ return hostname;
+ }
+
+ /** Returns (possibly a subset of) the IP addresses returned. */
+ public String[] getIpAddresses() {
+ return ipAddresses;
+ }
+
+ /**
+ * Returns the number of IP addresses returned from the DNS lookup event. May be different from
+ * the length of ipAddresses if there were too many addresses to log.
+ */
+ public int getIpAddressesCount() {
+ return ipAddressesCount;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("DnsEvent(%s, %s, %d, %d, %s)", hostname,
+ (ipAddresses == null) ? "NONE" : String.join(" ", ipAddresses),
+ ipAddressesCount, timestamp, packageName);
+ }
+
+ public static final Parcelable.Creator<DnsEvent> CREATOR
+ = new Parcelable.Creator<DnsEvent>() {
+ @Override
+ public DnsEvent createFromParcel(Parcel in) {
+ if (in.readInt() != PARCEL_TOKEN_DNS_EVENT) {
+ return null;
+ }
+ return new DnsEvent(in);
+ }
+
+ @Override
+ public DnsEvent[] newArray(int size) {
+ return new DnsEvent[size];
+ }
+ };
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ // write parcel token first
+ out.writeInt(PARCEL_TOKEN_DNS_EVENT);
+ out.writeString(hostname);
+ out.writeStringArray(ipAddresses);
+ out.writeInt(ipAddressesCount);
+ out.writeString(packageName);
+ out.writeLong(timestamp);
+ }
+}
+
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 3cfa1e807b96..b0aec8cd2571 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -17,6 +17,7 @@
package android.app.admin;
+import android.app.admin.NetworkEvent;
import android.app.admin.SystemUpdatePolicy;
import android.app.admin.PasswordMetrics;
import android.content.ComponentName;
@@ -317,4 +318,5 @@ interface IDevicePolicyManager {
void setNetworkLoggingEnabled(in ComponentName admin, boolean enabled);
boolean isNetworkLoggingEnabled(in ComponentName admin);
+ List<NetworkEvent> retrieveNetworkLogs(in ComponentName admin);
}
diff --git a/core/java/android/app/admin/NetworkEvent.aidl b/core/java/android/app/admin/NetworkEvent.aidl
new file mode 100644
index 000000000000..5fa5dbfabb5f
--- /dev/null
+++ b/core/java/android/app/admin/NetworkEvent.aidl
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2016 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.app.admin;
+
+/** {@hide} */
+parcelable NetworkEvent;
+
diff --git a/core/java/android/app/admin/NetworkEvent.java b/core/java/android/app/admin/NetworkEvent.java
new file mode 100644
index 000000000000..ec7ed00debb4
--- /dev/null
+++ b/core/java/android/app/admin/NetworkEvent.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2016 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.app.admin;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.ParcelFormatException;
+
+/**
+ * An abstract class that represents a network event.
+ * @hide
+ */
+public abstract class NetworkEvent implements Parcelable {
+
+ protected static final int PARCEL_TOKEN_DNS_EVENT = 1;
+ protected static final int PARCEL_TOKEN_CONNECT_EVENT = 2;
+
+ /** The package name of the UID that performed the query. */
+ protected String packageName;
+
+ /** The timestamp of the event being reported in milliseconds. */
+ protected long timestamp;
+
+ protected NetworkEvent() {
+ //empty constructor
+ }
+
+ protected NetworkEvent(String packageName, long timestamp) {
+ this.packageName = packageName;
+ this.timestamp = timestamp;
+ }
+
+ /** Returns the package name of the UID that performed the query. */
+ public String getPackageName() {
+ return packageName;
+ }
+
+ /** Returns the timestamp of the event being reported in milliseconds. */
+ public long getTimestamp() {
+ return timestamp;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ public static final Parcelable.Creator<NetworkEvent> CREATOR
+ = new Parcelable.Creator<NetworkEvent>() {
+ public NetworkEvent createFromParcel(Parcel in) {
+ final int initialPosition = in.dataPosition();
+ final int parcelToken = in.readInt();
+ // we need to move back to the position from before we read parcelToken
+ in.setDataPosition(initialPosition);
+ switch (parcelToken) {
+ case PARCEL_TOKEN_DNS_EVENT:
+ return DnsEvent.CREATOR.createFromParcel(in);
+ case PARCEL_TOKEN_CONNECT_EVENT:
+ return ConnectEvent.CREATOR.createFromParcel(in);
+ default:
+ throw new ParcelFormatException("Unexpected NetworkEvent token in parcel: "
+ + parcelToken);
+ }
+ }
+
+ public NetworkEvent[] newArray(int size) {
+ return new NetworkEvent[size];
+ }
+ };
+}
+
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index da4eb2d288cf..1f013ae02a87 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -189,4 +189,17 @@ public abstract class PackageManagerInternal {
public abstract void revokeRuntimePermission(String packageName, String name, int userId,
boolean overridePolicy);
+ /**
+ * Retrieve the official name associated with a user id. This name is
+ * guaranteed to never change, though it is possible for the underlying
+ * user id to be changed. That is, if you are storing information about
+ * user ids in persistent storage, you should use the string returned
+ * by this function instead of the raw user-id.
+ *
+ * @param uid The user id for which you would like to retrieve a name.
+ * @return Returns a unique name for the given user id, or null if the
+ * user id is not currently assigned.
+ */
+ public abstract String getNameForUid(int uid);
+
}
diff --git a/core/jni/android_os_HwBinder.cpp b/core/jni/android_os_HwBinder.cpp
index 816d5df1c710..1a33d9111fdb 100644
--- a/core/jni/android_os_HwBinder.cpp
+++ b/core/jni/android_os_HwBinder.cpp
@@ -24,8 +24,9 @@
#include "android_os_HwRemoteBinder.h"
#include <JNIHelp.h>
+#include <android/hidl/manager/1.0/IServiceManager.h>
#include <android_runtime/AndroidRuntime.h>
-#include <hidl/IServiceManager.h>
+#include <hidl/ServiceManagement.h>
#include <hidl/Status.h>
#include <hwbinder/ProcessState.h>
#include <nativehelper/ScopedLocalRef.h>
@@ -220,27 +221,31 @@ static void JHwBinder_native_registerService(
return; // XXX exception already pending?
}
- const hardware::hidl_version kVersion =
- hardware::make_hidl_version(versionMajor, versionMinor);
+ using android::hidl::manager::V1_0::IServiceManager;
+
+ const IServiceManager::Version kVersion {
+ .major = static_cast<uint16_t>(versionMajor),
+ .minor = static_cast<uint16_t>(versionMinor),
+ };
sp<hardware::IBinder> binder = JHwBinder::GetNativeContext(env, thiz);
- status_t err = hardware::defaultServiceManager()->addService(
- String16(
- reinterpret_cast<const char16_t *>(serviceName),
- env->GetStringLength(serviceNameObj)),
+ bool ok = hardware::defaultServiceManager()->add(
+ String8(String16(
+ reinterpret_cast<const char16_t *>(serviceName),
+ env->GetStringLength(serviceNameObj))).string(),
binder,
kVersion);
env->ReleaseStringCritical(serviceNameObj, serviceName);
serviceName = NULL;
- if (err == OK) {
+ if (ok) {
LOG(INFO) << "Starting thread pool.";
::android::hardware::ProcessState::self()->startThreadPool();
}
- signalExceptionForError(env, err);
+ signalExceptionForError(env, (ok ? OK : UNKNOWN_ERROR));
}
static jobject JHwBinder_native_getService(
@@ -268,8 +273,12 @@ static jobject JHwBinder_native_getService(
return NULL; // XXX exception already pending?
}
- const hardware::hidl_version kVersion =
- hardware::make_hidl_version(versionMajor, versionMinor);
+ using android::hidl::manager::V1_0::IServiceManager;
+
+ const IServiceManager::Version kVersion {
+ .major = static_cast<uint16_t>(versionMajor),
+ .minor = static_cast<uint16_t>(versionMinor),
+ };
LOG(INFO) << "looking for service '"
<< String8(String16(
@@ -277,12 +286,15 @@ static jobject JHwBinder_native_getService(
env->GetStringLength(serviceNameObj))).string()
<< "'";
- sp<hardware::IBinder> service =
- hardware::defaultServiceManager()->getService(
- String16(
- reinterpret_cast<const char16_t *>(serviceName),
- env->GetStringLength(serviceNameObj)),
- kVersion);
+ sp<hardware::IBinder> service;
+ hardware::defaultServiceManager()->get(
+ String8(String16(
+ reinterpret_cast<const char16_t *>(serviceName),
+ env->GetStringLength(serviceNameObj))).string(),
+ kVersion,
+ [&service](sp<hardware::IBinder> out) {
+ service = out;
+ });
env->ReleaseStringCritical(serviceNameObj, serviceName);
serviceName = NULL;
diff --git a/core/jni/android_os_HwRemoteBinder.cpp b/core/jni/android_os_HwRemoteBinder.cpp
index 3023ba87d24b..1d5d6d59639a 100644
--- a/core/jni/android_os_HwRemoteBinder.cpp
+++ b/core/jni/android_os_HwRemoteBinder.cpp
@@ -24,7 +24,6 @@
#include <JNIHelp.h>
#include <android_runtime/AndroidRuntime.h>
-#include <hidl/IServiceManager.h>
#include <hidl/Status.h>
#include <nativehelper/ScopedLocalRef.h>
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index b38bb1ec779f..80775aea30f1 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -454,6 +454,7 @@
<protected-broadcast android:name="com.android.server.Wifi.action.TOGGLE_PNO" />
<protected-broadcast android:name="intent.action.ACTION_RF_BAND_INFO" />
<protected-broadcast android:name="android.intent.action.MEDIA_RESOURCE_GRANTED" />
+ <protected-broadcast android:name="android.app.action.NETWORK_LOGS_AVAILABLE" />
<protected-broadcast android:name="android.app.action.SECURITY_LOGS_AVAILABLE" />
<protected-broadcast android:name="android.app.action.INTERRUPTION_FILTER_CHANGED" />
@@ -1774,12 +1775,12 @@
android:protectionLevel="signature|privileged" />
<!-- Allows applications to set the system time zone.
- <p>Protection level: normal
+ <p>Not for use by third-party applications.
-->
<permission android:name="android.permission.SET_TIME_ZONE"
android:label="@string/permlab_setTimeZone"
android:description="@string/permdesc_setTimeZone"
- android:protectionLevel="normal" />
+ android:protectionLevel="signature|privileged" />
<!-- ==================================================== -->
<!-- Permissions related to changing status bar -->
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 57aa38d1728b..6915075e4ff9 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -21236,6 +21236,11 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
PackageManagerService.this.revokeRuntimePermission(packageName, name, userId,
overridePolicy);
}
+
+ @Override
+ public String getNameForUid(int uid) {
+ return PackageManagerService.this.getNameForUid(uid);
+ }
}
@Override
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 13099dc76f80..243c4a579962 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -928,7 +928,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
+ " mLayoutNeeded=" + mLayoutNeeded);
pw.println();
- pw.println(" Application tokens in top down Z order:");
+ pw.println(prefix + "Application tokens in top down Z order:");
for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
final TaskStack stack = mTaskStackContainers.get(stackNdx);
stack.dump(prefix + " ", pw);
@@ -947,11 +947,11 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
}
}
pw.println();
- mDimLayerController.dump(prefix + " ", pw);
+ mDimLayerController.dump(prefix, pw);
pw.println();
- mDividerControllerLocked.dump(prefix + " ", pw);
+ mDividerControllerLocked.dump(prefix, pw);
pw.println();
- mPinnedStackControllerLocked.dump(prefix + " ", pw);
+ mPinnedStackControllerLocked.dump(prefix, pw);
if (mInputMethodAnimLayerAdjustment != 0) {
pw.println(subPrefix
diff --git a/services/core/java/com/android/server/wm/PinnedStackController.java b/services/core/java/com/android/server/wm/PinnedStackController.java
index e9e47846728f..faca8db3ab87 100644
--- a/services/core/java/com/android/server/wm/PinnedStackController.java
+++ b/services/core/java/com/android/server/wm/PinnedStackController.java
@@ -18,6 +18,7 @@ package com.android.server.wm;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.util.TypedValue.COMPLEX_UNIT_DIP;
+import static android.view.Display.DEFAULT_DISPLAY;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -81,6 +82,7 @@ class PinnedStackController {
// Temp vars for calculation
private final DisplayMetrics mTmpMetrics = new DisplayMetrics();
private final Rect mTmpInsets = new Rect();
+ private final Rect mTmpRect = new Rect();
/**
* The callback object passed to listeners for them to notify the controller of state changes.
@@ -298,6 +300,11 @@ class PinnedStackController {
void dump(String prefix, PrintWriter pw) {
pw.println(prefix + "PinnedStackController");
+ pw.print(prefix + " defaultBounds="); getDefaultBounds().printShortString(pw);
+ pw.println();
+ mService.getStackBounds(PINNED_STACK_ID, mTmpRect);
+ pw.print(prefix + " movementBounds="); getMovementBounds(mTmpRect).printShortString(pw);
+ pw.println();
pw.println(prefix + " mIsImeShowing=" + mIsImeShowing);
pw.println(prefix + " mInInteractiveMode=" + mInInteractiveMode);
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 66b2cbc3c7a5..0abcd9fa756a 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -8088,7 +8088,6 @@ public class WindowManagerService extends IWindowManager.Stub
pw.println(" a[animator]: animator state");
pw.println(" s[essions]: active sessions");
pw.println(" surfaces: active surfaces (debugging enabled only)");
- pw.println(" pip: PIP state");
pw.println(" d[isplays]: active display contents");
pw.println(" t[okens]: token list");
pw.println(" w[indows]: window list");
@@ -8161,18 +8160,6 @@ public class WindowManagerService extends IWindowManager.Stub
pw.println(output.toString());
}
return;
- } else if ("pip".equals(cmd)) {
- synchronized(mWindowMap) {
- pw.print("defaultBounds=");
- getPictureInPictureDefaultBounds(DEFAULT_DISPLAY).printShortString(pw);
- pw.println();
- pw.print("movementBounds=");
- getPictureInPictureMovementBounds(DEFAULT_DISPLAY).printShortString(pw);
- pw.println();
- getDefaultDisplayContentLocked().getPinnedStackController().dump("", pw);
- pw.println();
- }
- return;
} else {
// Dumping a single name?
if (!dumpWindows(pw, cmd, args, opti, dumpAll)) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 42b5dc0f0bd0..6006c6bf6d3b 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -51,6 +51,7 @@ import android.app.admin.DeviceAdminReceiver;
import android.app.admin.DevicePolicyManager;
import android.app.admin.DevicePolicyManagerInternal;
import android.app.admin.IDevicePolicyManager;
+import android.app.admin.NetworkEvent;
import android.app.admin.PasswordMetrics;
import android.app.admin.SecurityLog;
import android.app.admin.SecurityLog.SecurityEvent;
@@ -9558,4 +9559,23 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked();
return (deviceOwner != null) && deviceOwner.isNetworkLoggingEnabled;
}
+
+ /*
+ * A maximum of 1200 events are returned, and the total marshalled size is in the order of
+ * 100kB, so returning a List instead of ParceledListSlice is acceptable.
+ * Ideally this would be done with ParceledList, however it only supports homogeneous types.
+ */
+ @Override
+ public synchronized List<NetworkEvent> retrieveNetworkLogs(ComponentName admin) {
+ if (!mHasFeature) {
+ return null;
+ }
+ Preconditions.checkNotNull(admin);
+ ensureDeviceOwnerManagingSingleUser(admin);
+
+ if (mNetworkLogger == null) {
+ return null;
+ }
+ return isNetworkLoggingEnabledInternal() ? mNetworkLogger.retrieveLogs() : null;
+ }
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/NetworkLogger.java b/services/devicepolicy/java/com/android/server/devicepolicy/NetworkLogger.java
index db17ca23aa5f..185ccc232aa9 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/NetworkLogger.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/NetworkLogger.java
@@ -16,9 +16,16 @@
package com.android.server.devicepolicy;
+import android.app.admin.ConnectEvent;
+import android.app.admin.DnsEvent;
+import android.app.admin.NetworkEvent;
import android.content.pm.PackageManagerInternal;
import android.net.IIpConnectivityMetrics;
import android.net.INetdEventCallback;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.os.Process;
import android.os.RemoteException;
import android.util.Log;
import android.util.Slog;
@@ -40,6 +47,8 @@ final class NetworkLogger {
private final PackageManagerInternal mPm;
private IIpConnectivityMetrics mIpConnectivityMetrics;
+ private ServiceThread mHandlerThread;
+ private NetworkLoggingHandler mNetworkLoggingHandler;
private boolean mIsLoggingEnabled;
private final INetdEventCallback mNetdEventCallback = new INetdEventCallback.Stub() {
@@ -49,7 +58,9 @@ final class NetworkLogger {
if (!mIsLoggingEnabled) {
return;
}
- // TODO(mkarpinski): send msg with data to Handler
+ DnsEvent dnsEvent = new DnsEvent(hostname, ipAddresses, ipAddressesCount,
+ mPm.getNameForUid(uid), timestamp);
+ sendNetworkEvent(dnsEvent);
}
@Override
@@ -57,7 +68,18 @@ final class NetworkLogger {
if (!mIsLoggingEnabled) {
return;
}
- // TODO(mkarpinski): send msg with data to Handler
+ ConnectEvent connectEvent = new ConnectEvent(ipAddr, port, mPm.getNameForUid(uid),
+ timestamp);
+ sendNetworkEvent(connectEvent);
+ }
+
+ private void sendNetworkEvent(NetworkEvent event) {
+ Message msg = mNetworkLoggingHandler.obtainMessage(
+ NetworkLoggingHandler.LOG_NETWORK_EVENT_MSG);
+ Bundle bundle = new Bundle();
+ bundle.putParcelable(NetworkLoggingHandler.NETWORK_EVENT_KEY, event);
+ msg.setData(bundle);
+ mNetworkLoggingHandler.sendMessage(msg);
}
};
@@ -87,7 +109,13 @@ final class NetworkLogger {
}
try {
if (mIpConnectivityMetrics.registerNetdEventCallback(mNetdEventCallback)) {
- // TODO(mkarpinski): start a new ServiceThread, instantiate a Handler etc.
+ mHandlerThread = new ServiceThread(TAG, Process.THREAD_PRIORITY_BACKGROUND,
+ /* allowIo */ false);
+ mHandlerThread.start();
+ mNetworkLoggingHandler = new NetworkLoggingHandler(mHandlerThread.getLooper(),
+ mDpm);
+ mNetworkLoggingHandler.scheduleBatchFinalization(
+ NetworkLoggingHandler.BATCH_FINALIZATION_TIMEOUT_MS);
mIsLoggingEnabled = true;
return true;
} else {
@@ -101,7 +129,7 @@ final class NetworkLogger {
boolean stopNetworkLogging() {
Log.d(TAG, "Stopping network logging");
- // stop the logging regardless of whether we failed to unregister listener
+ // stop the logging regardless of whether we fail to unregister listener
mIsLoggingEnabled = false;
try {
if (!checkIpConnectivityMetricsService()) {
@@ -114,8 +142,12 @@ final class NetworkLogger {
} catch (RemoteException re) {
Slog.wtf(TAG, "Failed to make remote calls to unregister the callback", re);
} finally {
- // TODO(mkarpinski): quitSafely() the Handler
+ mHandlerThread.quitSafely();
return true;
}
}
+
+ List<NetworkEvent> retrieveLogs() {
+ return mNetworkLoggingHandler.retrieveFullLogBatch();
+ }
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/NetworkLoggingHandler.java b/services/devicepolicy/java/com/android/server/devicepolicy/NetworkLoggingHandler.java
new file mode 100644
index 000000000000..96884e6db711
--- /dev/null
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/NetworkLoggingHandler.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.devicepolicy;
+
+import android.app.admin.DeviceAdminReceiver;
+import android.app.admin.ConnectEvent;
+import android.app.admin.DnsEvent;
+import android.app.admin.NetworkEvent;
+import android.net.IIpConnectivityMetrics;
+import android.net.INetdEventCallback;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+import android.util.Log;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A Handler class for managing network logging on a background thread.
+ */
+final class NetworkLoggingHandler extends Handler {
+
+ private static final String TAG = NetworkLoggingHandler.class.getSimpleName();
+
+ static final String NETWORK_EVENT_KEY = "network_event";
+
+ // est. ~128kB of memory usage per full batch TODO(mkarpinski): fine tune based on testing data
+ // If this value changes, update DevicePolicyManager#retrieveNetworkLogs() javadoc
+ private static final int MAX_EVENTS_PER_BATCH = 1200;
+ static final long BATCH_FINALIZATION_TIMEOUT_MS = TimeUnit.MINUTES.toMillis(90);
+
+ static final int LOG_NETWORK_EVENT_MSG = 1;
+ static final int FINALIZE_BATCH_MSG = 2;
+
+ private final DevicePolicyManagerService mDpm;
+
+ // threadsafe as it's Handler's thread confined
+ private ArrayList<NetworkEvent> mNetworkEvents = new ArrayList<NetworkEvent>();
+
+ @GuardedBy("this")
+ private ArrayList<NetworkEvent> mFullBatch;
+
+ NetworkLoggingHandler(Looper looper, DevicePolicyManagerService dpm) {
+ super(looper);
+ mDpm = dpm;
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case LOG_NETWORK_EVENT_MSG: {
+ NetworkEvent networkEvent = msg.getData().getParcelable(NETWORK_EVENT_KEY);
+ if (networkEvent != null) {
+ mNetworkEvents.add(networkEvent);
+ if (mNetworkEvents.size() >= MAX_EVENTS_PER_BATCH) {
+ finalizeBatchAndNotifyDeviceOwner();
+ }
+ }
+ break;
+ }
+ case FINALIZE_BATCH_MSG: {
+ finalizeBatchAndNotifyDeviceOwner();
+ break;
+ }
+ }
+ }
+
+ void scheduleBatchFinalization(long delay) {
+ removeMessages(FINALIZE_BATCH_MSG);
+ sendMessageDelayed(obtainMessage(FINALIZE_BATCH_MSG), delay);
+ }
+
+ private synchronized void finalizeBatchAndNotifyDeviceOwner() {
+ mFullBatch = mNetworkEvents;
+ // start a new batch from scratch
+ mNetworkEvents = new ArrayList<NetworkEvent>();
+ scheduleBatchFinalization(BATCH_FINALIZATION_TIMEOUT_MS);
+ // notify DO that there's a new non-empty batch waiting
+ if (mFullBatch.size() > 0) {
+ mDpm.sendDeviceOwnerCommand(DeviceAdminReceiver.ACTION_NETWORK_LOGS_AVAILABLE,
+ /* extras */ null);
+ } else {
+ mFullBatch = null;
+ }
+ }
+
+ synchronized List<NetworkEvent> retrieveFullLogBatch() {
+ List<NetworkEvent> ret = mFullBatch;
+ mFullBatch = null;
+ return ret;
+ }
+}
+
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/NetworkEventTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/NetworkEventTest.java
new file mode 100644
index 000000000000..315d37cbd662
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/NetworkEventTest.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.devicepolicy;
+
+import android.app.admin.ConnectEvent;
+import android.app.admin.DnsEvent;
+import android.os.Parcel;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import static junit.framework.Assert.assertEquals;
+
+@SmallTest
+public class NetworkEventTest extends DpmTestBase {
+
+ /**
+ * Test parceling and unparceling of a ConnectEvent.
+ */
+ public void testConnectEventParceling() {
+ ConnectEvent event = new ConnectEvent("127.0.0.1", 80, "com.android.whateverdude", 100000);
+ Parcel p = Parcel.obtain();
+ p.writeParcelable(event, 0);
+ p.setDataPosition(0);
+ ConnectEvent unparceledEvent = p.readParcelable(NetworkEventTest.class.getClassLoader());
+ p.recycle();
+ assertEquals(event.getIpAddress(), unparceledEvent.getIpAddress());
+ assertEquals(event.getPort(), unparceledEvent.getPort());
+ assertEquals(event.getPackageName(), unparceledEvent.getPackageName());
+ assertEquals(event.getTimestamp(), unparceledEvent.getTimestamp());
+ }
+
+ /**
+ * Test parceling and unparceling of a DnsEvent.
+ */
+ public void testDnsEventParceling() {
+ DnsEvent event = new DnsEvent("d.android.com", new String[]{"192.168.0.1", "127.0.0.1"}, 2,
+ "com.android.whateverdude", 100000);
+ Parcel p = Parcel.obtain();
+ p.writeParcelable(event, 0);
+ p.setDataPosition(0);
+ DnsEvent unparceledEvent = p.readParcelable(NetworkEventTest.class.getClassLoader());
+ p.recycle();
+ assertEquals(event.getHostname(), unparceledEvent.getHostname());
+ assertEquals(event.getIpAddresses()[0], unparceledEvent.getIpAddresses()[0]);
+ assertEquals(event.getIpAddresses()[1], unparceledEvent.getIpAddresses()[1]);
+ assertEquals(event.getIpAddressesCount(), unparceledEvent.getIpAddressesCount());
+ assertEquals(event.getPackageName(), unparceledEvent.getPackageName());
+ assertEquals(event.getTimestamp(), unparceledEvent.getTimestamp());
+ }
+}
diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp
index 9b62e14d96a2..2e34197e97aa 100644
--- a/tools/aapt/Command.cpp
+++ b/tools/aapt/Command.cpp
@@ -803,7 +803,7 @@ int doDump(Bundle* bundle)
ResXMLTree tree(dynamicRefTable);
asset = assets.openNonAsset(assetsCookie, resname, Asset::ACCESS_BUFFER);
if (asset == NULL) {
- fprintf(stderr, "ERROR: dump failed because resource %s found\n", resname);
+ fprintf(stderr, "ERROR: dump failed because resource %s not found\n", resname);
goto bail;
}