diff options
author | Benjamin Franz <bfranz@google.com> | 2015-03-16 17:18:09 +0000 |
---|---|---|
committer | Benjamin Franz <bfranz@google.com> | 2015-04-15 15:57:14 +0100 |
commit | ea2ec97f37c649881f2be8a5cc40bf44080cc632 (patch) | |
tree | 25a5c8898f63b736c73cdb18add1e4b3ef1df67f | |
parent | de77be631184ff1204017c3d8996d7c71aa5cf02 (diff) | |
download | frameworks_base-ea2ec97f37c649881f2be8a5cc40bf44080cc632.zip frameworks_base-ea2ec97f37c649881f2be8a5cc40bf44080cc632.tar.gz frameworks_base-ea2ec97f37c649881f2be8a5cc40bf44080cc632.tar.bz2 |
Introduce device owner API to disable the status bar
Let the device owner disable the status bar to achieve multi-app single purpose
mode. When the status bar is disabled, quick settings, notifications and the
assist gesture are blocked.
Bug: 19533026
Change-Id: I72830798135136e5edc53e5e2221aebb9a7c7d57
7 files changed, 91 insertions, 8 deletions
diff --git a/api/current.txt b/api/current.txt index ea4aaf9..d2d7d95 100644 --- a/api/current.txt +++ b/api/current.txt @@ -5737,6 +5737,7 @@ package android.app.admin { method public void setRestrictionsProvider(android.content.ComponentName, android.content.ComponentName); method public void setScreenCaptureDisabled(android.content.ComponentName, boolean); method public void setSecureSetting(android.content.ComponentName, java.lang.String, java.lang.String); + method public void setStatusBarEnabledState(android.content.ComponentName, boolean); method public int setStorageEncryption(android.content.ComponentName, boolean); method public void setTrustAgentConfiguration(android.content.ComponentName, android.content.ComponentName, android.os.PersistableBundle); method public void setUninstallBlocked(android.content.ComponentName, java.lang.String, boolean); diff --git a/api/system-current.txt b/api/system-current.txt index 1a28546..fcb2ce6 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -5841,6 +5841,7 @@ package android.app.admin { method public void setRestrictionsProvider(android.content.ComponentName, android.content.ComponentName); method public void setScreenCaptureDisabled(android.content.ComponentName, boolean); method public void setSecureSetting(android.content.ComponentName, java.lang.String, java.lang.String); + method public void setStatusBarEnabledState(android.content.ComponentName, boolean); method public int setStorageEncryption(android.content.ComponentName, boolean); method public void setTrustAgentConfiguration(android.content.ComponentName, android.content.ComponentName, android.os.PersistableBundle); method public void setUninstallBlocked(android.content.ComponentName, java.lang.String, boolean); diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index a0a6c4c..44760ce 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -4210,4 +4210,20 @@ public class DevicePolicyManager { return false; } } + + /** + * Called by device owner to set the enabled state of the status bar. Disabling the status + * bar blocks notifications, quick settings and other screen overlays that allow escaping from + * a single use device. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param enabled New state of the status bar. + */ + public void setStatusBarEnabledState(ComponentName admin, boolean enabled) { + try { + mService.setStatusBarEnabledState(admin, enabled); + } catch (RemoteException re) { + Log.w(TAG, "Failed talking with device policy service", re); + } + } } diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index 131b99c..7502e1d 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -223,4 +223,5 @@ interface IDevicePolicyManager { PersistableBundle getOtaPolicy(); boolean setKeyguardEnabledState(in ComponentName admin, boolean enabled); + void setStatusBarEnabledState(in ComponentName who, boolean enabled); } diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl index 6cb839e..87e0603 100644 --- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl +++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl @@ -27,6 +27,7 @@ interface IStatusBarService void expandNotificationsPanel(); void collapsePanels(); void disable(int what, IBinder token, String pkg); + void disableForUser(int what, IBinder token, String pkg, int userId); void setIcon(String slot, String iconPackage, int iconId, int iconLevel, String contentDescription); void setIconVisibility(String slot, boolean visible); void removeIcon(String slot); diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java index f6df757..184224b 100644 --- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java +++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java @@ -79,7 +79,7 @@ public class StatusBarManagerService extends IStatusBarService.Stub { public void binderDied() { Slog.i(TAG, "binder died for pkg=" + pkg); - disableInternal(userId, 0, token, pkg); + disableForUser(0, token, pkg, userId); token.unlinkToDeath(this, 0); } } @@ -194,10 +194,11 @@ public class StatusBarManagerService extends IStatusBarService.Stub { @Override public void disable(int what, IBinder token, String pkg) { - disableInternal(mCurrentUserId, what, token, pkg); + disableForUser(what, token, pkg, mCurrentUserId); } - private void disableInternal(int userId, int what, IBinder token, String pkg) { + @Override + public void disableForUser(int what, IBinder token, String pkg, int userId) { enforceStatusBar(); synchronized (mLock) { diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index c7d2b86..fcf6189 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -32,6 +32,7 @@ import android.app.IActivityManager; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; +import android.app.StatusBarManager; import android.app.admin.DeviceAdminInfo; import android.app.admin.DeviceAdminReceiver; import android.app.admin.DevicePolicyManager; @@ -102,6 +103,7 @@ import android.view.IWindowManager; import com.android.internal.R; import com.android.internal.os.storage.ExternalStorageFormatter; +import com.android.internal.statusbar.IStatusBarService; import com.android.internal.util.FastXmlSerializer; import com.android.internal.util.JournaledFile; import com.android.internal.util.Preconditions; @@ -152,7 +154,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { private static final String DEVICE_POLICIES_XML = "device_policies.xml"; - private static final String LOCK_TASK_COMPONENTS_XML = "lock-task-component"; + private static final String TAG_LOCK_TASK_COMPONENTS = "lock-task-component"; + + private static final String TAG_STATUS_BAR = "statusbar"; + + private static final String ATTR_ENABLED = "enabled"; private static final int REQUEST_EXPIRE_PASSWORD = 5571; @@ -172,6 +178,12 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { private static final String ATTR_DELEGATED_CERT_INSTALLER = "delegated-cert-installer"; + private static final int STATUS_BAR_DISABLE_MASK = + StatusBarManager.DISABLE_EXPAND | + StatusBarManager.DISABLE_NOTIFICATION_ICONS | + StatusBarManager.DISABLE_NOTIFICATION_ALERTS | + StatusBarManager.DISABLE_SEARCH; + private static final Set<String> DEVICE_OWNER_USER_RESTRICTIONS; static { DEVICE_OWNER_USER_RESTRICTIONS = new HashSet(); @@ -237,6 +249,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { // Stores and loads state on device and profile owners. private DeviceOwner mDeviceOwner; + private final Binder mToken = new Binder(); + /** * Whether or not device admin feature is supported. If it isn't return defaults for all * public methods. @@ -287,6 +301,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { // This is the list of component allowed to start lock task mode. final List<String> mLockTaskPackages = new ArrayList<>(); + boolean mStatusBarEnabledState = true; + ComponentName mRestrictionsProvider; String mDelegatedCertInstallerPackage; @@ -1429,9 +1445,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { for (int i=0; i<policy.mLockTaskPackages.size(); i++) { String component = policy.mLockTaskPackages.get(i); - out.startTag(null, LOCK_TASK_COMPONENTS_XML); + out.startTag(null, TAG_LOCK_TASK_COMPONENTS); out.attribute(null, "name", component); - out.endTag(null, LOCK_TASK_COMPONENTS_XML); + out.endTag(null, TAG_LOCK_TASK_COMPONENTS); + } + + if (!policy.mStatusBarEnabledState) { + out.startTag(null, TAG_STATUS_BAR); + out.attribute(null, ATTR_ENABLED, Boolean.toString(policy.mStatusBarEnabledState)); + out.endTag(null, TAG_STATUS_BAR); } out.endTag(null, "policies"); @@ -1552,9 +1574,13 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { policy.mActivePasswordNonLetter = Integer.parseInt( parser.getAttributeValue(null, "nonletter")); XmlUtils.skipCurrentTag(parser); - } else if (LOCK_TASK_COMPONENTS_XML.equals(tag)) { + } else if (TAG_LOCK_TASK_COMPONENTS.equals(tag)) { policy.mLockTaskPackages.add(parser.getAttributeValue(null, "name")); XmlUtils.skipCurrentTag(parser); + } else if (TAG_STATUS_BAR.equals(tag)) { + policy.mStatusBarEnabledState = Boolean.parseBoolean( + parser.getAttributeValue(null, ATTR_ENABLED)); + XmlUtils.skipCurrentTag(parser); } else { Slog.w(LOG_TAG, "Unknown tag: " + tag); XmlUtils.skipCurrentTag(parser); @@ -1679,7 +1705,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (!mHasFeature) { return; } - getUserData(UserHandle.USER_OWNER); + DevicePolicyData policy = getUserData(UserHandle.USER_OWNER); loadDeviceOwner(); cleanUpOldUsers(); // Register an observer for watching for user setup complete. @@ -1696,6 +1722,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { getScreenCaptureDisabled(null, userHandle)); } + if (mDeviceOwner != null && mDeviceOwner.hasDeviceOwner() + && !policy.mStatusBarEnabledState) { + setStatusBarEnabledStateInternal(STATUS_BAR_DISABLE_MASK, UserHandle.USER_OWNER); + } } private void cleanUpOldUsers() { @@ -5830,6 +5860,38 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return true; } + @Override + public void setStatusBarEnabledState(ComponentName who, boolean enabled) { + int userId = UserHandle.getCallingUserId(); + synchronized (this) { + getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER); + DevicePolicyData policy = getUserData(userId); + if (policy.mStatusBarEnabledState != enabled) { + policy.mStatusBarEnabledState = enabled; + setStatusBarEnabledStateInternal( + enabled ? StatusBarManager.DISABLE_NONE : STATUS_BAR_DISABLE_MASK, + userId); + saveSettingsLocked(userId); + } + } + } + + private void setStatusBarEnabledStateInternal(int flags, int userId) { + long ident = Binder.clearCallingIdentity(); + try { + IStatusBarService statusBarService = IStatusBarService.Stub.asInterface( + ServiceManager.checkService(Context.STATUS_BAR_SERVICE)); + if (statusBarService != null) { + statusBarService.disableForUser(flags, mToken, + mDeviceOwner.getDeviceOwnerPackageName(), userId); + } + } catch (RemoteException e) { + Slog.e(LOG_TAG, "Failed to disable the status bar", e); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + /** * We need to update the internal state of whether a user has completed setup once. After * that, we ignore any changes that reset the Settings.Secure.USER_SETUP_COMPLETE changes |