Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fb1b1ab7 authored by Rubin Xu's avatar Rubin Xu Committed by Android (Google) Code Review
Browse files

Merge "Mask work widgets if work profile is in quiet mode."

parents 40e2ce37 cc52ce4b
Loading
Loading
Loading
Loading
+56 −0
Original line number Diff line number Diff line
<?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
+20 −0
Original line number Diff line number Diff line
<?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 −0
Original line number Diff line number Diff line
<?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>
+5 −0
Original line number Diff line number Diff line
@@ -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>
+106 −4
Original line number Diff line number Diff line
@@ -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;
        }
    }

    /**