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