diff options
author | TreeHugger Robot <treehugger-gerrit@google.com> | 2016-11-07 23:10:25 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2016-11-07 23:10:25 +0000 |
commit | 04056a844fac399a7b0d26256753f93a49e4a49e (patch) | |
tree | 92abb626fd6cc760239451965dc2d7ad6a3e0c9f | |
parent | 181bec756dd706c4e3f239eb1971f140bc78a768 (diff) | |
parent | 4f78e1fa55255a261247e9a112bc4433cd1a9ab0 (diff) | |
download | android_packages_apps_PackageInstaller-04056a844fac399a7b0d26256753f93a49e4a49e.tar.gz android_packages_apps_PackageInstaller-04056a844fac399a7b0d26256753f93a49e4a49e.tar.bz2 android_packages_apps_PackageInstaller-04056a844fac399a7b0d26256753f93a49e4a49e.zip |
Merge "Uninstaller: For result lifecycle safe"
14 files changed, 397 insertions, 161 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml index ed521b3d..c03d6fbb 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -95,10 +95,26 @@ </intent-filter> </activity> + <receiver android:name=".UninstallEventReceiver" + android:permission="android.permission.INSTALL_PACKAGES" + android:exported="true"> + <intent-filter android:priority="1"> + <action android:name="com.android.packageinstaller.ACTION_UNINSTALL_COMMIT" /> + </intent-filter> + <intent-filter> + <action android:name="android.intent.action.BOOT_COMPLETED" /> + </intent-filter> + </receiver> + + <activity android:name=".UninstallUninstalling" + android:excludeFromRecents="true" + android:theme="@style/AlertDialogActivity" + android:exported="false" /> + <receiver android:name=".UninstallFinish" android:exported="false" /> - <activity android:name=".UninstallAppProgress" + <activity android:name=".television.UninstallAppProgress" android:configChanges="mnc|mnc|touchscreen|navigation|screenLayout|screenSize|smallestScreenSize|orientation|locale|keyboard|keyboardHidden|fontScale|uiMode|layoutDirection|density" android:exported="false" /> diff --git a/res/layout/app_details.xml b/res/layout-television/app_details.xml index 86923c5c..86923c5c 100644 --- a/res/layout/app_details.xml +++ b/res/layout-television/app_details.xml diff --git a/res/layout/uninstall_progress.xml b/res/layout-television/uninstall_progress.xml index e24f63b5..e24f63b5 100644 --- a/res/layout/uninstall_progress.xml +++ b/res/layout-television/uninstall_progress.xml diff --git a/res/values/strings.xml b/res/values/strings.xml index a571beb2..98383343 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -100,6 +100,8 @@ <string name="app_not_found_dlg_text"> The app wasn\'t found in the list of installed apps.</string> <string name="user_is_not_allowed_dlg_title">Not allowed</string> <string name="user_is_not_allowed_dlg_text">The current user is not allowed to perform this uninstallation.</string> + <string name="generic_error_dlg_title">Error</string> + <string name="generic_error_dlg_text">App could not be uninstalled.</string> <string name="uninstall_application_title">Uninstall app</string> <string name="uninstall_update_title">Uninstall update</string> <string name="uninstall_activity_text"><xliff:g id="activity_name">%1$s</xliff:g> is part of the following app:</string> diff --git a/src/com/android/packageinstaller/EventResultPersister.java b/src/com/android/packageinstaller/EventResultPersister.java index 079d53f3..da091b38 100644 --- a/src/com/android/packageinstaller/EventResultPersister.java +++ b/src/com/android/packageinstaller/EventResultPersister.java @@ -79,6 +79,22 @@ class EventResultPersister { @GuardedBy("mLock") private boolean mIsPersistingStateValid; + /** + * @return a new event id. + */ + public int getNewId() throws OutOfIdsException { + synchronized (mLock) { + if (mCounter == Integer.MAX_VALUE) { + throw new OutOfIdsException(); + } + + mCounter++; + writeState(); + + return mCounter - 1; + } + } + /** Call back when a result is received. Observer is removed when onResult it called. */ interface EventResultObserver { void onResult(int status, int legacyStatus, @Nullable String message); @@ -253,20 +269,11 @@ class EventResultPersister { */ int addObserver(int id, @NonNull EventResultObserver observer) throws OutOfIdsException { - boolean stateChanged = false; - synchronized (mLock) { int resultIndex = -1; if (id == GENERATE_NEW_ID) { - if (mCounter == Integer.MAX_VALUE) { - throw new OutOfIdsException(); - } else { - id = mCounter; - mCounter++; - - stateChanged = true; - } + id = getNewId(); } else { resultIndex = mResults.indexOfKey(id); } @@ -277,14 +284,10 @@ class EventResultPersister { observer.onResult(result.status, result.legacyStatus, result.message); mResults.removeAt(resultIndex); - stateChanged = true; + writeState(); } else { mObservers.put(id, observer); } - - if (stateChanged) { - writeState(); - } } diff --git a/src/com/android/packageinstaller/UninstallEventReceiver.java b/src/com/android/packageinstaller/UninstallEventReceiver.java new file mode 100644 index 00000000..62e0b22a --- /dev/null +++ b/src/com/android/packageinstaller/UninstallEventReceiver.java @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.packageinstaller; + +import android.annotation.NonNull; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; + +import java.io.File; + +/** + * Receives uninstall events and persists them using a {@link EventResultPersister}. + */ +public class UninstallEventReceiver extends BroadcastReceiver { + private static final Object sLock = new Object(); + private static EventResultPersister sReceiver; + + /** + * Get the event receiver persisting the results + * + * @return The event receiver. + */ + @NonNull private static EventResultPersister getReceiver(@NonNull Context context) { + synchronized (sLock) { + if (sReceiver == null) { + sReceiver = new EventResultPersister(new File(context.getNoBackupFilesDir(), + "uninstall_results.xml")); + } + } + + return sReceiver; + } + + @Override + public void onReceive(Context context, Intent intent) { + if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) { + // Do not persist uninstalls over reboot + synchronized (sLock) { + new File(context.getNoBackupFilesDir(), "uninstall_results.xml").delete(); + } + } else { + getReceiver(context).onEventReceived(context, intent); + } + } + + /** + * Add an observer. If there is already an event for this id, call back inside of this call. + * + * @param context A context of the current app + * @param id The id the observer is for or {@code GENERATE_NEW_ID} to generate a new one. + * @param observer The observer to call back. + * + * @return The id for this event + */ + static int addObserver(@NonNull Context context, int id, + @NonNull EventResultPersister.EventResultObserver observer) + throws EventResultPersister.OutOfIdsException { + return getReceiver(context).addObserver(id, observer); + } + + /** + * Remove a observer. + * + * @param context A context of the current app + * @param id The id the observer was added for + */ + static void removeObserver(@NonNull Context context, int id) { + getReceiver(context).removeObserver(id); + } + + /** + * @param context A context of the current app + * + * @return A new uninstall id + */ + static int getNewId(@NonNull Context context) throws EventResultPersister.OutOfIdsException { + return getReceiver(context).getNewId(); + } +} diff --git a/src/com/android/packageinstaller/UninstallUninstalling.java b/src/com/android/packageinstaller/UninstallUninstalling.java new file mode 100644 index 00000000..84da17db --- /dev/null +++ b/src/com/android/packageinstaller/UninstallUninstalling.java @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.packageinstaller; + +import android.annotation.Nullable; +import android.app.Activity; +import android.app.ActivityThread; +import android.app.AlertDialog; +import android.app.Dialog; +import android.app.DialogFragment; +import android.app.Fragment; +import android.app.FragmentTransaction; +import android.app.PendingIntent; +import android.content.Intent; +import android.content.pm.ApplicationInfo; +import android.content.pm.IPackageDeleteObserver2; +import android.content.pm.PackageInstaller; +import android.content.pm.PackageManager; +import android.os.Bundle; +import android.os.IBinder; +import android.os.RemoteException; +import android.os.UserHandle; +import android.widget.Toast; + +/** + * Start an uninstallation, show a dialog while uninstalling and return result to the caller. + */ +public class UninstallUninstalling extends Activity implements + EventResultPersister.EventResultObserver { + private static final String UNINSTALL_ID = "com.android.packageinstaller.UNINSTALL_ID"; + private static final String BROADCAST_ACTION = + "com.android.packageinstaller.ACTION_UNINSTALL_COMMIT"; + + static final String EXTRA_APP_LABEL = "com.android.packageinstaller.extra.APP_LABEL"; + + private int mUninstallId; + private ApplicationInfo mAppInfo; + private IBinder mCallback; + private boolean mReturnResult; + private String mLabel; + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setFinishOnTouchOutside(false); + + mAppInfo = getIntent().getParcelableExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO); + mCallback = getIntent().getIBinderExtra(PackageInstaller.EXTRA_CALLBACK); + mReturnResult = getIntent().getBooleanExtra(Intent.EXTRA_RETURN_RESULT, false); + mLabel = getIntent().getStringExtra(EXTRA_APP_LABEL); + + try { + if (savedInstanceState == null) { + boolean allUsers = getIntent().getBooleanExtra(Intent.EXTRA_UNINSTALL_ALL_USERS, + false); + UserHandle user = getIntent().getParcelableExtra(Intent.EXTRA_USER); + + // Show dialog, which is the whole UI + FragmentTransaction transaction = getFragmentManager().beginTransaction(); + Fragment prev = getFragmentManager().findFragmentByTag("dialog"); + if (prev != null) { + transaction.remove(prev); + } + DialogFragment dialog = new UninstallUninstallingFragment(); + dialog.setCancelable(false); + dialog.show(transaction, "dialog"); + + mUninstallId = UninstallEventReceiver.addObserver(this, + EventResultPersister.GENERATE_NEW_ID, this); + + Intent broadcastIntent = new Intent(BROADCAST_ACTION); + broadcastIntent.putExtra(EventResultPersister.EXTRA_ID, mUninstallId); + + PendingIntent pendingIntent = PendingIntent.getBroadcast(this, mUninstallId, + broadcastIntent, PendingIntent.FLAG_UPDATE_CURRENT); + + try { + ActivityThread.getPackageManager().getPackageInstaller().uninstall( + mAppInfo.packageName, getPackageName(), + allUsers ? PackageManager.DELETE_ALL_USERS : 0, + pendingIntent.getIntentSender(), user.getIdentifier()); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } else { + mUninstallId = savedInstanceState.getInt(UNINSTALL_ID); + UninstallEventReceiver.addObserver(this, mUninstallId, this); + } + } catch (EventResultPersister.OutOfIdsException e) { + onResult(PackageInstaller.STATUS_FAILURE, PackageManager.DELETE_FAILED_INTERNAL_ERROR, + null); + } + } + + @Override + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + + outState.putInt(UNINSTALL_ID, mUninstallId); + } + + @Override + public void onBackPressed() { + // do nothing + } + + @Override + public void onResult(int status, int legacyStatus, @Nullable String message) { + if (mCallback != null) { + // The caller will be informed about the result via a callback + final IPackageDeleteObserver2 observer = IPackageDeleteObserver2.Stub + .asInterface(mCallback); + try { + observer.onPackageDeleted(mAppInfo.packageName, legacyStatus, message); + } catch (RemoteException ignored) { + } + return; + } else if (mReturnResult) { + // The caller will be informed about the result and might decide to display it + Intent result = new Intent(); + + result.putExtra(Intent.EXTRA_INSTALL_RESULT, legacyStatus); + setResult(status == PackageInstaller.STATUS_SUCCESS ? Activity.RESULT_OK + : Activity.RESULT_FIRST_USER, result); + } else { + // This is the rare case that the caller did not ask for the result, but wanted to be + // notified via onActivityResult when the installation finishes + if (status != PackageInstaller.STATUS_SUCCESS) { + Toast.makeText(this, getString(R.string.uninstall_failed_app, mLabel), + Toast.LENGTH_LONG).show(); + } + } + finish(); + } + + @Override + protected void onDestroy() { + UninstallEventReceiver.removeObserver(this, mUninstallId); + + super.onDestroy(); + } + + /** + * Dialog that shows that the app is uninstalling. + */ + public static class UninstallUninstallingFragment extends DialogFragment { + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(getActivity()); + + dialogBuilder.setCancelable(false); + dialogBuilder.setMessage(getActivity().getString(R.string.uninstalling_app, + ((UninstallUninstalling) getActivity()).mLabel)); + + Dialog dialog = dialogBuilder.create(); + dialog.setCanceledOnTouchOutside(false); + + return dialog; + } + } +} diff --git a/src/com/android/packageinstaller/UninstallerActivity.java b/src/com/android/packageinstaller/UninstallerActivity.java index c6b2305d..08befefd 100755 --- a/src/com/android/packageinstaller/UninstallerActivity.java +++ b/src/com/android/packageinstaller/UninstallerActivity.java @@ -41,17 +41,17 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.os.UserHandle; import android.os.UserManager; +import android.support.annotation.NonNull; +import android.support.annotation.StringRes; import android.util.Log; -import com.android.packageinstaller.handheld.AppNotFoundDialogFragment; +import com.android.packageinstaller.handheld.ErrorDialogFragment; import com.android.packageinstaller.handheld.UninstallAlertDialogFragment; -import com.android.packageinstaller.handheld.UserIsNotAllowedDialogFragment; -import com.android.packageinstaller.television.AppNotFoundFragment; +import com.android.packageinstaller.television.ErrorFragment; import com.android.packageinstaller.television.UninstallAlertFragment; -import com.android.packageinstaller.television.UserIsNotAllowedFragment; +import com.android.packageinstaller.television.UninstallAppProgress; import java.util.List; -import java.util.Random; /* * This activity presents UI to uninstall an application. Usually launched with intent @@ -154,25 +154,37 @@ public class UninstallerActivity extends Activity { private void showConfirmationDialog() { if (isTv()) { - showContentFragment(new UninstallAlertFragment()); + showContentFragment(new UninstallAlertFragment(), 0, 0); } else { - showDialogFragment(new UninstallAlertDialogFragment()); + showDialogFragment(new UninstallAlertDialogFragment(), 0, 0); } } private void showAppNotFound() { if (isTv()) { - showContentFragment(new AppNotFoundFragment()); + showContentFragment(new ErrorFragment(), R.string.app_not_found_dlg_title, + R.string.app_not_found_dlg_text); } else { - showDialogFragment(new AppNotFoundDialogFragment()); + showDialogFragment(new ErrorDialogFragment(), R.string.app_not_found_dlg_title, + R.string.app_not_found_dlg_text); } } private void showUserIsNotAllowed() { if (isTv()) { - showContentFragment(new UserIsNotAllowedFragment()); + showContentFragment(new ErrorFragment(), + R.string.user_is_not_allowed_dlg_title, R.string.user_is_not_allowed_dlg_text); } else { - showDialogFragment(new UserIsNotAllowedDialogFragment()); + showDialogFragment(new ErrorDialogFragment(), 0, R.string.user_is_not_allowed_dlg_text); + } + } + + private void showGenericError() { + if (isTv()) { + showContentFragment(new ErrorFragment(), + R.string.generic_error_dlg_title, R.string.generic_error_dlg_text); + } else { + showDialogFragment(new ErrorDialogFragment(), 0, R.string.generic_error_dlg_text); } } @@ -181,26 +193,41 @@ public class UninstallerActivity extends Activity { == Configuration.UI_MODE_TYPE_TELEVISION; } - private void showContentFragment(Fragment fragment) { + private void showContentFragment(@NonNull Fragment fragment, @StringRes int title, + @StringRes int text) { + Bundle args = new Bundle(); + args.putInt(ErrorFragment.TITLE, title); + args.putInt(ErrorFragment.TEXT, text); + fragment.setArguments(args); + getFragmentManager().beginTransaction() .replace(android.R.id.content, fragment) .commit(); } - private void showDialogFragment(DialogFragment fragment) { + private void showDialogFragment(@NonNull DialogFragment fragment, + @StringRes int title, @StringRes int text) { FragmentTransaction ft = getFragmentManager().beginTransaction(); Fragment prev = getFragmentManager().findFragmentByTag("dialog"); if (prev != null) { ft.remove(prev); } + + Bundle args = new Bundle(); + if (title != 0) { + args.putInt(ErrorDialogFragment.TITLE, title); + } + args.putInt(ErrorDialogFragment.TEXT, text); + + fragment.setArguments(args); fragment.show(ft, "dialog"); } public void startUninstallProgress() { boolean returnResult = getIntent().getBooleanExtra(Intent.EXTRA_RETURN_RESULT, false); + CharSequence label = mDialogInfo.appInfo.loadLabel(getPackageManager()); - if (isTv() || returnResult || mDialogInfo.callback != null - || getCallingActivity() != null) { + if (isTv()) { Intent newIntent = new Intent(Intent.ACTION_VIEW); newIntent.putExtra(Intent.EXTRA_USER, mDialogInfo.user); newIntent.putExtra(Intent.EXTRA_UNINSTALL_ALL_USERS, mDialogInfo.allUsers); @@ -214,9 +241,32 @@ public class UninstallerActivity extends Activity { newIntent.setClass(this, UninstallAppProgress.class); startActivity(newIntent); + } else if (returnResult || mDialogInfo.callback != null || getCallingActivity() != null) { + Intent newIntent = new Intent(this, UninstallUninstalling.class); + + newIntent.putExtra(Intent.EXTRA_USER, mDialogInfo.user); + newIntent.putExtra(Intent.EXTRA_UNINSTALL_ALL_USERS, mDialogInfo.allUsers); + newIntent.putExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO, mDialogInfo.appInfo); + newIntent.putExtra(UninstallUninstalling.EXTRA_APP_LABEL, label); + newIntent.putExtra(PackageInstaller.EXTRA_CALLBACK, mDialogInfo.callback); + + if (returnResult) { + newIntent.putExtra(Intent.EXTRA_RETURN_RESULT, true); + } + + if (returnResult || getCallingActivity() != null) { + newIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT); + } + + startActivity(newIntent); } else { - int uninstallId = (new Random()).nextInt(); - CharSequence label = mDialogInfo.appInfo.loadLabel(getPackageManager()); + int uninstallId; + try { + uninstallId = UninstallEventReceiver.getNewId(this); + } catch (EventResultPersister.OutOfIdsException e) { + showGenericError(); + return; + } Intent broadcastIntent = new Intent(this, UninstallFinish.class); @@ -243,7 +293,8 @@ public class UninstallerActivity extends Activity { mDialogInfo.allUsers ? PackageManager.DELETE_ALL_USERS : 0, pendingIntent.getIntentSender(), mDialogInfo.user.getIdentifier()); } catch (RemoteException e) { - e.rethrowFromSystemServer(); + Log.e(TAG, "Cannot start uninstall", e); + showGenericError(); } } } diff --git a/src/com/android/packageinstaller/handheld/AppNotFoundDialogFragment.java b/src/com/android/packageinstaller/handheld/ErrorDialogFragment.java index 3217bf4a..8171101b 100644 --- a/src/com/android/packageinstaller/handheld/AppNotFoundDialogFragment.java +++ b/src/com/android/packageinstaller/handheld/ErrorDialogFragment.java @@ -23,18 +23,23 @@ import android.app.DialogFragment; import android.content.DialogInterface; import android.os.Bundle; -import com.android.packageinstaller.R; import com.android.packageinstaller.UninstallerActivity; -public class AppNotFoundDialogFragment extends DialogFragment { +public class ErrorDialogFragment extends DialogFragment { + public static final String TITLE = "com.android.packageinstaller.arg.title"; + public static final String TEXT = "com.android.packageinstaller.arg.text"; @Override public Dialog onCreateDialog(Bundle savedInstanceState) { - return new AlertDialog.Builder(getActivity()) - .setTitle(R.string.app_not_found_dlg_title) - .setMessage(R.string.app_not_found_dlg_text) - .setPositiveButton(android.R.string.ok, null) - .create(); + AlertDialog.Builder b = new AlertDialog.Builder(getActivity()) + .setMessage(getArguments().getInt(TEXT)) + .setPositiveButton(android.R.string.ok, null); + + if (getArguments().containsKey(TITLE)) { + b.setTitle(getArguments().getInt(TITLE)); + } + + return b.create(); } @Override diff --git a/src/com/android/packageinstaller/handheld/UserIsNotAllowedDialogFragment.java b/src/com/android/packageinstaller/handheld/UserIsNotAllowedDialogFragment.java deleted file mode 100644 index 1f14cfba..00000000 --- a/src/com/android/packageinstaller/handheld/UserIsNotAllowedDialogFragment.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.packageinstaller.handheld; - -import android.app.Activity; -import android.app.AlertDialog; -import android.app.Dialog; -import android.app.DialogFragment; -import android.content.DialogInterface; -import android.os.Bundle; - -import com.android.packageinstaller.R; -import com.android.packageinstaller.UninstallerActivity; - -/** - * A dialog telling the user that he/she is currently not allowed to perform this uninstallation. - */ -public class UserIsNotAllowedDialogFragment extends DialogFragment { - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - return new AlertDialog.Builder(getActivity()) - .setMessage(R.string.user_is_not_allowed_dlg_text) - .setPositiveButton(android.R.string.ok, null) - .create(); - } - - @Override - public void onDismiss(DialogInterface dialog) { - super.onDismiss(dialog); - if (isAdded()) { - ((UninstallerActivity) getActivity()).dispatchAborted(); - getActivity().setResult(Activity.RESULT_FIRST_USER); - getActivity().finish(); - } - } -} diff --git a/src/com/android/packageinstaller/television/AppNotFoundFragment.java b/src/com/android/packageinstaller/television/ErrorFragment.java index b4e40423..4198b03d 100644 --- a/src/com/android/packageinstaller/television/AppNotFoundFragment.java +++ b/src/com/android/packageinstaller/television/ErrorFragment.java @@ -27,7 +27,9 @@ import com.android.packageinstaller.UninstallerActivity; import java.util.List; -public class AppNotFoundFragment extends GuidedStepFragment { +public class ErrorFragment extends GuidedStepFragment { + public static final String TITLE = "com.android.packageinstaller.arg.title"; + public static final String TEXT = "com.android.packageinstaller.arg.text"; @Override public int onProvideTheme() { @@ -37,8 +39,8 @@ public class AppNotFoundFragment extends GuidedStepFragment { @Override public GuidanceStylist.Guidance onCreateGuidance(Bundle savedInstanceState) { return new GuidanceStylist.Guidance( - getString(R.string.app_not_found_dlg_title), - getString(R.string.app_not_found_dlg_text), + getString(getArguments().getInt(TITLE)), + getString(getArguments().getInt(TEXT)), null, null); } diff --git a/src/com/android/packageinstaller/UninstallAppProgress.java b/src/com/android/packageinstaller/television/UninstallAppProgress.java index a8ca7e42..0418792e 100755 --- a/src/com/android/packageinstaller/UninstallAppProgress.java +++ b/src/com/android/packageinstaller/television/UninstallAppProgress.java @@ -14,7 +14,7 @@ ** See the License for the specific language governing permissions and ** limitations under the License. */ -package com.android.packageinstaller; +package com.android.packageinstaller.television; import android.app.Activity; import android.app.admin.IDevicePolicyManager; @@ -42,7 +42,8 @@ import android.util.TypedValue; import android.view.KeyEvent; import android.widget.Toast; -import com.android.packageinstaller.handheld.UninstallAppProgressFragment; +import com.android.packageinstaller.PackageUtil; +import com.android.packageinstaller.R; import java.lang.ref.WeakReference; import java.util.List; diff --git a/src/com/android/packageinstaller/handheld/UninstallAppProgressFragment.java b/src/com/android/packageinstaller/television/UninstallAppProgressFragment.java index e3def2fe..af6d9c58 100644 --- a/src/com/android/packageinstaller/handheld/UninstallAppProgressFragment.java +++ b/src/com/android/packageinstaller/television/UninstallAppProgressFragment.java @@ -14,7 +14,7 @@ * limitations under the License */ -package com.android.packageinstaller.handheld; +package com.android.packageinstaller.television; import android.annotation.Nullable; import android.app.Fragment; @@ -30,7 +30,6 @@ import android.widget.TextView; import com.android.packageinstaller.PackageUtil; import com.android.packageinstaller.R; -import com.android.packageinstaller.UninstallAppProgress; public class UninstallAppProgressFragment extends Fragment implements View.OnClickListener, UninstallAppProgress.ProgressFragment { diff --git a/src/com/android/packageinstaller/television/UserIsNotAllowedFragment.java b/src/com/android/packageinstaller/television/UserIsNotAllowedFragment.java deleted file mode 100644 index 06c98525..00000000 --- a/src/com/android/packageinstaller/television/UserIsNotAllowedFragment.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.packageinstaller.television; - -import android.app.Activity; -import android.os.Bundle; -import android.support.v17.leanback.app.GuidedStepFragment; -import android.support.v17.leanback.widget.GuidanceStylist; -import android.support.v17.leanback.widget.GuidedAction; - -import com.android.packageinstaller.R; -import com.android.packageinstaller.UninstallerActivity; - -import java.util.List; - -/** - * A dialog telling the user that he/she is currently not allowed to perform this uninstallation. - */ -public class UserIsNotAllowedFragment extends GuidedStepFragment { - @Override - public int onProvideTheme() { - return R.style.Theme_Leanback_GuidedStep; - } - - @Override - public GuidanceStylist.Guidance onCreateGuidance(Bundle savedInstanceState) { - return new GuidanceStylist.Guidance( - getString(R.string.user_is_not_allowed_dlg_title), - getString(R.string.user_is_not_allowed_dlg_text), - null, - null); - } - - @Override - public void onCreateActions(List<GuidedAction> actions, Bundle savedInstanceState) { - actions.add(new GuidedAction.Builder(getContext()) - .clickAction(GuidedAction.ACTION_ID_OK) - .build()); - } - - @Override - public void onGuidedActionClicked(GuidedAction action) { - if (isAdded()) { - ((UninstallerActivity) getActivity()).dispatchAborted(); - getActivity().setResult(Activity.RESULT_FIRST_USER); - getActivity().finish(); - } - } -} |