• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
20 
21 import android.app.Activity;
22 import android.app.Dialog;
23 import android.app.admin.DevicePolicyManager;
24 import android.app.settings.SettingsEnums;
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.ApplicationInfo;
30 import android.content.pm.PackageInfo;
31 import android.content.pm.PackageManager;
32 import android.content.pm.PackageManager.NameNotFoundException;
33 import android.hardware.usb.IUsbManager;
34 import android.os.Bundle;
35 import android.os.IBinder;
36 import android.os.ServiceManager;
37 import android.os.UserHandle;
38 import android.os.UserManager;
39 import android.text.TextUtils;
40 import android.util.Log;
41 
42 import androidx.appcompat.app.AlertDialog;
43 import androidx.fragment.app.DialogFragment;
44 import androidx.fragment.app.Fragment;
45 
46 import com.android.settings.SettingsActivity;
47 import com.android.settings.SettingsPreferenceFragment;
48 import com.android.settings.applications.manageapplications.ManageApplications;
49 import com.android.settings.core.SubSettingLauncher;
50 import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
51 import com.android.settings.overlay.FeatureFactory;
52 import com.android.settingslib.RestrictedLockUtilsInternal;
53 import com.android.settingslib.applications.ApplicationsState;
54 import com.android.settingslib.applications.ApplicationsState.AppEntry;
55 
56 import java.util.ArrayList;
57 
58 public abstract class AppInfoBase extends SettingsPreferenceFragment
59         implements ApplicationsState.Callbacks {
60 
61     public static final String ARG_PACKAGE_NAME = "package";
62     public static final String ARG_PACKAGE_UID = "uid";
63 
64     private static final String TAG = "AppInfoBase";
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 DevicePolicyManager 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, getSettingsLifecycle());
97         mDpm = (DevicePolicyManager) activity.getSystemService(Context.DEVICE_POLICY_SERVICE);
98         mUserManager = (UserManager) activity.getSystemService(Context.USER_SERVICE);
99         mPm = activity.getPackageManager();
100         IBinder b = ServiceManager.getService(Context.USB_SERVICE);
101         mUsbManager = IUsbManager.Stub.asInterface(b);
102 
103         retrieveAppEntry();
104         startListeningToPackageRemove();
105     }
106 
107     @Override
onResume()108     public void onResume() {
109         super.onResume();
110         mAppsControlDisallowedAdmin = RestrictedLockUtilsInternal.checkIfRestrictionEnforced(
111                 getActivity(), UserManager.DISALLOW_APPS_CONTROL, mUserId);
112         mAppsControlDisallowedBySystem = RestrictedLockUtilsInternal.hasBaseUserRestriction(
113                 getActivity(), UserManager.DISALLOW_APPS_CONTROL, mUserId);
114 
115         if (!refreshUi()) {
116             setIntentAndFinish(true /* appChanged */);
117         }
118     }
119 
120 
121     @Override
onDestroy()122     public void onDestroy() {
123         stopListeningToPackageRemove();
124         super.onDestroy();
125     }
126 
retrieveAppEntry()127     protected String retrieveAppEntry() {
128         final Bundle args = getArguments();
129         mPackageName = (args != null) ? args.getString(ARG_PACKAGE_NAME) : null;
130         Intent intent = (args == null) ?
131                 getIntent() : (Intent) args.getParcelable("intent");
132         if (mPackageName == null) {
133             if (intent != null && intent.getData() != null) {
134                 mPackageName = intent.getData().getSchemeSpecificPart();
135             }
136         }
137         if (intent != null && intent.hasExtra(Intent.EXTRA_USER_HANDLE)) {
138             mUserId = ((UserHandle) intent.getParcelableExtra(
139                     Intent.EXTRA_USER_HANDLE)).getIdentifier();
140         } else {
141             mUserId = UserHandle.myUserId();
142         }
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.getPackageInfoAsUser(mAppEntry.info.packageName,
148                         PackageManager.MATCH_DISABLED_COMPONENTS |
149                                 PackageManager.GET_SIGNING_CERTIFICATES |
150                                 PackageManager.GET_PERMISSIONS, mUserId);
151             } catch (NameNotFoundException e) {
152                 Log.e(TAG, "Exception when retrieving package:" + mAppEntry.info.packageName, e);
153             }
154         } else {
155             Log.w(TAG, "Missing AppEntry; maybe reinstalling?");
156             mPackageInfo = null;
157         }
158 
159         return mPackageName;
160     }
161 
setIntentAndFinish(boolean appChanged)162     protected void setIntentAndFinish(boolean appChanged) {
163         Log.i(TAG, "appChanged=" + appChanged);
164         Intent intent = new Intent();
165         intent.putExtra(ManageApplications.APP_CHG, appChanged);
166         SettingsActivity sa = (SettingsActivity) getActivity();
167         sa.finishPreferencePanel(Activity.RESULT_OK, intent);
168         mFinishing = true;
169     }
170 
showDialogInner(int id, int moveErrorCode)171     protected void showDialogInner(int id, int moveErrorCode) {
172         DialogFragment newFragment = MyAlertDialogFragment.newInstance(id, moveErrorCode);
173         newFragment.setTargetFragment(this, 0);
174         newFragment.show(getFragmentManager(), "dialog " + id);
175     }
176 
refreshUi()177     protected abstract boolean refreshUi();
178 
createDialog(int id, int errorCode)179     protected abstract AlertDialog createDialog(int id, int errorCode);
180 
181     @Override
onRunningStateChanged(boolean running)182     public void onRunningStateChanged(boolean running) {
183         // No op.
184     }
185 
186     @Override
onRebuildComplete(ArrayList<AppEntry> apps)187     public void onRebuildComplete(ArrayList<AppEntry> apps) {
188         // No op.
189     }
190 
191     @Override
onPackageIconChanged()192     public void onPackageIconChanged() {
193         // No op.
194     }
195 
196     @Override
onPackageSizeChanged(String packageName)197     public void onPackageSizeChanged(String packageName) {
198         // No op.
199     }
200 
201     @Override
onAllSizesComputed()202     public void onAllSizesComputed() {
203         // No op.
204     }
205 
206     @Override
onLauncherInfoChanged()207     public void onLauncherInfoChanged() {
208         // No op.
209     }
210 
211     @Override
onLoadEntriesCompleted()212     public void onLoadEntriesCompleted() {
213         // No op.
214     }
215 
216     @Override
onPackageListChanged()217     public void onPackageListChanged() {
218         if (!refreshUi()) {
219             setIntentAndFinish(true /* appChanged */);
220         }
221     }
222 
startAppInfoFragment(Class<?> fragment, String title, String pkg, int uid, Fragment source, int request, int sourceMetricsCategory)223     public static void startAppInfoFragment(Class<?> fragment, String title,
224             String pkg, int uid, Fragment source, int request, int sourceMetricsCategory) {
225         final Bundle args = new Bundle();
226         args.putString(AppInfoBase.ARG_PACKAGE_NAME, pkg);
227         args.putInt(AppInfoBase.ARG_PACKAGE_UID, uid);
228 
229         new SubSettingLauncher(source.getContext())
230                 .setDestination(fragment.getName())
231                 .setSourceMetricsCategory(sourceMetricsCategory)
232                 .setTitleText(title)
233                 .setArguments(args)
234                 .setUserHandle(new UserHandle(UserHandle.getUserId(uid)))
235                 .setResultListener(source, request)
236                 .launch();
237     }
238 
239     /** Starts app info fragment from SPA pages. */
startAppInfoFragment(Class<?> fragment, String title, ApplicationInfo app, Context context, int sourceMetricsCategory)240     public static void startAppInfoFragment(Class<?> fragment, String title, ApplicationInfo app,
241             Context context, int sourceMetricsCategory) {
242         final Bundle args = new Bundle();
243         args.putString(AppInfoBase.ARG_PACKAGE_NAME, app.packageName);
244         args.putInt(AppInfoBase.ARG_PACKAGE_UID, app.uid);
245 
246         new SubSettingLauncher(context)
247                 .setDestination(fragment.getName())
248                 .setSourceMetricsCategory(sourceMetricsCategory)
249                 .setTitleText(title)
250                 .setArguments(args)
251                 .setUserHandle(UserHandle.getUserHandleForUid(app.uid))
252                 .launch();
253     }
254 
255     public static class MyAlertDialogFragment extends InstrumentedDialogFragment {
256 
257         private static final String ARG_ID = "id";
258 
259         @Override
getMetricsCategory()260         public int getMetricsCategory() {
261             return SettingsEnums.DIALOG_BASE_APP_INFO_ACTION;
262         }
263 
264         @Override
onCreateDialog(Bundle savedInstanceState)265         public Dialog onCreateDialog(Bundle savedInstanceState) {
266             int id = getArguments().getInt(ARG_ID);
267             int errorCode = getArguments().getInt("moveError");
268             Dialog dialog = ((AppInfoBase) getTargetFragment()).createDialog(id, errorCode);
269             if (dialog == null) {
270                 throw new IllegalArgumentException("unknown id " + id);
271             }
272             return dialog;
273         }
274 
newInstance(int id, int errorCode)275         public static MyAlertDialogFragment newInstance(int id, int errorCode) {
276             MyAlertDialogFragment dialogFragment = new MyAlertDialogFragment();
277             Bundle args = new Bundle();
278             args.putInt(ARG_ID, id);
279             args.putInt("moveError", errorCode);
280             dialogFragment.setArguments(args);
281             return dialogFragment;
282         }
283     }
284 
startListeningToPackageRemove()285     protected void startListeningToPackageRemove() {
286         if (mListeningToPackageRemove) {
287             return;
288         }
289         mListeningToPackageRemove = true;
290         final IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_REMOVED);
291         filter.addDataScheme("package");
292         getContext().registerReceiver(mPackageRemovedReceiver, filter);
293     }
294 
stopListeningToPackageRemove()295     protected void stopListeningToPackageRemove() {
296         if (!mListeningToPackageRemove) {
297             return;
298         }
299         mListeningToPackageRemove = false;
300         getContext().unregisterReceiver(mPackageRemovedReceiver);
301     }
302 
onPackageRemoved()303     protected void onPackageRemoved() {
304         getActivity().finishAndRemoveTask();
305     }
306 
307     protected final BroadcastReceiver mPackageRemovedReceiver = new BroadcastReceiver() {
308         @Override
309         public void onReceive(Context context, Intent intent) {
310             String packageName = intent.getData().getSchemeSpecificPart();
311             if (!mFinishing && (mAppEntry == null || mAppEntry.info == null
312                     || TextUtils.equals(mAppEntry.info.packageName, packageName))) {
313                 onPackageRemoved();
314             }
315         }
316     };
317 
318 }
319