diff options
7 files changed, 85 insertions, 8 deletions
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index c2197b55ef97..2bcf9f22611d 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -6637,13 +6637,15 @@ public class DevicePolicyManager { /** * Return whether network logging is enabled by a device owner. * - * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Can only + * be {@code null} if the caller has MANAGE_USERS permission. * @return {@code true} if network logging is enabled by device owner, {@code false} otherwise. - * @throws {@link SecurityException} if {@code admin} is not a device owner. + * @throws {@link SecurityException} if {@code admin} is not a device owner and caller has + * no MANAGE_USERS permission * * @hide */ - public boolean isNetworkLoggingEnabled(@NonNull ComponentName admin) { + public boolean isNetworkLoggingEnabled(@Nullable ComponentName admin) { throwIfParentInstance("isNetworkLoggingEnabled"); try { return mService.isNetworkLoggingEnabled(admin); diff --git a/packages/SystemUI/res/drawable/ic_qs_network_logging.xml b/packages/SystemUI/res/drawable/ic_qs_network_logging.xml new file mode 100644 index 000000000000..8200fcb2ca10 --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_qs_network_logging.xml @@ -0,0 +1,29 @@ +<!-- +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. +--> + +<!-- Placeholder icon for network logging until the real icon is finalized--> + +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="12.0dp" + android:height="12.0dp" + android:viewportWidth="24.0" + android:viewportHeight="24.0" + android:tint="#4DFFFFFF" > + <path + android:fillColor="#FFFFFFFF" + android:pathData="M7,18v-2h6v2H7z M7,14v-2h10v2H7z M8.5,9 12,5.5 15.5,9 13,9 13,13 11,13 11,9z"/> + +</vector> diff --git a/packages/SystemUI/res/layout/quick_settings_footer.xml b/packages/SystemUI/res/layout/quick_settings_footer.xml index 53baf74ffee9..8667a5a8f5cd 100644 --- a/packages/SystemUI/res/layout/quick_settings_footer.xml +++ b/packages/SystemUI/res/layout/quick_settings_footer.xml @@ -39,4 +39,16 @@ android:src="@drawable/ic_qs_vpn" android:visibility="invisible" /> -</RelativeLayout>
\ No newline at end of file + <!-- Only shown if both images are visible --> + <ImageView + android:id="@+id/footer_icon2" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_centerVertical="true" + android:layout_marginEnd="8dp" + android:layout_toStartOf="@id/footer_icon" + android:contentDescription="@null" + android:src="@drawable/ic_qs_network_logging" + android:visibility="invisible" /> + +</RelativeLayout> diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java index ccb28e95802e..756513b61c45 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java @@ -46,6 +46,7 @@ public class QSFooter implements OnClickListener, DialogInterface.OnClickListene private final View mRootView; private final TextView mFooterText; private final ImageView mFooterIcon; + private final ImageView mFooterIcon2; private final Context mContext; private final Callback mCallback = new Callback(); @@ -57,8 +58,10 @@ public class QSFooter implements OnClickListener, DialogInterface.OnClickListene private boolean mIsVisible; private boolean mIsIconVisible; + private boolean mIsIcon2Visible; private int mFooterTextId; private int mFooterIconId; + private int mFooterIcon2Id; public QSFooter(QSPanel qsPanel, Context context) { mRootView = LayoutInflater.from(context) @@ -66,7 +69,9 @@ public class QSFooter implements OnClickListener, DialogInterface.OnClickListene mRootView.setOnClickListener(this); mFooterText = (TextView) mRootView.findViewById(R.id.footer_text); mFooterIcon = (ImageView) mRootView.findViewById(R.id.footer_icon); + mFooterIcon2 = (ImageView) mRootView.findViewById(R.id.footer_icon2); mFooterIconId = R.drawable.ic_qs_vpn; + mFooterIcon2Id = R.drawable.ic_qs_network_logging; mContext = context; mMainHandler = new Handler(); } @@ -113,17 +118,29 @@ public class QSFooter implements OnClickListener, DialogInterface.OnClickListene } private void handleRefreshState() { - mIsIconVisible = mSecurityController.isVpnEnabled(); // If the device has device owner, show "Device may be monitored", but -- // TODO See b/25779452 -- device owner doesn't actually have monitoring power. + boolean isVpnEnabled = mSecurityController.isVpnEnabled(); + boolean isNetworkLoggingEnabled = mSecurityController.isNetworkLoggingEnabled(); + mIsIconVisible = isVpnEnabled || isNetworkLoggingEnabled; + mIsIcon2Visible = isVpnEnabled && isNetworkLoggingEnabled; if (mSecurityController.isDeviceManaged()) { mFooterTextId = R.string.device_owned_footer; mIsVisible = true; + int footerIconId = isVpnEnabled + ? R.drawable.ic_qs_vpn + : R.drawable.ic_qs_network_logging; + if (mFooterIconId != footerIconId) { + mFooterIconId = footerIconId; + mMainHandler.post(mUpdateIcon); + } } else { boolean isBranded = mSecurityController.isVpnBranded(); mFooterTextId = isBranded ? R.string.branded_vpn_footer : R.string.vpn_footer; // Update the VPN footer icon, if needed. - int footerIconId = isBranded ? R.drawable.ic_qs_branded_vpn : R.drawable.ic_qs_vpn; + int footerIconId = isVpnEnabled + ? (isBranded ? R.drawable.ic_qs_branded_vpn : R.drawable.ic_qs_vpn) + : R.drawable.ic_qs_network_logging; if (mFooterIconId != footerIconId) { mFooterIconId = footerIconId; mMainHandler.post(mUpdateIcon); @@ -219,6 +236,7 @@ public class QSFooter implements OnClickListener, DialogInterface.OnClickListene @Override public void run() { mFooterIcon.setImageResource(mFooterIconId); + mFooterIcon2.setImageResource(mFooterIcon2Id); } }; @@ -230,6 +248,7 @@ public class QSFooter implements OnClickListener, DialogInterface.OnClickListene } mRootView.setVisibility(mIsVisible ? View.VISIBLE : View.GONE); mFooterIcon.setVisibility(mIsIconVisible ? View.VISIBLE : View.INVISIBLE); + mFooterIcon2.setVisibility(mIsIcon2Visible ? View.VISIBLE : View.INVISIBLE); } }; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityController.java index 014afae7bf5a..63d4381e4aaa 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityController.java @@ -21,6 +21,7 @@ public interface SecurityController { boolean hasProfileOwner(); String getDeviceOwnerName(); String getProfileOwnerName(); + boolean isNetworkLoggingEnabled(); boolean isVpnEnabled(); boolean isVpnRestricted(); /** Whether the VPN app should use branded VPN iconography. */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java index 07d3b596bc05..65a119ac0f1c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java @@ -154,6 +154,11 @@ public class SecurityControllerImpl implements SecurityController { } @Override + public boolean isNetworkLoggingEnabled() { + return mDevicePolicyManager.isNetworkLoggingEnabled(null); + } + + @Override public boolean isVpnEnabled() { for (int profileId : mUserManager.getProfileIdsWithDisabled(mVpnUserId)) { if (mCurrentVpns.get(profileId) != null) { diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 232300a2e70c..8189a7ec3b08 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -6531,6 +6531,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } + private void enforceDeviceOwnerOrManageUsers() { + synchronized (this) { + if (getActiveAdminWithPolicyForUidLocked(null, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER, + mInjector.binderGetCallingUid()) != null) { + return; + } + } + enforceManageUsers(); + } + private void ensureCallerPackage(@Nullable String packageName) { if (packageName == null) { Preconditions.checkState(isCallerWithSystemUid(), @@ -9488,9 +9498,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (!mHasFeature) { return false; } - Preconditions.checkNotNull(admin); synchronized (this) { - getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER); + enforceDeviceOwnerOrManageUsers(); return isNetworkLoggingEnabledInternalLocked(); } } |