Merge "Removing the debug header bar icon."
diff --git a/core/res/res/drawable/ic_corp_badge_off.xml b/core/res/res/drawable/ic_corp_badge_off.xml
new file mode 100644
index 0000000..6799bf7
--- /dev/null
+++ b/core/res/res/drawable/ic_corp_badge_off.xml
@@ -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>
\ No newline at end of file
diff --git a/core/res/res/drawable/work_widget_mask_view_background.xml b/core/res/res/drawable/work_widget_mask_view_background.xml
new file mode 100644
index 0000000..17f0dbc
--- /dev/null
+++ b/core/res/res/drawable/work_widget_mask_view_background.xml
@@ -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>
diff --git a/core/res/res/layout/work_widget_mask_view.xml b/core/res/res/layout/work_widget_mask_view.xml
new file mode 100644
index 0000000..ce86ddc
--- /dev/null
+++ b/core/res/res/layout/work_widget_mask_view.xml
@@ -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>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 36ba306..832984e 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -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>
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 25fef18..df18d3e 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -37,6 +37,7 @@
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.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.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 @@
} 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 @@
mCallbackHandler = new CallbackHandler(mContext.getMainLooper());
mBackupRestoreController = new BackupRestoreController();
mSecurityPolicy = new SecurityPolicy();
+
computeMaximumWidgetBitmapMemory();
registerBroadcastReceiver();
registerOnCrossProfileProvidersChangedListener();
@@ -251,8 +265,14 @@
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 @@
}
}
+ /**
+ * 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 @@
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 @@
Binder.getCallingUid(), callingPackage);
if (widget != null) {
- return cloneIfLocalBinder(widget.views);
+ return cloneIfLocalBinder(widget.getEffectiveViewsLocked());
}
return null;
@@ -1554,8 +1628,7 @@
// For a full update we replace the RemoteViews completely.
widget.views = views;
}
-
- scheduleNotifyUpdateAppWidgetLocked(widget, views);
+ scheduleNotifyUpdateAppWidgetLocked(widget, widget.getEffectiveViewsLocked());
}
}
@@ -3536,6 +3609,7 @@
int restoredId; // tracking & remapping any restored state
Provider provider;
RemoteViews views;
+ RemoteViews maskedViews;
Bundle options;
Host host;
@@ -3543,6 +3617,34 @@
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;
+ }
}
/**