• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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.car.settings.quicksettings;
18 
19 import android.app.Activity;
20 import android.app.ActivityManager;
21 import android.car.drivingstate.CarUxRestrictions;
22 import android.content.Context;
23 import android.content.Intent;
24 import android.content.pm.UserInfo;
25 import android.graphics.drawable.Drawable;
26 import android.os.Build;
27 import android.os.Bundle;
28 import android.os.SystemProperties;
29 import android.os.UserManager;
30 import android.view.View;
31 import android.widget.TextView;
32 
33 import androidx.activity.result.ActivityResultLauncher;
34 import androidx.activity.result.contract.ActivityResultContracts;
35 import androidx.annotation.LayoutRes;
36 import androidx.annotation.NonNull;
37 
38 import com.android.car.settings.R;
39 import com.android.car.settings.common.BaseFragment;
40 import com.android.car.settings.common.CarSettingActivities;
41 import com.android.car.settings.profiles.ProfileIconProvider;
42 import com.android.car.settings.profiles.ProfileSwitcherActivity;
43 import com.android.car.ui.recyclerview.CarUiRecyclerView;
44 import com.android.car.ui.toolbar.MenuItem;
45 import com.android.car.ui.toolbar.NavButtonMode;
46 
47 import java.util.Arrays;
48 import java.util.List;
49 import java.util.concurrent.TimeUnit;
50 
51 /**
52  * Shows a page to access frequently used settings.
53  */
54 public class QuickSettingFragment extends BaseFragment {
55     // Time to delay refreshing the build info, if the clock is not correct.
56     private static final long BUILD_INFO_REFRESH_TIME_MS = TimeUnit.SECONDS.toMillis(5);
57 
58     private UserManager mUserManager;
59     private ProfileIconProvider mProfileIconProvider;
60     private QuickSettingGridAdapter mGridAdapter;
61     private CarUiRecyclerView mListView;
62     private MenuItem mFullSettingsBtn;
63     private MenuItem mProfileSwitcherBtn;
64     private TextView mBuildInfo;
65 
66     private ActivityResultLauncher<Intent> mStartForResult = registerForActivityResult(
67             new ActivityResultContracts.StartActivityForResult(),
68             result -> {
69                 if (result.getResultCode() == Activity.FINISH_TASK_WITH_ACTIVITY) {
70                     getActivity().finish();
71                 }
72             });
73 
74     @Override
75     @LayoutRes
getLayoutId()76     protected int getLayoutId() {
77         return R.layout.quick_settings;
78     }
79 
80     @Override
onActivityCreated(Bundle savedInstanceState)81     public void onActivityCreated(Bundle savedInstanceState) {
82         super.onActivityCreated(savedInstanceState);
83         mUserManager = UserManager.get(getContext());
84         Activity activity = requireActivity();
85 
86         mProfileIconProvider = new ProfileIconProvider();
87         mListView = activity.findViewById(R.id.quick_settings_list);
88         mGridAdapter = new QuickSettingGridAdapter(activity);
89         mListView.setLayoutManager(mGridAdapter.getGridLayoutManager());
90 
91         setupProfileButton(activity);
92 
93         mGridAdapter
94                 .addTile(new WifiTile(activity, mGridAdapter, getLifecycle()))
95                 .addTile(new BluetoothTile(activity, mGridAdapter, getFragmentHost()))
96                 .addTile(new DayNightTile(activity, mGridAdapter, getFragmentHost()))
97                 .addTile(new CelluarTile(activity, mGridAdapter, getFragmentHost()))
98                 .addSeekbarTile(new BrightnessTile(activity));
99         mListView.setAdapter(mGridAdapter);
100     }
101 
102 
103     @Override
getToolbarNavButtonStyle()104     protected NavButtonMode getToolbarNavButtonStyle() {
105         if (getContext().getResources().getBoolean(R.bool.config_is_quick_settings_root)
106                 && !getContext().getResources()
107                 .getBoolean(R.bool.config_show_settings_root_exit_icon)) {
108             return NavButtonMode.DISABLED;
109         } else {
110             return NavButtonMode.CLOSE;
111         }
112     }
113 
114     @Override
getToolbarMenuItems()115     public List<MenuItem> getToolbarMenuItems() {
116         return Arrays.asList(mProfileSwitcherBtn, mFullSettingsBtn);
117     }
118 
119     @Override
onCreate(Bundle savedInstanceState)120     public void onCreate(Bundle savedInstanceState) {
121         super.onCreate(savedInstanceState);
122 
123         mProfileSwitcherBtn = new MenuItem.Builder(getContext())
124                 .setTitle(getString(R.string.user_switch))
125                 .setOnClickListener(i ->
126                         mStartForResult.launch(
127                                 new Intent(getContext(), ProfileSwitcherActivity.class)))
128                 .setIcon(R.drawable.ic_profile)
129                 .setShowIconAndTitle(true)
130                 .setVisible(showProfileSwitcher())
131                 .setTinted(false)
132                 .build();
133         mFullSettingsBtn = new MenuItem.Builder(getContext())
134                 .setTitle(getString(R.string.more_settings_label))
135                 .setOnClickListener(i -> launchFullSettings())
136                 .setIcon(R.drawable.ic_settings_gear)
137                 .setShowIconAndTitle(true)
138                 .setUxRestrictions(CarUxRestrictions.UX_RESTRICTIONS_NO_SETUP)
139                 .build();
140     }
141 
142     @Override
onViewCreated(@onNull View view, Bundle savedInstanceState)143     public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
144         super.onViewCreated(view, savedInstanceState);
145 
146         mBuildInfo = view.requireViewById(R.id.build_info);
147     }
148 
149     @Override
onStart()150     public void onStart() {
151         super.onStart();
152         mGridAdapter.start();
153 
154         // In non-user builds (that is, user-debug, eng, etc), display some version information.
155         if (!Build.IS_USER) {
156             refreshBuildInfo();
157         }
158     }
159 
launchFullSettings()160     private void launchFullSettings() {
161         startActivity(new Intent(getContext(), CarSettingActivities.HomepageActivity.class));
162         if (!getContext().getResources().getBoolean(R.bool.config_is_quick_settings_root)) {
163             getActivity().finish();
164         }
165     }
166 
refreshBuildInfo()167     private void refreshBuildInfo() {
168         if (!isAdded()) {
169             // This can happen if the delayed post happens before we're stopped. Just give up
170             // trying to get the right clock.
171             return;
172         }
173 
174         long buildTimeDiffDays =
175                 TimeUnit.MILLISECONDS.toDays(System.currentTimeMillis() - Build.TIME);
176         if (buildTimeDiffDays < 0) {
177             // If it's in the past, that likely means the current time is wrong (or the build time
178             // could be wrong, but that's less likely). Reschedule this to run in a few seconds to
179             // see whether the clock's been fixed.
180             mBuildInfo.postDelayed(this::refreshBuildInfo, BUILD_INFO_REFRESH_TIME_MS);
181         }
182 
183         String str = String.format(getResources().getString(R.string.build_info_fmt),
184                 Build.FINGERPRINT, SystemProperties.get("ro.build.date", "<unknown>"),
185                 buildTimeDiffDays < 0 ? "--" : Long.toString(buildTimeDiffDays));
186 
187         mBuildInfo.setVisibility(View.VISIBLE);
188         mBuildInfo.setText(str);
189     }
190 
191     @Override
onStop()192     public void onStop() {
193         super.onStop();
194         mGridAdapter.stop();
195     }
196 
setupProfileButton(Context context)197     private void setupProfileButton(Context context) {
198         UserInfo currentUserInfo = mUserManager.getUserInfo(ActivityManager.getCurrentUser());
199         Drawable profileIcon = mProfileIconProvider.getDrawableWithBadge(context, currentUserInfo);
200         mProfileSwitcherBtn.setIcon(profileIcon);
201         mProfileSwitcherBtn.setTitle(currentUserInfo.name);
202     }
203 
showProfileSwitcher()204     private boolean showProfileSwitcher() {
205         return !UserManager.isDeviceInDemoMode(getContext())
206                 && UserManager.supportsMultipleUsers()
207                 && !UserManager.get(getContext()).hasUserRestriction(
208                 UserManager.DISALLOW_USER_SWITCH);
209     }
210 
211     /**
212      * Quick Settings should be viewable while driving
213      */
214     @Override
canBeShown(@onNull CarUxRestrictions carUxRestrictions)215     protected boolean canBeShown(@NonNull CarUxRestrictions carUxRestrictions) {
216         return true;
217     }
218 }
219