Home | History | Annotate | Download | only in phone
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.systemui.pip.phone;
     18 
     19 import static android.app.AppOpsManager.MODE_ALLOWED;
     20 import static android.app.AppOpsManager.OP_PICTURE_IN_PICTURE;
     21 
     22 import android.app.AppOpsManager;
     23 import android.app.AppOpsManager.OnOpChangedListener;
     24 import android.app.IActivityManager;
     25 import android.content.ComponentName;
     26 import android.content.Context;
     27 import android.content.pm.ApplicationInfo;
     28 import android.content.pm.PackageManager.NameNotFoundException;
     29 import android.os.Handler;
     30 import android.util.Pair;
     31 
     32 public class PipAppOpsListener {
     33     private static final String TAG = PipAppOpsListener.class.getSimpleName();
     34 
     35     private Context mContext;
     36     private Handler mHandler;
     37     private IActivityManager mActivityManager;
     38     private AppOpsManager mAppOpsManager;
     39 
     40     private PipMotionHelper mMotionHelper;
     41 
     42     private AppOpsManager.OnOpChangedListener mAppOpsChangedListener = new OnOpChangedListener() {
     43         @Override
     44         public void onOpChanged(String op, String packageName) {
     45             try {
     46                 // Dismiss the PiP once the user disables the app ops setting for that package
     47                 final Pair<ComponentName, Integer> topPipActivityInfo =
     48                         PipUtils.getTopPinnedActivity(mContext, mActivityManager);
     49                 if (topPipActivityInfo.first != null) {
     50                     final ApplicationInfo appInfo = mContext.getPackageManager()
     51                             .getApplicationInfoAsUser(packageName, 0, topPipActivityInfo.second);
     52                     if (appInfo.packageName.equals(topPipActivityInfo.first.getPackageName()) &&
     53                             mAppOpsManager.checkOpNoThrow(OP_PICTURE_IN_PICTURE, appInfo.uid,
     54                                     packageName) != MODE_ALLOWED) {
     55                         mHandler.post(() -> mMotionHelper.dismissPip());
     56                     }
     57                 }
     58             } catch (NameNotFoundException e) {
     59                 // Unregister the listener if the package can't be found
     60                 unregisterAppOpsListener();
     61             }
     62         }
     63     };
     64 
     65     public PipAppOpsListener(Context context, IActivityManager activityManager,
     66             PipMotionHelper motionHelper) {
     67         mContext = context;
     68         mHandler = new Handler(mContext.getMainLooper());
     69         mActivityManager = activityManager;
     70         mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
     71         mMotionHelper = motionHelper;
     72     }
     73 
     74     public void onActivityPinned(String packageName) {
     75         // Register for changes to the app ops setting for this package while it is in PiP
     76         registerAppOpsListener(packageName);
     77     }
     78 
     79     public void onActivityUnpinned() {
     80         // Unregister for changes to the previously PiP'ed package
     81         unregisterAppOpsListener();
     82     }
     83 
     84     private void registerAppOpsListener(String packageName) {
     85         mAppOpsManager.startWatchingMode(OP_PICTURE_IN_PICTURE, packageName,
     86                 mAppOpsChangedListener);
     87     }
     88 
     89     private void unregisterAppOpsListener() {
     90         mAppOpsManager.stopWatchingMode(mAppOpsChangedListener);
     91     }
     92 }