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