1 /* 2 * Copyright (C) 2012 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.settings; 18 19 import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; 20 21 import android.appwidget.AppWidgetManager; 22 import android.appwidget.AppWidgetProviderInfo; 23 import android.content.ComponentName; 24 import android.content.Context; 25 import android.content.DialogInterface; 26 import android.content.Intent; 27 import android.content.pm.ApplicationInfo; 28 import android.content.pm.PackageManager; 29 import android.os.Bundle; 30 import android.os.UserHandle; 31 import android.util.Log; 32 import android.view.LayoutInflater; 33 import android.widget.CheckBox; 34 35 import androidx.appcompat.app.AlertDialog; 36 37 import com.android.internal.app.AlertActivity; 38 import com.android.internal.app.AlertController; 39 40 /** 41 * This activity is displayed when an app launches the BIND_APPWIDGET intent. This allows apps 42 * that don't have the BIND_APPWIDGET permission to bind specific widgets. 43 */ 44 public class AllowBindAppWidgetActivity extends AlertActivity implements 45 DialogInterface.OnClickListener { 46 47 private CheckBox mAlwaysUse; 48 private int mAppWidgetId; 49 private Bundle mBindOptions; 50 private UserHandle mProfile; 51 private ComponentName mComponentName; 52 private String mCallingPackage; 53 private AppWidgetManager mAppWidgetManager; 54 55 // Indicates whether this activity was closed because of a click 56 private boolean mClicked; 57 onClick(DialogInterface dialog, int which)58 public void onClick(DialogInterface dialog, int which) { 59 mClicked = true; 60 if (which == AlertDialog.BUTTON_POSITIVE) { 61 if (mAppWidgetId != -1 && mComponentName != null && mCallingPackage != null) { 62 try { 63 final boolean bound = mAppWidgetManager.bindAppWidgetIdIfAllowed(mAppWidgetId, 64 mProfile, mComponentName, mBindOptions); 65 if (bound) { 66 Intent result = new Intent(); 67 result.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId); 68 setResult(RESULT_OK, result); 69 } 70 } catch (Exception e) { 71 Log.v("BIND_APPWIDGET", "Error binding widget with id " 72 + mAppWidgetId + " and component " + mComponentName); 73 } 74 75 final boolean alwaysAllowBind = mAlwaysUse.isChecked(); 76 if (alwaysAllowBind != mAppWidgetManager.hasBindAppWidgetPermission( 77 mCallingPackage)) { 78 mAppWidgetManager.setBindAppWidgetPermission(mCallingPackage, 79 alwaysAllowBind); 80 } 81 } 82 } 83 finish(); 84 } 85 86 @Override onPause()87 protected void onPause() { 88 if (!mClicked) { // RESULT_CANCELED 89 finish(); 90 } 91 super.onPause(); 92 } 93 94 @Override onCreate(Bundle savedInstanceState)95 protected void onCreate(Bundle savedInstanceState) { 96 super.onCreate(savedInstanceState); 97 getWindow().addPrivateFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); 98 setResult(RESULT_CANCELED); // By default, set the result to cancelled 99 Intent intent = getIntent(); 100 CharSequence label = ""; 101 if (intent != null) { 102 try { 103 mAppWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1); 104 mProfile = intent.getParcelableExtra( 105 AppWidgetManager.EXTRA_APPWIDGET_PROVIDER_PROFILE); 106 if (mProfile == null) { 107 mProfile = android.os.Process.myUserHandle(); 108 } 109 mComponentName = 110 intent.getParcelableExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER); 111 mBindOptions = 112 intent.getParcelableExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS); 113 mCallingPackage = getCallingPackage(); 114 PackageManager pm = getPackageManager(); 115 ApplicationInfo ai = pm.getApplicationInfo(mCallingPackage, 0); 116 label = pm.getApplicationLabel(ai); 117 } catch (Exception e) { 118 mAppWidgetId = -1; 119 mComponentName = null; 120 mCallingPackage = null; 121 Log.v("BIND_APPWIDGET", "Error getting parameters"); 122 finish(); 123 return; 124 } 125 } 126 mAppWidgetManager = AppWidgetManager.getInstance(this); 127 final String widgetLabel = getWidgetLabel(); 128 AlertController.AlertParams ap = mAlertParams; 129 ap.mTitle = getString(R.string.allow_bind_app_widget_activity_allow_bind_title); 130 ap.mMessage = getString(R.string.allow_bind_app_widget_activity_allow_bind, label, 131 widgetLabel); 132 ap.mPositiveButtonText = getString(R.string.create); 133 ap.mNegativeButtonText = getString(android.R.string.cancel); 134 ap.mPositiveButtonListener = this; 135 ap.mNegativeButtonListener = this; 136 LayoutInflater inflater = 137 (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); 138 ap.mView = inflater.inflate(com.android.internal.R.layout.always_use_checkbox, null); 139 mAlwaysUse = (CheckBox) ap.mView.findViewById(com.android.internal.R.id.alwaysUse); 140 mAlwaysUse.setText( 141 getString(R.string.allow_bind_app_widget_activity_always_allow_bind, label)); 142 143 mAlwaysUse.setPadding(mAlwaysUse.getPaddingLeft(), 144 mAlwaysUse.getPaddingTop(), 145 mAlwaysUse.getPaddingRight(), 146 (int) (mAlwaysUse.getPaddingBottom() + 147 getResources().getDimension( 148 R.dimen.bind_app_widget_dialog_checkbox_bottom_padding))); 149 150 mAlwaysUse.setChecked(mAppWidgetManager.hasBindAppWidgetPermission(mCallingPackage, 151 mProfile.getIdentifier())); 152 153 setupAlert(); 154 } 155 getWidgetLabel()156 private String getWidgetLabel() { 157 String label = ""; 158 for (AppWidgetProviderInfo providerInfo : mAppWidgetManager.getInstalledProviders()) { 159 if (providerInfo.provider.equals(mComponentName)) { 160 label = providerInfo.loadLabel(getPackageManager()); 161 break; 162 } 163 } 164 return label; 165 } 166 } 167