Merge "Mask work widgets if work profile is in quiet mode."
This commit is contained in:
56
core/res/res/drawable/ic_corp_badge_off.xml
Normal file
56
core/res/res/drawable/ic_corp_badge_off.xml
Normal file
@@ -0,0 +1,56 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2015 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.
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="20dp"
|
||||
android:height="20dp"
|
||||
android:viewportWidth="20"
|
||||
android:viewportHeight="20">
|
||||
|
||||
<path
|
||||
android:fillColor="#607D8B"
|
||||
android:pathData="M10,0 C15.5228,0,20,4.47715,20,10 C20,15.5228,15.5228,20,10,20
|
||||
C4.47715,20,0,15.5228,0,10 C0,4.47715,4.47715,0,10,0 Z" />
|
||||
<path
|
||||
android:pathData="M1.91667,1.91667 L18.0833,1.91667 L18.0833,18.0833 L1.91667,18.0833
|
||||
L1.91667,1.91667 Z" />
|
||||
<path
|
||||
android:fillColor="#ffffff"
|
||||
android:pathData="M11.9167,11.9167 L11.4167,11.9167 L11.4167,12.8333 L8.5,12.8333 L8.5,11.9167
|
||||
L4.16667,11.9167 L4.16667,14.3333 C4.16667,14.8333,4.58333,15.25,5.08333,15.25
|
||||
L14.75,15.25 C14.9167,15.25,15,15.25,15.1667,15.1667 L11.9167,11.9167 Z" />
|
||||
<path
|
||||
android:fillColor="#ffffff"
|
||||
android:pathData="M15.8333,13.75 L15.8333,11.9167 L14,11.9167
|
||||
C14.6667,12.6667,15.3333,13.3333,15.8333,13.75 Z" />
|
||||
<path
|
||||
android:fillColor="#ffffff"
|
||||
android:pathData="M6.16667,6.16667 L4.66667,6.16667 C4.16667,6.16667,3.75,6.58333,3.75,7.08333
|
||||
L3.75,10 C3.75,10.5,4.16667,10.9167,4.66667,10.9167 L8.5,10.9167 L8.5,10 L10,10
|
||||
L6.16667,6.16667 Z" />
|
||||
<path
|
||||
android:fillColor="#ffffff"
|
||||
android:pathData="M8.08333,6 L8.08333,5.16667 L11.9167,5.16667 L11.9167,6.08333 L8.16667,6.08333
|
||||
C9.66667,7.58333,11.4167,9.33333,12.9167,10.8333 L15.25,10.8333
|
||||
C15.75,10.8333,16.1667,10.4167,16.1667,9.91667 L16.1667,7.08333
|
||||
C16.1667,6.58333,15.75,6.16667,15.25,6.16667 L12.8333,6.16667 L12.8333,5.25
|
||||
L11.9167,4.33333 L8.08333,4.33333 L7.16667,5.16667
|
||||
C7.41667,5.41667,7.75,5.75,8.08333,6 Z" />
|
||||
<path
|
||||
android:fillColor="#ffffff"
|
||||
android:pathData="M15.6824,15.676 L14.6807,16.6777 L3.24921,5.24624 L4.25093,4.24452
|
||||
L15.6824,15.676 Z" />
|
||||
</vector>
|
||||
20
core/res/res/drawable/work_widget_mask_view_background.xml
Normal file
20
core/res/res/drawable/work_widget_mask_view_background.xml
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2015 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.
|
||||
-->
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
|
||||
<padding android:left="5dp" android:right="5dp" android:top="5dp" android:bottom="5dp"/>
|
||||
<stroke android:width="1dp" android:color="#CCCCCC" />
|
||||
</shape>
|
||||
34
core/res/res/layout/work_widget_mask_view.xml
Normal file
34
core/res/res/layout/work_widget_mask_view.xml
Normal file
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2015 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.
|
||||
-->
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#F3374248" >
|
||||
|
||||
<ImageView android:id="@+id/work_widget_app_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"/>
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|right"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:layout_marginRight="4dp"
|
||||
android:src="@drawable/ic_corp_badge_off" />
|
||||
</FrameLayout>
|
||||
@@ -1243,6 +1243,7 @@
|
||||
<java-symbol type="drawable" name="cling_arrow_up" />
|
||||
<java-symbol type="drawable" name="cling_bg" />
|
||||
<java-symbol type="drawable" name="ic_corp_badge" />
|
||||
<java-symbol type="drawable" name="ic_corp_badge_off" />
|
||||
<java-symbol type="drawable" name="ic_corp_icon_badge" />
|
||||
<java-symbol type="drawable" name="ic_corp_icon" />
|
||||
<java-symbol type="drawable" name="ic_corp_statusbar_icon" />
|
||||
@@ -2384,4 +2385,8 @@
|
||||
<java-symbol type="dimen" name="notification_content_margin_top" />
|
||||
<java-symbol type="string" name="importance_from_topic" />
|
||||
<java-symbol type="string" name="importance_from_person" />
|
||||
|
||||
<java-symbol type="layout" name="work_widget_mask_view" />
|
||||
<java-symbol type="id" name="work_widget_app_icon" />
|
||||
<java-symbol type="drawable" name="work_widget_mask_view_background" />
|
||||
</resources>
|
||||
|
||||
@@ -37,6 +37,7 @@ import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.IPackageManager;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.content.pm.ParceledListSlice;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.pm.ServiceInfo;
|
||||
@@ -44,7 +45,10 @@ import android.content.pm.UserInfo;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.content.res.XmlResourceParser;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Binder;
|
||||
import android.os.Bundle;
|
||||
@@ -79,6 +83,7 @@ import com.android.internal.os.SomeArgs;
|
||||
import com.android.internal.util.FastXmlSerializer;
|
||||
import com.android.internal.widget.IRemoteViewsAdapterConnection;
|
||||
import com.android.internal.widget.IRemoteViewsFactory;
|
||||
import com.android.internal.R;
|
||||
import com.android.server.LocalServices;
|
||||
import com.android.server.WidgetBackupProvider;
|
||||
|
||||
@@ -149,6 +154,14 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
|
||||
} else if (Intent.ACTION_USER_STOPPED.equals(action)) {
|
||||
onUserStopped(intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
|
||||
UserHandle.USER_NULL));
|
||||
} else if (Intent.ACTION_USER_SWITCHED.equals(action)) {
|
||||
refreshProfileWidgetsMaskedState(intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
|
||||
UserHandle.USER_NULL));
|
||||
} else if (Intent.ACTION_MANAGED_PROFILE_AVAILABILITY_CHANGED.equals(action)) {
|
||||
UserHandle profile = (UserHandle)intent.getParcelableExtra(Intent.EXTRA_USER);
|
||||
if (profile != null) {
|
||||
refreshWidgetMaskedState(profile.getIdentifier());
|
||||
}
|
||||
} else {
|
||||
onPackageBroadcastReceived(intent, intent.getIntExtra(
|
||||
Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL));
|
||||
@@ -208,6 +221,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
|
||||
mCallbackHandler = new CallbackHandler(mContext.getMainLooper());
|
||||
mBackupRestoreController = new BackupRestoreController();
|
||||
mSecurityPolicy = new SecurityPolicy();
|
||||
|
||||
computeMaximumWidgetBitmapMemory();
|
||||
registerBroadcastReceiver();
|
||||
registerOnCrossProfileProvidersChangedListener();
|
||||
@@ -251,8 +265,14 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
|
||||
IntentFilter userFilter = new IntentFilter();
|
||||
userFilter.addAction(Intent.ACTION_USER_STARTED);
|
||||
userFilter.addAction(Intent.ACTION_USER_STOPPED);
|
||||
userFilter.addAction(Intent.ACTION_USER_SWITCHED);
|
||||
mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,
|
||||
userFilter, null, null);
|
||||
|
||||
IntentFilter offModeFilter = new IntentFilter();
|
||||
offModeFilter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABILITY_CHANGED);
|
||||
mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,
|
||||
offModeFilter, null, null);
|
||||
}
|
||||
|
||||
private void registerOnCrossProfileProvidersChangedListener() {
|
||||
@@ -395,6 +415,60 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh the masked state for all profiles under the given user.
|
||||
*/
|
||||
private void refreshProfileWidgetsMaskedState(int userId) {
|
||||
if (userId == UserHandle.USER_NULL) {
|
||||
return;
|
||||
}
|
||||
List<UserInfo> profiles = mUserManager.getEnabledProfiles(userId);
|
||||
if (profiles != null) {
|
||||
for (int i = 0; i < profiles.size(); i++) {
|
||||
UserInfo user = profiles.get(i);
|
||||
refreshWidgetMaskedState(user.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mask/unmask widgets in the given profile, depending on the quiet state of the profile.
|
||||
*/
|
||||
private void refreshWidgetMaskedState(int profileId) {
|
||||
final long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
UserInfo user = mUserManager.getUserInfo(profileId);
|
||||
if (!user.isManagedProfile()) {
|
||||
return;
|
||||
}
|
||||
boolean shouldMask = user.isQuietModeEnabled();
|
||||
final int iconSize = (int) mContext.getResources().getDimension(
|
||||
android.R.dimen.app_icon_size);
|
||||
synchronized (mLock) {
|
||||
final int N = mProviders.size();
|
||||
for (int i = 0; i < N; i++) {
|
||||
Provider provider = mProviders.get(i);
|
||||
int providerUserId = provider.getUserId();
|
||||
if (providerUserId == profileId) {
|
||||
final int widgetCount = provider.widgets.size();
|
||||
for (int j = 0; j < widgetCount; j++) {
|
||||
Widget widget = provider.widgets.get(j);
|
||||
if (shouldMask) {
|
||||
widget.replaceWithMaskedViewsLocked(mContext, iconSize);
|
||||
} else {
|
||||
widget.clearMaskedViewsLocked();
|
||||
}
|
||||
scheduleNotifyUpdateAppWidgetLocked(widget,
|
||||
widget.getEffectiveViewsLocked());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
}
|
||||
}
|
||||
|
||||
private void resolveHostUidLocked(String pkg, int uid) {
|
||||
final int N = mHosts.size();
|
||||
for (int i = 0; i < N; i++) {
|
||||
@@ -516,7 +590,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
|
||||
for (int i = 0; i < N; i++) {
|
||||
Widget widget = instances.get(i);
|
||||
updatedIds[i] = widget.appWidgetId;
|
||||
updatedViews.add(cloneIfLocalBinder(widget.views));
|
||||
updatedViews.add(cloneIfLocalBinder(widget.getEffectiveViewsLocked()));
|
||||
}
|
||||
|
||||
return updatedIds;
|
||||
@@ -1128,7 +1202,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
|
||||
Binder.getCallingUid(), callingPackage);
|
||||
|
||||
if (widget != null) {
|
||||
return cloneIfLocalBinder(widget.views);
|
||||
return cloneIfLocalBinder(widget.getEffectiveViewsLocked());
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -1554,8 +1628,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
|
||||
// For a full update we replace the RemoteViews completely.
|
||||
widget.views = views;
|
||||
}
|
||||
|
||||
scheduleNotifyUpdateAppWidgetLocked(widget, views);
|
||||
scheduleNotifyUpdateAppWidgetLocked(widget, widget.getEffectiveViewsLocked());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3536,6 +3609,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
|
||||
int restoredId; // tracking & remapping any restored state
|
||||
Provider provider;
|
||||
RemoteViews views;
|
||||
RemoteViews maskedViews;
|
||||
Bundle options;
|
||||
Host host;
|
||||
|
||||
@@ -3543,6 +3617,34 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
|
||||
public String toString() {
|
||||
return "AppWidgetId{" + appWidgetId + ':' + host + ':' + provider + '}';
|
||||
}
|
||||
|
||||
public void replaceWithMaskedViewsLocked(Context context, int iconSize) {
|
||||
if (maskedViews != null) {
|
||||
return;
|
||||
}
|
||||
maskedViews = new RemoteViews(context.getPackageName(), R.layout.work_widget_mask_view);
|
||||
try {
|
||||
Drawable icon = context.getPackageManager().getApplicationIcon(
|
||||
provider.info.provider.getPackageName());
|
||||
final int width = iconSize;
|
||||
final int height = iconSize;
|
||||
Bitmap iconBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
|
||||
Canvas canvas = new Canvas(iconBitmap);
|
||||
icon.setBounds(0, 0, width, height);
|
||||
icon.draw(canvas);
|
||||
maskedViews.setImageViewBitmap(R.id.work_widget_app_icon, iconBitmap);
|
||||
} catch (NameNotFoundException e) {
|
||||
Slog.e(TAG, "Fail to get application icon", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void clearMaskedViewsLocked() {
|
||||
maskedViews = null;
|
||||
}
|
||||
|
||||
public RemoteViews getEffectiveViewsLocked() {
|
||||
return maskedViews != null ? maskedViews : views;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user