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