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