/* * Copyright (C) 2015 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.settings.deviceinfo; import static android.os.storage.DiskInfo.EXTRA_DISK_ID; import static android.os.storage.VolumeInfo.EXTRA_VOLUME_ID; import static com.android.settings.deviceinfo.StorageSettings.TAG; import android.annotation.LayoutRes; import android.annotation.NonNull; import android.content.Intent; import android.content.res.Resources.Theme; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.SystemClock; import android.os.storage.DiskInfo; import android.os.storage.StorageEventListener; import android.os.storage.StorageManager; import android.os.storage.VolumeInfo; import android.text.TextUtils; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.widget.FrameLayout; import android.widget.ProgressBar; import android.widget.TextView; import androidx.fragment.app.FragmentActivity; import com.android.settings.R; import com.android.settingslib.Utils; import com.google.android.setupcompat.template.FooterBarMixin; import com.google.android.setupcompat.template.FooterButton; import com.google.android.setupdesign.GlifLayout; import java.text.NumberFormat; import java.util.List; import java.util.Objects; public abstract class StorageWizardBase extends FragmentActivity { protected static final String EXTRA_FORMAT_FORGET_UUID = "format_forget_uuid"; protected static final String EXTRA_FORMAT_PRIVATE = "format_private"; protected static final String EXTRA_FORMAT_SLOW = "format_slow"; protected static final String EXTRA_MIGRATE_SKIP = "migrate_skip"; protected StorageManager mStorage; protected VolumeInfo mVolume; protected DiskInfo mDisk; private FooterBarMixin mFooterBarMixin; private FooterButton mBack; private FooterButton mNext; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mStorage = getSystemService(StorageManager.class); final String volumeId = getIntent().getStringExtra(EXTRA_VOLUME_ID); if (!TextUtils.isEmpty(volumeId)) { mVolume = mStorage.findVolumeById(volumeId); } final String diskId = getIntent().getStringExtra(EXTRA_DISK_ID); if (!TextUtils.isEmpty(diskId)) { mDisk = mStorage.findDiskById(diskId); } else if (mVolume != null) { mDisk = mVolume.getDisk(); } if (mDisk != null) { mStorage.registerListener(mStorageListener); } } @Override public void setContentView(@LayoutRes int layoutResID) { super.setContentView(layoutResID); mFooterBarMixin = getGlifLayout().getMixin(FooterBarMixin.class); mFooterBarMixin.setSecondaryButton( new FooterButton.Builder(this) .setText(R.string.wizard_back) .setListener(this::onNavigateBack) .setButtonType(FooterButton.ButtonType.OTHER) .setTheme(R.style.SudGlifButton_Secondary) .build() ); mFooterBarMixin.setPrimaryButton( new FooterButton.Builder(this) .setText(R.string.wizard_next) .setListener(this::onNavigateNext) .setButtonType(FooterButton.ButtonType.NEXT) .setTheme(R.style.SudGlifButton_Primary) .build() ); mBack = mFooterBarMixin.getSecondaryButton(); mNext = mFooterBarMixin.getPrimaryButton(); setIcon(com.android.internal.R.drawable.ic_sd_card_48dp); } @Override protected void onDestroy() { mStorage.unregisterListener(mStorageListener); super.onDestroy(); } @Override protected void onApplyThemeResource(Theme theme, int resid, boolean first) { theme.applyStyle(R.style.SetupWizardPartnerResource, true); super.onApplyThemeResource(theme, resid, first); } protected FooterButton getBackButton() { return mBack; } protected FooterButton getNextButton() { return mNext; } protected GlifLayout getGlifLayout() { return requireViewById(R.id.setup_wizard_layout); } protected ProgressBar getProgressBar() { return requireViewById(R.id.storage_wizard_progress); } protected void setCurrentProgress(int progress) { getProgressBar().setProgress(progress); ((TextView) requireViewById(R.id.storage_wizard_progress_summary)).setText( NumberFormat.getPercentInstance().format((double) progress / 100)); } protected void setHeaderText(int resId, CharSequence... args) { final CharSequence headerText = TextUtils.expandTemplate(getText(resId), args); getGlifLayout().setHeaderText(headerText); setTitle(headerText); } protected void setBodyText(int resId, CharSequence... args) { final TextView body = requireViewById(R.id.storage_wizard_body); body.setText(TextUtils.expandTemplate(getText(resId), args)); body.setVisibility(View.VISIBLE); } protected void setAuxChecklist() { final FrameLayout aux = requireViewById(R.id.storage_wizard_aux); aux.addView(LayoutInflater.from(aux.getContext()) .inflate(R.layout.storage_wizard_checklist, aux, false)); aux.setVisibility(View.VISIBLE); // Customize string based on disk ((TextView) aux.requireViewById(R.id.storage_wizard_migrate_v2_checklist_media)) .setText(TextUtils.expandTemplate( getText(R.string.storage_wizard_migrate_v2_checklist_media), getDiskShortDescription())); } protected void setBackButtonText(int resId, CharSequence... args) { mBack.setText(TextUtils.expandTemplate(getText(resId), args)); mBack.setVisibility(View.VISIBLE); } protected void setNextButtonText(int resId, CharSequence... args) { mNext.setText(TextUtils.expandTemplate(getText(resId), args)); mNext.setVisibility(View.VISIBLE); } protected void setBackButtonVisibility(int visible) { mBack.setVisibility(visible); } protected void setNextButtonVisibility(int visible) { mNext.setVisibility(visible); } protected void setIcon(int resId) { final GlifLayout layout = getGlifLayout(); final Drawable icon = getDrawable(resId).mutate(); icon.setTintList(Utils.getColorAccent(layout.getContext())); layout.setIcon(icon); } protected void setKeepScreenOn(boolean keepScreenOn) { getGlifLayout().setKeepScreenOn(keepScreenOn); } public void onNavigateBack(View view) { throw new UnsupportedOperationException(); } public void onNavigateNext(View view) { throw new UnsupportedOperationException(); } private void copyStringExtra(Intent from, Intent to, String key) { if (from.hasExtra(key) && !to.hasExtra(key)) { to.putExtra(key, from.getStringExtra(key)); } } private void copyBooleanExtra(Intent from, Intent to, String key) { if (from.hasExtra(key) && !to.hasExtra(key)) { to.putExtra(key, from.getBooleanExtra(key, false)); } } @Override public void startActivity(Intent intent) { final Intent from = getIntent(); final Intent to = intent; copyStringExtra(from, to, EXTRA_DISK_ID); copyStringExtra(from, to, EXTRA_VOLUME_ID); copyStringExtra(from, to, EXTRA_FORMAT_FORGET_UUID); copyBooleanExtra(from, to, EXTRA_FORMAT_PRIVATE); copyBooleanExtra(from, to, EXTRA_FORMAT_SLOW); copyBooleanExtra(from, to, EXTRA_MIGRATE_SKIP); super.startActivity(intent); } protected VolumeInfo findFirstVolume(int type) { return findFirstVolume(type, 1); } protected VolumeInfo findFirstVolume(int type, int attempts) { while (true) { final List vols = mStorage.getVolumes(); for (VolumeInfo vol : vols) { if (Objects.equals(mDisk.getId(), vol.getDiskId()) && (vol.getType() == type) && (vol.getState() == VolumeInfo.STATE_MOUNTED)) { return vol; } } if (--attempts > 0) { Log.w(TAG, "Missing mounted volume of type " + type + " hosted by disk " + mDisk.getId() + "; trying again"); SystemClock.sleep(250); } else { return null; } } } protected @NonNull CharSequence getDiskDescription() { if (mDisk != null) { return mDisk.getDescription(); } else if (mVolume != null) { return mVolume.getDescription(); } else { return getText(R.string.unknown); } } protected @NonNull CharSequence getDiskShortDescription() { if (mDisk != null) { return mDisk.getShortDescription(); } else if (mVolume != null) { return mVolume.getDescription(); } else { return getText(R.string.unknown); } } private final StorageEventListener mStorageListener = new StorageEventListener() { @Override public void onDiskDestroyed(DiskInfo disk) { // We know mDisk != null. if (mDisk.id.equals(disk.id)) { finish(); } } }; }