AppInfoBase.java revision a8cac7a409957830c3e05acf346824ca47754a34
1/* 2 * Copyright (C) 2015 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 17package com.android.settings.applications; 18 19import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; 20 21import android.app.Activity; 22import android.app.AlertDialog; 23import android.app.Dialog; 24import android.app.DialogFragment; 25import android.app.Fragment; 26import android.app.admin.DevicePolicyManager; 27import android.content.BroadcastReceiver; 28import android.content.Context; 29import android.content.Intent; 30import android.content.IntentFilter; 31import android.content.pm.PackageInfo; 32import android.content.pm.PackageManager; 33import android.content.pm.PackageManager.NameNotFoundException; 34import android.hardware.usb.IUsbManager; 35import android.os.Bundle; 36import android.os.IBinder; 37import android.os.ServiceManager; 38import android.os.UserHandle; 39import android.os.UserManager; 40import android.text.TextUtils; 41import android.util.Log; 42 43import com.android.internal.logging.nano.MetricsProto; 44import com.android.settings.SettingsActivity; 45import com.android.settings.SettingsPreferenceFragment; 46import com.android.settings.Utils; 47import com.android.settings.applications.manageapplications.ManageApplications; 48import com.android.settings.core.instrumentation.InstrumentedDialogFragment; 49import com.android.settings.overlay.FeatureFactory; 50import com.android.settings.wrapper.DevicePolicyManagerWrapper; 51import com.android.settingslib.RestrictedLockUtils; 52import com.android.settingslib.applications.ApplicationsState; 53import com.android.settingslib.applications.ApplicationsState.AppEntry; 54 55import java.util.ArrayList; 56 57public abstract class AppInfoBase extends SettingsPreferenceFragment 58 implements ApplicationsState.Callbacks { 59 60 public static final String ARG_PACKAGE_NAME = "package"; 61 public static final String ARG_PACKAGE_UID = "uid"; 62 63 protected static final String TAG = AppInfoBase.class.getSimpleName(); 64 protected static final boolean localLOGV = false; 65 66 protected EnforcedAdmin mAppsControlDisallowedAdmin; 67 protected boolean mAppsControlDisallowedBySystem; 68 69 protected ApplicationFeatureProvider mApplicationFeatureProvider; 70 protected ApplicationsState mState; 71 protected ApplicationsState.Session mSession; 72 protected ApplicationsState.AppEntry mAppEntry; 73 protected PackageInfo mPackageInfo; 74 protected int mUserId; 75 protected String mPackageName; 76 77 protected IUsbManager mUsbManager; 78 protected DevicePolicyManagerWrapper mDpm; 79 protected UserManager mUserManager; 80 protected PackageManager mPm; 81 82 // Dialog identifiers used in showDialog 83 protected static final int DLG_BASE = 0; 84 85 protected boolean mFinishing; 86 protected boolean mListeningToPackageRemove; 87 88 @Override 89 public void onCreate(Bundle savedInstanceState) { 90 super.onCreate(savedInstanceState); 91 mFinishing = false; 92 final Activity activity = getActivity(); 93 mApplicationFeatureProvider = FeatureFactory.getFactory(activity) 94 .getApplicationFeatureProvider(activity); 95 mState = ApplicationsState.getInstance(activity.getApplication()); 96 mSession = mState.newSession(this, getLifecycle()); 97 mDpm = new DevicePolicyManagerWrapper( 98 (DevicePolicyManager) activity.getSystemService(Context.DEVICE_POLICY_SERVICE)); 99 mUserManager = (UserManager) activity.getSystemService(Context.USER_SERVICE); 100 mPm = activity.getPackageManager(); 101 IBinder b = ServiceManager.getService(Context.USB_SERVICE); 102 mUsbManager = IUsbManager.Stub.asInterface(b); 103 104 retrieveAppEntry(); 105 startListeningToPackageRemove(); 106 } 107 108 @Override 109 public void onResume() { 110 super.onResume(); 111 mAppsControlDisallowedAdmin = RestrictedLockUtils.checkIfRestrictionEnforced(getActivity(), 112 UserManager.DISALLOW_APPS_CONTROL, mUserId); 113 mAppsControlDisallowedBySystem = RestrictedLockUtils.hasBaseUserRestriction(getActivity(), 114 UserManager.DISALLOW_APPS_CONTROL, mUserId); 115 116 if (!refreshUi()) { 117 setIntentAndFinish(true, true); 118 } 119 } 120 121 122 @Override 123 public void onDestroy() { 124 stopListeningToPackageRemove(); 125 super.onDestroy(); 126 } 127 128 protected String retrieveAppEntry() { 129 final Bundle args = getArguments(); 130 mPackageName = (args != null) ? args.getString(ARG_PACKAGE_NAME) : null; 131 if (mPackageName == null) { 132 Intent intent = (args == null) ? 133 getActivity().getIntent() : (Intent) args.getParcelable("intent"); 134 if (intent != null) { 135 mPackageName = intent.getData().getSchemeSpecificPart(); 136 } 137 } 138 mUserId = UserHandle.myUserId(); 139 mAppEntry = mState.getEntry(mPackageName, mUserId); 140 if (mAppEntry != null) { 141 // Get application info again to refresh changed properties of application 142 try { 143 mPackageInfo = mPm.getPackageInfo(mAppEntry.info.packageName, 144 PackageManager.MATCH_DISABLED_COMPONENTS | 145 PackageManager.MATCH_ANY_USER | 146 PackageManager.GET_SIGNATURES | 147 PackageManager.GET_PERMISSIONS); 148 } catch (NameNotFoundException e) { 149 Log.e(TAG, "Exception when retrieving package:" + mAppEntry.info.packageName, e); 150 } 151 } else { 152 Log.w(TAG, "Missing AppEntry; maybe reinstalling?"); 153 mPackageInfo = null; 154 } 155 156 return mPackageName; 157 } 158 159 protected void setIntentAndFinish(boolean finish, boolean appChanged) { 160 if (localLOGV) Log.i(TAG, "appChanged="+appChanged); 161 Intent intent = new Intent(); 162 intent.putExtra(ManageApplications.APP_CHG, appChanged); 163 SettingsActivity sa = (SettingsActivity)getActivity(); 164 sa.finishPreferencePanel(this, Activity.RESULT_OK, intent); 165 mFinishing = true; 166 } 167 168 protected void showDialogInner(int id, int moveErrorCode) { 169 DialogFragment newFragment = MyAlertDialogFragment.newInstance(id, moveErrorCode); 170 newFragment.setTargetFragment(this, 0); 171 newFragment.show(getFragmentManager(), "dialog " + id); 172 } 173 174 protected abstract boolean refreshUi(); 175 protected abstract AlertDialog createDialog(int id, int errorCode); 176 177 @Override 178 public void onRunningStateChanged(boolean running) { 179 // No op. 180 } 181 182 @Override 183 public void onRebuildComplete(ArrayList<AppEntry> apps) { 184 // No op. 185 } 186 187 @Override 188 public void onPackageIconChanged() { 189 // No op. 190 } 191 192 @Override 193 public void onPackageSizeChanged(String packageName) { 194 // No op. 195 } 196 197 @Override 198 public void onAllSizesComputed() { 199 // No op. 200 } 201 202 @Override 203 public void onLauncherInfoChanged() { 204 // No op. 205 } 206 207 @Override 208 public void onLoadEntriesCompleted() { 209 // No op. 210 } 211 212 @Override 213 public void onPackageListChanged() { 214 if (!refreshUi()) { 215 setIntentAndFinish(true, true); 216 } 217 } 218 219 public static void startAppInfoFragment(Class<?> fragment, int titleRes, 220 String pkg, int uid, Fragment source, int request, int sourceMetricsCategory) { 221 startAppInfoFragment(fragment, titleRes, pkg, uid, source.getActivity(), request, 222 sourceMetricsCategory); 223 } 224 225 public static void startAppInfoFragment(Class<?> fragment, int titleRes, 226 String pkg, int uid, Activity source, int request, int sourceMetricsCategory) { 227 Bundle args = new Bundle(); 228 args.putString(AppInfoBase.ARG_PACKAGE_NAME, pkg); 229 args.putInt(AppInfoBase.ARG_PACKAGE_UID, uid); 230 231 Intent intent = Utils.onBuildStartFragmentIntent(source, fragment.getName(), 232 args, null, titleRes, null, false, sourceMetricsCategory); 233 source.startActivityForResultAsUser(intent, request, 234 new UserHandle(UserHandle.getUserId(uid))); 235 } 236 237 public static class MyAlertDialogFragment extends InstrumentedDialogFragment { 238 239 private static final String ARG_ID = "id"; 240 241 @Override 242 public int getMetricsCategory() { 243 return MetricsProto.MetricsEvent.DIALOG_APP_INFO_ACTION; 244 } 245 246 @Override 247 public Dialog onCreateDialog(Bundle savedInstanceState) { 248 int id = getArguments().getInt(ARG_ID); 249 int errorCode = getArguments().getInt("moveError"); 250 Dialog dialog = ((AppInfoBase) getTargetFragment()).createDialog(id, errorCode); 251 if (dialog == null) { 252 throw new IllegalArgumentException("unknown id " + id); 253 } 254 return dialog; 255 } 256 257 public static MyAlertDialogFragment newInstance(int id, int errorCode) { 258 MyAlertDialogFragment dialogFragment = new MyAlertDialogFragment(); 259 Bundle args = new Bundle(); 260 args.putInt(ARG_ID, id); 261 args.putInt("moveError", errorCode); 262 dialogFragment.setArguments(args); 263 return dialogFragment; 264 } 265 } 266 267 protected void startListeningToPackageRemove() { 268 if (mListeningToPackageRemove) { 269 return; 270 } 271 mListeningToPackageRemove = true; 272 final IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_REMOVED); 273 filter.addDataScheme("package"); 274 getContext().registerReceiver(mPackageRemovedReceiver, filter); 275 } 276 277 protected void stopListeningToPackageRemove() { 278 if (!mListeningToPackageRemove) { 279 return; 280 } 281 mListeningToPackageRemove = false; 282 getContext().unregisterReceiver(mPackageRemovedReceiver); 283 } 284 285 protected void onPackageRemoved() { 286 getActivity().finishAndRemoveTask(); 287 } 288 289 protected final BroadcastReceiver mPackageRemovedReceiver = new BroadcastReceiver() { 290 @Override 291 public void onReceive(Context context, Intent intent) { 292 String packageName = intent.getData().getSchemeSpecificPart(); 293 if (!mFinishing && (mAppEntry == null || mAppEntry.info == null 294 || TextUtils.equals(mAppEntry.info.packageName, packageName))) { 295 onPackageRemoved(); 296 } 297 } 298 }; 299 300} 301