summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java8
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_network_logging.xml29
-rw-r--r--packages/SystemUI/res/layout/quick_settings_footer.xml14
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSFooter.java24
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityController.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterTest.java49
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java3
8 files changed, 124 insertions, 9 deletions
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index ce10bad7a207..39f415e6ad8f 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -6939,11 +6939,13 @@ 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
*/
- 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..1340ae161729
--- /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 43308def0f4a..f3da47b1ba82 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
@@ -51,6 +51,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();
@@ -62,8 +63,11 @@ public class QSFooter implements OnClickListener, DialogInterface.OnClickListene
private boolean mIsVisible;
private boolean mIsIconVisible;
+ private boolean mIsIcon2Visible;
private CharSequence mFooterTextContent = null;
+ private int mFooterTextId;
private int mFooterIconId;
+ private int mFooterIcon2Id;
public QSFooter(QSPanel qsPanel, Context context) {
mRootView = LayoutInflater.from(context)
@@ -71,7 +75,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(Looper.getMainLooper());
}
@@ -119,7 +125,10 @@ public class QSFooter implements OnClickListener, DialogInterface.OnClickListene
}
private void handleRefreshState() {
- mIsIconVisible = mSecurityController.isVpnEnabled();
+ boolean isVpnEnabled = mSecurityController.isVpnEnabled();
+ boolean isNetworkLoggingEnabled = mSecurityController.isNetworkLoggingEnabled();
+ mIsIconVisible = isVpnEnabled || isNetworkLoggingEnabled;
+ mIsIcon2Visible = isVpnEnabled && isNetworkLoggingEnabled;
if (mSecurityController.isDeviceManaged()) {
final CharSequence organizationName =
mSecurityController.getDeviceOwnerOrganizationName();
@@ -131,12 +140,21 @@ public class QSFooter implements OnClickListener, DialogInterface.OnClickListene
mContext.getResources().getString(R.string.do_disclosure_generic);
}
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();
mFooterTextContent = mContext.getResources().getText(
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);
@@ -258,6 +276,7 @@ public class QSFooter implements OnClickListener, DialogInterface.OnClickListene
@Override
public void run() {
mFooterIcon.setImageResource(mFooterIconId);
+ mFooterIcon2.setImageResource(mFooterIcon2Id);
}
};
@@ -269,6 +288,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 69281b52142c..3142228551b6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityController.java
@@ -24,6 +24,7 @@ public interface SecurityController extends CallbackController<SecurityControlle
String getDeviceOwnerName();
String getProfileOwnerName();
CharSequence getDeviceOwnerOrganizationName();
+ 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 142f21b6f847..df959bd722ab 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
@@ -159,6 +159,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/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterTest.java
index 1987009f69de..4c25c62e82a3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterTest.java
@@ -35,9 +35,11 @@ import org.junit.runner.RunWith;
import static junit.framework.Assert.assertEquals;
import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyObject;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
@@ -53,6 +55,8 @@ public class QSFooterTest extends SysuiTestCase {
private ViewGroup mRootView = mock(ViewGroup.class);
private TextView mFooterText = mock(TextView.class);
+ private ImageView mFooterIcon = mock(ImageView.class);
+ private ImageView mFooterIcon2 = mock(ImageView.class);
private QSFooter mFooter;
private Resources mResources;
private SecurityController mSecurityController = mock(SecurityController.class);
@@ -60,7 +64,8 @@ public class QSFooterTest extends SysuiTestCase {
@Before
public void setUp() {
when(mRootView.findViewById(R.id.footer_text)).thenReturn(mFooterText);
- when(mRootView.findViewById(R.id.footer_icon)).thenReturn(mock(ImageView.class));
+ when(mRootView.findViewById(R.id.footer_icon)).thenReturn(mFooterIcon);
+ when(mRootView.findViewById(R.id.footer_icon2)).thenReturn(mFooterIcon2);
final LayoutInflater layoutInflater = mock(LayoutInflater.class);
when(layoutInflater.inflate(eq(R.layout.quick_settings_footer), anyObject(), anyBoolean()))
.thenReturn(mRootView);
@@ -114,6 +119,48 @@ public class QSFooterTest extends SysuiTestCase {
}
@Test
+ public void testNetworkLoggingEnabled() {
+ when(mSecurityController.isDeviceManaged()).thenReturn(true);
+ when(mSecurityController.isNetworkLoggingEnabled()).thenReturn(true);
+ when(mSecurityController.isVpnEnabled()).thenReturn(false);
+ mFooter.refreshState();
+
+ waitForIdleSync(mFooter.mHandler);
+ verify(mFooterIcon).setVisibility(View.VISIBLE);
+ verify(mFooterIcon).setImageResource(R.drawable.ic_qs_network_logging);
+ verify(mFooterIcon2).setVisibility(View.INVISIBLE);
+ }
+
+ @Test
+ public void testVpnEnabled() {
+ when(mSecurityController.isDeviceManaged()).thenReturn(true);
+ when(mSecurityController.isNetworkLoggingEnabled()).thenReturn(false);
+ when(mSecurityController.isVpnEnabled()).thenReturn(true);
+ when(mSecurityController.isVpnBranded()).thenReturn(false);
+ mFooter.refreshState();
+
+ waitForIdleSync(mFooter.mHandler);
+ verify(mFooterIcon).setVisibility(View.VISIBLE);
+ verify(mFooterIcon, never()).setImageResource(anyInt());
+ verify(mFooterIcon2).setVisibility(View.INVISIBLE);
+ }
+
+ @Test
+ public void testNetworkLoggingAndVpnEnabled() {
+ when(mSecurityController.isDeviceManaged()).thenReturn(true);
+ when(mSecurityController.isNetworkLoggingEnabled()).thenReturn(true);
+ when(mSecurityController.isVpnEnabled()).thenReturn(true);
+ when(mSecurityController.isVpnBranded()).thenReturn(false);
+ mFooter.refreshState();
+
+ waitForIdleSync(mFooter.mHandler);
+ verify(mFooterIcon).setVisibility(View.VISIBLE);
+ verify(mFooterIcon, never()).setImageResource(anyInt());
+ verify(mFooterIcon2).setVisibility(View.VISIBLE);
+ verify(mFooterIcon2, never()).setImageResource(anyInt());
+ }
+
+ @Test
public void testGetMessageWithNoOrganizationAndNoVPN() {
assertEquals(getExpectedMessage(false /* hasDeviceOwnerOrganization */, false /* hasVPN */),
mFooter.getMessage(DEVICE_OWNER_PACKAGE,
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 45f369819ea8..6492a23c236a 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -9856,9 +9856,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();
}
}