Home | History | Annotate | Download | only in about
      1 /*
      2  * Copyright (C) 2014 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.tv.settings.about;
     18 
     19 import com.android.tv.settings.R;
     20 import com.android.tv.settings.PreferenceUtils;
     21 import com.android.tv.settings.dialog.old.Action;
     22 import com.android.tv.settings.dialog.old.ActionAdapter;
     23 import com.android.tv.settings.dialog.old.ActionFragment;
     24 import com.android.tv.settings.dialog.old.ContentFragment;
     25 import com.android.tv.settings.dialog.old.DialogActivity;
     26 import com.android.tv.settings.name.DeviceManager;
     27 
     28 import android.app.Fragment;
     29 import android.app.FragmentTransaction;
     30 import android.content.ActivityNotFoundException;
     31 import android.content.ComponentName;
     32 import android.content.Context;
     33 import android.content.Intent;
     34 import android.content.pm.ApplicationInfo;
     35 import android.content.pm.PackageManager;
     36 import android.content.pm.ResolveInfo;
     37 import android.os.Build;
     38 import android.os.Bundle;
     39 import android.os.PowerManager;
     40 import android.os.SystemClock;
     41 import android.text.TextUtils;
     42 import android.util.Log;
     43 import android.widget.Toast;
     44 
     45 import java.util.ArrayList;
     46 import java.util.List;
     47 
     48 /**
     49  * Activity which shows the build / model / legal info / etc.
     50  */
     51 public class AboutActivity extends DialogActivity implements ActionAdapter.Listener,
     52         ActionAdapter.OnFocusListener {
     53 
     54     private static final String TAG = "AboutActivity";
     55 
     56     /**
     57      * Action keys for switching over in onActionClicked.
     58      */
     59     private static final String KEY_LEGAL_INFO = "about_legal_info";
     60     private static final String KEY_BUILD = "build";
     61     private static final String KEY_VERSION = "version";
     62     private static final String KEY_REBOOT = "reboot";
     63 
     64     /**
     65      * Intent action of SettingsLicenseActivity (for displaying open source licenses.)
     66      */
     67     private static final String SETTINGS_LEGAL_LICENSE_INTENT_ACTION = "android.settings.LICENSE";
     68 
     69     /**
     70      * Intent action of SettingsTosActivity (for displaying terms of service.)
     71      */
     72     private static final String SETTINGS_LEGAL_TERMS_OF_SERVICE = "android.settings.TERMS";
     73 
     74     /**
     75      * Intent action of device name activity.
     76      */
     77     private static final String SETTINGS_DEVICE_NAME_INTENT_ACTION = "android.settings.DEVICE_NAME";
     78 
     79     /**
     80      * Intent action of system update activity.
     81      */
     82     private static final String SETTINGS_UPDATE_SYSTEM = "android.settings.SYSTEM_UPDATE_SETTINGS";
     83 
     84     /**
     85      * Intent to launch ads activity.
     86      */
     87     private static final String SETTINGS_ADS_ACTIVITY_PACKAGE = "com.google.android.gms";
     88     private static final String SETTINGS_ADS_ACTIVITY_ACTION =
     89             "com.google.android.gms.settings.ADS_PRIVACY";
     90 
     91     /**
     92      * Intent component to launch PlatLogo Easter egg.
     93      */
     94     private static final ComponentName mPlatLogoActivity = new ComponentName("android",
     95             "com.android.internal.app.PlatLogoActivity");
     96 
     97     /**
     98      * Number of clicks it takes to be a developer.
     99      */
    100     private static final int NUM_DEVELOPER_CLICKS = 7;
    101 
    102     private int mDeveloperClickCount;
    103     private PreferenceUtils mPreferenceUtils;
    104     private Toast mToast;
    105     private int mSelectedIndex;
    106     private long[] mHits = new long[3];
    107     private int mHitsIndex;
    108 
    109     @Override
    110     protected void onCreate(Bundle savedInstanceState) {
    111         super.onCreate(savedInstanceState);
    112         mPreferenceUtils = new PreferenceUtils(this);
    113         setContentAndActionFragments(ContentFragment.newInstance(
    114                         getString(R.string.about_preference), null, null, R.drawable.ic_settings_about,
    115                         getResources().getColor(R.color.icon_background)),
    116                 ActionFragment.newInstance(getActions()));
    117         mSelectedIndex = 0;
    118     }
    119 
    120     @Override
    121     public void onResume() {
    122         super.onResume();
    123         mDeveloperClickCount = 0;
    124     }
    125 
    126     @Override
    127     public void onActionFocused(Action action) {
    128         mSelectedIndex = getActions().indexOf(action);
    129     }
    130 
    131     @Override
    132     public void onActionClicked(Action action) {
    133         final String key = action.getKey();
    134         if (TextUtils.equals(key, KEY_BUILD)) {
    135             mDeveloperClickCount++;
    136             if (!mPreferenceUtils.isDeveloperEnabled()) {
    137                 int numLeft = NUM_DEVELOPER_CLICKS - mDeveloperClickCount;
    138                 if (numLeft < 3 && numLeft > 0) {
    139                     showToast(getResources().getQuantityString(
    140                             R.plurals.show_dev_countdown, numLeft, numLeft));
    141                 }
    142                 if (numLeft == 0) {
    143                     mPreferenceUtils.setDeveloperEnabled(true);
    144                     showToast(getString(R.string.show_dev_on));
    145                     mDeveloperClickCount = 0;
    146                 }
    147             } else {
    148                 if (mDeveloperClickCount > 3) {
    149                     showToast(getString(R.string.show_dev_already));
    150                 }
    151             }
    152         } else if (TextUtils.equals(key, KEY_VERSION)) {
    153             mHits[mHitsIndex] = SystemClock.uptimeMillis();
    154             mHitsIndex = (mHitsIndex + 1) % mHits.length;
    155             if (mHits[mHitsIndex] >= SystemClock.uptimeMillis() - 500) {
    156                 Intent intent = new Intent();
    157                 intent.setComponent(mPlatLogoActivity);
    158                 startActivity(intent);
    159             }
    160         } else if (TextUtils.equals(key, KEY_LEGAL_INFO)) {
    161             ArrayList<Action> actions = getLegalActions();
    162             setContentAndActionFragments(ContentFragment.newInstance(
    163                     getString(R.string.about_legal_info), null, null),
    164                     ActionFragment.newInstance(actions));
    165         } else if (TextUtils.equals(key, KEY_REBOOT)) {
    166             PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);
    167             pm.reboot(null);
    168         } else {
    169             Intent intent = action.getIntent();
    170             if (intent != null) {
    171                 try {
    172                     startActivity(intent);
    173                 } catch (ActivityNotFoundException e) {
    174                     Log.e(TAG, "intent for (" + action.getTitle() + ") not found:", e);
    175                 }
    176             } else {
    177                 Log.e(TAG, "null intent for: " + action.getTitle());
    178             }
    179         }
    180     }
    181 
    182     private ArrayList<Action> getLegalActions() {
    183         ArrayList<Action> actions = new ArrayList<Action>();
    184         actions.add(new Action.Builder()
    185                 .intent(systemIntent(SETTINGS_LEGAL_LICENSE_INTENT_ACTION))
    186                 .title(getString(R.string.about_legal_license))
    187                 .build());
    188         actions.add(new Action.Builder()
    189                 .intent(systemIntent(SETTINGS_LEGAL_TERMS_OF_SERVICE))
    190                 .title(getString(R.string.about_terms_of_service))
    191                 .build());
    192 
    193         return actions;
    194     }
    195 
    196     private ArrayList<Action> getActions() {
    197         ArrayList<Action> actions = new ArrayList<Action>();
    198         actions.add(new Action.Builder()
    199                 .key("update")
    200                 .title(getString(R.string.about_system_update))
    201                 .intent(systemIntent(SETTINGS_UPDATE_SYSTEM))
    202                 .build());
    203         actions.add(new Action.Builder()
    204                 .key("name")
    205                 .title(getString(R.string.device_name))
    206                 .description(DeviceManager.getDeviceName(this))
    207                 .intent(new Intent(SETTINGS_DEVICE_NAME_INTENT_ACTION))
    208                 .build());
    209         actions.add(new Action.Builder()
    210                 .key(KEY_REBOOT)
    211                 .title(getString(R.string.restart_button_label))
    212                 .build());
    213         actions.add(new Action.Builder()
    214                 .key(KEY_LEGAL_INFO)
    215                 .title(getString(R.string.about_legal_info))
    216                 .build());
    217         Intent adsIntent = new Intent();
    218         adsIntent.setPackage(SETTINGS_ADS_ACTIVITY_PACKAGE);
    219         adsIntent.setAction(SETTINGS_ADS_ACTIVITY_ACTION);
    220         adsIntent.addCategory(Intent.CATEGORY_DEFAULT);
    221         List<ResolveInfo> resolveInfos = getPackageManager().queryIntentActivities(adsIntent,
    222                 PackageManager.MATCH_DEFAULT_ONLY);
    223         if (!resolveInfos.isEmpty()) {
    224             // Launch the phone ads id activity.
    225             actions.add(new Action.Builder()
    226                     .key("ads")
    227                     .title(getString(R.string.about_ads))
    228                     .intent(adsIntent)
    229                     .enabled(true)
    230                     .build());
    231         }
    232         actions.add(new Action.Builder()
    233                 .key("model")
    234                 .title(getString(R.string.about_model))
    235                 .description(Build.MODEL)
    236                 .enabled(false)
    237                 .build());
    238         actions.add(new Action.Builder()
    239                 .key(KEY_VERSION)
    240                 .title(getString(R.string.about_version))
    241                 .description(Build.VERSION.RELEASE)
    242                 .enabled(true)
    243                 .build());
    244         actions.add(new Action.Builder()
    245                 .key("serial")
    246                 .title(getString(R.string.about_serial))
    247                 .description(Build.SERIAL)
    248                 .enabled(false)
    249                 .build());
    250         actions.add(new Action.Builder()
    251                 .key(KEY_BUILD)
    252                 .title(getString(R.string.about_build))
    253                 .description(Build.DISPLAY)
    254                 .enabled(true)
    255                 .build());
    256         return actions;
    257     }
    258 
    259     private void displayFragment(Fragment fragment) {
    260         getFragmentManager()
    261             .beginTransaction()
    262             .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
    263             .replace(android.R.id.content, fragment)
    264             .addToBackStack(null)
    265             .commit();
    266     }
    267 
    268     private void showToast(String toastString) {
    269         if (mToast != null) {
    270             mToast.cancel();
    271         }
    272         mToast = Toast.makeText(this, toastString, Toast.LENGTH_SHORT);
    273         mToast.show();
    274     }
    275 
    276     // Returns an Intent for the given action if a system app can handle it, otherwise null.
    277     private Intent systemIntent(String action) {
    278         final Intent intent = new Intent(action);
    279 
    280         // Limit the intent to an activity that is in the system image.
    281         final PackageManager pm = getPackageManager();
    282         final List<ResolveInfo> activities = pm.queryIntentActivities(intent, 0);
    283         for (ResolveInfo info : activities) {
    284             if ((info.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
    285                 if (info.activityInfo.isEnabled()) {
    286                     intent.setPackage(info.activityInfo.packageName);
    287                     return intent;
    288                 }
    289             }
    290         }
    291         return null;  // No system image package found.
    292     }
    293 }
    294